shithub: riscv

Download patch

ref: d72a4043993d02b56873dfe40767cef9336685fc
parent: 8b79ad59f14c4ced6ae2af6277d94b3265bd211d
author: Ori Bernstein <[email protected]>
date: Tue Nov 5 05:48:51 EST 2019

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.

--- a/sys/src/cmd/tar.c
+++ b/sys/src/cmd/tar.c
@@ -516,11 +516,11 @@
 }
 
 static int
-isdir(Hdr *hp)
+isdir(Hdr *hp, char *name)
 {
 	/* the mode test is ugly but sometimes necessary */
 	return hp->linkflag == LF_DIR ||
-		strrchr(name(hp), '\0')[-1] == '/' ||
+		strrchr(name, '\0')[-1] == '/' ||
 		(strtoul(hp->mode, nil, 8)&0170000) == 040000;
 }
 
@@ -605,9 +605,9 @@
  * return the number of bytes recorded in the archive.
  */
 static Off
-arsize(Hdr *hp)
+arsize(Hdr *hp, char *fname)
 {
-	if(isdir(hp) || islink(hp->linkflag))
+	if(isdir(hp, fname) || islink(hp->linkflag))
 		return 0;
 	return hdrsize(hp);
 }
@@ -651,7 +651,7 @@
 		} while (hdrcksum == -1 || chksum(hp) != hdrcksum);
 		fprint(2, "found %s\n", name(hp));
 	}
-	nexthdr += Tblock*(1 + BYTES2TBLKS(arsize(hp)));
+	nexthdr += Tblock*(1 + BYTES2TBLKS(hdrsize(hp)));
 	return hp;
 }
 
@@ -670,7 +670,7 @@
 	char *sl, *osl;
 	String *slname = nil;
 
-	if (isdir(hp)) {
+	if (isdir(hp, name)) {
 		slname = s_new();
 		s_append(slname, name);
 		s_append(slname, "/");		/* posix requires this */
@@ -898,7 +898,7 @@
 	if (usefile && !docreate) {
 		/* skip quickly to the end */
 		while ((hp = readhdr(ar)) != nil) {
-			bytes = arsize(hp);
+			bytes = hdrsize(hp);
 			for (blksleft = BYTES2TBLKS(bytes);
 			     blksleft > 0 && getblkrd(ar, Justnxthdr) != nil;
 			     blksleft -= blksread) {
@@ -1147,10 +1147,10 @@
 	long mtime = strtol(hp->mtime, nil, 8);
 	ulong mode = strtoul(hp->mode, nil, 8) & 0777;
 	Off bytes = hdrsize(hp);		/* for printing */
-	ulong blksleft = BYTES2TBLKS(arsize(hp));
+	ulong blksleft = BYTES2TBLKS(arsize(hp, fname));
 
 	/* fiddle name, figure out mode and blocks */
-	if (isdir(hp)) {
+	if (isdir(hp, fname)) {
 		mode |= DMDIR|0700;
 		dir = 1;
 	}
@@ -1200,7 +1200,7 @@
 	ulong blksleft, blksread;
 	Hdr *hbp;
 
-	for (blksleft = BYTES2TBLKS(arsize(hp)); blksleft > 0;
+	for (blksleft = BYTES2TBLKS(arsize(hp, fname)); blksleft > 0;
 	     blksleft -= blksread) {
 		hbp = getblkrd(ar, Justnxthdr);
 		if (hbp == nil)
@@ -1226,7 +1226,7 @@
 	fname = name(hp);
 	if(hp->linkflag == LF_LONGNAME){
 		p = namebuf;
-		for (blksleft = BYTES2TBLKS(arsize(hp)); blksleft > 0;
+		for (blksleft = BYTES2TBLKS(hdrsize(hp)); blksleft > 0;
 		     blksleft -= blksread) {
 			hp = getblkrd(ar, Alldata);
 			if (hp == nil)