svn commit: r270661 - head/contrib/libarchive/tar

Andrey V. Elsukov ae at FreeBSD.org
Tue Aug 26 13:11:39 UTC 2014


Author: ae
Date: Tue Aug 26 13:11:38 2014
New Revision: 270661
URL: http://svnweb.freebsd.org/changeset/base/270661

Log:
  Remove leading '/' from hardlink name when removing them from the
  regular file name. This fixes the problem, when bsdtar can not create
  hardlinks to extracted files.
  
  Silence from:	kientzle@
  MFC after:	1 week
  Sponsored by:	Yandex LLC

Modified:
  head/contrib/libarchive/tar/util.c

Modified: head/contrib/libarchive/tar/util.c
==============================================================================
--- head/contrib/libarchive/tar/util.c	Tue Aug 26 11:13:07 2014	(r270660)
+++ head/contrib/libarchive/tar/util.c	Tue Aug 26 13:11:38 2014	(r270661)
@@ -372,6 +372,21 @@ strip_components(const char *p, int elem
 	}
 }
 
+static const char*
+strip_leading_slashes(const char *p)
+{
+
+	/* Remove leading "/../", "//", etc. */
+	while (p[0] == '/' || p[0] == '\\') {
+		if (p[1] == '.' && p[2] == '.' && (
+		    p[3] == '/' || p[3] == '\\')) {
+			p += 3; /* Remove "/..", leave "/" for next pass. */
+		} else
+			p += 1; /* Remove "/". */
+	}
+	return (p);
+}
+
 /*
  * Handle --strip-components and any future path-rewriting options.
  * Returns non-zero if the pathname should not be extracted.
@@ -474,16 +489,7 @@ edit_pathname(struct bsdtar *bsdtar, str
 				p += 2;
 				slashonly = 0;
 			}
-			/* Remove leading "/../", "//", etc. */
-			while (p[0] == '/' || p[0] == '\\') {
-				if (p[1] == '.' && p[2] == '.' &&
-					(p[3] == '/' || p[3] == '\\')) {
-					p += 3; /* Remove "/..", leave "/"
-							 * for next pass. */
-					slashonly = 0;
-				} else
-					p += 1; /* Remove "/". */
-			}
+			p = strip_leading_slashes(p);
 		} while (rp != p);
 
 		if (p != name && !bsdtar->warned_lead_slash) {
@@ -504,6 +510,19 @@ edit_pathname(struct bsdtar *bsdtar, str
 			name = ".";
 		else
 			name = p;
+
+		p = archive_entry_hardlink(entry);
+		if (p != NULL) {
+			rp = strip_leading_slashes(p);
+			if (rp == '\0')
+				return (1);
+			if (rp != p) {
+				char *linkname = strdup(rp);
+
+				archive_entry_copy_hardlink(entry, linkname);
+				free(linkname);
+			}
+		}
 	} else {
 		/* Strip redundant leading '/' characters. */
 		while (name[0] == '/' && name[1] == '/')


More information about the svn-src-all mailing list