From de71e746ae2571ce1892f472f8a8f1315b80f070 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 2 Apr 2019 16:37:35 -0500 Subject: More tar cleanup, more tests. --- tests/tar.test | 43 +++++++++++++++++++++++++++++++++++-------- toys/pending/tar.c | 24 +++++++++++++----------- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/tests/tar.test b/tests/tar.test index ef83ad94..27586b67 100644 --- a/tests/tar.test +++ b/tests/tar.test @@ -11,18 +11,18 @@ export TZ=utc OLDUMASK=$(umask) umask 0002 -# 3888 bytes, most of PATH_MAX -LONG=abcdefghijklmnopqrstuvwxyz0123456789 -LONG=$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG -LONG=$LONG$LONG$LONG$LONG$LONG$LONG -LONG=$LONG$LONG +# 255 bytes, longest VFS name +LONG=0123456789abcdef0123456789abcdef +LONG=$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG +LONG=${LONG:1:255} # Reproducible tarballs: override ownership and timestamp. Also amount of # trailing NUL padding varies (1024 bytes is minimum, gnu/dammit does more) # so look at first 3 512-byte frames when analyzing header content. TAR='tar c --owner root --group root --mtime @1234567890' -SUM='head -c $((3*512)) | sha1sum | sed "s/ .*//"' +export BLOCKS=3 +SUM='head -c $(($BLOCKS*512)) | sha1sum | sed "s/ .*//"' [ -n "$TARHD" ] && SUM="tee >(hd >&2) | $SUM" LST='tar tv | sed "s/[ \t][ \t]*/ /g"' @@ -88,8 +88,35 @@ testing "create dir/fifo" "$TAR dir/fifo | $SUM" \ # 4+96=100 (biggest short name), 4+97=101 (shortest long name) touch dir/${LONG:1:96} dir/${LONG:1:97} -testing "create longfilename" "$TAR dir/${LONG:1:97} dir/${LONG:1:96} | $SUM" \ - "08af4f9d8b7f4b2f6c264689efe42a4159314708\n" "" "" +testing "create long fname" "$TAR dir/${LONG:1:97} dir/${LONG:1:96} | $SUM" \ + "99348686fe9c9bf80f5740f1fc0c6f32f2021e3d\n" "" "" + +ln -s dir/${LONG:1:96} dir/lshort +ln -s dir/${LONG:1:97} dir/llong +testing "create long symlnk" "$TAR dir/lshort dir/llong | $SUM" \ + "8a5d652dc85f252a2e3b3f47d1ecd699e98a5f4b\n" "" "" + +ln -s $LONG dir/${LONG:5} +BLOCKS=7 testing "create long->long" "$TAR dir/${LONG:5} | $SUM" \ + "543116b8e690a116a559ab5b673f9b6d6601c925\n" "" "" +# absolute and relative link names, broken and not + +ln -s file dir/linkok +testing "create symlink" "$TAR dir/linkok | $SUM" \ + "55652846506cf0a9d43b3ef03ccf9e98123befaf\n" "" "" + +ln -s /dev/null dir/linknull +testing "pass absolute symlink" "$TAR dir/linknull | $LST" \ + "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/linknull -> /dev/null\n" "" "" + +ln -s rel/broken dir/relbrok +testing "pass broken symlink" "$TAR dir/relbrok | $LST" \ + "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/relbrok -> rel/broken\n" "" "" + +ln -s /does/not/exist dir/linkabsbrok +testing "pass broken absolute symlink" "$TAR dir/linkabsbrok | $LST" \ + "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/linkabsbrok -> /does/not/exist\n" \ + "" "" # this expects devtmpfs values diff --git a/toys/pending/tar.c b/toys/pending/tar.c index bff8b540..f7559b60 100644 --- a/toys/pending/tar.c +++ b/toys/pending/tar.c @@ -77,7 +77,7 @@ struct tar_hdr { prefix[155], padd[12]; }; -// convert to int to octal (or base-256) +// convert from int to octal (or base-256) static void itoo(char *str, int len, unsigned long long val) { // Do we need binary encoding? @@ -103,6 +103,7 @@ static unsigned long long otoi(char *str, unsigned len) return val; } +#define OTOI(x) otoi(x, sizeof(x)) // Calculate packet checksum, with cksum field treated as 8 spaces static unsigned cksum(void *data) @@ -172,6 +173,7 @@ static void alloread(void *buf, int len) b[len] = 0; } +// callback from dirtree to create archive static int add_to_tar(struct dirtree *node) { struct stat *st = &(node->st); @@ -195,7 +197,7 @@ static int add_to_tar(struct dirtree *node) if ((p == name || p[-1] == '/') && *p != '/' && filter(TT.excl, p)) goto done; - // The 1 extra byte from dirtree_path() + // Consume the 1 extra byte alocated in dirtree_path() if (S_ISDIR(st->st_mode) && name[i-1] != '/') strcat(name, "/"); // remove leading / and any .. entries from saved name @@ -282,6 +284,7 @@ static int add_to_tar(struct dirtree *node) } if (strlen(hname) > sizeof(hdr.name)) write_longname(hname, 'L'); + if (!FLAG(numeric_owner)) { if (TT.owner || (pw = bufgetpwuid(st->st_uid))) strncpy(hdr.uname, TT.owner ? TT.owner : pw->pw_name, sizeof(hdr.uname)); @@ -501,9 +504,8 @@ static void unpack_tar(void) // Is this a valid Unix Standard TAR header? if (memcmp(tar.magic, "ustar", 5)) error_exit("bad header"); - if (cksum(&tar) != otoi(tar.chksum, sizeof(tar.chksum))) - error_exit("bad cksum"); - TT.hdr.size = otoi(tar.size, sizeof(tar.size)); + if (cksum(&tar) != OTOI(tar.chksum)) error_exit("bad cksum"); + TT.hdr.size = OTOI(tar.size); // If this header isn't writing something to the filesystem if (tar.type<'0' || tar.type>'7') { @@ -538,13 +540,13 @@ static void unpack_tar(void) } // At this point, we have something to output. Convert metadata. - TT.hdr.mode = otoi(tar.mode, sizeof(tar.mode)); + TT.hdr.mode = OTOI(tar.mode); TT.hdr.mode |= (char []){8,8,10,2,6,4,1,8}[tar.type-'0']<<12; - TT.hdr.uid = otoi(tar.uid, sizeof(tar.uid)); - TT.hdr.gid = otoi(tar.gid, sizeof(tar.gid)); - TT.hdr.mtime = otoi(tar.mtime, sizeof(tar.mtime)); - maj = otoi(tar.major, sizeof(tar.major)); - min = otoi(tar.minor, sizeof(tar.minor)); + TT.hdr.uid = OTOI(tar.uid); + TT.hdr.gid = OTOI(tar.gid); + TT.hdr.mtime = OTOI(tar.mtime); + maj = OTOI(tar.major); + min = OTOI(tar.minor); TT.hdr.device = dev_makedev(maj, min); TT.hdr.uname = xstrndup(TT.owner ? TT.owner : tar.uname, sizeof(tar.uname)); -- cgit v1.2.3