aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/tar.test43
-rw-r--r--toys/pending/tar.c24
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));