]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Read/write birthtime in pax format archives.
authorTim Kientzle <kientzle@gmail.com>
Wed, 17 Sep 2008 22:27:56 +0000 (18:27 -0400)
committerTim Kientzle <kientzle@gmail.com>
Wed, 17 Sep 2008 22:27:56 +0000 (18:27 -0400)
Start a basic test for 'pax' format:  Write entries, read them back,
make sure they are the same.  This needs to be extended.  A lot.

Submitted by: Pedro Giffuni (birthtime)

SVN-Revision: 210

Makefile.am
libarchive/archive_read_support_format_tar.c
libarchive/archive_write_set_format_pax.c
libarchive/test/Makefile
libarchive/test/test_write_format_pax.c [new file with mode: 0644]

index cbdf87a180ed79917d5152c155384c51fca48d8e..ae4fa32d74b15cd179eaf5539285804d2319cb5d 100644 (file)
@@ -230,6 +230,7 @@ libarchive_test_SOURCES=                                    \
        libarchive/test/test_write_format_cpio_empty.c          \
        libarchive/test/test_write_format_cpio_odc.c            \
        libarchive/test/test_write_format_cpio_newc.c           \
+       libarchive/test/test_write_format_pax.c                 \
        libarchive/test/test_write_format_shar_empty.c          \
        libarchive/test/test_write_format_tar.c                 \
        libarchive/test/test_write_format_tar_empty.c           \
@@ -321,6 +322,7 @@ bsdtar_test_SOURCES=                                                \
        tar/test/test_option_T.c                                \
        tar/test/test_patterns.c                                \
        tar/test/test_stdio.c                                   \
+       tar/test/test_symlink_dir.c                             \
        tar/test/test_version.c
 
 bsdtar_test_CPPFLAGS= -I$(top_builddir)/tar/test
