From: Michihiro NAKAJIMA Date: Fri, 23 Dec 2011 00:19:37 +0000 (-0500) Subject: Add support for symlink to ZIP writer. X-Git-Tag: v3.0.2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb8015a80ee25404ce1f75eaa31d833dc560d8ed;p=thirdparty%2Flibarchive.git Add support for symlink to ZIP writer. SVN-Revision: 3966 --- diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index 0e684f06e..f07a14f47 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -339,7 +339,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) /* Entries other than a regular file or a folder are skipped. */ type = archive_entry_filetype(entry); - if ((type != AE_IFREG) & (type != AE_IFDIR)) { + if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Filetype not supported"); return ARCHIVE_FAILED; @@ -414,8 +414,20 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) /* Initialize the CRC variable and potentially the local crc32(). */ l->crc32 = crc32(0, NULL, 0); - l->compression = zip->compression; - l->compressed_size = 0; + if (type == AE_IFLNK) { + const char *p = archive_entry_symlink(l->entry); + if (p != NULL) + size = strlen(p); + else + size = 0; + zip->remaining_data_bytes = 0; + archive_entry_set_size(l->entry, size); + l->compression = COMPRESSION_STORE; + l->compressed_size = size; + } else { + l->compression = zip->compression; + l->compressed_size = 0; + } l->next = NULL; if (zip->central_directory == NULL) { zip->central_directory = l; @@ -432,11 +444,11 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) archive_le32enc(&h.signature, ZIP_SIGNATURE_LOCAL_FILE_HEADER); archive_le16enc(&h.version, ZIP_VERSION_EXTRACT); archive_le16enc(&h.flags, l->flags); - archive_le16enc(&h.compression, zip->compression); + archive_le16enc(&h.compression, l->compression); archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(entry))); archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry)); - switch (zip->compression) { + switch (l->compression) { case COMPRESSION_STORE: /* Setting compressed and uncompressed sizes even when * specification says to set to zero when using data @@ -501,6 +513,17 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(e); + if (type == AE_IFLNK) { + const unsigned char *p; + + p = (const unsigned char *)archive_entry_symlink(l->entry); + ret = __archive_write_output(a, p, size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += size; + l->crc32 = crc32(l->crc32, p, size); + } + if (ret2 != ARCHIVE_OK) return (ret2); return (ARCHIVE_OK); @@ -518,7 +541,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) if (s == 0) return 0; - switch (zip->compression) { + switch (l->compression) { case COMPRESSION_STORE: ret = __archive_write_output(a, buff, s); if (ret != ARCHIVE_OK) return (ret); @@ -571,7 +594,7 @@ archive_write_zip_finish_entry(struct archive_write *a) size_t reminder; #endif - switch(zip->compression) { + switch(l->compression) { case COMPRESSION_STORE: break; #if HAVE_ZLIB_H diff --git a/libarchive/test/test_write_format_zip.c b/libarchive/test/test_write_format_zip.c index c11732d1e..4f672346d 100644 --- a/libarchive/test/test_write_format_zip.c +++ b/libarchive/test/test_write_format_zip.c @@ -77,6 +77,24 @@ verify_contents(struct archive *a, int expect_details) archive_read_data(a, filedata, sizeof(filedata))); assertEqualMem(filedata, "1234", 4); + /* + * Read the third file back. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_atime(ae)); + assertEqualInt(0, archive_entry_ctime(ae)); + assertEqualString("symlink", archive_entry_pathname(ae)); + if (expect_details) { + assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualString("file1", archive_entry_symlink(ae)); + } else { + assertEqualInt(AE_IFREG | 0777, archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + } + /* * Read the dir entry back. */ @@ -131,7 +149,7 @@ DEFINE_TEST(test_write_format_zip) assertEqualInt(10, archive_entry_mtime_nsec(ae)); archive_entry_copy_pathname(ae, "file"); assertEqualString("file", archive_entry_pathname(ae)); - archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_mode(ae, AE_IFREG | 0755); assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); archive_entry_set_size(ae, 8); @@ -149,7 +167,7 @@ DEFINE_TEST(test_write_format_zip) assertEqualInt(10, archive_entry_mtime_nsec(ae)); archive_entry_copy_pathname(ae, "file2"); assertEqualString("file2", archive_entry_pathname(ae)); - archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_mode(ae, AE_IFREG | 0755); assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); archive_entry_set_size(ae, 4); @@ -157,6 +175,24 @@ DEFINE_TEST(test_write_format_zip) archive_entry_free(ae); assertEqualInt(4, archive_write_data(a, "1234", 5)); + /* + * Write symbolic like file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 10); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualInt(10, archive_entry_mtime_nsec(ae)); + archive_entry_copy_pathname(ae, "symlink"); + assertEqualString("symlink", archive_entry_pathname(ae)); + archive_entry_copy_symlink(ae, "file1"); + assertEqualString("file1", archive_entry_symlink(ae)); + archive_entry_set_mode(ae, AE_IFLNK | 0755); + assertEqualInt((S_IFLNK | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 4); + + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + /* * Write a directory to it. */