From a46c33df050c896ff5550fca1f445264482c9d40 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <kientzle@FreeBSD.org>
Date: Tue, 8 Nov 2005 07:41:03 +0000
Subject: [PATCH] Fine-tune the format detection for CPIO and ISO9660
 sub-types. This has no impact on the actual operation, it just fixes some
 inaccuracies in the format code and description reported back to the caller.

---
 lib/libarchive/archive.h.in                   |  4 ++++
 .../archive_read_support_format_cpio.c        | 20 +++++++++++++------
 .../archive_read_support_format_iso9660.c     | 11 ++++++----
 3 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/lib/libarchive/archive.h.in b/lib/libarchive/archive.h.in
index 61a076cd41df..666917c9055f 100644
--- a/lib/libarchive/archive.h.in
+++ b/lib/libarchive/archive.h.in
@@ -132,6 +132,10 @@ typedef int	archive_close_callback(struct archive *, void *_client_data);
 #define	ARCHIVE_FORMAT_BASE_MASK		0xff0000U
 #define	ARCHIVE_FORMAT_CPIO			0x10000
 #define	ARCHIVE_FORMAT_CPIO_POSIX		(ARCHIVE_FORMAT_CPIO | 1)
+#define	ARCHIVE_FORMAT_CPIO_BIN_LE		(ARCHIVE_FORMAT_CPIO | 2)
+#define	ARCHIVE_FORMAT_CPIO_BIN_BE		(ARCHIVE_FORMAT_CPIO | 3)
+#define	ARCHIVE_FORMAT_CPIO_SVR4_NOCRC		(ARCHIVE_FORMAT_CPIO | 4)
+#define	ARCHIVE_FORMAT_CPIO_SVR4_CRC		(ARCHIVE_FORMAT_CPIO | 5)
 #define	ARCHIVE_FORMAT_SHAR			0x20000
 #define	ARCHIVE_FORMAT_SHAR_BASE		(ARCHIVE_FORMAT_SHAR | 1)
 #define	ARCHIVE_FORMAT_SHAR_DUMP		(ARCHIVE_FORMAT_SHAR | 2)
diff --git a/lib/libarchive/archive_read_support_format_cpio.c b/lib/libarchive/archive_read_support_format_cpio.c
index e74ca3a51083..65b4316492e6 100644
--- a/lib/libarchive/archive_read_support_format_cpio.c
+++ b/lib/libarchive/archive_read_support_format_cpio.c
@@ -317,9 +317,6 @@ header_newc(struct archive *a, struct cpio *cpio, struct stat *st,
 	const struct cpio_newc_header *header;
 	size_t bytes;
 
-	a->archive_format = ARCHIVE_FORMAT_CPIO;
-	a->archive_format_name = "ASCII cpio (SVR4 with no CRC)";
-
 	/* Read fixed-size portion of header. */
 	bytes = (a->compression_read_ahead)(a, &h, sizeof(struct cpio_newc_header));
 	if (bytes < sizeof(struct cpio_newc_header))
@@ -328,6 +325,17 @@ header_newc(struct archive *a, struct cpio *cpio, struct stat *st,
 
 	/* Parse out hex fields into struct stat. */
 	header = h;
+
+	if (memcmp(header->c_magic, "070701", 6) == 0) {
+		a->archive_format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC;
+		a->archive_format_name = "ASCII cpio (SVR4 with no CRC)";
+	} else if (memcmp(header->c_magic, "070702", 6) == 0) {
+		a->archive_format = ARCHIVE_FORMAT_CPIO_SVR4_CRC;
+		a->archive_format_name = "ASCII cpio (SVR4 with CRC)";
+	} else {
+		/* TODO: Abort here? */
+	}
+
 	st->st_ino = atol16(header->c_ino, sizeof(header->c_ino));
 	st->st_mode = atol16(header->c_mode, sizeof(header->c_mode));
 	st->st_uid = atol16(header->c_uid, sizeof(header->c_uid));
@@ -360,7 +368,7 @@ header_odc(struct archive *a, struct cpio *cpio, struct stat *st,
 	const struct cpio_odc_header *header;
 	size_t bytes;
 
-	a->archive_format = ARCHIVE_FORMAT_CPIO;
+	a->archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
 	a->archive_format_name = "POSIX octet-oriented cpio";
 
 	/* Read fixed-size portion of header. */
@@ -404,7 +412,7 @@ header_bin_le(struct archive *a, struct cpio *cpio, struct stat *st,
 	const struct cpio_bin_header *header;
 	size_t bytes;
 
-	a->archive_format = ARCHIVE_FORMAT_CPIO;
+	a->archive_format = ARCHIVE_FORMAT_CPIO_BIN_LE;
 	a->archive_format_name = "cpio (little-endian binary)";
 
 	/* Read fixed-size portion of header. */
@@ -441,7 +449,7 @@ header_bin_be(struct archive *a, struct cpio *cpio, struct stat *st,
 	const struct cpio_bin_header *header;
 	size_t bytes;
 
-	a->archive_format = ARCHIVE_FORMAT_CPIO;
+	a->archive_format = ARCHIVE_FORMAT_CPIO_BIN_BE;
 	a->archive_format_name = "cpio (big-endian binary)";
 
 	/* Read fixed-size portion of header. */
diff --git a/lib/libarchive/archive_read_support_format_iso9660.c b/lib/libarchive/archive_read_support_format_iso9660.c
index 25482a2f8a05..510d7f08253c 100644
--- a/lib/libarchive/archive_read_support_format_iso9660.c
+++ b/lib/libarchive/archive_read_support_format_iso9660.c
@@ -302,10 +302,7 @@ archive_read_format_iso9660_read_header(struct archive *a,
 
 	iso9660 = *(a->pformat_data);
 
-	if (iso9660->seenRockridge) {
-		a->archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
-		a->archive_format_name = "ISO9660 with Rockridge extensions";
-	} else {
+	if (!a->archive_format) {
 		a->archive_format = ARCHIVE_FORMAT_ISO9660;
 		a->archive_format_name = "ISO9660";
 	}
@@ -402,6 +399,12 @@ archive_read_format_iso9660_read_header(struct archive *a,
 					continue;
 				child = parse_file_info(iso9660, file, dr);
 				add_entry(iso9660, child);
+				if (iso9660->seenRockridge) {
+					a->archive_format =
+					    ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
+					a->archive_format_name =
+					    "ISO9660 with Rockridge extensions";
+				}
 			}
 		}
 	}