PERFORCE change 144892 for review
Anselm Strauss
strauss at FreeBSD.org
Tue Jul 8 16:30:22 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=144892
Change 144892 by strauss at 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);
}
More information about the p4-projects
mailing list