aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-02-12 12:28:40 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-02-12 12:28:40 +0100
commitb635c78530d5d7f27f9805790c1f7ca227959177 (patch)
tree9581e10402219bcae6009c81087a9f525e8cece3
parent9a7a07d047b6baffb095f16074402630fe2f0270 (diff)
libtar: Add a test for the tar writing code
Generate a simple tarball and compare it with a reference. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--bin/gensquashfs/test/fstree_glob1.c7
-rw-r--r--bin/tar2sqfs/test/sqfs.sha5121
-rw-r--r--lib/tar/Makemodule.am8
-rw-r--r--lib/tar/test/data/CREDITS4
-rw-r--r--lib/tar/test/data/write/simple.tarbin0 -> 10240 bytes
-rw-r--r--lib/tar/test/tar_write_simple.c221
6 files changed, 240 insertions, 1 deletions
diff --git a/bin/gensquashfs/test/fstree_glob1.c b/bin/gensquashfs/test/fstree_glob1.c
index 5f4fdfe..2d3cb80 100644
--- a/bin/gensquashfs/test/fstree_glob1.c
+++ b/bin/gensquashfs/test/fstree_glob1.c
@@ -202,6 +202,13 @@ static void check_hierarchy(tree_node_t *root, bool subdir, bool recursive)
n = n->next;
TEST_NOT_NULL(n);
+ TEST_STR_EQUAL(n->name, "write");
+ TEST_ASSERT(S_ISDIR(n->mode));
+ TEST_ASSERT(n->parent == parentdir);
+ TEST_NULL(n->data.dir.children);
+
+ n = n->next;
+ TEST_NOT_NULL(n);
TEST_STR_EQUAL(n->name, "xattr");
TEST_ASSERT(S_ISDIR(n->mode));
TEST_ASSERT(n->parent == parentdir);
diff --git a/bin/tar2sqfs/test/sqfs.sha512 b/bin/tar2sqfs/test/sqfs.sha512
index 609e154..a915b02 100644
--- a/bin/tar2sqfs/test/sqfs.sha512
+++ b/bin/tar2sqfs/test/sqfs.sha512
@@ -25,4 +25,5 @@ a5e95c464f41249da9a4156db3a23d30e01652881e839912f632f2614f1775e62a3fed184efbec1a
627a69ed25f9b5380d269fbe12603818d73b29d6a1155fcf7bebca2ba30ec1cce7b8405394498333f9847f10f0768b80b94b723551dbff10c633d2887e62b804 test_tar/data/xattr/xattr-schily.sqfs
627a69ed25f9b5380d269fbe12603818d73b29d6a1155fcf7bebca2ba30ec1cce7b8405394498333f9847f10f0768b80b94b723551dbff10c633d2887e62b804 test_tar/data/xattr/xattr-libarchive.sqfs
b8e0e1cb41663c3d6278bf214234ac00ae8b86b9bc16d086bd0a7bfa9b0d28d626f70c6a1bd6f05dbbfa46431ce3f4518a4be38caf87b1f071d57edae24c5b10 test_tar/data/xattr/acl.sqfs
+6b201a275180d93459f6e9d94900a9bbb14da1c4f68cc7ca5850eb8cab982617ec6ae5695ca3c23c6cbbfa93cc3957367d4f3ae636706ef176059090b3d92c3f test_tar/data/write/simple.sqfs
bae693082a771c500c2d6b52a8eeb91decd98e90eaae379951bcc80589533ff43b58375f8a7f3de77c35456ee7fb269a6b17e4c29b291475578ba8453f152d0e test_tar/root-becomes.sqfs
diff --git a/lib/tar/Makemodule.am b/lib/tar/Makemodule.am
index 9faeecf..07eb497 100644
--- a/lib/tar/Makemodule.am
+++ b/lib/tar/Makemodule.am
@@ -179,6 +179,11 @@ test_tar_istream3_CPPFLAGS += -DTESTFILE=istream/sparse.tar
tar_fuzz_SOURCES = lib/tar/test/tar_fuzz.c
tar_fuzz_LDADD = libtar.a libio.a libutil.a libcompat.a
+test_tar_write_simple_SOURCES = lib/tar/test/tar_write_simple.c
+test_tar_write_simple_LDADD = libtar.a libio.a libutil.a libcompat.a
+test_tar_write_simple_CPPFLAGS = $(AM_CPPFLAGS) -DTESTPATH=$(TARDATADIR)
+test_tar_write_simple_CPPFLAGS += -DTESTFILE=write/simple.tar
+
LIBTAR_TESTS = \
test_tar_ustar0 test_tar_ustar1 test_tar_ustar2 test_tar_ustar3 \
test_tar_ustar4 test_tar_ustar5 test_tar_ustar6 \
@@ -190,7 +195,8 @@ LIBTAR_TESTS = \
test_tar_sparse_gnu2 test_tar_sparse_gnu3 \
test_tar_xattr_bsd test_tar_xattr_schily test_tar_xattr_schily_bin \
test_tar_target_filled \
- test_tar_istream test_tar_istream2 test_tar_istream3
+ test_tar_istream test_tar_istream2 test_tar_istream3 \
+ test_tar_write_simple
check_PROGRAMS += $(LIBTAR_TESTS)
TESTS += $(LIBTAR_TESTS)
diff --git a/lib/tar/test/data/CREDITS b/lib/tar/test/data/CREDITS
index dab8951..1e7fb32 100644
--- a/lib/tar/test/data/CREDITS
+++ b/lib/tar/test/data/CREDITS
@@ -36,3 +36,7 @@ The following addtional files have been added:
- istream/sparse.tar
Derived from sparse/gnu.tar and contains some test data for testing the
tar istream implementation.
+ - write/simple.tar
+ Created using the tar writer to verify that it works as intended. Used
+ for testing the tar writer to check if it still produces identical
+ output.
diff --git a/lib/tar/test/data/write/simple.tar b/lib/tar/test/data/write/simple.tar
new file mode 100644
index 0000000..a910daa
--- /dev/null
+++ b/lib/tar/test/data/write/simple.tar
Binary files differ
diff --git a/lib/tar/test/tar_write_simple.c b/lib/tar/test/tar_write_simple.c
new file mode 100644
index 0000000..c78565b
--- /dev/null
+++ b/lib/tar/test/tar_write_simple.c
@@ -0,0 +1,221 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * tar_write_simple.c
+ *
+ * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+#include "tar/tar.h"
+#include "io/ostream.h"
+#include "io/file.h"
+#include "util/test.h"
+#include "compat.h"
+
+/*****************************************************************************/
+
+static int buffer_append(ostream_t *strm, const void *data, size_t size);
+static const char *buffer_get_filename(ostream_t *strm);
+
+static ostream_t mem_stream = {
+ { 1, NULL, NULL },
+ buffer_append,
+ NULL,
+ NULL,
+ buffer_get_filename,
+};
+
+static sqfs_u8 wr_buffer[1024 * 10];
+static size_t wr_offset = 0;
+
+static sqfs_u8 rd_buffer[1024 * 10];
+
+static int buffer_append(ostream_t *strm, const void *data, size_t size)
+{
+ TEST_ASSERT(strm == &mem_stream);
+ TEST_NOT_NULL(data);
+ TEST_ASSERT(wr_offset < sizeof(wr_buffer));
+ TEST_ASSERT(size > 0);
+ TEST_ASSERT((sizeof(wr_buffer) - wr_offset) >= size);
+
+ memcpy(wr_buffer + wr_offset, data, size);
+ wr_offset += size;
+ return 0;
+}
+
+static const char *buffer_get_filename(ostream_t *strm)
+{
+ TEST_ASSERT(strm == &mem_stream);
+ return "dummy";
+}
+
+/*****************************************************************************/
+
+#define TIME_STAMP (1057296600)
+
+static tar_xattr_t *mkxattr(const char *key, const sqfs_u8 *value,
+ size_t value_len)
+{
+ size_t key_len = strlen(key);
+ tar_xattr_t *out = malloc(sizeof(*out) + key_len + 1 + value_len + 1);
+
+ TEST_NOT_NULL(out);
+
+ out->next = NULL;
+ out->key = out->data;
+ out->value = (sqfs_u8 *)(out->data + key_len + 1);
+ out->value_len = value_len;
+
+ memcpy(out->data, key, key_len);
+ out->data[key_len] = '\0';
+
+ memcpy(out->data + key_len + 1, value, value_len);
+ out->data[key_len + 1 + value_len] = '\0';
+
+ return out;
+}
+
+static tar_xattr_t *mkxattr_chain(void)
+{
+ static const uint8_t value[] = {
+ 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ };
+ tar_xattr_t *list;
+
+ list = mkxattr("user.mime_type", (const sqfs_u8 *)"blob/magic", 10);
+ list->next = mkxattr("security.capability", value, sizeof(value));
+
+ return list;
+}
+
+int main(int argc, char **argv)
+{
+ tar_xattr_t *xattr;
+ struct stat sb;
+ istream_t *fp;
+ int ret;
+ (void)argc; (void)argv;
+
+ /* genereate some archive contents */
+ memset(&sb, 0, sizeof(sb));
+ sb.st_mode = S_IFDIR | 0755;
+ sb.st_mtime = TIME_STAMP;
+ ret = write_tar_header(&mem_stream, &sb, "dev/", NULL, NULL, 0);
+ TEST_EQUAL_I(ret, 0);
+
+ /* device files */
+ sb.st_mode = S_IFCHR | 0620;
+ sb.st_gid = 5;
+ sb.st_rdev = makedev(4, 0);
+ ret = write_tar_header(&mem_stream, &sb, "dev/tty0", NULL, NULL, 1);
+ TEST_EQUAL_I(ret, 0);
+
+ sb.st_rdev = makedev(4, 1);
+ ret = write_tar_header(&mem_stream, &sb, "dev/tty1", NULL, NULL, 2);
+ TEST_EQUAL_I(ret, 0);
+
+ sb.st_rdev = makedev(4, 2);
+ ret = write_tar_header(&mem_stream, &sb, "dev/tty2", NULL, NULL, 3);
+ TEST_EQUAL_I(ret, 0);
+
+ memset(&sb, 0, sizeof(sb));
+ sb.st_mode = S_IFDIR | 0755;
+ sb.st_mtime = TIME_STAMP;
+ ret = write_tar_header(&mem_stream, &sb, "usr/", NULL, NULL, 4);
+ TEST_EQUAL_I(ret, 0);
+
+ ret = write_tar_header(&mem_stream, &sb, "usr/bin/", NULL, NULL, 5);
+ TEST_EQUAL_I(ret, 0);
+
+ /* sym link */
+ sb.st_mode = S_IFLNK | 0777;
+ sb.st_size = 7;
+ ret = write_tar_header(&mem_stream, &sb, "bin", "usr/bin", NULL, 6);
+ TEST_EQUAL_I(ret, 0);
+
+ memset(&sb, 0, sizeof(sb));
+ sb.st_mode = S_IFDIR | 0755;
+ sb.st_mtime = TIME_STAMP;
+ ret = write_tar_header(&mem_stream, &sb, "home/", NULL, NULL, 7);
+ TEST_EQUAL_I(ret, 0);
+
+ sb.st_mode = S_IFDIR | 0750;
+ sb.st_uid = 1000;
+ sb.st_gid = 1000;
+ ret = write_tar_header(&mem_stream, &sb, "home/goliath/",
+ NULL, NULL, 8);
+ TEST_EQUAL_I(ret, 0);
+
+ /* regular file with actual content */
+ sb.st_mode = S_IFREG | 0644;
+ sb.st_size = 14;
+ ret = write_tar_header(&mem_stream, &sb, "home/goliath/hello.txt",
+ NULL, NULL, 9);
+ TEST_EQUAL_I(ret, 0);
+
+ ret = ostream_append(&mem_stream, "Hello, World!\n", 14);
+ TEST_EQUAL_I(ret, 0);
+ ret = padd_file(&mem_stream, 14);
+ TEST_EQUAL_I(ret, 0);
+
+ /* hard link */
+ ret = write_hard_link(&mem_stream, &sb, "home/goliath/world.txt",
+ "home/goliath/hello.txt", 10);
+ TEST_EQUAL_I(ret, 0);
+
+ /* something with xattrs */
+ xattr = mkxattr_chain();
+ sb.st_mode = S_IFREG | 0750;
+ sb.st_size = 4;
+ ret = write_tar_header(&mem_stream, &sb, "home/goliath/test.exe",
+ NULL, xattr, 11);
+ TEST_EQUAL_I(ret, 0);
+ free_xattr_list(xattr);
+
+ ret = ostream_append(&mem_stream, ":-)\n", 4);
+ TEST_EQUAL_I(ret, 0);
+ ret = padd_file(&mem_stream, 4);
+ TEST_EQUAL_I(ret, 0);
+
+ /* now try something with a long name */
+ memset(&sb, 0, sizeof(sb));
+ sb.st_mode = S_IFREG | 0755;
+ sb.st_mtime = TIME_STAMP;
+ sb.st_size = 42;
+ ret = write_tar_header(&mem_stream, &sb,
+ "mnt/windows_drive/C/Documents and Settings/"
+ "Joe Random User/My Documents/My Evil Plans/"
+ "file format nonsense/really long name.doc",
+ NULL, NULL, 12);
+ TEST_EQUAL_I(ret, 0);
+
+ ret = ostream_append(&mem_stream,
+ "Annoy people with really long file paths!\n",
+ 42);
+ TEST_EQUAL_I(ret, 0);
+ ret = padd_file(&mem_stream, 42);
+ TEST_EQUAL_I(ret, 0);
+
+ /* compare with reference */
+ TEST_EQUAL_UI(wr_offset, sizeof(wr_buffer));
+ TEST_EQUAL_UI(sizeof(rd_buffer), sizeof(wr_buffer));
+
+ fp = istream_open_file(STRVALUE(TESTPATH) "/" STRVALUE(TESTFILE));
+ TEST_NOT_NULL(fp);
+
+ ret = istream_read(fp, rd_buffer, sizeof(rd_buffer));
+ TEST_ASSERT(ret > 0);
+ TEST_EQUAL_UI(ret, sizeof(rd_buffer));
+
+ ret = istream_read(fp, rd_buffer, sizeof(rd_buffer));
+ TEST_EQUAL_I(ret, 0);
+
+ sqfs_drop(fp);
+
+ ret = memcmp(wr_buffer, rd_buffer, sizeof(rd_buffer));
+ TEST_EQUAL_I(ret, 0);
+ return EXIT_SUCCESS;
+}