Date: Tue, 22 Jul 2008 13:04:08 GMT From: Anselm Strauss <strauss@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 145604 for review Message-ID: <200807221304.m6MD48Ge042071@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=145604 Change 145604 by strauss@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++; } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807221304.m6MD48Ge042071>