aboutsummaryrefslogtreecommitdiff
path: root/lib/tar
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tar')
-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
4 files changed, 232 insertions, 1 deletions
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;
+}