Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Jul 2008 16:30:21 GMT
From:      Anselm Strauss <strauss@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 144892 for review
Message-ID:  <200807081630.m68GUL9j077770@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=144892

Change 144892 by strauss@strauss_marvelman on 2008/07/08 16:30:03

	- Todos
	- Work on ZIP writer

Affected files ...

.. //depot/projects/soc2008/strauss_libarchive/GSOC2008#3 edit
.. //depot/projects/soc2008/strauss_libarchive/TODO#5 edit
.. //depot/projects/soc2008/strauss_libarchive/libarchive/archive_write_set_format_zip.c#3 edit

Differences ...

==== //depot/projects/soc2008/strauss_libarchive/GSOC2008#3 (text+ko) ====

@@ -3,6 +3,7 @@
  * This file
  * TODO: for todos management
  * Stuff in misc/
+ * libarchive/archive_write_set_format_zip.c
 
 
 Removed:

==== //depot/projects/soc2008/strauss_libarchive/TODO#5 (text+ko) ====

@@ -3,6 +3,8 @@
 
 - About the keywords: of course they always change when integrating ...
 - Not all P4 keywords do expand (tested on OS X and FreeBSD)
+- Integrate libarchive 2.5.5
+- Update ZIP writer in: docs, headers?
 
 
 Already Done

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

@@ -9,7 +9,8 @@
  *   - Central directory is missing.
  *   - No support for splitting and spanning.
  * 
- * So far, the code here is simply a modified copy of the cpio writer.
+ * Note that generally data in ZIP files is little-endian encoded,
+ * with some exceptions.
  * 
  */
 
@@ -27,24 +28,23 @@
 #include <string.h>
 #endif
 
+#define ZIP_SIGNATURE_LOCAL_FILE_HEADER 0x04034b50
+#define ZIP_SIGNATURE_DATA_DESCRIPTOR 0x08074b50
+
 #include "archive.h"
 #include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_write_private.h"
 
+int archive_write_set_format_zip(struct archive *);
 static ssize_t archive_write_zip_data(struct archive_write *, const void *buff, size_t s);
 static int archive_write_zip_finish(struct archive_write *);
 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 int	format_octal(int64_t, void *, int);
-static int64_t	format_octal_recursive(int64_t, char *, int);
+static void encode(int64_t, void *, size_t);
 
-struct zip {
-	/* Do I need this? */
-};
-
-struct zip_file_header {
+struct zip_local_file_header {
 	char signature[4];
 	char version[2];
 	char flags[2];
@@ -58,11 +58,23 @@
 };
 
 struct zip_data_descriptor {
+	char signature[4]; /* Not mandatory, but recommended by specification. */
 	char crc32[4];
 	char compressed_size[4];
 	char uncompressed_size[4];
 };
 
+struct zip_file_header {
+	struct zip_file_header *next;
+	struct archive_entry *entry;
+	uint64_t offset;
+};
+
+struct zip {
+	struct zip_data_descriptor data_descriptor;
+	struct zip_file_header *central_directory;
+};
+
 int
 archive_write_set_format_zip(struct archive *_a)
 {
@@ -89,33 +101,57 @@
 	a->format_destroy = archive_write_zip_destroy;
 	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
 	a->archive.archive_format_name = "ZIP";
+	
+	encode(
+		ZIP_SIGNATURE_DATA_DESCRIPTOR,
+		&zip->data_descriptor.signature,
+		sizeof(zip->data_descriptor.signature)
+	);
+	
 	return (ARCHIVE_OK);
 }
 
 static int
 archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
 {
+	/* TODO: Also handle non-regular file entries. */
+	if (archive_entry_filetype(entry) != AE_IFREG)
+		return ARCHIVE_FAILED;
+	
 	struct zip *zip;
 	int ret;
-	struct zip_file_header h;
+	struct zip_local_file_header h;
 
 	zip = (struct zip *)a->format_data;
 	ret = 0;
 
 	memset(&h, 0, sizeof(h));
 	
-	format_octal(0x04034b50, &h.signature, sizeof(h.signature));
-	format_octal(0x0200, &h.version, sizeof(h.version)); /* TODO: Set individually for each file entry. */
-	format_octal(8, &h.flags, sizeof(h.flags)); /* Flagging bit 3 for using data descriptor. */
-	format_octal(0, &h.compression, sizeof(h.compression)); /* No compression. */
-	format_octal(0, &h.timedate, sizeof(h.timedate)); /* TODO: Using zero (means standard input) for now. */
+	encode(ZIP_SIGNATURE_LOCAL_FILE_HEADER, &h.version, sizeof(h.version));
+	
+	encode(0x0200, &h.version, sizeof(h.version));
+	
+	/* Flagging bit 3 for using data descriptor. */
+	encode(1 << 2, &h.flags, sizeof(h.flags));
+	
+	/* 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. */
-	format_octal(0, &h.crc32, sizeof(h.crc32));
-	format_octal(0, &h.compressed_size, sizeof(h.compressed_size));
-	format_octal(0, &h.uncompressed_size, sizeof(h.uncompressed_size));
-	format_octal(sizeof(archive_entry_pathname(entry)), &h.filename_length, sizeof(h.filename_length));
-	format_octal(0x0000, &h.extra_length, sizeof(h.extra_length)); /* Not using. */
+	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));
+	
+	/* TODO: Append entry to central directory. */
 	
 	ret = (a->compressor.write)(a, &h, sizeof(h));
 	if (ret != ARCHIVE_OK)
@@ -128,18 +164,19 @@
 archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
 {
 	return (a->compressor.write)(a, buff, s);
+	/* TODO: Compute data descriptor fields. */
 }
 
 static int
 archive_write_zip_finish_entry(struct archive_write *a)
 {
-	/* Write file data descriptor here. */
+	/* TODO: Write data descriptor. */
 }
 
 static int
 archive_write_zip_finish(struct archive_write *a)
 {
-	/* Write central directory here. */
+	/* TODO: Write central directory. */
 }
 
 static int
@@ -153,33 +190,14 @@
 	return (ARCHIVE_OK);
 }
 
-/*
- * Format a number into the specified field.
- * (Stolen from cpio writer ;-)
- */
-static int
-format_octal(int64_t v, void *p, int digits)
+/* Encode data in little-endian for writing it to a ZIP file. */
+static void
+encode(int64_t value, void *_p, size_t size)
 {
-	int64_t	max;
-	int	ret;
-
-	max = (((int64_t)1) << (digits * 3)) - 1;
-	if (v >= 0  &&  v <= max) {
-	    format_octal_recursive(v, (char *)p, digits);
-	    ret = 0;
-	} else {
-	    format_octal_recursive(max, (char *)p, digits);
-	    ret = -1;
+	unsigned char *p = (unsigned char *) _p;
+	size_t i;
+	for (i = 0; i <= size; ++i) {
+		*p = (value >>= i) & 0xff;
+		p++;
 	}
-	return (ret);
-}
-
-static int64_t
-format_octal_recursive(int64_t v, char *p, int s)
-{
-	if (s == 0)
-		return (v);
-	v = format_octal_recursive(v, p+1, s-1);
-	*p = '0' + (v & 7);
-	return (v >>= 3);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807081630.m68GUL9j077770>