bin/86690: bsdtar sparse file problems

Tim Kientzle kientzle at freebsd.org
Sun Oct 2 20:21:22 PDT 2005


Juergen Lock wrote:
> 
> Hmm i just tried it on a 60beta4 vm i still had lying around:
> 
> FreeBSD qemutest.kn-bremen.de 6.0-BETA4 FreeBSD 6.0-BETA4 #0: Sun Sep  4 09:18:09 UTC 2005     root at x64.samsco.home:/usr/obj/usr/src/sys/GENERIC  i386
> 
>  and there it still extracts it to a 1 byte file.  Has this been
> fixed between beta4 and 5?

Juergen,

Try the attached patch against libarchive in 6.0 and let me know if this 
fixes it for you.  Looks like the offset for the very first sparse block
was being ignored.

Tim
-------------- next part --------------
Index: archive_read_support_format_tar.c
===================================================================
RCS file: /home/ncvs/src/lib/libarchive/archive_read_support_format_tar.c,v
retrieving revision 1.36
diff -u -r1.36 archive_read_support_format_tar.c
--- archive_read_support_format_tar.c	24 Sep 2005 21:15:00 -0000	1.36
+++ archive_read_support_format_tar.c	3 Oct 2005 03:17:35 -0000
@@ -450,24 +450,34 @@
 	struct sparse_block *p;
 
 	tar = *(a->pformat_data);
-	if (tar->entry_bytes_remaining > 0) {
-		bytes_read = (a->compression_read_ahead)(a, buff, 1);
-		if (bytes_read <= 0)
-			return (ARCHIVE_FATAL);
-		if (bytes_read > tar->entry_bytes_remaining)
-			bytes_read = tar->entry_bytes_remaining;
+	if (tar->sparse_list != NULL) {
+		/* Remove exhausted entries from sparse list. */
 		while (tar->sparse_list != NULL &&
 		    tar->sparse_list->remaining == 0) {
 			p = tar->sparse_list;
 			tar->sparse_list = p->next;
 			free(p);
-			if (tar->sparse_list != NULL)
-				tar->entry_offset = tar->sparse_list->offset;
 		}
+		if (tar->sparse_list == NULL) {
+			/* We exhausted the entire sparse list. */
+			tar->entry_bytes_remaining = 0;
+		}
+	}
+
+	if (tar->entry_bytes_remaining > 0) {
+		bytes_read = (a->compression_read_ahead)(a, buff, 1);
+		if (bytes_read <= 0)
+			return (ARCHIVE_FATAL);
+		if (bytes_read > tar->entry_bytes_remaining)
+			bytes_read = tar->entry_bytes_remaining;
 		if (tar->sparse_list != NULL) {
+			/* Don't read more than is available in the
+			 * current sparse block. */
 			if (tar->sparse_list->remaining < bytes_read)
 				bytes_read = tar->sparse_list->remaining;
+			tar->entry_offset = tar->sparse_list->offset;
 			tar->sparse_list->remaining -= bytes_read;
+			tar->sparse_list->offset += bytes_read;
 		}
 		*size = bytes_read;
 		*offset = tar->entry_offset;


More information about the freebsd-bugs mailing list