]>
Dogcows Code - chaz/tar/blob - src/tar.c
1 /* Tar -- a tape archiver.
2 Copyright (C) 1988, 1992 Free Software Foundation
4 This file is part of GNU Tar.
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 * A tar (tape archiver) program.
23 * Written by John Gilmore, ihnp4!hoptoad!gnu, starting 25 Aug 85.
27 #include <sys/types.h> /* Needed for typedefs in tar.h */
33 * The following causes "tar.h" to produce definitions of all the
34 * global variables, rather than just "extern" declarations of them.
36 #define TAR_EXTERN /**/
41 #if defined(_POSIX_VERSION) || defined(DIRENT)
47 #define DP_NAMELEN(x) strlen((x)->d_name)
48 #endif /* _POSIX_VERSION or DIRENT */
49 #if !defined(_POSIX_VERSION) && !defined(DIRENT) && defined(BSD42)
51 #define DP_NAMELEN(x) (x)->d_namlen
52 #endif /* not _POSIX_VERSION and BSD42 */
55 #define DP_NAMELEN(x) (x)->d_namlen
58 #if defined(USG) && !defined(_POSIX_VERSION) && !defined(DIRENT)
60 #define DP_NAMELEN(x) strlen((x)->d_name)
61 #endif /* USG and not _POSIX_VERSION and not DIRENT */
64 * We should use a conversion routine that does reasonable error
65 * checking -- atoi doesn't. For now, punt. FIXME.
70 extern int getoldopt ();
71 extern void read_and ();
72 extern void list_archive ();
73 extern void extract_archive ();
74 extern void diff_archive ();
75 extern void create_archive ();
76 extern void update_archive ();
77 extern void junk_archive ();
80 extern time_t get_date ();
84 static FILE *namef
; /* File to read names from */
85 static char **n_argv
; /* Argv used by name routines */
86 static int n_argc
; /* Argc used by name routines */
87 static char **n_ind
; /* Store an array of names */
88 static int n_indalloc
; /* How big is the array? */
89 static int n_indused
; /* How many entries does it have? */
90 static int n_indscan
; /* How many of the entries have we scanned? */
93 extern FILE *msg_file
;
97 void add_exclude_file ();
106 char *un_quote_string ();
113 #define DEFBLOCKING 20
117 #define DEF_AR_FILE "tar.out"
120 /* For long options that unconditionally set a single flag, we have getopt
121 do it. For the others, we share the code for the equivalent short
122 named option, the name of which is stored in the otherwise-unused `val'
123 field of the `struct option'; for long options that have no equivalent
124 short option, we use nongraphic characters as pseudo short option
125 characters, starting (for no particular reason) with character 10. */
127 struct option long_options
[] =
129 {"create", 0, 0, 'c'},
130 {"append", 0, 0, 'r'},
131 {"extract", 0, 0, 'x'},
134 {"update", 0, 0, 'u'},
135 {"catenate", 0, 0, 'A'},
136 {"concatenate", 0, 0, 'A'},
137 {"compare", 0, 0, 'd'},
139 {"delete", 0, 0, 14},
143 {"directory", 1, 0, 'C'},
144 {"record-number", 0, &f_sayblock
, 1},
145 {"files-from", 1, 0, 'T'},
146 {"label", 1, 0, 'V'},
147 {"exclude-from", 1, 0, 'X'},
148 {"exclude", 1, 0, 15},
150 {"block-size", 1, 0, 'b'},
151 {"version", 0, 0, 11},
152 {"verbose", 0, 0, 'v'},
153 {"totals", 0, &f_totals
, 1},
155 {"read-full-blocks", 0, &f_reblock
, 1},
156 {"starting-file", 1, 0, 'K'},
157 {"to-stdout", 0, &f_exstdout
, 1},
158 {"ignore-zeros", 0, &f_ignorez
, 1},
159 {"keep-old-files", 0, 0, 'k'},
160 {"uncompress", 0, &f_compress
, 1},
161 {"same-permissions", 0, &f_use_protection
, 1},
162 {"preserve-permissions", 0, &f_use_protection
, 1},
163 {"modification-time", 0, &f_modified
, 1},
164 {"preserve", 0, 0, 10},
165 {"same-order", 0, &f_sorted_names
, 1},
166 {"same-owner", 0, &f_do_chown
, 1},
167 {"preserve-order", 0, &f_sorted_names
, 1},
169 {"newer", 1, 0, 'N'},
170 {"after-date", 1, 0, 'N'},
171 {"newer-mtime", 1, 0, 13},
172 {"incremental", 0, 0, 'G'},
173 {"listed-incremental", 1, 0, 'g'},
174 {"multi-volume", 0, &f_multivol
, 1},
175 {"info-script", 1, 0, 'F'},
176 {"absolute-paths", 0, &f_absolute_paths
, 1},
177 {"interactive", 0, &f_confirm
, 1},
178 {"confirmation", 0, &f_confirm
, 1},
180 {"verify", 0, &f_verify
, 1},
181 {"dereference", 0, &f_follow_links
, 1},
182 {"one-file-system", 0, &f_local_filesys
, 1},
183 {"old-archive", 0, 0, 'o'},
184 {"portability", 0, 0, 'o'},
185 {"compress", 0, &f_compress
, 1},
186 {"compress-block", 0, &f_compress
, 2},
187 {"sparse", 0, &f_sparse_files
, 1},
188 {"tape-length", 1, 0, 'L'},
189 {"remove-files", 0, &f_remove_files
, 1},
190 {"ignore-failed-read", 0, &f_ignore_failed_read
, 1},
191 {"checkpoint", 0, &f_checkpoint
, 1},
192 {"show-omitted-dirs", 0, &f_show_omitted_dirs
, 1},
193 {"volno-file", 1, 0, 17},
194 {"force-local", 0, &f_force_local
, 1},
195 {"atime-preserve", 0, &f_atime_preserve
, 1},
201 * Main routine for tar.
208 extern char version_string
[];
210 tar
= argv
[0]; /* JF: was "tar" Set program name */
211 filename_terminator
= '\n';
214 options (argc
, argv
);
217 name_init (argc
, argv
);
220 init_volume_number ();
235 fprintf (stderr
, "Total bytes written: %d\n", tot_written
);
241 label_pattern
= (struct re_pattern_buffer
*)
242 ck_malloc (sizeof *label_pattern
);
243 err
= re_compile_pattern (f_volhdr
, strlen (f_volhdr
),
247 fprintf (stderr
, "Bad regular expression: %s\n",
255 read_and (extract_archive
);
261 label_pattern
= (struct re_pattern_buffer
*)
262 ck_malloc (sizeof *label_pattern
);
263 err
= re_compile_pattern (f_volhdr
, strlen (f_volhdr
),
267 fprintf (stderr
, "Bad regular expression: %s\n",
273 read_and (list_archive
);
281 read_and (diff_archive
);
284 fprintf (stderr
, "%s\n", version_string
);
287 msg ("you must specify exactly one of the r, c, t, x, or d options\n");
288 fprintf (stderr
, "For more information, type ``%s --help''.\n", tar
);
292 closeout_volume_number ();
299 * Parse the options for tar.
306 register int c
; /* Option letter */
309 /* Set default option values */
310 blocking
= DEFBLOCKING
; /* From Makefile */
311 ar_files
= (char **) malloc (sizeof (char *) * 10);
317 while ((c
= getoldopt (argc
, argv
,
318 "-01234567Ab:BcC:df:F:g:GhikK:lL:mMN:oOpPrRsStT:uvV:wWxX:zZ",
319 long_options
, &ind
)) != EOF
)
323 case 0: /* long options that set a single flag */
326 /* File name or non-parsed option */
333 case 10: /* preserve */
334 f_use_protection
= f_sorted_names
= 1;
337 if (cmd_mode
!= CMD_NONE
)
339 cmd_mode
= CMD_VERSION
;
342 printf ("This is GNU tar, the tape archiving program.\n");
349 case 14: /* Delete in the archive */
350 if (cmd_mode
!= CMD_NONE
)
352 cmd_mode
= CMD_DELETE
;
357 add_exclude (optarg
);
360 case 16: /* -T reads null terminated filenames. */
361 filename_terminator
= '\0';
365 f_volno_file
= optarg
;
368 case 'g': /* We are making a GNU dump; save
369 directories at the beginning of
370 the archive, and include in each
371 directory its contents */
375 gnu_dumpfile
= optarg
;
388 /* JF this'll have to be modified for other
389 systems, of course! */
393 d
= getoldopt (argc
, argv
, "lmh");
395 sprintf (buf
, "/dev/rmt/%d%c", c
, d
);
411 sprintf (buf
, "/dev/rmt%d", add
+ c
- '0');
413 if (n_ar_files
== ar_files_len
)
416 ck_malloc (sizeof (char *)
417 * (ar_files_len
*= 2));
418 ar_files
[n_ar_files
++] = buf
;
422 case 'A': /* Arguments are tar files,
423 just cat them onto the end
425 if (cmd_mode
!= CMD_NONE
)
430 case 'b': /* Set blocking factor */
431 blocking
= intconv (optarg
);
434 case 'B': /* Try to reblock input */
435 f_reblock
++; /* For reading 4.2BSD pipes */
438 case 'c': /* Create an archive */
439 if (cmd_mode
!= CMD_NONE
)
441 cmd_mode
= CMD_CREATE
;
446 if (chdir (optarg
) < 0)
447 msg_perror ("Can't change directory to %d", optarg
);
451 case 'd': /* Find difference tape/disk */
452 if (cmd_mode
!= CMD_NONE
)
457 case 'f': /* Use ar_file for the archive */
458 if (n_ar_files
== ar_files_len
)
460 = (char **) ck_malloc (sizeof (char *)
461 * (ar_files_len
*= 2));
463 ar_files
[n_ar_files
++] = optarg
;
467 /* Since -F is only useful with -M , make it implied */
468 f_run_script_at_end
++;/* run this script at the end */
469 info_script
= optarg
; /* of each tape */
473 case 'G': /* We are making a GNU dump; save
474 directories at the beginning of
475 the archive, and include in each
476 directory its contents */
484 f_follow_links
++; /* follow symbolic links */
488 f_ignorez
++; /* Ignore zero records (eofs) */
490 * This can't be the default, because Unix tar
491 * writes two records of zeros, then pads out the
492 * block with garbage.
496 case 'k': /* Don't overwrite files */
498 msg ("can't keep old files on this system");
510 case 'l': /* When dumping directories, don't
511 dump files/subdirectories that are
512 on other filesystems. */
517 tape_length
= intconv (optarg
);
524 case 'M': /* Make Multivolume archive:
525 When we can't write any more
526 into the archive, re-open it,
527 and continue writing */
531 case 'N': /* Only write files newer than X */
534 new_time
= get_date (optarg
, (PTR
) 0);
535 if (new_time
== (time_t) - 1)
537 msg ("invalid date format `%s'", optarg
);
542 case 'o': /* Generate old archive */
543 if (f_gnudump
/* || f_dironly */ )
560 case 'r': /* Append files to the archive */
561 if (cmd_mode
!= CMD_NONE
)
563 cmd_mode
= CMD_APPEND
;
567 f_sayblock
++; /* Print block #s for debug */
568 break; /* of bad tar archives */
571 f_sorted_names
++; /* Names to extr are sorted */
574 case 'S': /* deal with sparse files */
578 if (cmd_mode
!= CMD_NONE
)
581 f_verbose
++; /* "t" output == "cv" or "xv" */
589 case 'u': /* Append files to the archive that
590 aren't there, or are newer than the
591 copy in the archive */
592 if (cmd_mode
!= CMD_NONE
)
594 cmd_mode
= CMD_UPDATE
;
613 case 'x': /* Extract files from the archive */
614 if (cmd_mode
!= CMD_NONE
)
616 cmd_mode
= CMD_EXTRACT
;
621 add_exclude_file (optarg
);
624 case 'z': /* Easy to type */
625 case 'Z': /* Like the filename extension .Z */
631 msg ("Unknown option. Use '%s --help' for a complete list of options.", tar
);
637 blocksize
= blocking
* RECORDSIZE
;
641 ar_files
[0] = getenv ("TAPE"); /* From environment, or */
642 if (ar_files
[0] == 0)
643 ar_files
[0] = DEF_AR_FILE
; /* From Makefile */
645 if (n_ar_files
> 1 && !f_multivol
)
647 msg ("Multiple archive files requires --multi-volume\n");
654 * Print as much help as the user's gonna get.
656 * We have to sprinkle in the KLUDGE lines because too many compilers
657 * cannot handle character strings longer than about 512 bytes. Yuk!
658 * In particular, MS-DOS and Xenix MSC and PDP-11 V7 Unix have this
664 puts ("choose one of the following:");
667 --concatenate append tar files to an archive\n\
668 -c, --create create a new archive\n\
670 --compare find differences between archive and file system\n\
671 --delete delete from the archive (not for use on mag tapes!)\n\
672 -r, --append append files to the end of an archive\n\
673 -t, --list list the contents of an archive\n\
674 -u, --update only append files that are newer than copy in archive\n\
676 --get extract files from an archive\n", stdout
);
680 --atime-preserve don't change access times on dumped files\n\
681 -b, --block-size N block size of Nx512 bytes (default N=%d)\n", DEFBLOCKING
);
683 -B, --read-full-blocks reblock as we read (for reading 4.2BSD pipes)\n\
684 -C, --directory DIR change to directory DIR\n\
685 --checkpoint print directory names while reading the archive\n\
686 ", stdout
); /* KLUDGE */
688 -f, --file [HOSTNAME:]F use archive file or device F (default %s)\n",
691 --force-local archive file is local even if has a colon\n\
692 -F, --info-script F run script at end of each tape (implies -M)\n\
693 -G, --incremental create/list/extract old GNU-format incremental backup\n\
694 -g, --listed-incremental F create/list/extract new GNU-format incremental backup\n\
695 -h, --dereference don't dump symlinks; dump the files they point to\n\
696 -i, --ignore-zeros ignore blocks of zeros in archive (normally mean EOF)\n\
697 --ignore-failed-read don't exit with non-zero status on unreadable files\n\
698 -k, --keep-old-files keep existing files; don't overwrite them from archive\n\
699 -K, --starting-file FILE begin at FILE in the archive\n\
700 -l, --one-file-system stay in local file system when creating an archive\n\
701 -L, --tape-length LENGTH change tapes after writing LENGTH\n\
702 ", stdout
); /* KLUDGE */
704 -m, --modification-time don't extract file modified time\n\
705 -M, --multi-volume create/list/extract multi-volume archive\n\
706 -N, --after-date DATE,\n\
707 --newer DATE only store files newer than DATE\n\
708 -o, --old-archive,\n\
709 --portability write a V7 format archive, rather than ANSI format\n\
710 -O, --to-stdout extract files to standard output\n\
711 -p, --same-permissions,\n\
712 --preserve-permissions extract all protection information\n\
713 -P, --absolute-paths don't strip leading `/'s from file names\n\
714 --preserve like -p -s\n\
715 ", stdout
); /* KLUDGE */
717 -R, --record-number show record number within archive with each message\n\
718 --remove-files remove files after adding them to the archive\n\
720 --preserve-order list of names to extract is sorted to match archive\n\
721 --same-owner create extracted files with the same ownership \n\
722 -S, --sparse handle sparse files efficiently\n\
723 -T, --files-from F get names to extract or create from file F\n\
724 --null -T reads null-terminated names, disable -C\n\
725 --totals print total bytes written with --create\n\
726 -v, --verbose verbosely list files processed\n\
727 -V, --label NAME create archive with volume name NAME\n\
728 --version print tar program version number\n\
729 -w, --interactive,\n\
730 --confirmation ask for confirmation for every action\n\
731 ", stdout
); /* KLUDGE */
733 -W, --verify attempt to verify the archive after writing it\n\
734 --exclude FILE exclude file FILE\n\
735 -X, --exclude-from FILE exclude files listed in FILE\n\
736 -z, -Z, --compress,\n\
737 --uncompress filter the archive through compress\n\
738 -[0-7][lmh] specify drive and density\n\
746 if (n_indalloc
== n_indused
)
749 n_ind
= (char **) (n_indused
? ck_realloc (n_ind
, n_indalloc
* sizeof (char *)): ck_malloc (n_indalloc
* sizeof (char *)));
751 n_ind
[n_indused
++] = name
;
755 * Set up to gather file names for tar.
757 * They can either come from stdin or from argv.
760 name_init (argc
, argv
)
769 msg ("too many args with -T option");
772 if (!strcmp (name_file
, "-"))
778 namef
= fopen (name_file
, "r");
781 msg_perror ("can't open file %s", name_file
);
788 /* Get file names from argv, after options. */
794 /* Read the next filename read from STREAM and null-terminate it.
795 Put it into BUFFER, reallocating and adjusting *PBUFFER_SIZE if necessary.
796 Return the new value for BUFFER, or NULL at end of file. */
799 read_name_from_file (buffer
, pbuffer_size
, stream
)
801 size_t *pbuffer_size
;
805 register int indx
= 0;
806 register size_t buffer_size
= *pbuffer_size
;
808 while ((c
= getc (stream
)) != EOF
&& c
!= filename_terminator
)
810 if (indx
== buffer_size
)
812 buffer_size
+= NAMSIZ
;
813 buffer
= ck_realloc (buffer
, buffer_size
+ 2);
817 if (indx
== 0 && c
== EOF
)
819 if (indx
== buffer_size
)
821 buffer_size
+= NAMSIZ
;
822 buffer
= ck_realloc (buffer
, buffer_size
+ 2);
825 *pbuffer_size
= buffer_size
;
830 * Get the next name from argv or the name file.
832 * Result is in static storage and can't be relied upon across two calls.
834 * If CHANGE_DIRS is non-zero, treat a filename of the form "-C" as
835 * meaning that the next filename is the name of a directory to change to.
836 * If `filename_terminator' is '\0', CHANGE_DIRS is effectively always 0.
840 name_next (change_dirs
)
843 static char *buffer
; /* Holding pattern */
844 static int buffer_siz
;
846 register char *q
= 0;
847 register int next_name_is_dir
= 0;
848 extern char *un_quote_string ();
852 buffer
= ck_malloc (NAMSIZ
+ 2);
855 if (filename_terminator
== '\0')
860 if (n_indscan
< n_indused
)
861 p
= n_ind
[n_indscan
++];
862 else if (optind
< n_argc
)
863 /* Names come from argv, after options */
864 p
= n_argv
[optind
++];
868 msg ("Missing filename after -C");
872 /* JF trivial support for -C option. I don't know if
873 chdir'ing at this point is dangerous or not.
874 It seems to work, which is all I ask. */
875 if (change_dirs
&& !q
&& p
[0] == '-' && p
[1] == 'C' && p
[2] == '\0')
883 msg_perror ("Can't chdir to %s", p
);
887 /* End of JF quick -C hack */
889 if (f_exclude
&& check_exclude (p
))
891 return un_quote_string (p
);
893 while (p
= read_name_from_file (buffer
, &buffer_siz
, namef
))
897 continue; /* Ignore empty lines. */
898 q
= p
+ strlen (p
) - 1;
899 while (q
> p
&& *q
== '/')/* Zap trailing "/"s. */
901 if (change_dirs
&& next_name_is_dir
== 0
902 && p
[0] == '-' && p
[1] == 'C' && p
[2] == '\0')
904 next_name_is_dir
= 1;
907 if (next_name_is_dir
)
910 msg_perror ("Can't change to directory %s", p
);
911 next_name_is_dir
= 0;
914 if (f_exclude
&& check_exclude (p
))
916 return un_quote_string (p
);
923 * Close the name file, if any.
929 if (namef
!= NULL
&& namef
!= stdin
)
935 * Gather names in a list for scanning.
936 * Could hash them later if we really care.
938 * If the names are already sorted to match the archive, we just
939 * read them one by one. name_gather reads the first one, and it
940 * is called by name_match as appropriate to read the next ones.
941 * At EOF, the last name read is just left in the buffer.
942 * This option lets users of small machines extract an arbitrary
943 * number of files by doing "tar t" and editing down the list of files.
949 static struct name
*namebuf
; /* One-name buffer */
951 static char *chdir_name
;
958 namebuf
= (struct name
*) ck_malloc (sizeof (struct name
) + NAMSIZ
);
963 if (*p
== '-' && p
[1] == 'C' && p
[2] == '\0')
965 chdir_name
= name_next (0);
969 msg ("Missing file name after -C");
972 namebuf
->change_dir
= chdir_name
;
974 namebuf
->length
= strlen (p
);
975 if (namebuf
->length
>= namelen
)
977 namebuf
= (struct name
*) ck_realloc (namebuf
, sizeof (struct name
) + namebuf
->length
);
978 namelen
= namebuf
->length
;
980 strncpy (namebuf
->name
, p
, namebuf
->length
);
981 namebuf
->name
[namebuf
->length
] = 0;
982 namebuf
->next
= (struct name
*) NULL
;
990 /* Non sorted names -- read them all in */
991 while (p
= name_next (0))
996 * Add a name to the namelist.
1000 char *name
; /* pointer to name */
1002 register int i
; /* Length of string */
1003 register struct name
*p
; /* Current struct pointer */
1004 static char *chdir_name
;
1007 if (name
[0] == '-' && name
[1] == 'C' && name
[2] == '\0')
1009 chdir_name
= name_next (0);
1010 name
= name_next (0);
1013 msg ("Missing file name after -C");
1016 if (chdir_name
[0] != '/')
1018 char *path
= ck_malloc (PATH_MAX
);
1019 #if defined(__MSDOS__) || defined(USG) || defined(_POSIX_VERSION)
1020 if (!getcwd (path
, PATH_MAX
))
1022 msg ("Couldn't get current directory.");
1030 msg ("Couldn't get current directory: %s", path
);
1034 chdir_name
= new_name (path
, chdir_name
);
1043 p
= (struct name
*) malloc ((unsigned) (sizeof (struct name
) + i
));
1046 p
= (struct name
*) malloc ((unsigned) (sizeof (struct name
)));
1050 msg ("cannot allocate mem for name '%s'.", name
);
1052 msg ("cannot allocate mem for chdir record.");
1055 p
->next
= (struct name
*) NULL
;
1060 strncpy (p
->name
, name
, i
);
1061 p
->name
[i
] = '\0'; /* Null term */
1066 p
->regexp
= 0; /* Assume not a regular expression */
1067 p
->firstch
= 1; /* Assume first char is literal */
1068 p
->change_dir
= chdir_name
;
1069 p
->dir_contents
= 0; /* JF */
1072 if (index (name
, '*') || index (name
, '[') || index (name
, '?'))
1074 p
->regexp
= 1; /* No, it's a regexp */
1075 if (name
[0] == '*' || name
[0] == '[' || name
[0] == '?')
1076 p
->firstch
= 0; /* Not even 1st char literal */
1088 * Return nonzero if name P (from an archive) matches any name from
1089 * the namelist, zero if not.
1095 register struct name
*nlp
;
1099 if (0 == (nlp
= namelist
)) /* Empty namelist is easy */
1103 if (nlp
->change_dir
&& chdir (nlp
->change_dir
))
1104 msg_perror ("Can't change to directory %d", nlp
->change_dir
);
1109 for (; nlp
!= 0; nlp
= nlp
->next
)
1111 /* If first chars don't match, quick skip */
1112 if (nlp
->firstch
&& nlp
->name
[0] != p
[0])
1115 /* Regular expressions (shell globbing, actually). */
1118 if (fnmatch (nlp
->name
, p
, FNM_TARPATH
) == 0)
1120 nlp
->found
= 1; /* Remember it matched */
1123 free ((void *) namelist
);
1126 if (nlp
->change_dir
&& chdir (nlp
->change_dir
))
1127 msg_perror ("Can't change to directory %s", nlp
->change_dir
);
1128 return 1; /* We got a match */
1133 /* Plain Old Strings */
1134 if (nlp
->length
<= len
/* Archive len >= specified */
1135 && (p
[nlp
->length
] == '\0' || p
[nlp
->length
] == '/')
1136 /* Full match on file/dirname */
1137 && strncmp (p
, nlp
->name
, nlp
->length
) == 0) /* Name compare */
1139 nlp
->found
= 1; /* Remember it matched */
1142 free ((void *) namelist
);
1145 if (nlp
->change_dir
&& chdir (nlp
->change_dir
))
1146 msg_perror ("Can't change to directory %s", nlp
->change_dir
);
1147 return 1; /* We got a match */
1152 * Filename from archive not found in namelist.
1153 * If we have the whole namelist here, just return 0.
1154 * Otherwise, read the next name in and compare it.
1155 * If this was the last name, namelist->found will remain on.
1156 * If not, we loop to compare the newly read name.
1158 if (f_sorted_names
&& namelist
->found
)
1160 name_gather (); /* Read one more */
1161 if (!namelist
->found
)
1169 * Print the names of things in the namelist that were not matched.
1174 register struct name
*nlp
, *next
;
1177 for (nlp
= namelist
; nlp
!= 0; nlp
= next
)
1181 msg ("%s not found in archive", nlp
->name
);
1184 * We could free() the list, but the process is about
1185 * to die anyway, so save some CPU time. Amigas and
1186 * other similarly broken software will need to waste
1190 if (!f_sorted_names
)
1194 namelist
= (struct name
*) NULL
;
1195 namelast
= (struct name
*) NULL
;
1199 while (0 != (p
= name_next (1)))
1200 msg ("%s not found in archive", p
);
1204 /* These next routines were created by JF */
1212 /* This is like name_match(), except that it returns a pointer to the name
1213 it matched, and doesn't set ->found The caller will have to do that
1214 if it wants to. Oh, and if the namelist is empty, it returns 0, unlike
1215 name_match(), which returns TRUE */
1221 register struct name
*nlp
;
1225 if (0 == (nlp
= namelist
)) /* Empty namelist is easy */
1228 for (; nlp
!= 0; nlp
= nlp
->next
)
1230 /* If first chars don't match, quick skip */
1231 if (nlp
->firstch
&& nlp
->name
[0] != p
[0])
1234 /* Regular expressions */
1237 if (fnmatch (nlp
->name
, p
, FNM_TARPATH
) == 0)
1238 return nlp
; /* We got a match */
1242 /* Plain Old Strings */
1243 if (nlp
->length
<= len
/* Archive len >= specified */
1244 && (p
[nlp
->length
] == '\0' || p
[nlp
->length
] == '/')
1245 /* Full match on file/dirname */
1246 && strncmp (p
, nlp
->name
, nlp
->length
) == 0) /* Name compare */
1247 return nlp
; /* We got a match */
1251 * Filename from archive not found in namelist.
1252 * If we have the whole namelist here, just return 0.
1253 * Otherwise, read the next name in and compare it.
1254 * If this was the last name, namelist->found will remain on.
1255 * If not, we loop to compare the newly read name.
1257 if (f_sorted_names
&& namelist
->found
)
1259 name_gather (); /* Read one more */
1260 if (!namelist
->found
)
1263 return (struct name
*) 0;
1266 /* This returns a name from the namelist which doesn't have ->found set.
1267 It sets ->found before returning, so successive calls will find and return
1268 all the non-found names in the namelist */
1270 struct name
*gnu_list_name
;
1276 gnu_list_name
= namelist
;
1277 while (gnu_list_name
&& gnu_list_name
->found
)
1278 gnu_list_name
= gnu_list_name
->next
;
1281 gnu_list_name
->found
++;
1282 if (gnu_list_name
->change_dir
)
1283 if (chdir (gnu_list_name
->change_dir
) < 0)
1284 msg_perror ("can't chdir to %s", gnu_list_name
->change_dir
);
1285 return gnu_list_name
->name
;
1296 for (n
= namelist
; n
; n
= n
->next
)
1301 new_name (path
, name
)
1306 path_buf
= (char *) malloc (strlen (path
) + strlen (name
) + 2);
1309 msg ("Can't allocate memory for name '%s/%s", path
, name
);
1312 (void) sprintf (path_buf
, "%s/%s", path
, name
);
1316 /* returns non-zero if the luser typed 'y' or 'Y', zero otherwise. */
1319 confirm (action
, file
)
1320 char *action
, *file
;
1323 static FILE *confirm_file
= 0;
1324 extern FILE *msg_file
;
1325 extern char TTY_NAME
[];
1327 fprintf (msg_file
, "%s %s?", action
, file
);
1331 confirm_file
= (archive
== 0) ? fopen (TTY_NAME
, "r") : stdin
;
1334 msg ("Can't read confirmation from user");
1338 c
= getc (confirm_file
);
1339 for (nl
= c
; nl
!= '\n' && nl
!= EOF
; nl
= getc (confirm_file
))
1341 return (c
== 'y' || c
== 'Y');
1349 int size_exclude
= 0;
1350 int free_exclude
= 0;
1352 char **re_exclude
= 0;
1353 int size_re_exclude
= 0;
1354 int free_re_exclude
= 0;
1361 /* char **tmp_ptr;*/
1364 un_quote_string (name
);
1365 size_buf
= strlen (name
);
1369 x_buffer
= (char *) ck_malloc (size_buf
+ 1024);
1370 free_x_buffer
= 1024;
1372 else if (free_x_buffer
<= size_buf
)
1377 old_x_buffer
= x_buffer
;
1378 x_buffer
= (char *) ck_realloc (x_buffer
, size_x_buffer
+ 1024);
1379 free_x_buffer
= 1024;
1380 for (tmp_ptr
= exclude
; tmp_ptr
< exclude
+ size_exclude
; tmp_ptr
++)
1381 *tmp_ptr
= x_buffer
+ ((*tmp_ptr
) - old_x_buffer
);
1382 for (tmp_ptr
= re_exclude
; tmp_ptr
< re_exclude
+ size_re_exclude
; tmp_ptr
++)
1383 *tmp_ptr
= x_buffer
+ ((*tmp_ptr
) - old_x_buffer
);
1386 if (is_regex (name
))
1388 if (free_re_exclude
== 0)
1390 re_exclude
= (char **) (re_exclude
? ck_realloc (re_exclude
, (size_re_exclude
+ 32) * sizeof (char *)): ck_malloc (sizeof (char *) * 32));
1391 free_re_exclude
+= 32;
1393 re_exclude
[size_re_exclude
] = x_buffer
+ size_x_buffer
;
1399 if (free_exclude
== 0)
1401 exclude
= (char **) (exclude
? ck_realloc (exclude
, (size_exclude
+ 32) * sizeof (char *)): ck_malloc (sizeof (char *) * 32));
1404 exclude
[size_exclude
] = x_buffer
+ size_x_buffer
;
1408 strcpy (x_buffer
+ size_x_buffer
, name
);
1409 size_x_buffer
+= size_buf
+ 1;
1410 free_x_buffer
-= size_buf
+ 1;
1414 add_exclude_file (file
)
1420 if (strcmp (file
, "-"))
1421 fp
= fopen (file
, "r");
1423 /* Let's hope the person knows what they're doing. */
1424 /* Using -X - -T - -f - will get you *REALLY* strange
1430 msg_perror ("can't open %s", file
);
1433 while (fgets (buf
, 1024, fp
))
1438 end_str
= rindex (buf
, '\n');
1451 return index (str
, '*') || index (str
, '[') || index (str
, '?');
1454 /* Returns non-zero if the file 'name' should not be added/extracted */
1456 check_exclude (name
)
1461 extern char *strstr ();
1463 for (n
= 0; n
< size_re_exclude
; n
++)
1465 if (fnmatch (re_exclude
[n
], name
, FNM_TARPATH
) == 0)
1468 for (n
= 0; n
< size_exclude
; n
++)
1470 /* Accept the output from strstr only if it is the last
1471 part of the string. There is certainly a faster way to
1473 if ((str
= strstr (name
, exclude
[n
]))
1474 && (str
== name
|| str
[-1] == '/')
1475 && str
[strlen (exclude
[n
])] == '\0')
This page took 0.111317 seconds and 5 git commands to generate.