X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftar.c;h=31d7d3064b37e0a3c10541b2ef9a304ab4306cbc;hb=664ec232d43d5f88cd28e7b5f67f0ed78731553b;hp=2f393f622fd9d4d8dc9ff0c51c301f93e5a2a0f9;hpb=a447fd3714cbcb37950f399390809f797b0633ec;p=chaz%2Ftar diff --git a/src/tar.c b/src/tar.c index 2f393f6..31d7d30 100644 --- a/src/tar.c +++ b/src/tar.c @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "system.h" +#include #include #include @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -128,6 +129,7 @@ static struct fmttab { { "star", STAR_FORMAT }, #endif { "gnu", GNU_FORMAT }, + { "pax", POSIX_FORMAT }, /* An alias for posix */ { NULL, 0 } }; @@ -185,8 +187,8 @@ enum CHECK_LINKS_OPTION, DELETE_OPTION, EXCLUDE_OPTION, + EXCLUDE_CACHES_OPTION, FORCE_LOCAL_OPTION, - FORMAT_OPTION, GROUP_OPTION, IGNORE_CASE_OPTION, IGNORE_FAILED_READ_OPTION, @@ -207,6 +209,7 @@ enum NUMERIC_OWNER_OPTION, OCCURRENCE_OPTION, OLD_ARCHIVE_OPTION, + ONE_FILE_SYSTEM_OPTION, OVERWRITE_OPTION, OWNER_OPTION, PAX_OPTION, @@ -233,7 +236,7 @@ enum WILDCARDS_MATCH_SLASH_OPTION }; -const char *argp_program_version = "tar (" PACKAGE ") " VERSION; +const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION; const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; static char doc[] = N_("GNU `tar' saves many files together into a single tape or disk archive, and can restore individual files from the archive.\n\ \n\ @@ -248,6 +251,20 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\n\n never, simple always make simple backups\n"); +/* NOTE: + + Available option letters are DEIJQY and aeqy. Consider the following + assignments: + + [For Solaris tar compatibility] + e exit immediately with a nonzero exit status if unexpected errors occur + E use extended headers (--format=posix) + [q alias for --occurrence=1 =/= this would better be used for quiet?] + [I same as T =/= will harm star compatibility] + + y per-file gzip compression + Y per-block gzip compression */ + static struct argp_option options[] = { {NULL, 0, NULL, 0, N_("Main operation mode:"), 0}, @@ -256,7 +273,7 @@ static struct argp_option options[] = { N_("list the contents of an archive"), 10 }, {"extract", 'x', 0, 0, N_("extract files from an archive"), 10 }, - {"get", 0, 0, OPTION_ALIAS, NULL}, + {"get", 0, 0, OPTION_ALIAS, NULL, 0 }, {"create", 'c', 0, 0, N_("create a new archive"), 10 }, {"diff", 'd', 0, 0, @@ -303,7 +320,9 @@ static struct argp_option options[] = { N_("do not exit with nonzero on unreadable files"), 21 }, {"occurrence", OCCURRENCE_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL, N_("process only the NUMth occurrence of each file in the archive. This option is valid only in conjunction with one of the subcommands --delete, --diff, --extract or --list and when a list of files is given either on the command line or via -T option. NUMBER defaults to 1."), 21 }, - + {"seek", 'n', NULL, 0, + N_("Archive is seekable"), 21 }, + {NULL, 0, NULL, 0, N_("Handling of file attributes:"), 30 }, @@ -346,7 +365,8 @@ static struct argp_option options[] = { {"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0, N_("use remote COMMAND instead of rsh"), 41 }, #ifdef DEVICE_PREFIX - {"-[0-7][lmh]", 0, NULL, OPTION_DOC, + {"-[0-7][lmh]", 0, NULL, OPTION_DOC, /* It is OK, since `name' will never be + translated */ N_("specify drive and density"), 41 }, #endif {NULL, '0', NULL, OPTION_HIDDEN, NULL, 41 }, @@ -385,16 +405,21 @@ static struct argp_option options[] = { {NULL, 0, NULL, 0, N_("Archive format selection:"), 60 }, - {"format", FORMAT_OPTION, N_("FORMAT"), 0, + {"format", 'H', N_("FORMAT"), 0, N_("create archive of the given format."), 61 }, - {"", 0, NULL, OPTION_DOC, N_("FORMAT is one of the following:"), 62}, - {"", 0, NULL, OPTION_DOC, N_("v7 old V7 tar format"), 63}, - {"", 0, NULL, OPTION_DOC, N_("oldgnu GNU format as per tar <= 1.12"), 63}, - {"", 0, NULL, OPTION_DOC, N_("gnu GNU tar 1.13.x format"), 63}, - {"", 0, NULL, OPTION_DOC, N_("ustar POSIX 1003.1-1988 (ustar) format"), 63 }, - {"", 0, NULL, OPTION_DOC, N_("posix POSIX 1003.1-2001 (pax) format"), 63 }, - + {NULL, 0, NULL, 0, N_("FORMAT is one of the following:"), 62 }, + {" v7", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, N_("old V7 tar format"), 63}, + {" oldgnu", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, + N_("GNU format as per tar <= 1.12"), 63}, + {" gnu", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, + N_("GNU tar 1.13.x format"), 63}, + {" ustar", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, + N_("POSIX 1003.1-1988 (ustar) format"), 63 }, + {" pax", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, + N_("POSIX 1003.1-2001 (pax) format"), 63 }, + {" posix", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, N_("Same as pax"), 63 }, + {"old-archive", OLD_ARCHIVE_OPTION, 0, 0, /* FIXME */ N_("same as --format=v7"), 68 }, {"portability", 0, 0, OPTION_ALIAS, NULL, 68 }, @@ -429,12 +454,14 @@ static struct argp_option options[] = { N_("exclude files, given as a PATTERN"), 71 }, {"exclude-from", 'X', N_("FILE"), 0, N_("exclude patterns listed in FILE"), 71 }, + {"exclude-caches", EXCLUDE_CACHES_OPTION, 0, 0, + N_("exclude directories containing a cache tag"), 71 }, {"ignore-case", IGNORE_CASE_OPTION, 0, 0, N_("exclusion ignores case"), 71 }, {"anchored", ANCHORED_OPTION, 0, 0, - N_("exclude patterns match file name start (default)"), 71 }, + N_("exclude patterns match file name start"), 71 }, {"no-anchored", NO_ANCHORED_OPTION, 0, 0, - N_("exclude patterns match after any /"), 71 }, + N_("exclude patterns match after any / (default)"), 71 }, {"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0, N_("exclusion is case sensitive (default)"), 71 }, {"no-wildcards", NO_WILDCARDS_OPTION, 0, 0, @@ -443,8 +470,9 @@ static struct argp_option options[] = { N_("exclude pattern wildcards do not match '/'"), 71 }, {"no-recursion", NO_RECURSION_OPTION, 0, 0, N_("avoid descending automatically in directories"), 71 }, - {"one-file-system", 'l', 0, 0, /* FIXME: emit warning */ + {"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0, N_("stay in local file system when creating archive"), 71 }, + {NULL, 'l', 0, OPTION_HIDDEN, "", 71}, {"recursion", RECURSION_OPTION, 0, 0, N_("recurse into directories (default)"), 71 }, {"absolute-names", 'P', 0, 0, @@ -476,7 +504,7 @@ static struct argp_option options[] = { {"verbose", 'v', 0, 0, N_("verbosely list files processed"), 81 }, {"checkpoint", CHECKPOINT_OPTION, 0, 0, - N_("print directory names while reading the archive"), 81 }, + N_("display progress messages every 10th record"), 81 }, {"check-links", CHECK_LINKS_OPTION, 0, 0, N_("print a message if not all links are dumped"), 82 }, {"totals", TOTALS_OPTION, 0, 0, @@ -511,7 +539,7 @@ static struct argp_option options[] = { /* FIXME -V (--label) conflicts with the default short option for --version */ - {0, 0, 0, 0} + {0, 0, 0, 0, 0, 0} }; struct tar_args { @@ -528,10 +556,14 @@ static void show_default_settings (FILE *stream) { fprintf (stream, - "--format=%s -f%s -b%d --rmt-command=%s --rsh-command=%s\n", + "--format=%s -f%s -b%d --rmt-command=%s", archive_format_string (DEFAULT_ARCHIVE_FORMAT), DEFAULT_ARCHIVE, DEFAULT_BLOCKING, - DEFAULT_RMT_COMMAND, REMOTE_SHELL); + DEFAULT_RMT_COMMAND); +#ifdef REMOTE_SHELL + fprintf (stream, " --rsh-command=%s", REMOTE_SHELL); +#endif + fprintf (stream, "\n"); } static void @@ -548,7 +580,8 @@ set_subcommand_option (enum subcommand subcommand) static void set_use_compress_program_option (const char *string) { - if (use_compress_program_option && strcmp (use_compress_program_option, string) != 0) + if (use_compress_program_option + && strcmp (use_compress_program_option, string) != 0) USAGE_ERROR ((0, 0, _("Conflicting compression options"))); use_compress_program_option = string; @@ -566,13 +599,13 @@ for complete list of authors.\n")); " the Free Software Foundation; either version 2 of the License, or\n" " (at your option) any later version.\n" "\n" - " GNU Mailutils is distributed in the hope that it will be useful,\n" + " GNU tar is distributed in the hope that it will be useful,\n" " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" " GNU General Public License for more details.\n" "\n" " You should have received a copy of the GNU General Public License\n" - " along with GNU Mailutils; if not, write to the Free Software\n" + " along with GNU tar; if not, write to the Free Software\n" " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n")); exit (0); } @@ -696,9 +729,19 @@ parse_opt(int key, char *arg, struct argp_state *state) break; case 'l': + /* Historically equivalent to --one-file-system. This usage is + incompatible with UNIX98 and POSIX specs and therefore is + deprecated. The semantics of -l option will be changed in + future versions. See TODO. + */ + WARN ((0, 0, + _("Semantics of -l option will change in the future releases."))); + WARN ((0, 0, + _("Please use --one-file-system option instead."))); + /* FALL THROUGH */ + case ONE_FILE_SYSTEM_OPTION: /* When dumping directories, don't dump files/subdirectories - that are on other filesystems. */ - + that are on other filesystems. */ one_file_system_option = true; break; @@ -723,6 +766,10 @@ parse_opt(int key, char *arg, struct argp_state *state) multi_volume_option = true; break; + + case 'n': + seekable_archive = true; + break; #if !MSDOS case 'N': @@ -733,7 +780,7 @@ parse_opt(int key, char *arg, struct argp_state *state) if (NEWER_OPTION_INITIALIZED (newer_mtime_option)) USAGE_ERROR ((0, 0, _("More than one threshold date"))); - if (FILESYSTEM_PREFIX_LEN (arg) != 0 + if (FILE_SYSTEM_PREFIX_LEN (arg) != 0 || ISSLASH (*arg) || *arg == '.') { @@ -893,11 +940,15 @@ parse_opt(int key, char *arg, struct argp_state *state) add_exclude (excluded, arg, args->exclude_options | recursion_option); break; + case EXCLUDE_CACHES_OPTION: + exclude_caches_option = true; + break; + case FORCE_LOCAL_OPTION: force_local_option = true; break; - case FORMAT_OPTION: + case 'H': set_archive_format (arg); break; @@ -1039,7 +1090,7 @@ parse_opt(int key, char *arg, struct argp_state *state) break; case RMT_COMMAND_OPTION: - rmt_command_option = arg; + rmt_command = arg; break; case RSH_COMMAND_OPTION: @@ -1234,7 +1285,7 @@ static struct argp argp = { void usage (int status) { - argp_help (&argp, stderr, ARGP_HELP_SEE, program_name); + argp_help (&argp, stderr, ARGP_HELP_SEE, (char*) program_name); exit (status); } @@ -1247,29 +1298,16 @@ find_argp_option (struct argp_option *options, int letter) !(options->name == NULL && options->key == 0 && options->arg == 0 - && options->flags + && options->flags == 0 && options->doc == NULL); options++) if (options->key == letter) return options; return NULL; } -/* FIXME: - - Available option letters are DEHIJQY and aenqy. Some are reserved: - - e exit immediately with a nonzero exit status if unexpected errors occur - E use extended headers (draft POSIX headers, that is) - I same as T (for compatibility with Solaris tar) - n the archive is quickly seekable, so don't worry about random seeks - q stop after extracting the first occurrence of the named file - y per-file gzip compression - Y per-block gzip compression */ - static void decode_options (int argc, char **argv) { - int optchar; /* option letter */ int index; struct tar_args args; @@ -1281,7 +1319,6 @@ decode_options (int argc, char **argv) args.backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); args.version_control_string = 0; args.input_files = 0; - subcommand_option = UNKNOWN_SUBCOMMAND; archive_format = DEFAULT_FORMAT; @@ -1358,7 +1395,7 @@ decode_options (int argc, char **argv) if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP, &index, &args)) - exit (1); /* FIXME */ + exit (1); /* Special handling for 'o' option: @@ -1380,7 +1417,7 @@ decode_options (int argc, char **argv) else { /* UNIX98 compatibility */ - same_owner_option = 1; + same_owner_option = -1; } } @@ -1427,6 +1464,18 @@ decode_options (int argc, char **argv) _("--occurrence cannot be used in the requested operation mode"))); } + if (seekable_archive && subcommand_option == DELETE_SUBCOMMAND) + { + /* The current code in delete.c is based on the assumption that + skip_member() reads all data from the archive. So, we should + make sure it won't use seeks. On the other hand, the same code + depends on the ability to backspace a record in the archive, + so setting seekable_archive to false is technically incorrect. + However, it is tested only in skip_member(), so it's not a + problem. */ + seekable_archive = false; + } + if (archive_names == 0) { /* If no archive file name given, try TAPE from the environment, or @@ -1503,9 +1552,6 @@ decode_options (int argc, char **argv) if (utc_option) verbose_option = 2; - if (!rmt_command_option) - rmt_command_option = DEFAULT_RMT_COMMAND; - /* Forbid using -c with no input files whatsoever. Check that `-f -', explicit or implied, is used correctly. */ @@ -1573,10 +1619,7 @@ decode_options (int argc, char **argv) int main (int argc, char **argv) { -#if HAVE_CLOCK_GETTIME - if (clock_gettime (CLOCK_REALTIME, &start_timespec) != 0) -#endif - start_time = time (0); + set_start_time (); program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR);