PERFORCE change 145416 for review
Anselm Strauss
strauss at FreeBSD.org
Fri Jul 18 09:50:55 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=145416
Change 145416 by strauss at 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;
More information about the p4-projects
mailing list