diff options
Diffstat (limited to 'lib/sqfs')
-rw-r--r-- | lib/sqfs/Makemodule.am | 5 | ||||
-rw-r--r-- | lib/sqfs/src/xattr/xattr.c | 96 | ||||
-rw-r--r-- | lib/sqfs/test/xattr.c | 111 |
3 files changed, 211 insertions, 1 deletions
diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am index 3500aad..d54134c 100644 --- a/lib/sqfs/Makemodule.am +++ b/lib/sqfs/Makemodule.am @@ -107,6 +107,9 @@ pkgconfig_DATA += lib/sqfs/libsquashfs1.pc test_abi_SOURCES = lib/sqfs/test/abi.c test_abi_LDADD = libsquashfs.la libcompat.a +test_xattr_SOURCES = lib/sqfs/test/xattr.c +test_xattr_LDADD = libsquashfs.la libcompat.a + test_table_SOURCES = lib/sqfs/test/table.c test_table_LDADD = libsquashfs.la libcompat.a @@ -120,7 +123,7 @@ test_get_node_path_SOURCES = lib/sqfs/test/get_node_path.c test_get_node_path_LDADD = libcommon.a libsquashfs.la libcompat.a LIBSQFS_TESTS = \ - test_abi test_table test_xattr_writer test_get_node_path + test_abi test_xattr test_table test_xattr_writer test_get_node_path noinst_PROGRAMS += xattr_benchmark diff --git a/lib/sqfs/src/xattr/xattr.c b/lib/sqfs/src/xattr/xattr.c index 29ecebf..9dc284d 100644 --- a/lib/sqfs/src/xattr/xattr.c +++ b/lib/sqfs/src/xattr/xattr.c @@ -8,8 +8,10 @@ #include "config.h" #include "sqfs/xattr.h" #include "sqfs/error.h" +#include "compat.h" #include <string.h> +#include <stdlib.h> static const struct { const char *prefix; @@ -47,3 +49,97 @@ const char *sqfs_get_xattr_prefix(SQFS_XATTR_TYPE id) return NULL; } + +static sqfs_xattr_t *mkxattr(const char *prefix, const char *key, + const sqfs_u8 *value, size_t value_len) +{ + size_t pfx_len = (prefix == NULL) ? 0 : strlen(prefix); + size_t key_len = strlen(key); + sqfs_xattr_t *out; + size_t len; + + /* len = pfx_len + (key_len + 1) + (value_len + 1) + sizeof(*out) */ + if (SZ_ADD_OV(pfx_len, key_len, &len)) + return NULL; + if (SZ_ADD_OV(len, value_len, &len)) + return NULL; + if (SZ_ADD_OV(len, 2, &len)) + return NULL; + if (SZ_ADD_OV(len, sizeof(*out), &len)) + return NULL; + + out = calloc(1, len); + + if (out != NULL) { + size_t value_offset = pfx_len + key_len + 1; + + out->key = (const char *)out->data; + out->value = out->data + value_offset; + out->value_len = value_len; + + if (prefix != NULL) + memcpy(out->data, prefix, pfx_len); + + memcpy(out->data + pfx_len, key, key_len); + memcpy(out->data + value_offset, value, value_len); + } + + return out; +} + +sqfs_xattr_t *sqfs_xattr_create(const char *key, const sqfs_u8 *value, + size_t value_len) +{ + return mkxattr(NULL, key, value, value_len); +} + +int sqfs_xattr_create_prefixed(sqfs_xattr_t **out, sqfs_u16 id, + const char *key, const sqfs_u8 *value, + size_t value_len) +{ + const char *prefix = sqfs_get_xattr_prefix(id & (~SQFS_XATTR_FLAG_OOL)); + + if (prefix == NULL) { + *out = NULL; + return SQFS_ERROR_UNSUPPORTED; + } + + *out = mkxattr(prefix, key, value, value_len); + if (*out == NULL) + return SQFS_ERROR_ALLOC; + + return 0; +} + +sqfs_xattr_t *sqfs_xattr_list_copy(const sqfs_xattr_t *list) +{ + sqfs_xattr_t *copy = NULL, *copy_last = NULL; + + for (const sqfs_xattr_t *it = list; it != NULL; it = it->next) { + sqfs_xattr_t *new = mkxattr(NULL, it->key, + it->value, it->value_len); + if (new == NULL) { + sqfs_xattr_list_free(copy); + return NULL; + } + + if (copy_last == NULL) { + copy = new; + } else { + copy_last->next = new; + } + + copy_last = new; + } + + return copy; +} + +void sqfs_xattr_list_free(sqfs_xattr_t *list) +{ + while (list != NULL) { + sqfs_xattr_t *old = list; + list = list->next; + free(old); + } +} diff --git a/lib/sqfs/test/xattr.c b/lib/sqfs/test/xattr.c new file mode 100644 index 0000000..a5222f4 --- /dev/null +++ b/lib/sqfs/test/xattr.c @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * xattr.c + * + * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "compat.h" +#include "util/test.h" + +#include "sqfs/xattr.h" +#include "sqfs/error.h" + +int main(int argc, char **argv) +{ + sqfs_xattr_t *ent, *ent2, *list; + const char *str; + int id, ret; + (void)argc; (void)argv; + + /* prefix API */ + id = sqfs_get_xattr_prefix_id("user.mime_type"); + TEST_EQUAL_I(id, SQFS_XATTR_USER); + + str = sqfs_get_xattr_prefix(id); + TEST_STR_EQUAL(str, "user."); + + id = sqfs_get_xattr_prefix_id("security.selinux"); + TEST_EQUAL_I(id, SQFS_XATTR_SECURITY); + + str = sqfs_get_xattr_prefix(id); + TEST_STR_EQUAL(str, "security."); + + id = sqfs_get_xattr_prefix_id("trusted.bla"); + TEST_EQUAL_I(id, SQFS_XATTR_TRUSTED); + + str = sqfs_get_xattr_prefix(id); + TEST_STR_EQUAL(str, "trusted."); + + id = sqfs_get_xattr_prefix_id("system.acl"); + TEST_EQUAL_I(id, SQFS_ERROR_UNSUPPORTED); + + str = sqfs_get_xattr_prefix(id); + TEST_NULL(str); + + /* combined entry API */ + ent = sqfs_xattr_create("foo.bar", (const sqfs_u8 *)"Hello, World!", 5); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->value_len, 5); + TEST_STR_EQUAL(ent->key, "foo.bar"); + TEST_STR_EQUAL((const char *)ent->value, "Hello"); + sqfs_xattr_list_free(ent); + + /* with prefix */ + ret = sqfs_xattr_create_prefixed(&ent, SQFS_XATTR_SECURITY, "selinux", + (const sqfs_u8 *)"Hello, World!", 5); + TEST_EQUAL_I(ret, 0); + TEST_NOT_NULL(ent); + TEST_EQUAL_UI(ent->value_len, 5); + TEST_STR_EQUAL(ent->key, "security.selinux"); + TEST_STR_EQUAL((const char *)ent->value, "Hello"); + sqfs_xattr_list_free(ent); + + ret = sqfs_xattr_create_prefixed(&ent, 42, "selinux", + (const sqfs_u8 *)"Hello, World!", 5); + TEST_EQUAL_I(ret, SQFS_ERROR_UNSUPPORTED); + TEST_NULL(ent); + + /* list copy */ + ent = sqfs_xattr_create("foo.bar", (const sqfs_u8 *)"Hello, World!", 5); + TEST_NOT_NULL(ent); + + ent2 = sqfs_xattr_create("bla.blu", (const sqfs_u8 *)"test", 4); + TEST_NOT_NULL(ent2); + + list = sqfs_xattr_list_copy(NULL); + TEST_NULL(list); + + list = sqfs_xattr_list_copy(ent); + TEST_NOT_NULL(list); + TEST_ASSERT(list != ent); + TEST_STR_EQUAL(list->key, ent->key); + TEST_STR_EQUAL((const char *)list->value, (const char *)ent->value); + TEST_EQUAL_UI(list->value_len, ent->value_len); + sqfs_xattr_list_free(list); + + ent->next = ent2; + ent2->next = NULL; + + list = sqfs_xattr_list_copy(ent); + TEST_NOT_NULL(list); + TEST_ASSERT(list != ent && list != ent2); + TEST_STR_EQUAL(list->key, ent->key); + TEST_STR_EQUAL((const char *)list->value, (const char *)ent->value); + TEST_EQUAL_UI(list->value_len, ent->value_len); + + TEST_NOT_NULL(list->next); + TEST_ASSERT(list->next != ent && list->next != ent2); + TEST_STR_EQUAL(list->next->key, ent2->key); + TEST_STR_EQUAL((const char *)list->next->value, + (const char *)ent2->value); + TEST_EQUAL_UI(list->next->value_len, ent2->value_len); + sqfs_xattr_list_free(list); + + ent->next = NULL; + ent2->next = NULL; + sqfs_xattr_list_free(ent); + sqfs_xattr_list_free(ent2); + + return EXIT_SUCCESS; +} |