changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: Fix directory heuristic for long file names.

changeset 7429: 1dd6759b578b
parent 7428: fe7fc19b1e64
child 7430: 88a2f67638e2
author: Ori Bernstein <ori@eigenstate.org>
date: Tue, 05 Nov 2019 10:48:51 -0800
files: sys/src/cmd/tar.c
description: Fix directory heuristic for long file names.

Tar specifies that a filename ending with '/' is a directory. We were
incorrectly looking at the short name. This meant that when we have long
filenames with a '/' at the 100th character, we would decide it was a
directory.

This change uses the long name when deciding the size for extraction,
and trusts the header size when just skipping forward in the stream.
     1.1--- a/sys/src/cmd/tar.c
     1.2+++ b/sys/src/cmd/tar.c
     1.3@@ -516,11 +516,11 @@ name(Hdr *hp)
     1.4 }
     1.5 
     1.6 static int
     1.7-isdir(Hdr *hp)
     1.8+isdir(Hdr *hp, char *name)
     1.9 {
    1.10 	/* the mode test is ugly but sometimes necessary */
    1.11 	return hp->linkflag == LF_DIR ||
    1.12-		strrchr(name(hp), '\0')[-1] == '/' ||
    1.13+		strrchr(name, '\0')[-1] == '/' ||
    1.14 		(strtoul(hp->mode, nil, 8)&0170000) == 040000;
    1.15 }
    1.16 
    1.17@@ -605,9 +605,9 @@ hdrsize(Hdr *hp)
    1.18  * return the number of bytes recorded in the archive.
    1.19  */
    1.20 static Off
    1.21-arsize(Hdr *hp)
    1.22+arsize(Hdr *hp, char *fname)
    1.23 {
    1.24-	if(isdir(hp) || islink(hp->linkflag))
    1.25+	if(isdir(hp, fname) || islink(hp->linkflag))
    1.26 		return 0;
    1.27 	return hdrsize(hp);
    1.28 }
    1.29@@ -651,7 +651,7 @@ readhdr(int ar)
    1.30 		} while (hdrcksum == -1 || chksum(hp) != hdrcksum);
    1.31 		fprint(2, "found %s\n", name(hp));
    1.32 	}
    1.33-	nexthdr += Tblock*(1 + BYTES2TBLKS(arsize(hp)));
    1.34+	nexthdr += Tblock*(1 + BYTES2TBLKS(hdrsize(hp)));
    1.35 	return hp;
    1.36 }
    1.37 
    1.38@@ -670,7 +670,7 @@ putfullname(Hdr *hp, char *name)
    1.39 	char *sl, *osl;
    1.40 	String *slname = nil;
    1.41 
    1.42-	if (isdir(hp)) {
    1.43+	if (isdir(hp, name)) {
    1.44 		slname = s_new();
    1.45 		s_append(slname, name);
    1.46 		s_append(slname, "/");		/* posix requires this */
    1.47@@ -898,7 +898,7 @@ replace(char **argv)
    1.48 	if (usefile && !docreate) {
    1.49 		/* skip quickly to the end */
    1.50 		while ((hp = readhdr(ar)) != nil) {
    1.51-			bytes = arsize(hp);
    1.52+			bytes = hdrsize(hp);
    1.53 			for (blksleft = BYTES2TBLKS(bytes);
    1.54 			     blksleft > 0 && getblkrd(ar, Justnxthdr) != nil;
    1.55 			     blksleft -= blksread) {
    1.56@@ -1147,10 +1147,10 @@ extract1(int ar, Hdr *hp, char *fname)
    1.57 	long mtime = strtol(hp->mtime, nil, 8);
    1.58 	ulong mode = strtoul(hp->mode, nil, 8) & 0777;
    1.59 	Off bytes = hdrsize(hp);		/* for printing */
    1.60-	ulong blksleft = BYTES2TBLKS(arsize(hp));
    1.61+	ulong blksleft = BYTES2TBLKS(arsize(hp, fname));
    1.62 
    1.63 	/* fiddle name, figure out mode and blocks */
    1.64-	if (isdir(hp)) {
    1.65+	if (isdir(hp, fname)) {
    1.66 		mode |= DMDIR|0700;
    1.67 		dir = 1;
    1.68 	}
    1.69@@ -1200,7 +1200,7 @@ skip(int ar, Hdr *hp, char *fname)
    1.70 	ulong blksleft, blksread;
    1.71 	Hdr *hbp;
    1.72 
    1.73-	for (blksleft = BYTES2TBLKS(arsize(hp)); blksleft > 0;
    1.74+	for (blksleft = BYTES2TBLKS(arsize(hp, fname)); blksleft > 0;
    1.75 	     blksleft -= blksread) {
    1.76 		hbp = getblkrd(ar, Justnxthdr);
    1.77 		if (hbp == nil)
    1.78@@ -1226,7 +1226,7 @@ getname(int ar, Hdr *hp)
    1.79 	fname = name(hp);
    1.80 	if(hp->linkflag == LF_LONGNAME){
    1.81 		p = namebuf;
    1.82-		for (blksleft = BYTES2TBLKS(arsize(hp)); blksleft > 0;
    1.83+		for (blksleft = BYTES2TBLKS(hdrsize(hp)); blksleft > 0;
    1.84 		     blksleft -= blksread) {
    1.85 			hp = getblkrd(ar, Alldata);
    1.86 			if (hp == nil)