From owner-p4-projects@FreeBSD.ORG Tue Jul 8 16:30:22 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 49662106567B; Tue, 8 Jul 2008 16:30:22 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0BB4B1065678 for ; Tue, 8 Jul 2008 16:30:22 +0000 (UTC) (envelope-from strauss@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id ED1FD8FC1A for ; Tue, 8 Jul 2008 16:30:21 +0000 (UTC) (envelope-from strauss@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m68GULRO077772 for ; Tue, 8 Jul 2008 16:30:21 GMT (envelope-from strauss@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m68GUL9j077770 for perforce@freebsd.org; Tue, 8 Jul 2008 16:30:21 GMT (envelope-from strauss@FreeBSD.org) Date: Tue, 8 Jul 2008 16:30:21 GMT Message-Id: <200807081630.m68GUL9j077770@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to strauss@FreeBSD.org using -f From: Anselm Strauss To: Perforce Change Reviews Cc: Subject: PERFORCE change 144892 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Jul 2008 16:30:22 -0000 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 #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); }