When needing a more complex resource (a file hierarchy), packing every single
file as a single resource would be very ineffective. For that purpose, it is
possible to pack the files into a tar archive, extract it before test from the
resource and finally clean up all the created files.
This patch introduces functions resource_untar and resource_rm_by_tar to
perform those tasks. An example of using those functions is included as a test.
Signed-off-by: Jan Viktorin
---
app/test/Makefile| 4 ++
app/test/resource.c | 180 +++
app/test/resource.h | 13
app/test/test_resource.c | 29
4 files changed, 226 insertions(+)
diff --git a/app/test/Makefile b/app/test/Makefile
index a9502f1..90acd63 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -77,6 +77,9 @@ SRCS-y += test.c
SRCS-y += resource.c
SRCS-y += test_resource.c
$(eval $(call resource,test_resource_c,resource.c))
+$(eval $(call resource,test_resource_tar,resource.tar))
+resource.tar: test_resource.c
+ tar -C $(dir $<) -cf $@ $(notdir $<)
SRCS-y += test_pci.c
SRCS-y += test_prefetch.c
SRCS-y += test_byteorder.c
@@ -196,6 +199,7 @@ CFLAGS += $(WERROR_FLAGS)
CFLAGS += -D_GNU_SOURCE
LDLIBS += -lm
+LDLIBS += -larchive
# Disable VTA for memcpy test
ifeq ($(CC), gcc)
diff --git a/app/test/resource.c b/app/test/resource.c
index a11c86e..7732bc7 100644
--- a/app/test/resource.c
+++ b/app/test/resource.c
@@ -33,6 +33,8 @@
#include
#include
+#include
+#include
#include
#include
@@ -90,6 +92,184 @@ int resource_fwrite_file(const struct resource *r, const
char *fname)
return ret;
}
+static int do_copy(struct archive *r, struct archive *w)
+{
+ const void *buf;
+ size_t len;
+ off_t off;
+ int ret;
+
+ while (1) {
+ ret = archive_read_data_block(r, , , );
+ if (ret == ARCHIVE_RETRY)
+ continue;
+
+ if (ret == ARCHIVE_EOF)
+ return 0;
+
+ if (ret != ARCHIVE_OK)
+ return ret;
+
+ do {
+ ret = archive_write_data_block(w, buf, len, off);
+ if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
+ return ret;
+ } while (ret != ARCHIVE_OK);
+ }
+}
+
+int resource_untar(const struct resource *res)
+{
+ struct archive *r;
+ struct archive *w;
+ struct archive_entry *e;
+ void *p;
+ int flags = 0;
+ int ret;
+
+ p = malloc(resource_size(res));
+ if (p == NULL)
+ rte_panic("Failed to malloc %zu B\n", resource_size(res));
+
+ memcpy(p, res->beg, resource_size(res));
+
+ r = archive_read_new();
+ if (r == NULL) {
+ free(p);
+ return -1;
+ }
+
+ archive_read_support_format_all(r);
+ archive_read_support_filter_all(r);
+
+ w = archive_write_disk_new();
+ if (w == NULL) {
+ archive_read_free(r);
+ free(p);
+ return -1;
+ }
+
+ flags |= ARCHIVE_EXTRACT_PERM;
+ flags |= ARCHIVE_EXTRACT_FFLAGS;
+ archive_write_disk_set_options(w, flags);
+ archive_write_disk_set_standard_lookup(w);
+
+ ret = archive_read_open_memory(r, p, resource_size(res));
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ while (1) {
+ ret = archive_read_next_header(r, );
+ if (ret == ARCHIVE_EOF)
+ break;
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ ret = archive_write_header(w, e);
+ if (ret == ARCHIVE_EOF)
+ break;
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ if (archive_entry_size(e) == 0)
+ continue;
+
+ ret = do_copy(r, w);
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ ret = archive_write_finish_entry(w);
+ if (ret != ARCHIVE_OK)
+ goto fail;
+ }
+
+ archive_write_free(w);
+ archive_read_free(r);
+ free(p);
+ return 0;
+
+fail:
+ archive_write_free(w);
+ archive_read_free(r);
+ free(p);
+ rte_panic("Failed: %s\n", archive_error_string(r));
+ return -1;
+}
+
+int resource_rm_by_tar(const struct resource *res)
+{
+ struct archive *r;
+ struct archive_entry *e;
+ void *p;
+ int try_again = 1;
+ int ret;
+
+ p = malloc(resource_size(res));
+ if (p == NULL)
+ rte_panic("Failed to malloc %zu B\n", resource_size(res));
+
+ memcpy(p, res->beg, resource_size(res));
+
+ while (try_again) {
+ r = archive_read_new();
+ if (r == NULL) {
+ free(p);
+