aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-04-03 10:36:10 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-04-03 10:36:10 -0700
commitc30508d0c9631227b377a1bcda09c14ff7d47bca (patch)
treef818f8af1e5c4af48d4e5085d331b1373f6d6ad5
parent03df06d931d43332eb470038be0d1f782cb688b9 (diff)
parentd0d3b0c6819a453383bca1e6c96e75c6a3ebd93b (diff)
downloadtoybox-c30508d0c9631227b377a1bcda09c14ff7d47bca.tar.gz
Merge remote-tracking branch 'toybox/master' into HEAD am: 7f1341e5d3
am: d0d3b0c681 Change-Id: I14e7f53c6752422d95e9f76f67604524f068f712
-rw-r--r--generated/flags.h6
-rw-r--r--generated/globals.h4
-rw-r--r--generated/help.h2
-rw-r--r--generated/newtoys.h2
-rw-r--r--lib/lib.c11
-rw-r--r--lib/xwrap.c7
-rwxr-xr-xtests/rm.test2
-rw-r--r--tests/tar.test75
-rw-r--r--toys/pending/tar.c120
-rw-r--r--toys/posix/id.c2
10 files changed, 159 insertions, 72 deletions
diff --git a/generated/flags.h b/generated/flags.h
index 9f387ef3..7019fc94 100644
--- a/generated/flags.h
+++ b/generated/flags.h
@@ -2742,9 +2742,9 @@
#undef FLAG_f
#endif
-// tar &(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz] &(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]
+// tar &(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz] &(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]
#undef OPTSTR_tar
-#define OPTSTR_tar "&(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]"
+#define OPTSTR_tar "&(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]"
#ifdef CLEANUP_tar
#undef CLEANUP_tar
#undef FOR_tar
@@ -2773,6 +2773,7 @@
#undef FLAG_no_same_permissions
#undef FLAG_numeric_owner
#undef FLAG_no_recursion
+#undef FLAG_full_time
#endif
// taskset <1^pa <1^pa
@@ -5669,6 +5670,7 @@
#define FLAG_no_same_permissions (1<<22)
#define FLAG_numeric_owner (1<<23)
#define FLAG_no_recursion (1<<24)
+#define FLAG_full_time (1<<25)
#endif
#ifdef FOR_taskset
diff --git a/generated/globals.h b/generated/globals.h
index 188d2b67..8f40ea18 100644
--- a/generated/globals.h
+++ b/generated/globals.h
@@ -811,7 +811,7 @@ struct tar_data {
struct double_list *incl, *excl, *seen;
struct string_list *dirs;
char *cwd;
- int fd, ouid, ggid, hlc, warn;
+ int fd, ouid, ggid, hlc, warn, adev, aino;
time_t mtt;
// hardlinks seen so far (hlc many)
@@ -822,7 +822,7 @@ struct tar_data {
} *hlx;
// Parsed information about a tar header.
- struct {
+ struct tar_header {
char *name, *link_target, *uname, *gname;
long long size;
uid_t uid;
diff --git a/generated/help.h b/generated/help.h
index bd0db872..f4728dcc 100644
--- a/generated/help.h
+++ b/generated/help.h
@@ -544,7 +544,7 @@
#define HELP_groups "usage: groups [user]\n\nPrint the groups a user is in.\n\n"
-#define HELP_id "usage: id [-GZgnru] \n\nPrint user and group ID.\n-G Show only the group IDs\n-Z Show only security context\n-g Show only the effective group ID\n-n Print names instead of numeric IDs (to be used with -Ggu)\n-r Show real ID instead of effective ID\n-u Show only the effective user ID\n"
+#define HELP_id "usage: id [-GZgnru] [USER...]\n\nPrint user and group ID.\n-G Show only the group IDs\n-Z Show only security context\n-g Show only the effective group ID\n-n Print names instead of numeric IDs (to be used with -Ggu)\n-r Show real ID instead of effective ID\n-u Show only the effective user ID\n"
#define HELP_iconv "usage: iconv [-f FROM] [-t TO] [FILE...]\n\nConvert character encoding of files.\n\n-c Omit invalid chars\n-f Convert from (default utf8)\n-t Convert to (default utf8)\n\n"
diff --git a/generated/newtoys.h b/generated/newtoys.h
index e7b09a4f..e8205572 100644
--- a/generated/newtoys.h
+++ b/generated/newtoys.h
@@ -246,7 +246,7 @@ USE_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_SBIN))
USE_SYSLOGD(NEWTOY(syslogd,">0l#<1>8=8R:b#<0>99=1s#<0=200m#<0>71582787=20O:p:f:a:nSKLD", TOYFLAG_SBIN|TOYFLAG_STAYROOT))
USE_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN))
USE_TAIL(NEWTOY(tail, "?fc-n-[-cn]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_TAR(NEWTOY(tar, "&(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TAR(NEWTOY(tar, "&(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]", TOYFLAG_USR|TOYFLAG_BIN))
USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1C:b#=20<0u:l:hEv", TOYFLAG_USR|TOYFLAG_BIN))
USE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/lib/lib.c b/lib/lib.c
index 14cedb60..c4d871c2 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -55,11 +55,14 @@ void error_exit(char *msg, ...)
// Die with an error message and strerror(errno)
void perror_exit(char *msg, ...)
{
- va_list va;
+ // Die silently if our pipeline exited.
+ if (errno != EPIPE) {
+ va_list va;
- va_start(va, msg);
- verror_msg(msg, errno, va);
- va_end(va);
+ va_start(va, msg);
+ verror_msg(msg, errno, va);
+ va_end(va);
+ }
xexit();
}
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 778cb38d..31843edf 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -141,7 +141,7 @@ char *xmprintf(char *format, ...)
void xflush(void)
{
- if (fflush(0) || ferror(stdout)) perror_exit("write");
+ if (fflush(stdout) || ferror(stdout)) perror_exit("write");
}
void xprintf(char *format, ...)
@@ -517,7 +517,8 @@ void xstat(char *path, struct stat *st)
}
// Canonicalize path, even to file with one or more missing components at end.
-// if exact, require last path component to exist
+// Returns allocated string for pathname or NULL if doesn't exist
+// exact = 1 file must exist, 0 dir must exist, -1 show theoretical location
char *xabspath(char *path, int exact)
{
struct string_list *todo, *done = 0;
@@ -963,7 +964,7 @@ void xparsedate(char *str, time_t *t, unsigned *nano, int endian)
struct tm tm;
time_t now = *t;
int len = 0, i = 0;
- // Formats with years must come first. Posix can't agree on whether 12 digits
+ // Formats with seconds come first. Posix can't agree on whether 12 digits
// has year before (touch -t) or year after (date), so support both.
char *s = str, *p, *oldtz = 0, *formats[] = {"%Y-%m-%d %T", "%Y-%m-%dT%T",
"%H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%d", "%H:%M", "%m%d%H%M",
diff --git a/tests/rm.test b/tests/rm.test
index 42727442..f0a123c3 100755
--- a/tests/rm.test
+++ b/tests/rm.test
@@ -52,7 +52,7 @@ chmod 777 one 2>/dev/null ; rm -rf one
mkdir -p d1
touch d1/f1.txt d1/f2.txt
testing "-rv dir" \
- "rm -rv d1" "rm 'd1/f1.txt'\nrm 'd1/f2.txt'\nrmdir 'd1'\n" "" ""
+ "rm -rv d1 | sort" "rm 'd1/f1.txt'\nrm 'd1/f2.txt'\nrmdir 'd1'\n" "" ""
rm -rf d1
touch "'"
diff --git a/tests/tar.test b/tests/tar.test
index 4936320c..ef83ad94 100644
--- a/tests/tar.test
+++ b/tests/tar.test
@@ -4,15 +4,19 @@
#testing "name" "command" "result" "infile" "stdin"
-# assumes umask 0002
+# For reproducibility: UTC and umask 0002
-LONG=abcdefghijklmnopqrstuvwxyz0123456789
-LONG=$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG
OLDTZ="$TZ"
-TZ=utc
+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
+
# 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.
@@ -20,25 +24,48 @@ umask 0002
TAR='tar c --owner root --group root --mtime @1234567890'
SUM='head -c $((3*512)) | sha1sum | sed "s/ .*//"'
[ -n "$TARHD" ] && SUM="tee >(hd >&2) | $SUM"
-SPC='sed "s/[ \t][ \t]*/ /g"'
+LST='tar tv | sed "s/[ \t][ \t]*/ /g"'
touch file
testing "create file" "$TAR file | $SUM" \
"fecaecba936e604bb115627a6ef4db7c7a3a8f81\n" "" ""
+testing "pass file" "$TAR file | $LST" \
+ "-rw-rw-r-- root/root 0 2009-02-13 23:31 file\n" "" ""
+
+# The kernel has two hardwired meaningful UIDs: 0 (root) and 65534 (nobody).
+# (Technically changeable via /proc/sys/*/overflowuid but nobody ever does)
+skipnot id nobody >/dev/null
+testing "pass user" "tar -c --owner nobody --group root --mtime @0 file | $LST" \
+ "-rw-rw-r-- nobody/root 0 1970-01-01 00:00 file\n" "" ""
+skipnot grep nobody /etc/group >/dev/null
+testing "pass group" "tar c --owner root --group nobody --mtime @0 file | $LST" \
+ "-rw-rw-r-- root/nobody 0 1970-01-01 00:00 file\n" "" ""
+
+touch -t 198701231234.56 file
+testing "pass mtime" \
+ "tar c --owner root --group root file | tar tv --full-time | sed 's/[ \t][ \t]*/ /g'" \
+ "-rw-rw-r-- root/root 0 1987-01-23 12:34:56 file\n" "" ""
+
mkdir dir
testing "create dir" "$TAR dir | $SUM" \
"05739c423d7d4a7f12b3dbb7c94149acb2bb4f8d\n" "" ""
+testing "pass dir" "$TAR dir | $LST" \
+ "drwxrwxr-x root/root 0 2009-02-13 23:31 dir/\n" "" ""
+
# note: does _not_ include dir entry in archive, just file
touch dir/file
-testing "create dir and file" "$TAR dir/file | $SUM" \
+testing "create file in dir" "$TAR dir/file | $SUM" \
"2d7b96c7025987215f5a41f10eaa84311160afdb\n" "" ""
# Tests recursion without worrying about content order
-testing "create dir/file 2" "$TAR dir | $SUM" \
+testing "create dir and dir/file" "$TAR dir | $SUM" \
"0bcc8005a3e07eb63c9b735267aecc5b774795d7\n" "" ""
+testing "pass dir/file" "$TAR dir | $LST" \
+ "drwxrwxr-x root/root 0 2009-02-13 23:31 dir/\n-rw-rw-r-- root/root 0 2009-02-13 23:31 dir/file\n" "" ""
+
# / and .. only stripped from name, not symlink target.
ln -s ../name.././.. dir/link
testing "create symlink" "$TAR dir/link | $SUM" \
@@ -57,3 +84,37 @@ skipnot mkfifo dir/fifo
testing "create dir/fifo" "$TAR dir/fifo | $SUM" \
"bd1365db6e8ead4c813333f9666994c1899924d9\n" "" ""
+# test L and K records
+
+# 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" "" ""
+
+# this expects devtmpfs values
+
+testing "pass /dev/null" \
+ "tar c --mtime @0 /dev/null 2>/dev/null | $LST" \
+ "crw-rw-rw- root/root 1,3 1970-01-01 00:00 dev/null\n" "" ""
+
+testing "pass /dev/loop0" \
+ "tar c --numeric-owner --mtime @0 /dev/loop0 2>/dev/null | $LST" \
+ "brw-rw---- 0/6 7,0 1970-01-01 00:00 dev/loop0\n" "" ""
+
+skipnot mknod dir/char c 12 34
+testing "create char2" "$TAR /dev/null | $SUM" \
+ "" "" ""
+
+#testing "create block" "$TAR /dev/
+
+skipnot mknod dir/block b 56 78
+testing "create dir/block" "$TAR dir/block | $SUM" \
+ "" "" ""
+
+skipnot chown nobody dir/file
+testing "ownership" "$TAR dir/block | $SUM" \
+ "blat" "" ""
+
+TZ="$OLDTZ"
+umask $OLDUMASK
+unset LONG TAR SUM OLDUMASK OLDTZ LST
diff --git a/toys/pending/tar.c b/toys/pending/tar.c
index 77c03540..bff8b540 100644
--- a/toys/pending/tar.c
+++ b/toys/pending/tar.c
@@ -18,7 +18,7 @@
* Extract into dir same as filename, --restrict? "Tarball is splodey"
*
-USE_TAR(NEWTOY(tar, "&(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TAR(NEWTOY(tar, "&(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jz]", TOYFLAG_USR|TOYFLAG_BIN))
config TAR
bool "tar"
@@ -49,7 +49,7 @@ GLOBALS(
struct double_list *incl, *excl, *seen;
struct string_list *dirs;
char *cwd;
- int fd, ouid, ggid, hlc, warn;
+ int fd, ouid, ggid, hlc, warn, adev, aino;
time_t mtt;
// hardlinks seen so far (hlc many)
@@ -60,7 +60,7 @@ GLOBALS(
} *hlx;
// Parsed information about a tar header.
- struct {
+ struct tar_header {
char *name, *link_target, *uname, *gname;
long long size;
uid_t uid;
@@ -121,7 +121,6 @@ static void write_longname(char *name, char type)
memset(&tmp, 0, sizeof(tmp));
strcpy(tmp.name, "././@LongLink");
- ITOO(tmp.mode, 0);
ITOO(tmp.uid, 0);
ITOO(tmp.gid, 0);
ITOO(tmp.size, sz);
@@ -129,8 +128,13 @@ static void write_longname(char *name, char type)
tmp.type = type;
strcpy(tmp.magic, "ustar ");
- // Calculate checksum. Since 0777777 is twice 512*255 it can never use more
- // than 6 digits, last byte is ' ' or historical reasons.
+ // Historical nonsense to match other implementations. Never used.
+ ITOO(tmp.mode, 0644);
+ strcpy(tmp.uname, "root");
+ strcpy(tmp.gname, "root");
+
+ // Calculate checksum. Since 512*255 = 0377000 in octal, this can never
+ // use more than 6 digits. The last byte is ' ' or historical reasons.
itoo(tmp.chksum, sizeof(tmp.chksum)-1, cksum(&tmp));
tmp.chksum[7] = ' ';
@@ -168,34 +172,42 @@ static void alloread(void *buf, int len)
b[len] = 0;
}
-static void add_file(char **nam, struct stat *st)
+static int add_to_tar(struct dirtree *node)
{
+ struct stat *st = &(node->st);
struct tar_hdr hdr;
struct passwd *pw = pw;
struct group *gr = gr;
int i, fd =-1;
- char *c, *p, *name = *nam, *lnk, *hname;
+ char *c, *p, *name, *lnk = lnk, *hname;
+
+ if (!dirtree_notdotdot(node)) return 0;
+ if (TT.adev == st->st_dev && TT.aino == st->st_ino) {
+ error_msg("'%s' file is the archive; not dumped", node->name);
+ return 0;
+ }
+
+ i = 1;
+ name = dirtree_path(node, &i);
// exclusion defaults to --no-anchored and --wildcards-match-slash
for (p = name; *p; p++)
- if ((p == name || p[-1] == '/') && *p != '/' && filter(TT.excl, p)) return;
+ if ((p == name || p[-1] == '/') && *p != '/' && filter(TT.excl, p))
+ goto done;
- if (S_ISDIR(st->st_mode) && name[strlen(name)-1] != '/') {
- lnk = xmprintf("%s/", name);
- free(name);
- *nam = name = lnk;
- }
+ // The 1 extra byte from dirtree_path()
+ if (S_ISDIR(st->st_mode) && name[i-1] != '/') strcat(name, "/");
// remove leading / and any .. entries from saved name
for (hname = name; *hname == '/'; hname++);
for (c = hname;;) {
if (!(c = strstr(c, ".."))) break;
if (c == hname || c[-1] == '/') {
- if (!c[2]) return;
+ if (!c[2]) goto done;
if (c[2]=='/') c = hname = c+3;
} else c+= 2;
}
- if (!*hname) return;
+ if (!*hname) goto done;
if (TT.warn && hname != name) {
fprintf(stderr, "removing leading '%.*s' from member names\n",
@@ -214,6 +226,7 @@ static void add_file(char **nam, struct stat *st)
ITOO(hdr.gid, st->st_gid);
ITOO(hdr.size, 0); //set size later
ITOO(hdr.mtime, st->st_mtime);
+ strcpy(hdr.magic, "ustar ");
// Hard link or symlink? i=0 neither, i=1 hardlink, i=2 symlink
@@ -228,7 +241,7 @@ static void add_file(char **nam, struct stat *st)
lnk = TT.hlx[i].arg;
i = 1;
} else {
- // first time we've seen it, store as normal file.
+ // first time we've seen it. Store as normal file, but remember it.
if (!(TT.hlc&255)) TT.hlx = xrealloc(TT.hlx, TT.hlc+256);
TT.hlx[TT.hlc].arg = xstrdup(hname);
TT.hlx[TT.hlc].ino = st->st_ino;
@@ -247,7 +260,10 @@ static void add_file(char **nam, struct stat *st)
// Handle file types
if (i) {
hdr.type = '0'+i;
- if (i==2 && !(lnk = xreadlink(name))) return perror_msg("readlink");
+ if (i==2 && !(lnk = xreadlink(name))) {
+ perror_msg("readlink");
+ goto done;
+ }
if (strlen(lnk) > sizeof(hdr.link)) write_longname(lnk, 'K');
strncpy(hdr.link, lnk, sizeof(hdr.link));
if (i) free(lnk);
@@ -260,10 +276,12 @@ static void add_file(char **nam, struct stat *st)
hdr.type = (S_ISCHR(st->st_mode))?'3':'4';
ITOO(hdr.major, dev_major(st->st_rdev));
ITOO(hdr.minor, dev_minor(st->st_rdev));
- } else return error_msg("unknown file type '%o'", st->st_mode & S_IFMT);
+ } else {
+ error_msg("unknown file type '%o'", st->st_mode & S_IFMT);
+ goto done;
+ }
if (strlen(hname) > sizeof(hdr.name)) write_longname(hname, 'L');
- strcpy(hdr.magic, "ustar ");
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));
@@ -278,29 +296,16 @@ static void add_file(char **nam, struct stat *st)
// Write header and data to archive
xwrite(TT.fd, &hdr, 512);
- if (hdr.type != '0') return; //nothing to write
- if ((fd = open(name, O_RDONLY)) < 0)
- return perror_msg("can't open '%s'", name);
- xsendfile_pad(fd, TT.fd, st->st_size);
- if (st->st_size%512) writeall(TT.fd, toybuf, (512-(st->st_size%512)));
- close(fd);
-}
-
-static int add_to_tar(struct dirtree *node)
-{
- struct stat st;
- char *path;
-
- if (!dirtree_notdotdot(node)) return 0;
- if (!fstat(TT.fd, &st) && st.st_dev == node->st.st_dev
- && st.st_ino == node->st.st_ino) {
- error_msg("'%s' file is the archive; not dumped", TT.f);
- return 0;
+ if (hdr.type == '0') {
+ if ((fd = open(name, O_RDONLY)) < 0) perror_msg("can't open '%s'", name);
+ else {
+ xsendfile_pad(fd, TT.fd, st->st_size);
+ if (st->st_size%512) writeall(TT.fd, toybuf, (512-(st->st_size%512)));
+ close(fd);
+ }
}
-
- path = dirtree_path(node, 0);
- add_file(&path, &(node->st)); //path may be modified
- free(path);
+done:
+ free(name);
return (DIRTREE_RECURSE|(FLAG(h)?DIRTREE_SYMFOLLOW:0))*!FLAG(no_recursion);
}
@@ -425,18 +430,18 @@ static void extract_to_disk(void)
return perror_msg("can't create '%s'", name);
+ // Set ownership
if (!FLAG(o) && !geteuid()) {
- //set ownership..., --no-same-owner, --numeric-owner
int u = TT.hdr.uid, g = TT.hdr.gid;
if (TT.owner) TT.hdr.uid = TT.ouid;
- else if (!FLAG(numeric_owner)) {
+ else if (!FLAG(numeric_owner) && *TT.hdr.uname) {
struct passwd *pw = getpwnam(TT.hdr.uname);
if (pw && (TT.owner || !FLAG(numeric_owner))) TT.hdr.uid = pw->pw_uid;
}
if (TT.group) TT.hdr.gid = TT.ggid;
- else if (!FLAG(numeric_owner)) {
+ else if (!FLAG(numeric_owner) && *TT.hdr.uname) {
struct group *gr = getgrnam(TT.hdr.gname);
if (gr) TT.hdr.gid = gr->gr_gid;
}
@@ -598,16 +603,21 @@ static void unpack_tar(void)
else if (FLAG(t)) {
if (FLAG(v)) {
struct tm *lc = localtime(TT.mtime ? &TT.mtt : &TT.hdr.mtime);
- char perm[11];
+ char perm[12], gname[12];
mode_to_string(TT.hdr.mode, perm);
- printf("%s %s/%s ", perm, TT.hdr.uname, TT.hdr.gname);
+ printf("%s", perm);
+ sprintf(perm, "%u", TT.hdr.uid);
+ sprintf(gname, "%u", TT.hdr.gid);
+ printf(" %s/%s ", *TT.hdr.uname ? TT.hdr.uname : perm,
+ *TT.hdr.gname ? TT.hdr.gname : gname);
if (tar.type=='3' || tar.type=='4') printf("%u,%u", maj, min);
else printf("%9lld", (long long)TT.hdr.size);
- printf(" %d-%02d-%02d %02d:%02d:%02d ", 1900+lc->tm_year, 1+lc->tm_mon,
- lc->tm_mday, lc->tm_hour, lc->tm_min, lc->tm_sec);
+ sprintf(perm, ":%02d", lc->tm_sec);
+ printf(" %d-%02d-%02d %02d:%02d%s ", 1900+lc->tm_year, 1+lc->tm_mon,
+ lc->tm_mday, lc->tm_hour, lc->tm_min, FLAG(full_time) ? perm : "");
}
- printf("%s", TT.hdr.name);
+ printf(" %s", TT.hdr.name);
if (TT.hdr.link_target) printf(" -> %s", TT.hdr.link_target);
xputc('\n');
skippy(TT.hdr.size);
@@ -663,6 +673,16 @@ void tar_main(void)
if (TT.f && strcmp(TT.f, "-"))
TT.fd = xcreate(TT.f, TT.fd*(O_WRONLY|O_CREAT|O_TRUNC), 0666);
+ // grab archive inode
+ {
+ struct stat st;
+
+ if (!fstat(TT.fd, &st)) {
+ TT.aino = st.st_ino;
+ TT.adev = st.st_dev;
+ }
+ }
+
// Get destination directory
if (TT.C) xchdir(TT.C);
TT.cwd = xabspath(s = xgetcwd(), 1);
diff --git a/toys/posix/id.c b/toys/posix/id.c
index cf30ae74..db3cc317 100644
--- a/toys/posix/id.c
+++ b/toys/posix/id.c
@@ -15,7 +15,7 @@ config ID
bool "id"
default y
help
- usage: id [-nGgru]
+ usage: id [-nGgru] [USER...]
Print user and group ID.