3 * This file is part of dds2tar.
4 * Copyright by J"org Weule
14 * fnmatch() and FNM_LEADING_DIR
26 int dds_strcmp(const char*n1,const char*n2){
30 while ( n1[i] == '\\' ) i++ ;
31 while ( n2[j] == '\\' ) j++ ;
32 if ( i > 90 || j > 90 || n1[i] == '\0' || n2[j] == '\0' )
34 if ( n1[i] != n2[j] ) return 1 ;
42 * To count the number of blocks written, we use the variable nblocks.
44 static int nblocks = 0;
47 * Fill the buffer 'cur_block' the block of the given number.
48 * first we check the block number of the copy that is hold inside the
52 set_cur_block(int const sb)
57 fprintf(stderr,"%d\n",__LINE__);
58 fprintf(stderr, "set_cur_block(%d)\n", sb);
61 if (sb != cur_blkno) {
63 * We have to read the block.
65 next_blkno = dds_getpos(device);
67 * next_blkno stores now the number of the next block of the
72 * In some cases reading is faster then seeking.
74 if ((n > 0) && (n < DONT_SKIP)) {
80 * Now we should be at the position.
88 * Now we read the block. cur_n == 0 indicates a filemark.
96 * procedure to extract the files from the specified area (sb:sr-eb:er).
97 * If area is of the form (sb:sr-0:0), the file at position (sb,sr) is
98 * extracted. The length of the file is read from the tar header record.
100 * If list_only is set to 1, only the name of the extraction is printed.
103 extract(char const *const name, int const sb, int const sr)
106 int cur_rec, n, size;
110 fprintf(stderr,"%d\n",__LINE__);
111 fprintf(stderr, "extract(%s,%d,%d)\n", name, sb, sr);
115 * Print only the name.
117 if (list_only == 1) {
118 printf("%7d%3d: %s\n", sb, sr, name);
122 * Print the filename and the location for verbose output.
126 "dds2tar at rec %d: %7d%3d: %s\n",
127 nblocks, sb, sr, name);
130 * Check the buffer for the right tape block.
136 * Check the header block.
137 * The Name field should contain the given name.
138 * The Program will stop if its not.
140 * Note that for links we can only compare the first
141 * characters, when the index contains somethins like
142 * 'linkname -> filename' (soft link) or
143 * 'linkname link to filename' (hard link)
144 * doesn't match 'linkname'.
146 p = (char*) (cur_block + cur_rec) ;
147 if ( dds_is_tar_header_record((tar_record*)p) == 0 ) {
149 " dds2tar: FATAL ERROR\n"
150 " dds2tar: header expected, not found\n"
152 if ( force_nochk == 0 ) exit(5);
155 if ( ( (dds_strcmp(name, p)!=0 )
156 && (((tar_record*)p)->hdr.linkflag!='2')
157 && (((tar_record*)p)->hdr.linkflag!='1')
158 ) || ( strstr(name, p)!=name ) ) {
160 "dds2tar: FATAL ERROR\n"
161 "dds2tar: Looked for %s at %d %d\n"
162 "dds2tar: Could not find %s at %d %d.\n"
163 "dds2tar: Found %s\n"
164 "dds2tar: Link flag: %c\n"
165 "dds2tar: Is it the right tape?\n",
167 name, dds_getpos(device) - 1, cur_rec,p,
168 ((tar_record*)p)->hdr.linkflag);
169 if ( force_nochk == 0 ) exit(5);
172 * First calculate the number of records of the object.
177 p = cur_block[cur_rec].hdr.size;
179 sscanf(p, "%o", &size);
185 * Now write the records to stdout.
189 "dd2tar: %s needs %d blocks\n", name, n);
191 if ( write_body == 1 ) {
193 while ((size > 0) && (cur_n > 0)) {
194 if (cur_rec >= cur_bs) {
198 write(1, cur_block + cur_rec, (size>=512)? 512:size );
204 while ((n > 0) && (cur_n > 0)) {
205 if (cur_rec >= cur_bs) {
209 write(1, cur_block + cur_rec, 512);
219 extract_loc(char const *const *loc_list)
223 while (*loc_list != NULL) {
226 sscanf(*loc_list, "%u:%u-%u:%u", &sb, &sr, &eb, &er);
232 if ((cur_n & 0x1ff) != 0) {
234 "tape record size (%d) is not a"
235 " multiple of tar records\n"
244 while (cur_rec < i) {
245 write(1, cur_block + cur_rec++, 512);
249 * if eb==-1 extract until eof
251 if ((cur_rec == er && cur_blkno == eb))
255 if ((cur_rec == er && cur_blkno == eb))
267 * Now we are scanning the table of contents (index file) and match the
268 * pathnames there with the given pattern. If a pattern matches, we
269 * extract the parent directories (dir_extract()) and the file.
272 dds_cmp(char const *const *const pattern_list)
275 char *fgets_return_value ;
276 char const *const *p;
277 int so = 0 ; /*scanoffset*/
280 * To scan the line of the table of contents (index file)
281 * we need some variables.
284 int blkno, recno, size;
287 * List of directories entries.
290 char n[128-2*sizeof(int)]; /* name of the dir */
291 int b, r; /* block address */
294 int de = 0; /* first empty list entry */
297 * Format of the table of contents.
298 * dds2index --> tar_index_file == 0
299 * tar -Rvt --> tar_index_file == 1
301 int tar_index_file = 1;
304 * Bug fix for tar. First record number found inside the
305 * table of contents (index file).
307 int tar_first_recno = -1;
310 fprintf(stderr,"%d\n",__LINE__);
311 fprintf(stderr,"dds_cmp(%s ...)\n",*pattern_list);
316 * First we need some memory.
318 dl = malloc(sizeof (*dl) * 64);
321 fprintf(stderr, "dds2tar: no address space available\n");
324 memset(cur_line, 0, 1024);
327 * Scan the table of conten|s (index file) until eof.
330 fprintf(stderr,"%d\n",__LINE__);
332 while (!feof(index_fp)) {
333 fgets_return_value = fgets(cur_line, MAXPATHLEN<<2, index_fp);
334 if ( fgets_return_value == NULL ) {
335 if ( feof(index_fp) ) {
343 fprintf(stderr,"%d\n",__LINE__);
344 fputs(cur_line, stderr);
348 * Check for comment and empty lines.
350 if ((*cur_line == '#') ||
351 (*cur_line == ' ') ||
356 * Check the line for location information.
359 fprintf(stderr,"%d\n",__LINE__);
361 if (0 == rt_loc_line())
365 * Check for the first line of the dds2index.
367 if ((0 == strcmp(cur_line, dds_headline))
368 || (0 == strcmp(cur_line, dds_old_headline))) {
371 tar_bs = buf_n >> 9 ;
372 if ( vid != HP ) dds_set_bs(tar_n);
376 fprintf(stderr,"%d\n",__LINE__);
380 * dds2index indicates eof with the string '-end-'.
381 * This line has to be processed in the normal way.
382 * We can stop now processing.
384 if ((*cur_line == '-') &&
385 (strncmp(cur_line, "-end-", 5) == 0)) {
387 fprintf(stderr,"%d\n",__LINE__);
393 * Scan the line of the index.
394 * Note: The index file of dds2index contains the magic string
395 * of the tar header, witch depends on the used tar version.
397 if (tar_index_file == 0) {
398 rt_line(&blkno, &recno, &size, &name);
401 * check for record line
403 if ((0 != strncmp(cur_line, "rec", 3)) &&
404 (0 != strncmp(cur_line, "block", 5)))
408 * cook the input line and delete all the quoted
411 dds_unquote(cur_line);
413 if (0 == strncmp(cur_line, "block ", 6))
420 if (2 == sscanf(cur_line + so, "%d%c%n",
425 fprintf(stderr,"Blocks found:%d\n",x);
439 recno = atoi(cur_line + 4);
443 cur_line+so,"block %d%c%n",&x,&c,&n
448 fprintf(stderr,"Blocks found:%d\n",x);
454 * Now we are fixing a bug of gnu tar ...
455 * The first number should be zero, othewise we
456 * correct all the numbers.
457 * If tar_first_recno is .lt. zero, no recno is read
460 if (tar_first_recno < 0)
461 tar_first_recno = recno;
462 recno -= tar_first_recno;
464 * Calculate the block number of the record.
467 fprintf(stderr,"file-loc(%d,%d)\n",recno,tar_fb);
469 blkno = recno / tar_bs;
470 recno -= blkno * tar_bs;
471 if ( vid != HP ) blkno *= tar_bs ;
473 fprintf(stderr,"file-loc(%d:%d,%d)\n",tar_bs,blkno,recno);
477 fprintf(stderr,"file-loc(%d:%d,%d)\n",tar_bs,blkno,recno);
480 /* skip file permissions */
481 name = strchr(cur_line + so, ' ');
483 /* skip owner/group */
484 name = strchr(name + 1, ' ');
487 while (*++name == ' ');
488 name = strchr(name, ' ');
491 name = strchr(name + 1, ' ');
494 name = strchr(name + 1, ' ');
504 if (!name || (name[-4] != ':'))
506 name = cur_line + so;
510 fprintf(stderr,"%d\n",__LINE__);
511 fprintf(stderr,"filename=%s\n",name);
515 fprintf(stderr,"%d\n",__LINE__);
517 i = strlen(name) -1 ;
518 if (name[i] == '\n') name[i] = '\0', i-- ;
520 * We leave the list of directories empty on quick mode.
522 if (( name[i] == '/' )&&( quick_mode == 0 )) {
524 for (i = 0 , dp = dl ; i < de; i++ , dp ++ ) {
525 if (strstr(name, dp->n) != name)
534 * Now we try to match one pattern with the name.
537 fprintf(stderr,"%d\n",__LINE__);
538 fprintf(stderr,"scanning pattern list for '%s'\n",name);
542 static int ll_blkno = -1 ;
543 static int ll_recno = -1 ;
544 static int ln_blkno = -1 ;
545 static int ln_recno = -1 ;
546 static const char *ll = "././@LongLink" ;
548 fprintf(stderr," p = '%p' , *p = %p \n",p,*p);
551 * Thanks Andreas Bagge for this trick.
552 * I use the fnmatch function from the
556 fprintf(stderr,"fnmatch '%s' for '%s'\n",name,*p);
558 if (0 == fnmatch(*p, name, FNM_LEADING_DIR)) {
560 for (i = 0, dp = dl; i < de; i++, dp++) {
561 char *p = strstr(name, dp->n);
563 extract(dp->n, dp->b, dp->r);
567 if ( ln_blkno >= 0 ) extract(
571 if ( ll_blkno >= 0 ) extract(
575 extract(name, blkno, recno);
578 if ( 0==strncmp(ll,name,strlen(name)) ){
580 ln_blkno = blkno , ln_recno = recno ;
582 ll_blkno = blkno , ll_recno = recno ;
592 fprintf(stderr,"end of scanning pattern list\n");
596 * Write an empty record to the end of the archive.
598 memset(cur_block, 0, buf_n );
599 write(1, cur_block, 512);
602 fprintf(stderr, "dds2tar: %d blocks written\n", nblocks);
604 fprintf(stderr,"%d\n",__LINE__);
605 fprintf(stderr,"return of dds_cmp(...)");