PERFORCE change 145416 for review

Anselm Strauss strauss at FreeBSD.org
Fri Jul 18 09:50:55 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=145416

Change 145416 by strauss at strauss_marvelman on 2008/07/18 09:50:01

	- code cosmetics- implemented central directory stuff, yet missing offset thing- corrected sizeof/strlen issue for char pointers

Affected files ...

.. //depot/projects/soc2008/strauss_libarchive/libarchive/archive_write_set_format_zip.c#12 edit

Differences ...

==== //depot/projects/soc2008/strauss_libarchive/libarchive/archive_write_set_format_zip.c#12 (text+ko) ====

@@ -3,7 +3,7 @@
  * 
  * The current implementation is very limited:
  * 
- *   - No compressions support.
+ *   - No compression support.
  *   - No encryption support.
  *   - No ZIP64 support.
  *   - Central directory is missing.
@@ -30,6 +30,7 @@
 
 #define ZIP_SIGNATURE_LOCAL_FILE_HEADER 0x04034b50
 #define ZIP_SIGNATURE_DATA_DESCRIPTOR 0x08074b50
+#define ZIP_SIGNATURE_FILE_HEADER 0x02014b50
 
 #include "archive.h"
 #include "archive_entry.h"
@@ -41,7 +42,7 @@
 static int archive_write_zip_destroy(struct archive_write *);
 static int archive_write_zip_finish_entry(struct archive_write *);
 static int archive_write_zip_header(struct archive_write *, struct archive_entry *);
-static void encode(int64_t, void *, size_t);
+static void zip_encode(int64_t, void *, size_t);
 
 struct zip_local_file_header {
 	char signature[4];
@@ -82,15 +83,15 @@
 	char uncompressed_size[4];
 };
 
