X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftar.c;h=9de90990fb313de67cf55b44c9f41382457fb276;hb=1521a94b11b0b7a2fe2a8318207d7d6b4bdbf76b;hp=24b0f90bf72097c17f9dd5da1ca734397968d49c;hpb=5e0e89eac1a00a2edb87ea7b69f1f38c2b1249e1;p=chaz%2Ftar diff --git a/src/tar.c b/src/tar.c index 24b0f90..9de9099 100644 --- a/src/tar.c +++ b/src/tar.c @@ -1,5 +1,5 @@ /* A tar (tape archiver) program. - Copyright (C) 1988, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. + Copyright (C) 1988, 92,93,94,95,96,97, 1999 Free Software Foundation, Inc. Written by John Gilmore, starting 1985-08-25. This program is free software; you can redistribute it and/or modify it @@ -27,12 +27,7 @@ #define GLOBAL #include "common.h" -#include "backupfile.h" -enum backup_type get_version (); - -/* FIXME: We should use a conversion routine that does reasonable error - checking -- atoi doesn't. For now, punt. */ -#define intconv atoi +#include "xstrtol.h" time_t get_date (); @@ -50,39 +45,6 @@ static void usage PARAMS ((int)); /* Miscellaneous. */ -/*------------------------------------------------------------------------. -| Check if STRING is the decimal representation of number, and return its | -| value. If not a decimal number, return -1. | -`------------------------------------------------------------------------*/ - -static int -check_decimal (const char *string) -{ - int value = -1; - - while (*string) - switch (*string) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - value = value < 0 ? *string - '0' : 10 * value + *string - '0'; - string++; - break; - - default: - return -1; - } - return value; -} - /*----------------------------------------------. | Doesn't return if stdin already requested. | `----------------------------------------------*/ @@ -208,6 +170,7 @@ struct option long_options[] = {"dereference", no_argument, NULL, 'h'}, {"diff", no_argument, NULL, 'd'}, {"directory", required_argument, NULL, 'C'}, + {"ending-file", required_argument, NULL, 'E'}, {"exclude", required_argument, NULL, EXCLUDE_OPTION}, {"exclude-from", required_argument, NULL, 'X'}, {"extract", no_argument, NULL, 'x'}, @@ -388,6 +351,7 @@ Local file selection:\n\ -h, --dereference dump instead the files symlinks point to\n\ --no-recursion avoid descending automatically in directories\n\ -l, --one-file-system stay in local file system when creating archive\n\ + -E, --ending-file=NAME end reading the archive before file NAME\n\ -K, --starting-file=NAME begin at file NAME in the archive\n"), stdout); #if !MSDOS @@ -442,13 +406,13 @@ Report bugs to .\n"), | Parse the options for tar. | `----------------------------*/ -/* Available option letters are DEHIJQY and aejnqy. Some are reserved: +/* Available option letters are DHIJQY and aejnqy. Some are reserved: y per-file gzip compression Y per-block gzip compression */ #define OPTION_STRING \ - "-01234567ABC:F:GK:L:MN:OPRST:UV:WX:Zb:cdf:g:hiklmoprstuvwxz" + "-01234567ABC:E:F:GK:L:MN:OPRST:UV:WX:Zb:cdf:g:hiklmoprstuvwxz" static void set_subcommand_option (enum subcommand subcommand) @@ -476,7 +440,7 @@ decode_options (int argc, char *const *argv) int optchar; /* option letter */ int input_files; /* number of input files */ const char *backup_suffix_string; - const char *version_control_string; + const char *version_control_string = NULL; /* Set some default option values. */ @@ -489,7 +453,6 @@ decode_options (int argc, char *const *argv) group_option = -1; backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); - version_control_string = getenv ("VERSION_CONTROL"); /* Convert old-style tar call by exploding option element and rearranging options accordingly. */ @@ -526,11 +489,13 @@ decode_options (int argc, char *const *argv) *out++ = xstrdup (buffer); cursor = strchr (OPTION_STRING, *letter); if (cursor && cursor[1] == ':') - if (in < argv + argc) - *out++ = *in++; - else - USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."), - *letter)); + { + if (in < argv + argc) + *out++ = *in++; + else + USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."), + *letter)); + } } /* Copy all remaining options. */ @@ -579,8 +544,14 @@ decode_options (int argc, char *const *argv) /* Fall through. */ case 'b': - blocking_factor = intconv (optarg); - record_size = blocking_factor * BLOCKSIZE; + { + long l; + if (! (xstrtol (optarg, (char **) 0, 10, &l, "") == LONGINT_OK + && l == (blocking_factor = l) + && 0 < blocking_factor + && l == (record_size = l * (size_t) BLOCKSIZE) / BLOCKSIZE)) + USAGE_ERROR ((0, 0, _("Invalid blocking factor"))); + } break; case OBSOLETE_READ_FULL_RECORDS: @@ -612,6 +583,10 @@ decode_options (int argc, char *const *argv) set_subcommand_option (DIFF_SUBCOMMAND); break; + case 'E': + ending_file_option = optarg; + break; + case 'f': if (archive_names == allocated_archive_names) { @@ -676,10 +651,15 @@ decode_options (int argc, char *const *argv) break; case 'L': - clear_tarlong (tape_length_option); - add_to_tarlong (tape_length_option, intconv (optarg)); - mult_tarlong (tape_length_option, 1024); - multi_volume_option = 1; + { + unsigned long u; + if (xstrtoul (optarg, (char **) 0, 10, &u, "") != LONG_MAX) + USAGE_ERROR ((0, 0, _("Invalid tape length"))); + clear_tarlong (tape_length_option); + add_to_tarlong (tape_length_option, u); + mult_tarlong (tape_length_option, 1024); + multi_volume_option = 1; + } break; case OBSOLETE_TOUCH: @@ -835,11 +815,16 @@ decode_options (int argc, char *const *argv) break; case GROUP_OPTION: - if (!gname_to_gid (optarg, &group_option)) - if (!check_decimal (optarg) >= 0) - ERROR ((TAREXIT_FAILURE, 0, _("Invalid group given on option"))); - else - group_option = check_decimal (optarg); + if (! (strlen (optarg) < GNAME_FIELD_SIZE + && gname_to_gid (optarg, &group_option))) + { + uintmax_t g; + if (xstrtoumax (optarg, (char **) 0, 10, &g, "") == LONGINT_OK + && g == (gid_t) g) + group_option = g; + else + ERROR ((TAREXIT_FAILURE, 0, _("Invalid group given on option"))); + } break; case MODE_OPTION: @@ -861,11 +846,16 @@ decode_options (int argc, char *const *argv) break; case OWNER_OPTION: - if (!uname_to_uid (optarg, &owner_option)) - if (!check_decimal (optarg) >= 0) - ERROR ((TAREXIT_FAILURE, 0, _("Invalid owner given on option"))); - else - owner_option = check_decimal (optarg); + if (! (strlen (optarg) < UNAME_FIELD_SIZE + && uname_to_uid (optarg, &owner_option))) + { + uintmax_t u; + if (xstrtoumax (optarg, (char **) 0, 10, &u, "") == LONGINT_OK + && u == (uid_t) u) + owner_option = u; + else + ERROR ((TAREXIT_FAILURE, 0, _("Invalid owner given on option"))); + } break; case POSIX_OPTION: @@ -888,11 +878,17 @@ decode_options (int argc, char *const *argv) break; case RECORD_SIZE_OPTION: - record_size = intconv (optarg); - if (record_size % BLOCKSIZE != 0) - USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."), - BLOCKSIZE)); - blocking_factor = record_size / BLOCKSIZE; + { + uintmax_t u; + if (! (xstrtoumax (optarg, (char **) 0, 10, &u, "") == LONG_MAX + && u == (size_t) u)) + USAGE_ERROR ((0, 0, _("Invalid record size"))); + record_size = u; + if (record_size % BLOCKSIZE != 0) + USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."), + BLOCKSIZE)); + blocking_factor = record_size / BLOCKSIZE; + } break; case RSH_COMMAND_OPTION: @@ -998,7 +994,7 @@ decode_options (int argc, char *const *argv) printf ("tar (GNU %s) %s\n", PACKAGE, VERSION); fputs (_("\ \n\ -Copyright (C) 1988, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.\n"), +Copyright (C) 1988, 92,93,94,95,96,97,98, 1999 Free Software Foundation, Inc.\n"), stdout); fputs (_("\ This is free software; see the source for copying conditions. There is NO\n\ @@ -1098,7 +1094,7 @@ Written by John Gilmore and Jay Fenlason.\n"), simple_backup_suffix = xstrdup (backup_suffix_string); if (backup_option) - backup_type = get_version (version_control_string); + backup_type = xget_version ("--backup", version_control_string); } /* Tar proper. */