index 4ebe57aa73c2bab64a2dc562f136bf5f00938397..3258b3cf49c7e7763e224f835c5e55d714efb610 100644 (file)
@@ -1451,6 +1451,10 @@ pax_attribute(struct tar *tar, struct archive_entry *entry,
                if (strcmp(key, "LIBARCHIVE.xxxxxxx")==0)
                        archive_entry_set_xxxxxx(entry, value);
 */
+               if (strcmp(key, "LIBARCHIVE.creationtime")==0) {
+                       pax_time(value, &s, &n);
+                       archive_entry_set_birthtime(entry, s, n);
+               }
                if (strncmp(key, "LIBARCHIVE.xattr.", 17)==0)
                        pax_attribute_xattr(entry, key, value);
                break;
index ee6cafda37e34b87b21fd17febf6950720e3a4dc..345cb92a2532f24f529ac2e4d1c8959411b80c2c 100644 (file)
@@ -762,6 +762,15 @@ archive_write_pax_header(struct archive_write *a,
                            archive_entry_atime(entry_main),
                            archive_entry_atime_nsec(entry_main));
 
+               /* Store birth/creationtime only if it's earlier than mtime */
+               if (archive_entry_birthtime_is_set(entry_main) &&
+                   archive_entry_birthtime(entry_main)
+                   < archive_entry_mtime(entry_main))
+                       add_pax_attr_time(&(pax->pax_header),
+                           "LIBARCHIVE.creationtime",
+                           archive_entry_birthtime(entry_main),
+                           archive_entry_birthtime_nsec(entry_main));
+
                /* I use a star-compatible file flag attribute. */
                p = archive_entry_fflags_text(entry_main);
                if (p != NULL  &&  *p != '\0')
index 0bd338b0af958fc7b8654e960700e948a6ba9497..219a5df2524a05d2d277373d34b348e66bc56816 100644 (file)
@@ -62,6 +62,7 @@ TESTS= \
        test_write_format_cpio_empty.c          \
        test_write_format_cpio_newc.c           \
        test_write_format_cpio_odc.c            \
+       test_write_format_pax.c                 \
        test_write_format_shar_empty.c          \
        test_write_format_tar.c                 \
        test_write_format_tar_empty.c           \
diff --git a/libarchive/test/test_write_format_pax.c b/libarchive/test/test_write_format_pax.c
new file mode 100644 (file)
index 0000000..06cfca6
--- /dev/null
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2003-2008 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+char buff2[64];
+
+DEFINE_TEST(test_write_format_pax)
+{
+       size_t buffsize = 1000000;
+       char *buff;
+       struct archive_entry *ae;
+       struct archive *a;
+       size_t used;
+
+       buff = malloc(buffsize); /* million bytes of work area */
+       assert(buff != NULL);
+
+       /* Create a new archive in memory. */
+       assert((a = archive_write_new()) != NULL);
+       assertA(0 == archive_write_set_format_pax(a));
+       assertA(0 == archive_write_set_compression_none(a));
+       assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));
+
+       /*
+        * "file" has a bunch of attributes and 8 bytes of data.
+        */
+       assert((ae = archive_entry_new()) != NULL);
+       archive_entry_set_atime(ae, 2, 20);
+       archive_entry_set_birthtime(ae, 3, 30);
+       archive_entry_set_ctime(ae, 4, 40);
+       archive_entry_set_mtime(ae, 5, 50);
+       archive_entry_copy_pathname(ae, "file");
+       archive_entry_set_mode(ae, S_IFREG | 0755);
+       archive_entry_set_size(ae, 8);
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+       archive_entry_free(ae);
+       assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
+
+       /*
+        * "file2" is similar but has birthtime later than mtime.
+        */
+       assert((ae = archive_entry_new()) != NULL);
+       archive_entry_set_atime(ae, 2, 20);
+       archive_entry_set_birthtime(ae, 8, 80);
+       archive_entry_set_ctime(ae, 4, 40);
+       archive_entry_set_mtime(ae, 5, 50);
+       archive_entry_copy_pathname(ae, "file2");
+       archive_entry_set_mode(ae, S_IFREG | 0755);
+       archive_entry_set_size(ae, 8);
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+       archive_entry_free(ae);
+       assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
+
+       /*
+        * XXX TODO XXX Archive directory, other file types.
+        * Archive extended attributes, ACLs, other metadata.
+        * Verify they get read back correctly.
+        */
+
+       /* Close out the archive. */
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_finish(a));
+
+       /*
+        *
+        * Now, read the data back.
+        *
+        */
+       assert((a = archive_read_new()) != NULL);
+       assertEqualIntA(a, 0, archive_read_support_format_all(a));
+       assertEqualIntA(a, 0, archive_read_support_compression_all(a));
+       assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used));
+
+       /*
+        * Read "file"
+        */
+       assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+       assertEqualInt(2, archive_entry_atime(ae));
+       assertEqualInt(20, archive_entry_atime_nsec(ae));
+       assertEqualInt(3, archive_entry_birthtime(ae));
+       assertEqualInt(30, archive_entry_birthtime_nsec(ae));
+       assertEqualInt(4, archive_entry_ctime(ae));
+       assertEqualInt(40, archive_entry_ctime_nsec(ae));
+       assertEqualInt(5, archive_entry_mtime(ae));
+       assertEqualInt(50, archive_entry_mtime_nsec(ae));
+       assertEqualString("file", archive_entry_pathname(ae));
+       assert((S_IFREG | 0755) == archive_entry_mode(ae));
+       assertEqualInt(8, archive_entry_size(ae));
+       assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+       assertEqualMem(buff2, "12345678", 8);
+
+       /*
+        * Read "file2"
+        */
+       assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+       assert(archive_entry_atime_is_set(ae));
+       assertEqualInt(2, archive_entry_atime(ae));
+       assertEqualInt(20, archive_entry_atime_nsec(ae));
+       /* Birthtime > mtime above, so it doesn't get stored at all. */
+       assert(!archive_entry_birthtime_is_set(ae));
+       assertEqualInt(0, archive_entry_birthtime(ae));
+       assertEqualInt(0, archive_entry_birthtime_nsec(ae));
+       assert(archive_entry_ctime_is_set(ae));
+       assertEqualInt(4, archive_entry_ctime(ae));
+       assertEqualInt(40, archive_entry_ctime_nsec(ae));
+       assert(archive_entry_mtime_is_set(ae));
+       assertEqualInt(5, archive_entry_mtime(ae));
+       assertEqualInt(50, archive_entry_mtime_nsec(ae));
+       assertEqualString("file2", archive_entry_pathname(ae));
+       assert((S_IFREG | 0755) == archive_entry_mode(ae));
+       assertEqualInt(8, archive_entry_size(ae));
+       assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+       assertEqualMem(buff2, "12345678", 8);
+
+       /*
+        * Verify the end of the archive.
+        */
+       assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_finish(a));
+
+       free(buff);
+}