bsdtar breakage on 5.3-BETA2

Tim Kientzle kientzle at freebsd.org
Sat Sep 4 14:22:29 PDT 2004


Will Froning wrote:
> 
> On a FBSD4.10 box I have created a tar file of a users home directory
> and then copied it over to a 5.3-BETA2 box (MD5 checksums match).
>
 > [ ... file with long name gets reported as a dir instead of regular 
file ....]
 >

Good catch!  The code for handling certain
very old tar archives was getting confused
by the long filename extensions.

The attached patch fixes it for me.
If you have a chance, apply it to
src/lib/libarchive and then rebuild
both libarchive and src/usr.bin/tar and
let me know if this fixes it for you as well.

Tim
-------------- next part --------------
--- libarchive-current/archive_read_support_format_tar.c	Wed Aug 25 20:25:58 2004
+++ libarchive/archive_read_support_format_tar.c	Sat Sep  4 13:59:40 2004
@@ -351,12 +351,33 @@
 {
 	struct stat st;
 	struct tar *tar;
+	const char *p;
+	int r;
+	size_t l;
 
 	memset(&st, 0, sizeof(st));
 	tar = *(a->pformat_data);
 	tar->entry_offset = 0;
 
-	return (tar_read_header(a, tar, entry, &st));
+	r = tar_read_header(a, tar, entry, &st);
+
+	if (r == ARCHIVE_OK) {
+		/*
+		 * "Regular" entry with trailing '/' is really
+		 * directory: This is needed for certain old tar
+		 * variants and even for some broken newer ones.
+		 */
+		p = archive_entry_pathname(entry);
+		l = strlen(p);
+		if (S_ISREG(st.st_mode) && p[l-1] == '/') {
+			st.st_mode &= ~S_IFMT;
+			st.st_mode |= S_IFDIR;
+		}
+
+		/* Copy the final stat data into the entry. */
+		archive_entry_copy_stat(entry, &st);
+	}
+	return (r);
 }
 
 static int
@@ -421,8 +442,6 @@
 	ssize_t bytes;
 	int err;
 	const void *h;
-	const char *p;
-	size_t l;
 	const struct archive_entry_header_ustar *header;
 
 	/* Read 512-byte header record */
@@ -513,17 +532,9 @@
 			a->archive_format_name = "tar (non-POSIX)";
 			err = header_old_tar(a, tar, entry, st, h);
 		}
-
-		/* "Regular" entry with trailing '/' is really directory. */
-		p = archive_entry_pathname(entry);
-		l = strlen(p);
-		if (S_ISREG(st->st_mode) && p[l-1] == '/') {
-			st->st_mode &= ~S_IFMT;
-			st->st_mode |= S_IFDIR;
-		}
 	}
-	archive_entry_copy_stat(entry, st);
 	--tar->header_recursion_depth;
+
 	return (err);
 }
 


More information about the freebsd-current mailing list