summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorJoshua M. Clulow <jmc@joyent.com>2015-07-21 15:56:04 -0700
committerJoshua M. Clulow <jmc@joyent.com>2015-07-22 16:23:41 +0000
commit26ec8019eb106158083e10fb0be7d2ee9baa9056 (patch)
tree4386ee4c59cd9617ce63f7e185b484f4cee84109 /usr
parente6ea578d40797b9b8e2fd62969b9bc4b0060bf92 (diff)
downloadillumos-joyent-26ec8019eb106158083e10fb0be7d2ee9baa9056.tar.gz
OS-4526 tar should check prefix field when detecting EOT
OS-4529 tar debug output should be available in all builds Reviewed by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr')
-rw-r--r--usr/src/cmd/tar/tar.c240
1 files changed, 140 insertions, 100 deletions
diff --git a/usr/src/cmd/tar/tar.c b/usr/src/cmd/tar/tar.c
index ae96ff27c7..46e6e38612 100644
--- a/usr/src/cmd/tar/tar.c
+++ b/usr/src/cmd/tar/tar.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -124,13 +124,6 @@ int utimes(const char *path, const struct timeval timeval_ptr[]);
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
-/* -DDEBUG ONLY for debugging */
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(a, b, c)\
- (void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c)
-#endif
-
#define TBLOCK 512 /* tape block size--should be universal */
#ifdef BSIZE
@@ -482,7 +475,7 @@ static int checkupdate(char *arg);
static int checkw(char c, char *name);
static int cmp(char *b, char *s, int n);
static int defset(char *arch);
-static int endtape(void);
+static boolean_t endtape(void);
static int is_in_table(file_list_t *table[], char *str);
static int notsame(void);
static int is_prefix(char *s1, char *s2);
@@ -558,6 +551,8 @@ static char *add_suffix();
static void wait_pid(pid_t);
static void verify_compress_opt(const char *t);
static void detect_compress(void);
+static void dlog(const char *, ...);
+static boolean_t should_enable_debug(void);
static struct stat stbuf;
@@ -633,7 +628,7 @@ static int extno; /* number of extent: starts at 1 */
static int extotal; /* total extents in this file */
static off_t extsize; /* size of current extent during extraction */
static ushort_t Oumask = 0; /* old umask value */
-static int is_posix; /* true if archive we're reading is POSIX-conformant */
+static boolean_t is_posix; /* true if archive is POSIX-conformant */
static const char *magic_type = "ustar";
static size_t xrec_size = 8 * PATH_MAX; /* extended rec initial size */
static char *xrec_ptr;
@@ -645,6 +640,8 @@ static u_longlong_t xhdr_flgs; /* Bits set determine which items */
/* need to be in extended header. */
static pid_t comp_pid = 0;
+static boolean_t debug_output = B_FALSE;
+
#define _X_DEVMAJOR 0x1
#define _X_DEVMINOR 0x2
#define _X_GID 0x4
@@ -736,6 +733,8 @@ main(int argc, char *argv[])
if (argc < 2)
usage();
+ debug_output = should_enable_debug();
+
tfile = NULL;
if ((myname = strdup(argv[0])) == NULL) {
(void) fprintf(stderr, gettext(
@@ -1193,6 +1192,49 @@ main(int argc, char *argv[])
return (1);
}
+static boolean_t
+should_enable_debug(void)
+{
+ const char *val;
+ const char *truth[] = {
+ "true",
+ "1",
+ "yes",
+ "y",
+ "please",
+ NULL
+ };
+ unsigned int i;
+
+ if ((val = getenv("DEBUG_TAR")) == NULL) {
+ return (B_FALSE);
+ }
+
+ for (i = 0; truth[i] != NULL; i++) {
+ if (strcmp(val, truth[i]) == 0) {
+ return (B_TRUE);
+ }
+ }
+
+ return (B_FALSE);
+}
+
+/*PRINTFLIKE1*/
+static void
+dlog(const char *format, ...)
+{
+ va_list ap;
+
+ if (!debug_output) {
+ return;
+ }
+
+ va_start(ap, format);
+ (void) fprintf(stderr, "tar: DEBUG: ");
+ (void) vfprintf(stderr, format, ap);
+ va_end(ap);
+}
+
static void
usage(void)
{
@@ -1427,13 +1469,26 @@ dorep(char *argv[])
* 1 if EOT, tape position unaffected
*/
-static int
+static boolean_t
endtape(void)
{
- if (dblock.dbuf.name[0] == '\0') { /* null header = EOT */
- return (1);
- } else
- return (0);
+ if (dblock.dbuf.name[0] != '\0') {
+ /*
+ * The name field is populated.
+ */
+ return (B_FALSE);
+ }
+
+ if (is_posix && dblock.dbuf.prefix[0] != '\0') {
+ /*
+ * This is a ustar/POSIX archive, and although the name
+ * field is empty the prefix field is not.
+ */
+ return (B_FALSE);
+ }
+
+ dlog("endtape(): found null header; EOT\n");
+ return (B_TRUE);
}
/*
@@ -1471,9 +1526,11 @@ top:
is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0);
sp->st_mode = Gen.g_mode;
- if (is_posix && (sp->st_mode & S_IFMT) == 0)
+ if (is_posix && (sp->st_mode & S_IFMT) == 0) {
switch (dblock.dbuf.typeflag) {
- case '0': case 0: case _XATTR_HDRTYPE:
+ case '0':
+ case 0:
+ case _XATTR_HDRTYPE:
sp->st_mode |= S_IFREG;
break;
case '1': /* hard link */
@@ -1498,6 +1555,7 @@ top:
sp->st_mode |= S_IFREG;
break;
}
+ }
if ((dblock.dbuf.typeflag == 'X') || (dblock.dbuf.typeflag == 'L')) {
Xhdrflag = 1; /* Currently processing extended header */
@@ -1605,7 +1663,7 @@ top:
* The tape directory entry must be in dblock.dbuf. This
* routine just eats the number of blocks computed from the
* directory size entry; the tape must be (logically) positioned
- * right after thee directory info.
+ * right after the directory info.
*/
static void
@@ -1615,6 +1673,18 @@ passtape(void)
char buf[TBLOCK];
/*
+ * Print some debugging information about the directory entry
+ * we are skipping over:
+ */
+ dlog("passtape: typeflag \"%c\"\n", dblock.dbuf.typeflag);
+ if (dblock.dbuf.name[0] != '\0') {
+ dlog("passtape: name \"%s\"\n", dblock.dbuf.name);
+ }
+ if (is_posix && dblock.dbuf.prefix[0] != '\0') {
+ dlog("passtape: prefix \"%s\"\n", dblock.dbuf.prefix);
+ }
+
+ /*
* Types link(1), sym-link(2), char special(3), blk special(4),
* directory(5), and FIFO(6) do not have data blocks associated
* with them so just skip reading the data block.
@@ -1625,6 +1695,8 @@ passtape(void)
return;
blocks = TBLOCKS(stbuf.st_size);
+ dlog("passtape: block count %" FMT_blkcnt_t "\n", blocks);
+
/* if operating on disk, seek instead of reading */
if (NotTape)
seekdisk(blocks);
@@ -2070,11 +2142,9 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
(void) writetbuf((char *)&dblock, 1);
}
if (vflag) {
-#ifdef DEBUG
- if (NotTape)
- DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
- 0);
-#endif
+ if (NotTape) {
+ dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
+ }
if (filetype == XATTR_FILE && Hiddendir) {
(void) fprintf(vfile,
gettext("a %s attribute %s "),
@@ -2083,12 +2153,13 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
} else {
(void) fprintf(vfile, "a %s/ ", longname);
}
- if (NotTape)
+ if (NotTape) {
(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
K(blocks));
- else
+ } else {
(void) fprintf(vfile, gettext("%" FMT_blkcnt_t
" tape blocks\n"), blocks);
+ }
}
/*
@@ -2270,20 +2341,16 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
}
newvol(); /* not worth it--just get new volume */
}
-#ifdef DEBUG
- DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
+ dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
blocks);
-#endif
if (build_dblock(name, tchar, '0', filetype,
&stbuf, stbuf.st_dev, prefix) != 0) {
goto out;
}
if (vflag) {
-#ifdef DEBUG
- if (NotTape)
- DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
- 0);
-#endif
+ if (NotTape) {
+ dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
+ }
(void) fprintf(vfile, "a %s%s%s%s ", longname,
rw_sysattr ? gettext(" system") : "",
(filetype == XATTR_FILE) ? gettext(
@@ -2367,23 +2434,19 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
}
newvol();
}
-#ifdef DEBUG
- DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
+ dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
blocks);
-#endif
if (vflag) {
-#ifdef DEBUG
- if (NotTape)
- DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
- 0);
-#endif
- if (NotTape)
+ if (NotTape) {
+ dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
+
(void) fprintf(vfile, gettext("a %s %"
FMT_blkcnt_t "K\n "), longname, K(blocks));
- else
+ } else {
(void) fprintf(vfile, gettext(
"a %s %" FMT_blkcnt_t " tape blocks\n"),
longname, blocks);
+ }
}
if (build_dblock(name, tchar, '6', filetype,
&stbuf, stbuf.st_dev, prefix) != 0)
@@ -2418,23 +2481,19 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
}
newvol();
}
-#ifdef DEBUG
- DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
+ dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
blocks);
-#endif
if (vflag) {
-#ifdef DEBUG
- if (NotTape)
- DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
- 0);
-#endif
- if (NotTape)
+ if (NotTape) {
+ dlog("seek = %" FMT_blkcnt_t "K\t", K(tapepos));
+
(void) fprintf(vfile, gettext("a %s %"
FMT_blkcnt_t "K\n"), longname, K(blocks));
- else
+ } else {
(void) fprintf(vfile, gettext("a %s %"
FMT_blkcnt_t " tape blocks\n"), longname,
blocks);
+ }
}
if (build_dblock(name, tchar, '3',
filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
@@ -2469,16 +2528,13 @@ putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo,
}
newvol();
}
-#ifdef DEBUG
- DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
+ dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
blocks);
-#endif
if (vflag) {
-#ifdef DEBUG
- if (NotTape)
- DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
- 0);
-#endif
+ if (NotTape) {
+ dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
+ }
+
(void) fprintf(vfile, "a %s ", longname);
if (NotTape)
(void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
@@ -4790,9 +4846,7 @@ newvol(void)
int c;
if (dumping) {
-#ifdef DEBUG
- DEBUG("newvol called with 'dumping' set\n", 0, 0);
-#endif
+ dlog("newvol called with 'dumping' set\n");
putempty((blkcnt_t)2); /* 2 EOT marks */
closevol();
flushtape();
@@ -4825,10 +4879,8 @@ newvol(void)
"tar: cannot reopen %s (%s)\n"),
dumping ? gettext("output") : gettext("input"), usefile);
-#ifdef DEBUG
- DEBUG("update=%d, usefile=%s ", update, usefile);
- DEBUG("mt=%d, [%s]\n", mt, strerror(errno));
-#endif
+ dlog("update=%d, usefile=%s ", update, usefile);
+ dlog("mt=%d, [%s]\n", mt, strerror(errno));
done(2);
}
@@ -5013,9 +5065,7 @@ seekdisk(blkcnt_t blocks)
#endif
tapepos += blocks;
-#ifdef DEBUG
- DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0);
-#endif
+ dlog("seekdisk(%" FMT_blkcnt_t ") called\n", blocks);
if (recno + blocks <= nblock) {
recno += blocks;
return;
@@ -5026,10 +5076,8 @@ seekdisk(blkcnt_t blocks)
recno = nblock; /* so readtape() reads next time through */
#if SYS_BLOCK > TBLOCK
nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK));
-#ifdef DEBUG
- DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n",
+ dlog("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n",
nxb, seekval);
-#endif
if (nxb && nxb > seekval) /* don't seek--we'll read */
goto noseek;
seekval -= nxb; /* don't seek quite so far */
@@ -5043,9 +5091,7 @@ seekdisk(blkcnt_t blocks)
/* read those extra blocks */
noseek:
if (nxb) {
-#ifdef DEBUG
- DEBUG("reading extra blocks\n", 0, 0);
-#endif
+ dlog("reading extra blocks\n", 0, 0);
if (read(mt, tbuf, TBLOCK*nblock) < 0) {
(void) fprintf(stderr, gettext(
"tar: read error while skipping file\n"));
@@ -5217,10 +5263,8 @@ static void
backtape(void)
{
struct mtop mtcmd;
-#ifdef DEBUG
- DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno,
+ dlog("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno,
nblock);
-#endif
/*
* Backup to the position in the archive where the record
* currently sitting in the tbuf buffer is situated.
@@ -5278,9 +5322,7 @@ backtape(void)
static void
flushtape(void)
{
-#ifdef DEBUG
- DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0);
-#endif
+ dlog("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno);
if (recno > 0) { /* anything buffered? */
if (NotTape) {
#if SYS_BLOCK > TBLOCK
@@ -5293,20 +5335,16 @@ flushtape(void)
* boundary.
*/
if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) {
-#ifdef DEBUG
- DEBUG("flushtape() %d rounding blocks\n", i, 0);
-#endif
+ dlog("flushtape() %d rounding blocks\n", i);
recno += i; /* round up to even SYS_BLOCK */
}
#endif
if (recno > nblock)
recno = nblock;
}
-#ifdef DEBUG
- DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t
+ dlog("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t
" bytes\n", (blkcnt_t)(NotTape ? recno : nblock),
(blkcnt_t)(NotTape ? recno : nblock) * TBLOCK);
-#endif
if (write(mt, tbuf,
(size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) {
(void) fprintf(stderr, gettext(
@@ -5436,12 +5474,10 @@ defset(char *arch)
else
NotTape = (blocklim != 0);
(void) defopen(NULL);
-#ifdef DEBUG
- DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile);
- DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n",
+ dlog("defset: archive='%s'; usefile='%s'\n", arch, usefile);
+ dlog("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n",
nblock, blocklim);
- DEBUG("defset: not tape = %d\n", NotTape, 0);
-#endif
+ dlog("defset: not tape = %d\n", NotTape);
return (TRUE);
}
@@ -5752,6 +5788,9 @@ top:
if (endtape()) {
if (Bflag) {
+ ssize_t sz;
+ size_t extra_blocks = 0;
+
/*
* Logically at EOT - consume any extra blocks
* so that write to our stdin won't fail and
@@ -5760,10 +5799,13 @@ top:
* will produce a bogus error message from "dd".
*/
- while (read(mt, tbuf, TBLOCK*nblock) > 0) {
- /* empty body */
+ while ((sz = read(mt, tbuf, TBLOCK*nblock)) > 0) {
+ extra_blocks += sz;
}
+ dlog("wantit(): %d bytes of extra blocks\n",
+ extra_blocks);
}
+ dlog("wantit(): at end of tape.\n");
return (-1);
}
@@ -8016,11 +8058,9 @@ put_link(char *name, char *longname, char *component, char *longattrname,
*/
if (vflag) {
-#ifdef DEBUG
if (NotTape)
- DEBUG("seek = %" FMT_blkcnt_t
- "K\t", K(tapepos), 0);
-#endif
+ dlog("seek = %" FMT_blkcnt_t
+ "K\n", K(tapepos));
if (filetype == XATTR_FILE) {
(void) fprintf(vfile, gettext(
"a %s attribute %s link to "