aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/src/xattr/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/src/xattr/xattr.c')
-rw-r--r--lib/sqfs/src/xattr/xattr.c96
1 files changed, 96 insertions, 0 deletions
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);
+ }
+}