Make --xform work on archive creation side, with some tests.
diff --git a/tests/tar.test b/tests/tar.test
index df63c2f..43005a4 100755
--- a/tests/tar.test
+++ b/tests/tar.test
@@ -32,6 +32,11 @@
   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 @@
   "three/four/five/six\n" "" ""
 
 # toybox tar --xform depends on toybox sed
-sed --tarxform '' </dev/null 2>/dev/null || SKIP=99
-testing "--xform" "$TAR one --xform=s@three/four/@zero@ | tar t | grep six" \
+[ -z "$TEST_HOST" ] && ! sed --tarxform '' </dev/null 2>/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 7441a85..67795af 100644
--- a/toys/posix/sed.c
+++ b/toys/posix/sed.c
@@ -474,7 +474,7 @@
 
         // 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 @@
     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 f75b33f..44a3b3b 100644
--- a/toys/posix/tar.c
+++ b/toys/posix/tar.c
@@ -236,7 +236,7 @@
   }
 
   // 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 @@
     }
     if (!*hname) hname = "./";
   }
-
   if (!*hname) goto done;
 
   if (TT.warn && hname != name) {
@@ -263,6 +262,7 @@
     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 @@
   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; i<TT.hlc; i++) if (same_dev_ino(st, &TT.hlx[i].di)) break;
-    if (i != TT.hlc) {
-      lnk = TT.hlx[i].arg;
-      i = 1;
-    } else {
+    if (i != TT.hlc) lnk = TT.hlx[i].arg;
+    else {
       // first time we've seen it. Store as normal file, but remember it.
       if (!(TT.hlc&255))
         TT.hlx = xrealloc(TT.hlx, sizeof(*TT.hlx)*(TT.hlc+256));
@@ -295,20 +289,25 @@
       TT.hlx[TT.hlc].di.ino = st->st_ino;
       TT.hlx[TT.hlc].di.dev = st->st_dev;
       TT.hlc++;
-      i = 0;
     }
-  } else i = 0;
+  }
 
-  // Handle file types
-  if (i || S_ISLNK(st->st_mode)) {
-    hdr.type = '1'+!i;
-    if (!i && !(lnk = xreadlink(name))) {
+  xfname = xform(&hname, 'r');
+  strncpy(hdr.name, hname, sizeof(hdr.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 @@
           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 {