]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Add support for symlink to ZIP writer.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Fri, 23 Dec 2011 00:19:37 +0000 (19:19 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Fri, 23 Dec 2011 00:19:37 +0000 (19:19 -0500)
SVN-Revision: 3966

libarchive/archive_write_set_format_zip.c
libarchive/test/test_write_format_zip.c

index 0e684f06e66b6bad1ff82b725974821bf81d5992..f07a14f47f5a47278ef82d3e9bbee1c4648d73d6 100644 (file)
@@ -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
index c11732d1e5f3e254d242806a963764cbd1a2dbdd..4f672346d4249fe31fc39dc65f98cf1ac001f7bd 100644 (file)
@@ -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.
         */