Date: Fri, 18 Jul 2008 09:50:54 GMT From: Anselm Strauss <strauss@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 145416 for review Message-ID: <200807180950.m6I9osC1039900@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=145416 Change 145416 by strauss@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807180950.m6I9osC1039900>