-struct zip_entry_list {
-	struct zip_entry_list *next;
+struct zip_file_header_link {
+	struct zip_file_header_link *next;
 	struct archive_entry *entry;
 	/* uint64_t offset; */ /* Whatfor? */
 };
 
 struct zip {
 	struct zip_data_descriptor data_descriptor;
-	struct zip_entry_list *central_directory;
+	struct zip_file_header_link *central_directory;
 };
 
 int
@@ -120,7 +121,7 @@
 	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
 	a->archive.archive_format_name = "ZIP";
 	
-	encode(
+	zip_encode(
 		ZIP_SIGNATURE_DATA_DESCRIPTOR,
 		&zip->data_descriptor.signature,
 		sizeof(zip->data_descriptor.signature)
@@ -139,41 +140,47 @@
 	struct zip *zip;
 	struct zip_local_file_header h;
 	struct zip_data_descriptor *d;
-	struct zip_entry_list *l;
+	struct zip_file_header_link *l;
+	const char *path;
 	int ret;
 	
 	zip = (struct zip *) a->format_data;
 	d = (struct zip_data_descriptor *) &zip->data_descriptor;
-	ret = 0;
+	path = archive_entry_pathname(entry);
 	
-	encode(ZIP_SIGNATURE_LOCAL_FILE_HEADER, &h.version, sizeof(h.version));
+	/* 
+	 * Formatting local file header.
+	 * Some fields are not explicitely set after they were set to 0
+	 * by the memset() call, meaning they are unused or contain the default value.
+	 * The fields this is true for and the reason why are:
+	 * 
+	 *   - compression: Not yet supported (TODO)
+	 *   - timedate: Means standard input (TODO)
+	 *   - crc32, compressed_size, uncompressed_size: written in data descriptor
+	 *   - extra_length: first used when
+	 */
+	memset(&h, 0, sizeof(h));
+	zip_encode(ZIP_SIGNATURE_LOCAL_FILE_HEADER, &h.version, sizeof(h.version));
+	zip_encode(0x0200, &h.version, sizeof(h.version));
+	zip_encode(1 << 2, &h.flags, sizeof(h.flags)); /* Flagging bit 3 for using data descriptor. */
+	zip_encode(strlen(path), &h.filename_length, sizeof(h.filename_length));
 	
-	encode(0x0200, &h.version, sizeof(h.version));
+	/* This will surely change when compression is implemented. */
+	int64_t size = archive_entry_size(entry);
+	zip_encode(size, &d->compressed_size, sizeof(d->compressed_size));
+	zip_encode(size, &d->uncompressed_size, sizeof(d->uncompressed_size));
 	
-	/* Flagging bit 3 for using data descriptor. */
-	encode(1 << 2, &h.flags, sizeof(h.flags));
+	ret = (a->compressor.write)(a, &h, sizeof(h));
+	if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL);
+
+	ret = (a->compressor.write)(a, path, strlen(path));
+	if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL);
 	
-	/* No compression. */
-	encode(0, &h.compression, sizeof(h.compression));
-	
-	/* TODO: Using zero (means standard input) for now. */
-	encode(0, &h.timedate, sizeof(h.timedate));
-	
-	/* Next 3 fields are specified in the data descriptor after writing file data. 
-	 * Can't compute them before having seen the data stream. */
-	encode(0, &h.crc32, sizeof(h.crc32));
-	encode(0, &h.compressed_size, sizeof(h.compressed_size));
-	encode(0, &h.uncompressed_size, sizeof(h.uncompressed_size));
-	
-	encode(sizeof(archive_entry_pathname(entry)), &h.filename_length, sizeof(h.filename_length));
-	
-	/* Not used. */
-	encode(0, &h.extra_length, sizeof(h.extra_length));
-	
+
 	/* Append archive entry to the central directory data.
 	 * Storing in reverse order, for ease of coding.
 	 * According to specification order should not matter, right? */
-	l = (struct zip_entry_list *) malloc(sizeof(*l));
+	l = (struct zip_file_header_link *) malloc(sizeof(*l));
 	if (l == NULL) {
 		archive_set_error(&a->archive, ENOMEM, "Can't allocate zip header data");
 		return (ARCHIVE_FATAL);
@@ -182,22 +189,7 @@
 	l->next = zip->central_directory;
 	zip->central_directory = l;
 	
-	int64_t size = archive_entry_size(entry);
-	encode(size, &d->compressed_size, sizeof(d->compressed_size));
-	encode(size, &d->uncompressed_size, sizeof(d->uncompressed_size));
-	
-	ret = (a->compressor.write)(a, &h, sizeof(h));
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	
-	/* Write filename and extra field (extra field is currently null).
-	 * These are not included in the header structure due to variable size. */
-	const char *path = archive_entry_pathname(entry);
-	ret = (a->compressor.write)(a, path, strlen(path));
-	if (ret != ARCHIVE_OK)
-		return (ARCHIVE_FATAL);
-	
-	return (ret);
+	return (ARCHIVE_OK);
 }
 
 static ssize_t
@@ -231,18 +223,62 @@
 static int
 archive_write_zip_finish(struct archive_write *a)
 {
-	/* TODO: Write central directory. */
-	return 0;
+	struct zip *zip;
+	struct zip_file_header_link *l;
+	struct zip_file_header h;
+	int64_t size;
+	const char *path;
+	int ret;
+	
+	zip = (struct zip *) a->format_data;
+	l = (struct zip_file_header_link *) zip->central_directory;
+	
+	/*
+	 * Formatting central directory file header fields that are fixed for all entries.
+	 * Fields not used are:
+	 * 
+	 *   - flags
+	 *   - timedate (TODO)
+	 *   - extra_length
+	 *   - comment_length
+	 *   - disk_number
+	 *   - attributes_internal, attributes_external
+	 */
+	memset(&h, 0, sizeof(h));
+	zip_encode(ZIP_SIGNATURE_FILE_HEADER, &h.signature, sizeof(h.signature));
+	zip_encode(0x0200, &h.version_extract, sizeof(h.version_extract));
+	
+	while (l != NULL) {
+		
+		/* Formatting individual header fields per entry. */
+		size = archive_entry_size(l->entry);
+		path = archive_entry_pathname(l->entry);
+		zip_encode(size, &h.compressed_size, sizeof(h.compressed_size));
+		zip_encode(size, &h.uncompressed_size, sizeof(h.uncompressed_size));
+		zip_encode(strlen(path), &h.filename_length, sizeof(h.filename_length));
+		
+		/* Writing file header. */
+		ret = (a->compressor.write)(a, &h, sizeof(h));
+		if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL);
+		
+		/* Writing filename. */
+		ret = (a->compressor.write)(a, &path, strlen(path));
+		if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL);
+
+		l = l->next;
+	}
+
+	return (ARCHIVE_OK);
 }
 
 static int
 archive_write_zip_destroy(struct archive_write *a)
 {	
 	struct zip *zip;
-	struct zip_entry_list *l;
+	struct zip_file_header_link *l;
 
 	zip = (struct zip *)a->format_data;
-	l = (struct zip_entry_list *) zip->central_directory;
+	l = (struct zip_file_header_link *) zip->central_directory;
 	while (l != NULL) {
 		l = l->next;
 		free(l);
@@ -254,7 +290,7 @@
 
 /* Encode data in little-endian for writing it to a ZIP file. */
 static void
-encode(int64_t value, void *_p, size_t size)
+zip_encode(int64_t value, void *_p, size_t size)
 {
 	unsigned char *p = (unsigned char *) _p;
 	size_t i;


More information about the p4-projects mailing list