PERFORCE change 145604 for review
Anselm Strauss
strauss at FreeBSD.org
Tue Jul 22 13:04:08 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=145604
Change 145604 by strauss at strauss_marvelman on 2008/07/22 13:03:28
- Added writing of end of central directory in ZIP writer
- Added ZIP writer empty test from Tim
- Fixed zip_encode() function (littel-endian encoding)
Affected files ...
.. //depot/projects/soc2008/strauss_libarchive/Makefile.am#8 edit
.. //depot/projects/soc2008/strauss_libarchive/libarchive/archive_write_set_format_zip.c#14 edit
.. //depot/projects/soc2008/strauss_libarchive/libarchive/test/test_write_format_zip_empty.c#1 add
Differences ...
==== //depot/projects/soc2008/strauss_libarchive/Makefile.am#8 (text+ko) ====
@@ -232,6 +232,7 @@
libarchive/test/test_write_format_tar.c \
libarchive/test/test_write_format_tar_empty.c \
libarchive/test/test_write_format_tar_ustar.c \
+ libarchive/test/test_write_format_zip_empty.c \
libarchive/test/test_write_open_memory.c
libarchive_test_CPPFLAGS= -I$(top_builddir)/libarchive -I$(top_srcdir)/libarchive -I$(top_builddir)/libarchive/test
==== //depot/projects/soc2008/strauss_libarchive/libarchive/archive_write_set_format_zip.c#14 (text+ko) ====
@@ -12,6 +12,11 @@
* Note that generally data in ZIP files is little-endian encoded,
* with some exceptions.
*
+ * TODO: Since Libarchive is generally 64bit oriented, but this implementation
+ * does not yet support sizes exceeding 32bit, it is highly fragile for
+ * big archives. This should change when ZIP64 is finally implemented, otherwise
+ * some serious checking has to be done.
+ *
*/
#include "archive_platform.h"
@@ -31,6 +36,7 @@
#define ZIP_SIGNATURE_LOCAL_FILE_HEADER 0x04034b50
#define ZIP_SIGNATURE_DATA_DESCRIPTOR 0x08074b50
#define ZIP_SIGNATURE_FILE_HEADER 0x02014b50
+#define ZIP_SIGNATURE_CENTRAL_DIRECTORY_END 0x06054b50
#include "archive.h"
#include "archive_entry.h"
@@ -42,7 +48,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 zip_encode(int64_t, void *, size_t);
+static void zip_encode(uint64_t, void *, size_t);
struct zip_local_file_header {
char signature[4];
@@ -94,6 +100,17 @@
struct zip_file_header_link *central_directory;
};
+struct zip_central_directory_end {
+ char signature[4];
+ char disk[2];
+ char start_disk[2];
+ char entries_disk[2];
+ char entries[2];
+ char size[4];
+ char offset[4];
+ char comment_length[2];
+};
+
int
archive_write_set_format_zip(struct archive *_a)
{
@@ -160,9 +177,7 @@
l->next = zip->central_directory;
zip->central_directory = l;
- /* Store the offset of this header for later use in central directory.
- * TODO: Offset actually are 8 bytes, for big archives this won't fit into
- * the 4 bytes field. Either use ZIP64, or return error. */
+ /* Store the offset of this header for later use in central directory. */
l->offset = a->archive.raw_position;
/*
@@ -230,8 +245,11 @@
struct zip *zip;
struct zip_file_header_link *l;
struct zip_file_header h;
- int64_t size;
+ struct zip_central_directory_end end;
+ uint64_t size;
+ off_t offset;
const char *path;
+ int entries;
int ret;
zip = (struct zip *) a->format_data;
@@ -252,6 +270,8 @@
zip_encode(ZIP_SIGNATURE_FILE_HEADER, &h.signature, sizeof(h.signature));
zip_encode(0x0200, &h.version_extract, sizeof(h.version_extract));
+ entries = 0;
+ offset = a->archive.raw_position;
while (l != NULL) {
/* Formatting individual header fields per entry. */
@@ -271,7 +291,20 @@
if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL);
l = l->next;
+ ++entries;
}
+
+ /* Formatting end of central directory. */
+ memset(&end, 0, sizeof(end));
+ zip_encode(ZIP_SIGNATURE_CENTRAL_DIRECTORY_END, &end.signature, sizeof(end.signature));
+ zip_encode(entries, &end.entries, sizeof(end.entries));
+ zip_encode(entries, &end.entries_disk, sizeof(end.entries_disk));
+ zip_encode(entries * sizeof(h), &end.size, sizeof(end.size));
+ zip_encode(offset, &end.offset, sizeof(end.offset));
+
+ /* Writing end of central directory. */
+ ret = (a->compressor.write)(a, &end, sizeof(end));
+ if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL);
return (ARCHIVE_OK);
}
@@ -295,12 +328,13 @@
/* Encode data in little-endian for writing it to a ZIP file. */
static void
-zip_encode(int64_t value, void *_p, size_t size)
+zip_encode(uint64_t value, void *_p, size_t size)
{
unsigned char *p = (unsigned char *) _p;
size_t i;
for (i = 0; i <= size; ++i) {
- *p = (value >>= i) & 0xff;
+ *p = value & 0xff;
+ value >>= 8;
p++;
}
}
More information about the p4-projects
mailing list