aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/tar.test106
-rw-r--r--toys/pending/tar.c66
2 files changed, 46 insertions, 126 deletions
diff --git a/tests/tar.test b/tests/tar.test
index 50a94e60..31aee386 100644
--- a/tests/tar.test
+++ b/tests/tar.test
@@ -1,104 +1,14 @@
#!/bin/bash
-# Copyright 2014 Divya Kothari <divya.s.kothari@gmail.com>
-# Copyright 2014 Naha Maggu <maggu.neha@gmail.com>
-
[ -f testing.sh ] && . testing.sh
#testing "name" "command" "result" "infile" "stdin"
-#Creating dir
-mkdir dir/dir1 -p
-echo "This is testdata" > dir/dir1/file
-testing "tgz - compession, extraction and data validation" "tar -czf dir.tgz dir/ && [ -e dir.tgz ] && echo 'yes'; rm -rf dir; tar -xf dir.tgz && [ -f dir/dir1/file ] && cat dir/dir1/file; rm -rf dir.tgz" "yes\nThis is testdata\n" "" ""
-
-#Creating dir
-mkdir dir/dir1 -p
-echo "This is testdata" > dir/dir1/file
-testing "tar.gz - compession, extraction and data validation" "tar -czf dir.tar.gz dir/ && [ -e dir.tar.gz ] && echo 'yes'; rm -rf dir; tar -xf dir.tar.gz && [ -f dir/dir1/file ] && cat dir/dir1/file; rm -rf dir.tar.gz" "yes\nThis is testdata\n" "" ""
-
-#Creating dir
-mkdir dir/dir1 -p
-echo "This is testdata" > dir/dir1/file
-testing "verbose compression" "tar -cvzf dir.tgz dir/; rm -rf dir.tgz" "dir/\ndir/dir1/\ndir/dir1/file\n" "" ""
-rm -rf dir/
-
-#creating test file
-dd if=/dev/zero of=testFile ibs=4096 obs=4096 count=1000 2>/dev/null
-testing "- compession and extraction of a file" "tar -czf testFile.tgz testFile && [ -e testFile.tgz ] && echo 'yes'; rm -rf testFile; tar -xf testFile.tgz && [ -f testFile ] && echo 'yes'; rm -rf testFile.tgz" "yes\nyes\n" "" ""
-
-#creating empty test file
-touch testFile
-testing "- compession and extraction of a empty file" "tar -czf testFile.tgz testFile && [ -e testFile.tgz ] && echo 'yes'; rm -rf testFile; tar -xf testFile.tgz && [ -f testFile ] && echo 'yes'; rm -rf testFile.tgz" "yes\nyes\n" "" ""
-
-#Creating dir
-mkdir dir/dir1 -p
-touch dir/dir1/file1 dir/dir1/file2 dir/dir1/file3 dir/dir1/file4
-testing "-t option" "tar -czf dir.tar.gz dir/; rm -rf dir; tar -tf dir.tar.gz | sort; rm -rf dir.tar.gz" "dir/\ndir/dir1/\ndir/dir1/file1\ndir/dir1/file2\ndir/dir1/file3\ndir/dir1/file4\n" "" ""
-rm -rf dir/
-
-#Creating nested directory
-mkdir -p dir/dir1 dir/dir2 dir/dir3 dir/dir4
-echo "This is testdata" > dir/dir1/file; echo "Dont exclude me" > dir/dir3/file1 ;
-echo "Exclude me" > dir/dir3/file2 ; echo "YO" > dir/dir4/file1 ; echo "Hello" >dir/dir4/file2; echo "Dont" > dir/dir2/file1
-echo -ne "dir/dir4\ndir/dir3/file2\n" > exclude_file
-testing "create with files excluded : -X" "tar -czf dir.tgz dir/ -X exclude_file ; rm -rf dir ; tar -tf dir.tgz | sort; rm -rf dir.tgz " "dir/\ndir/dir1/\ndir/dir1/file\ndir/dir2/\ndir/dir2/file1\ndir/dir3/\ndir/dir3/file1\n" "" ""
-rm -rf exclude_file
-
-#Creating nested directory
-mkdir dir/dir1 -p ; mkdir dir/dir2 ; mkdir dir/dir3 ; mkdir dir/dir4
-echo "This is testdata" > dir/dir1/file
-echo "Dont exclude me" > dir/dir3/file1 ; echo "Exclude me" > dir/dir3/file2 ; echo "YO" > dir/dir4/file1 ; echo "Hello" >dir/dir4/file2; echo "Dont" > dir/dir2/file1
-testing "with pattern --exclude" "tar --exclude=dir/dir3/* -czf dir.tgz dir/ ; rm -rf dir ; tar -tf dir.tgz | sort; rm -rf dir.tgz " "dir/\ndir/dir1/\ndir/dir1/file\ndir/dir2/\ndir/dir2/file1\ndir/dir3/\ndir/dir4/\ndir/dir4/file1\ndir/dir4/file2\n" "" ""
-
-#Creating directory to be compressed
-mkdir dir/dir1 -p
-echo "This is testdata" > dir/dir1/file
-mkdir temp
-testing "extract with -C Dir" "tar -czf dir.tgz dir/ ;rm -rf dir ;tar -xf dir.tgz -C temp/ ; [ -e temp/dir ] && echo 'yes' ; rm -rf dir dir.tgz" "yes\n" "" ""
-rm -rf temp
-
-#Creating nested directory
-mkdir dir/dir1 -p ; mkdir dir/dir2 ; mkdir dir/dir3 ; mkdir dir/dir4 ; mkdir temp_dir
-echo "dir1/file" > dir/dir1/file ; echo "temp_dir/file" > temp_dir/file
-echo "dir3/file1" > dir/dir3/file1 ; echo "dir3/file2" > dir/dir3/file2 ; echo "YO" > dir/dir4/file1 ; echo "Hello" >dir/dir4/file2; echo "dir2/file1" > dir/dir2/file1
-echo "temp_dir/file" > exclude_file
-testing "create with extra files/directory included : -T" "tar -czf dir.tgz dir/ -T exclude_file ; rm -rf dir ; tar -tf dir.tgz | sort; rm -rf dir.tgz " "dir/\ndir/dir1/\ndir/dir1/file\ndir/dir2/\ndir/dir2/file1\ndir/dir3/\ndir/dir3/file1\ndir/dir3/file2\ndir/dir4/\ndir/dir4/file1\ndir/dir4/file2\ntemp_dir/file\n" "" ""
-rm -rf exclude_file
-rm -rf temp_dir
-
-#Creating dir
-mkdir dir/dir1 -p
-echo "Inside dir/dir1" > dir/dir1/file ; echo "Hello Inside dir" > dir/file
-testing "extract to STDOUT : -O" " tar -czf dir.tgz dir/ ; rm -rf dir ; tar -xf dir.tgz -O ; [ -e 'Inside dir/dir1/\nHello Inside dir\n' ] && echo 'yes'; rm -rf dir.tgz " "" "" ""
-
-#Creating short filename
-f="filename_with_100_chars_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-echo "This is testdata" > $f
-testing "shortname filename" "tar -cf testFile.tar $f && [ -e testFile.tar ] && echo 'yes'; rm -f $f; tar -xf testFile.tar && [ -f $f ] && cat $f && strings testFile.tar | grep -o LongLink; rm -f testFile.tar; rm -f $f" "yes\nThis is testdata\n" "" ""
-
-#Creating long filename
-f="filename_with_101_chars_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-echo "This is testdata" > $f
-testing "longname filename" "tar -cf testFile.tar $f && [ -e testFile.tar ] && echo 'yes'; rm -f $f; tar -xf testFile.tar && [ -f $f ] && cat $f && strings testFile.tar | grep -o LongLink; rm -f testFile.tar; rm -f $f" "yes\nThis is testdata\nLongLink\n" "" ""
-
-#Creating long pathname
-d="dirname_with_50_chars_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-f="filename_with_50_chars_xxxxxxxxxxxxxxxxxxxxxxxxxxx"
-mkdir $d
-echo "This is testdata" > $d/$f
-testing "longname pathname" "tar -cf testFile.tar $d/$f && [ -e testFile.tar ] && echo 'yes'; rm -rf $d; tar -xf testFile.tar && [ -f $d/$f ] && cat $d/$f && strings testFile.tar | grep -o LongLink; rm -f testFile.tar; rm -rf $d" "yes\nThis is testdata\nLongLink\n" "" ""
-
-# gzip
-rm -rf d
-mkdir d
-echo "hello world" > d/f
-testing "gzip compression" "tar zcf f d && file f | grep -q gzip && echo y ; rm -rf d ; tar xf f && cat d/f" "y\nhello world\n" "" ""
-testing "gzip decompression" "tar xf $FILES/tar/tar.tgz && cat dir/file" "hello world\n" "" ""
-
-# bzip2
-rm -rf d
-mkdir d
-echo "hello world" > d/f
-testing "bzip2 compression" "tar jcf f d && file f | grep -q bzip2 && echo y ; rm -rf d ; tar xf f && cat d/f" "y\nhello world\n" "" ""
-testing "bzip2 decompression" "tar xf $FILES/tar/tar.tbz2 && cat dir/file" "hello world\n" "" ""
+TARSUM='--owner root --group root | head -c $((3*512)) | sha1sum | sed "s/ .*//"'
+touch -t 198001010101 file
+testing "create file" "tar c file $TARSUM" \
+ "d551292408833aa5e9db32c0d14d7f32e7e96882\n" "" ""
+mkdir walrus
+touch -t 198001010101 dir
+testing "create dir" "tar c dir $TARSUM" \
+ "c4e630d9c89f4f20d603a6f71ff4410ab56fe965\n" "" ""
diff --git a/toys/pending/tar.c b/toys/pending/tar.c
index 18a078e1..0e7a49f9 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)*(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, "&(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(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))
todo: support .txz
todo: directory timestamps not set on extract
@@ -47,14 +47,14 @@ config TAR
GLOBALS(
char *f, *C;
struct arg_list *T, *X;
- char *to_command;
+ char *to_command, *owner, *group;
struct arg_list *exclude;
// exc is an argument but inc isn't?
struct double_list *incl, *excl, *seen;
void *inodes;
char *cwd;
- int fd;
+ int fd, ouid, ggid;
// Parsed information about a tar header.
struct {
@@ -204,7 +204,7 @@ static void add_file(char **nam, struct stat *st)
char *c, *p, *name = *nam, *lnk, *hname;
static int warn = 1;
-// TODO what/why? fnmatch()?
+// TODO TT.incl defaults to --anchored TT.excl defaults to --no-anchored
for (p = name; *p; p++)
if ((p == name || p[-1] == '/') && *p != '/' && filter(TT.excl, p)) return;
@@ -224,6 +224,9 @@ static void add_file(char **nam, struct stat *st)
warn = 0;
}
+ if (TT.owner) st->st_uid = TT.ouid;
+ if (TT.group) st->st_gid = TT.ggid;
+
memset(&hdr, 0, sizeof(hdr));
strncpy(hdr.name, hname, sizeof(hdr.name));
ITOO(hdr.mode, st->st_mode &07777);
@@ -234,13 +237,13 @@ static void add_file(char **nam, struct stat *st)
// Hard link or symlink?
i = !!S_ISLNK(st->st_mode);
+// TODO: hardlink to symlink?
if (i || (node = seen_inode(&TT.inodes, st, hname))) {
// TODO: test preserve symlink ownership
hdr.type = '1'+i;
if (!(lnk = i ? xreadlink(name) : node->arg)) return perror_msg("readlink");
// TODO: does this need NUL terminator?
- if (strlen(lnk) > sizeof(hdr.link))
- write_longname(lnk, 'K'); //write longname LINK
+ if (strlen(lnk) > sizeof(hdr.link)) write_longname(lnk, 'K');
strncpy(hdr.link, lnk, sizeof(hdr.link));
if (i) free(lnk);
} else if (S_ISREG(st->st_mode)) {
@@ -255,16 +258,18 @@ static void add_file(char **nam, struct stat *st)
ITOO(hdr.minor, dev_minor(st->st_rdev));
} else return error_msg("unknown file type '%o'", st->st_mode & S_IFMT);
- if (strlen(hname) > sizeof(hdr.name))
- write_longname(hname, 'L'); //write longname NAME
+ if (strlen(hname) > sizeof(hdr.name)) write_longname(hname, 'L');
strcpy(hdr.magic, "ustar ");
- if ((pw = bufgetpwuid(st->st_uid)))
- snprintf(hdr.uname, sizeof(hdr.uname), "%s", pw->pw_name);
- else sprintf(hdr.uname, "%d", st->st_uid);
-
- if ((gr = bufgetgrgid(st->st_gid)))
- snprintf(hdr.gname, sizeof(hdr.gname), "%s", gr->gr_name);
- else sprintf(hdr.gname, "%d", st->st_gid);
+ if (!FLAG(numeric_owner)) {
+ if (!TT.owner && !(pw = bufgetpwuid(st->st_uid)))
+ sprintf(hdr.uname, "%d", st->st_uid);
+ else snprintf(hdr.uname, sizeof(hdr.uname), "%s",
+ TT.owner ? TT.owner : pw->pw_name);
+ if (!TT.group && !(gr = bufgetgrgid(st->st_gid)))
+ sprintf(hdr.gname, "%d", st->st_gid);
+ else snprintf(hdr.gname, sizeof(hdr.gname), "%s",
+ TT.group ? TT.group : gr->gr_name);
+ }
itoo(hdr.chksum, sizeof(hdr.chksum)-1, cksum(&hdr));
hdr.chksum[7] = ' ';
@@ -311,13 +316,10 @@ static void extract_to_command(void)
int pipefd[2], status = 0;
pid_t cpid;
- xpipe(pipefd);
if (!S_ISREG(TT.hdr.mode)) return; //only regular files are supported.
- cpid = fork();
- if (cpid == -1) perror_exit("fork");
-
- if (!cpid) { // Child reads from pipe
+ xpipe(pipefd);
+ if (!(cpid = xfork())) { // Child reads from pipe
char buf[64], *argv[4] = {"sh", "-c", TT.to_command, NULL};
setenv("TAR_FILETYPE", "f", 1);
@@ -411,18 +413,24 @@ COPY:
xsendfile_len(TT.fd, dst_fd, TT.hdr.size);
close(dst_fd);
- if (!FLAG(o)) {
+ if (!FLAG(o) && !geteuid()) {
//set ownership..., --no-same-owner, --numeric-owner
uid_t u = TT.hdr.uid;
gid_t g = TT.hdr.gid;
- if (!FLAG(numeric_owner)) {
- struct group *gr = getgrnam(TT.hdr.gname);
+ if (TT.owner) u = TT.ouid;
+ else if (!FLAG(numeric_owner)) {
struct passwd *pw = getpwnam(TT.hdr.uname);
- if (pw) u = pw->pw_uid;
+ if (pw && (TT.owner || !FLAG(numeric_owner))) u = pw->pw_uid;
+ }
+
+ if (TT.group) g = TT.ggid;
+ else if (!FLAG(numeric_owner)) {
+ struct group *gr = getgrnam(TT.hdr.gname);
if (gr) g = gr->gr_gid;
}
- if (!geteuid() && lchown(TT.hdr.name, u, g))
+
+ if (lchown(TT.hdr.name, u, g))
perror_msg("chown %d:%d '%s'", u, g, TT.hdr.name);;
}
@@ -499,7 +507,7 @@ static void unpack_tar(void)
continue;
}
- // At this point, we're writing to the filesystem.
+ // At this point, we have something to output. Convert metadata.
TT.hdr.mode = otoi(tar.mode, sizeof(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));
@@ -508,8 +516,8 @@ static void unpack_tar(void)
TT.hdr.device = dev_makedev(otoi(tar.major, sizeof(tar.major)),
otoi(tar.minor, sizeof(tar.minor)));
- TT.hdr.uname = xstrndup(tar.uname, sizeof(tar.uname));
- TT.hdr.gname = xstrndup(tar.gname, sizeof(tar.gname));
+ TT.hdr.uname = xstrndup(TT.owner ? TT.owner : tar.uname,sizeof(tar.uname));
+ TT.hdr.gname = xstrndup(TT.group ? TT.group : tar.gname,sizeof(tar.gname));
if (!TT.hdr.link_target && *tar.link)
TT.hdr.link_target = xstrndup(tar.link, sizeof(tar.link));
if (!TT.hdr.name) {
@@ -597,6 +605,8 @@ void tar_main(void)
signal(SIGPIPE, SIG_IGN);
if (!geteuid()) toys.optflags |= FLAG_p;
+ if (TT.owner) TT.ouid = xgetuid(TT.owner);
+ if (TT.group) TT.ggid = xgetgid(TT.group);
// Collect file list. Note: trim_list appends to TT.incl when !TT.X
for (;TT.X; TT.X = TT.X->next) do_lines(xopenro(TT.X->arg), '\n', trim_list);