From f2edc776dc6e87330780fdf1e31940fe0b19e74f Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 16 Oct 2022 07:22:57 -0500 Subject: [PATCH] Make --xform work on archive creation side, with some tests. --- tests/tar.test | 46 ++++++++++++++++++++++++++++++++++++++++++---- toys/posix/sed.c | 7 ++++--- toys/posix/tar.c | 40 ++++++++++++++++++++-------------------- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/tests/tar.test b/tests/tar.test index df63c2ff..43005a44 100755 --- a/tests/tar.test +++ b/tests/tar.test @@ -32,6 +32,11 @@ function LST() tar tv "$@" | sed 's/[ \t][ \t]*/ /g' } +function LST2() +{ + LST | sed 's/^.* 23:31 //' +} + # Check that stored empty file is binary identical and decodes as expected. touch file testing "store file" "$TAR file | SUM 3" \ @@ -318,16 +323,49 @@ testing "--strip" "$TAR one | tar t --strip=2 --show-transformed | grep six" \ "three/four/five/six\n" "" "" # toybox tar --xform depends on toybox sed -sed --tarxform '' /dev/null || SKIP=99 -testing "--xform" "$TAR one --xform=s@three/four/@zero@ | tar t | grep six" \ +[ -z "$TEST_HOST" ] && ! sed --tarxform '' /dev/null && SKIP=99 + +mkdir uno +ln -s tres uno/dos +touch uno/tres +ln uno/tres uno/quatro +testing 'xform S' \ + "$TAR --no-recursion uno uno/{dos,tres,quatro} --xform 's/uno/one/S;s/dos/two/S;s/tres/three/S;s/quatro/four/S' | LST2" \ + "one/\none/two -> tres\none/three\none/four link to one/three\n" "" "" + +testing 'xform flags=rh starts with all disabled' \ + "$TAR --no-recursion uno uno/{dos,tres,quatro} --xform 's/uno/one/;flags=rh;s/dos/two/;s/tres/three/;s/quatro/four/' | LST2" \ + "one/\none/two -> tres\none/three\none/four link to one/three\n" "" "" + +testing 'xform flags=rHhsS toggles' \ + "$TAR --no-recursion uno uno/{dos,tres,quatro} --xform 's/uno/one/;flags=rHhsS;s/dos/two/;s/tres/three/;s/quatro/four/' | LST2" \ + "one/\none/two -> tres\none/three\none/four link to one/three\n" "" "" + +testing 'xform flags= is not a delta from previous' \ + "$TAR --no-recursion uno uno/{dos,tres,quatro} --xform 'flags=s;flags=rh;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' | LST2" \ + "one/\none/two -> tres\none/three\none/four link to one/three\n" "" "" + +testing 'xform H' \ + "$TAR --no-recursion uno uno/{dos,tres,quatro} --xform 'flags=rsH;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' | LST2" \ + "one/\none/two -> three\none/three\none/four link to uno/tres\n" "" "" + +testing 'xform R' \ + "$TAR --no-recursion uno uno/{dos,tres,quatro} --xform 'flags=rshR;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' | LST2" \ + "uno/\nuno/dos -> three\nuno/tres\nuno/quatro link to one/three\n" "" "" + +testing "xform path" "$TAR one --xform=s@three/four/@zero@ | tar t | grep six" \ "one/two/zerofive/six\n" "" "" -rm -rf one + +testing "xform trailing slash special case" \ + "$TAR --xform 's#^.+/##x' one/two/three/four/five | tar t" 'five/\nsix\n' '' '' +rm -rf uno SKIP=0 +rm -rf one testing '-P' "$TAR -P --no-recursion -C / /// .. | SUM 3" \ "a3e94211582da121845d823374d8f41ead62d7bd\n" "" "" -testing 'without -P' "$TAR --no-recursion -C / /// .. | SUM 3" \ +testing 'without -P' "$TAR --no-recursion -C / /// .. 2>/dev/null | SUM 3" \ "077d03243e247b074806904885e6da272fd5857a\n" "" "" if false diff --git a/toys/posix/sed.c b/toys/posix/sed.c index 7441a856..67795af8 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -474,7 +474,7 @@ static void sed_line(char **pline, long plen) // xform matches ending in / aren't allowed to match entire line if ((command->sflags & SFLAG_slash) && mlen==len) { - while (len && line[--len]=='/') bonk++; + while (len && ++bonk && line[--len]=='/'); continue; } @@ -793,9 +793,10 @@ static void parse_pattern(char **pline, long len) if (!*line) return; if (FLAG(tarxform) && strstart(&line, "flags=")) { + TT.xflags = 7; while (0<=(i = stridx("rRsShH", *line))) { - if (i&1) TT.xflags |= i>>1; - else TT.xflags &= ~(i>>1); + if (i&1) TT.xflags |= 1<<(i>>1); + else TT.xflags &= ~(1<<(i>>1)); line++; } continue; diff --git a/toys/posix/tar.c b/toys/posix/tar.c index f75b33fd..44a3b3b9 100644 --- a/toys/posix/tar.c +++ b/toys/posix/tar.c @@ -236,7 +236,7 @@ static int add_to_tar(struct dirtree *node) } // Consume the 1 extra byte alocated in dirtree_path() - if (S_ISDIR(st->st_mode) && name[i-1] != '/') strcat(name, "/"); + if (S_ISDIR(st->st_mode) && lnk[-1] != '/') strcpy(lnk, "/"); // remove leading / and any .. entries from saved name if (!FLAG(P)) { @@ -254,7 +254,6 @@ static int add_to_tar(struct dirtree *node) } if (!*hname) hname = "./"; } - if (!*hname) goto done; if (TT.warn && hname != name) { @@ -263,6 +262,7 @@ static int add_to_tar(struct dirtree *node) TT.warn = 0; } + // Override dentry data from command line and fill out header data if (TT.owner) st->st_uid = TT.ouid; if (TT.group) st->st_gid = TT.ggid; if (TT.mode) st->st_mode = string_to_mode(TT.mode, st->st_mode); @@ -275,19 +275,13 @@ static int add_to_tar(struct dirtree *node) ITOO(hdr.mtime, st->st_mtime); strcpy(hdr.magic, "ustar "); - xfname = xform(&hname, 'r'); - strncpy(hdr.name, hname, sizeof(hdr.name)); - - // Hard link or symlink? i=0 neither, i=1 hardlink, i=2 symlink - // Are there hardlinks to a non-directory entry? + lnk = 0; if (st->st_nlink>1 && !S_ISDIR(st->st_mode)) { // Have we seen this dev&ino before? for (i = 0; ist_ino; TT.hlx[TT.hlc].di.dev = st->st_dev; TT.hlc++; - i = 0; } - } else i = 0; + } + + xfname = xform(&hname, 'r'); + strncpy(hdr.name, hname, sizeof(hdr.name)); - // Handle file types - if (i || S_ISLNK(st->st_mode)) { - hdr.type = '1'+!i; - if (!i && !(lnk = xreadlink(name))) { + // Handle file types: 0=reg, 1=hardlink, 2=sym, 3=chr, 4=blk, 5=dir, 6=fifo + if (lnk || S_ISLNK(st->st_mode)) { + hdr.type = '1'+!lnk; + if (lnk) { + if (!xform(&lnk, 'h')) lnk = xstrdup(lnk); + } else if (!(lnk = xreadlink(name))) { perror_msg("readlink"); goto done; - } + } else xform(&lnk, 's'); + maybe_prefix_block(lnk, sizeof(hdr.link), 'K'); strncpy(hdr.link, lnk, sizeof(hdr.link)); - if (!i) free(lnk); + free(lnk); } else if (S_ISREG(st->st_mode)) { hdr.type = '0'; ITOO(hdr.size, st->st_size); @@ -833,7 +832,8 @@ static void unpack_tar(char *first) lc->tm_mday, lc->tm_hour, lc->tm_min, FLAG(full_time) ? perm : ""); } printf("%s", name); - if (TT.hdr.link_target) printf(" -> %s", TT.hdr.link_target); + if (TT.hdr.link_target) + printf(" %s %s", tar.type=='2' ? "->" : "link to", TT.hdr.link_target); xputc('\n'); skippy(TT.hdr.size); } else { -- 2.39.2