diff options
-rw-r--r-- | usr.bin/tar/bsdtar.1 | 20 | ||||
-rw-r--r-- | usr.bin/tar/bsdtar.c | 72 |
2 files changed, 70 insertions, 22 deletions
diff --git a/usr.bin/tar/bsdtar.1 b/usr.bin/tar/bsdtar.1 index ab0ea59..7518a81 100644 --- a/usr.bin/tar/bsdtar.1 +++ b/usr.bin/tar/bsdtar.1 @@ -140,6 +140,9 @@ In c and r mode, this changes the directory before adding the following files. In x mode, change directories after opening the archive but before extracting entries from the archive. +.It Fl -check-links ( Fl W Cm check-links ) +(c and r modes only) +Issue a warning message unless all links to each file are archived. .It Fl -exclude Ar pattern ( Fl W Cm exclude Ns = Ns Ar pattern ) Do not process files or directories that match the specified pattern. @@ -220,8 +223,16 @@ All symbolic links will be followed. Normally, symbolic links are archived as such. With this option, the target of the link will be archived instead. .It Fl l -(c mode only) -Issue a warning message unless all links to each file are archived. +If +.Ev POSIXLY_CORRECT +is specified in the environment, this is a synonym for the +.Fl -check-links +option. +Otherwise, an error will be displayed. +Users who desire behavior compatible with GNU tar should use +the +.Fl -one-file-system +option instead. .It Fl m (x mode only) Do not extract modification time. @@ -387,6 +398,11 @@ The locale to use. See .Xr environ 7 for more information. +.It Ev POSIXLY_CORRECT +If this environment variable is defined, the +.Fl l +option will be interpreted in accordance with +.St -p1003.1-96 . .It Ev TAPE The default tape device. The diff --git a/usr.bin/tar/bsdtar.c b/usr.bin/tar/bsdtar.c index da99da6..c4f00a7 100644 --- a/usr.bin/tar/bsdtar.c +++ b/usr.bin/tar/bsdtar.c @@ -92,15 +92,16 @@ static const char *tar_opts = "+Bb:C:cF:f:HhjkLlmnOoPprtT:UuvW:wX:xyZz"; */ /* Fake short equivalents for long options that otherwise lack them. */ -#define OPTION_EXCLUDE 1 -#define OPTION_FAST_READ 2 -#define OPTION_HELP 3 -#define OPTION_INCLUDE 4 -#define OPTION_NODUMP 5 -#define OPTION_NO_SAME_PERMISSIONS 6 -#define OPTION_NULL 7 -#define OPTION_ONE_FILE_SYSTEM 8 -#define OPTION_VERSION 9 +#define OPTION_CHECK_LINKS 3 +#define OPTION_EXCLUDE 6 +#define OPTION_FAST_READ 9 +#define OPTION_HELP 12 +#define OPTION_INCLUDE 15 +#define OPTION_NODUMP 18 +#define OPTION_NO_SAME_PERMISSIONS 21 +#define OPTION_NULL 24 +#define OPTION_ONE_FILE_SYSTEM 27 +#define OPTION_VERSION 30 static const struct option tar_longopts[] = { { "absolute-paths", no_argument, NULL, 'P' }, @@ -110,6 +111,7 @@ static const struct option tar_longopts[] = { { "bzip", no_argument, NULL, 'j' }, { "bzip2", no_argument, NULL, 'j' }, { "cd", required_argument, NULL, 'C' }, + { "check-links", no_argument, NULL, OPTION_CHECK_LINKS }, { "confirmation", no_argument, NULL, 'w' }, { "create", no_argument, NULL, 'c' }, { "dereference", no_argument, NULL, 'L' }, @@ -154,6 +156,7 @@ main(int argc, char **argv) const struct option *option; int opt, t; char mode; + char option_o; char possible_help_request; char buff[16]; @@ -164,6 +167,7 @@ main(int argc, char **argv) bsdtar = &bsdtar_storage; memset(bsdtar, 0, sizeof(*bsdtar)); bsdtar->fd = -1; /* Mark as "unused" */ + option_o = 0; if (setlocale(LC_ALL, "") == NULL) bsdtar_warnc(bsdtar, 0, "Failed to set default locale"); @@ -227,6 +231,9 @@ main(int argc, char **argv) opt, mode); mode = opt; break; + case OPTION_CHECK_LINKS: /* GNU tar */ + bsdtar->option_warn_links = 1; + break; case OPTION_EXCLUDE: /* GNU tar */ if (exclude(bsdtar, optarg)) bsdtar_errc(bsdtar, 1, 0, @@ -274,8 +281,19 @@ main(int argc, char **argv) case 'L': /* BSD convention */ bsdtar->symlink_mode = 'L'; break; - case 'l': /* SUSv2; note that GNU -l conflicts */ - bsdtar->option_warn_links = 1; + case 'l': /* SUSv2 and GNU conflict badly here */ + if (getenv("POSIXLY_CORRECT") != NULL) { + /* User has asked for POSIX/SUS behavior. */ + bsdtar->option_warn_links = 1; + } else { + fprintf(stderr, +"Error: -l has different behaviors in different tar programs.\n"); + fprintf(stderr, +" For the GNU behavior, use --one-file-system instead.\n"); + fprintf(stderr, +" For the POSIX behavior, use --check-links instead.\n"); + usage(bsdtar); + } break; case 'm': /* SUSv2 */ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_TIME; @@ -300,9 +318,8 @@ main(int argc, char **argv) case 'O': /* GNU tar */ bsdtar->option_stdout = 1; break; - case 'o': /* SUSv2; note that GNU -o conflicts */ - bsdtar->option_no_owner = 1; - bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; + case 'o': /* SUSv2 and GNU conflict here */ + option_o = 1; /* Record it and resolve it later. */ break; case OPTION_ONE_FILE_SYSTEM: /* -l in GNU tar */ bsdtar->option_dont_traverse_mounts = 1; @@ -424,18 +441,33 @@ main(int argc, char **argv) only_mode(bsdtar, mode, "--fast-read", "xt"); if (bsdtar->option_honor_nodump) only_mode(bsdtar, mode, "--nodump", "cru"); - if (bsdtar->option_no_owner) { - only_mode(bsdtar, mode, "-o", "xc"); - /* Warn about nonsensical -co combination, but ignore it. */ - if (mode == 'c') - bsdtar_warnc(bsdtar, 0, "Ignoring nonsensical -o option"); + if (option_o > 0) { + switch (mode) { + case 'c': + /* + * In GNU tar, -o means "old format." The + * "ustar" format is the closest thing + * supported by libarchive. + */ + bsdtar->create_format = "ustar"; + /* TODO: bsdtar->create_format = "v7"; */ + break; + case 'x': + /* POSIX-compatible behavior. */ + bsdtar->option_no_owner = 1; + bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; + break; + default: + only_mode(bsdtar, mode, "-o", "xc"); + break; + } } if (bsdtar->option_no_subdirs) only_mode(bsdtar, mode, "-n", "cru"); if (bsdtar->option_stdout) only_mode(bsdtar, mode, "-O", "x"); if (bsdtar->option_warn_links) - only_mode(bsdtar, mode, "-l", "cr"); + only_mode(bsdtar, mode, "--check-links", "cr"); /* Check other parameters only permitted in certain modes. */ if (bsdtar->create_compression == 'Z' && mode == 'c') { |