diff options
Diffstat (limited to 'lib/sqfshelper')
-rw-r--r-- | lib/sqfshelper/Makemodule.am | 3 | ||||
-rw-r--r-- | lib/sqfshelper/serialize_fstree.c | 2 | ||||
-rw-r--r-- | lib/sqfshelper/tree_node_to_inode.c | 41 | ||||
-rw-r--r-- | lib/sqfshelper/write_xattr.c | 278 |
4 files changed, 13 insertions, 311 deletions
diff --git a/lib/sqfshelper/Makemodule.am b/lib/sqfshelper/Makemodule.am index 896605a..2ae1ac2 100644 --- a/lib/sqfshelper/Makemodule.am +++ b/lib/sqfshelper/Makemodule.am @@ -6,8 +6,7 @@ libsqfshelper_a_SOURCES += lib/sqfshelper/print_version.c libsqfshelper_a_SOURCES += lib/sqfshelper/inode_stat.c libsqfshelper_a_SOURCES += lib/sqfshelper/data_reader_dump.c libsqfshelper_a_SOURCES += lib/sqfshelper/compress.c lib/sqfshelper/comp_opt.c -libsqfshelper_a_SOURCES += lib/sqfshelper/data_writer.c -libsqfshelper_a_SOURCES += lib/sqfshelper/write_xattr.c include/highlevel.h +libsqfshelper_a_SOURCES += lib/sqfshelper/data_writer.c include/highlevel.h libsqfshelper_a_SOURCES += lib/sqfshelper/get_path.c lib/sqfshelper/io_stdin.c noinst_LIBRARIES += libsqfshelper.a diff --git a/lib/sqfshelper/serialize_fstree.c b/lib/sqfshelper/serialize_fstree.c index 2ec7daa..9a122ac 100644 --- a/lib/sqfshelper/serialize_fstree.c +++ b/lib/sqfshelper/serialize_fstree.c @@ -36,7 +36,7 @@ static sqfs_inode_generic_t *write_dir_entries(sqfs_dir_writer_t *dirw, if (sqfs_dir_writer_end(dirw)) return NULL; - xattr = (node->xattr == NULL) ? 0xFFFFFFFF : node->xattr->index; + xattr = node->xattr_idx; parent_inode = (node->parent == NULL) ? 1 : node->parent->inode_num; inode = sqfs_dir_writer_create_inode(dirw, 0, xattr, parent_inode); diff --git a/lib/sqfshelper/tree_node_to_inode.c b/lib/sqfshelper/tree_node_to_inode.c index d75e959..bafaaf7 100644 --- a/lib/sqfshelper/tree_node_to_inode.c +++ b/lib/sqfshelper/tree_node_to_inode.c @@ -18,26 +18,11 @@ static int get_type(tree_node_t *node) { switch (node->mode & S_IFMT) { - case S_IFSOCK: - if (node->xattr != NULL) - return SQFS_INODE_EXT_SOCKET; - return SQFS_INODE_SOCKET; - case S_IFIFO: - if (node->xattr != NULL) - return SQFS_INODE_EXT_FIFO; - return SQFS_INODE_FIFO; - case S_IFLNK: - if (node->xattr != NULL) - return SQFS_INODE_EXT_SLINK; - return SQFS_INODE_SLINK; - case S_IFBLK: - if (node->xattr != NULL) - return SQFS_INODE_EXT_BDEV; - return SQFS_INODE_BDEV; - case S_IFCHR: - if (node->xattr != NULL) - return SQFS_INODE_EXT_CDEV; - return SQFS_INODE_CDEV; + case S_IFSOCK: return SQFS_INODE_SOCKET; + case S_IFIFO: return SQFS_INODE_FIFO; + case S_IFLNK: return SQFS_INODE_SLINK; + case S_IFBLK: return SQFS_INODE_BDEV; + case S_IFCHR: return SQFS_INODE_CDEV; } assert(0); } @@ -47,7 +32,6 @@ sqfs_inode_generic_t *tree_node_to_inode(sqfs_id_table_t *idtbl, { sqfs_inode_generic_t *inode; sqfs_u16 uid_idx, gid_idx; - sqfs_u32 xattr = 0xFFFFFFFF; size_t extra = 0; if (S_ISREG(node->mode)) { @@ -78,8 +62,8 @@ sqfs_inode_generic_t *tree_node_to_inode(sqfs_id_table_t *idtbl, if (sqfs_id_table_id_to_index(idtbl, node->gid, &gid_idx)) goto fail; - if (node->xattr != NULL) - xattr = node->xattr->index; + if (node->xattr_idx != 0xFFFFFFFF) + sqfs_inode_make_extended(inode); inode->base.mode = node->mode; inode->base.uid_idx = uid_idx; @@ -95,7 +79,7 @@ sqfs_inode_generic_t *tree_node_to_inode(sqfs_id_table_t *idtbl, case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: inode->data.ipc_ext.nlink = 1; - inode->data.ipc_ext.xattr_idx = xattr; + inode->data.ipc_ext.xattr_idx = node->xattr_idx; break; case SQFS_INODE_SLINK: inode->data.slink.nlink = 1; @@ -104,7 +88,7 @@ sqfs_inode_generic_t *tree_node_to_inode(sqfs_id_table_t *idtbl, case SQFS_INODE_EXT_SLINK: inode->data.slink_ext.nlink = 1; inode->data.slink_ext.target_size = extra; - inode->data.slink_ext.xattr_idx = xattr; + inode->data.slink_ext.xattr_idx = node->xattr_idx; break; case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: @@ -115,15 +99,12 @@ sqfs_inode_generic_t *tree_node_to_inode(sqfs_id_table_t *idtbl, case SQFS_INODE_EXT_CDEV: inode->data.dev_ext.nlink = 1; inode->data.dev_ext.devno = node->data.devno; - inode->data.dev_ext.xattr_idx = xattr; + inode->data.dev_ext.xattr_idx = node->xattr_idx; break; case SQFS_INODE_FILE: - if (xattr != 0xFFFFFFFF) { - sqfs_inode_make_extended(inode); - inode->data.file_ext.xattr_idx = xattr; - } break; case SQFS_INODE_EXT_FILE: + inode->data.file_ext.xattr_idx = node->xattr_idx; break; default: goto fail; diff --git a/lib/sqfshelper/write_xattr.c b/lib/sqfshelper/write_xattr.c deleted file mode 100644 index a3f5170..0000000 --- a/lib/sqfshelper/write_xattr.c +++ /dev/null @@ -1,278 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * write_xattr.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "config.h" - -#include "sqfs/meta_writer.h" -#include "sqfs/xattr.h" -#include "highlevel.h" -#include "util.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -static int write_key(sqfs_meta_writer_t *mw, const char *key, - tree_xattr_t *xattr, bool value_is_ool) -{ - sqfs_xattr_entry_t kent; - int type; - - type = sqfs_get_xattr_prefix_id(key); - if (type < 0) { - fprintf(stderr, "unsupported xattr key '%s'\n", key); - return -1; - } - - key = strchr(key, '.'); - assert(key != NULL); - ++key; - - if (value_is_ool) - type |= SQFS_XATTR_FLAG_OOL; - - kent.type = htole16(type); - kent.size = htole16(strlen(key)); - - if (sqfs_meta_writer_append(mw, &kent, sizeof(kent))) - return -1; - if (sqfs_meta_writer_append(mw, key, strlen(key))) - return -1; - - xattr->size += sizeof(sqfs_xattr_entry_t) + strlen(key); - return 0; -} - -static int write_value(sqfs_meta_writer_t *mw, const char *value, - tree_xattr_t *xattr, sqfs_u64 *value_ref_out) -{ - sqfs_xattr_value_t vent; - sqfs_u32 offset; - sqfs_u64 block; - - sqfs_meta_writer_get_position(mw, &block, &offset); - *value_ref_out = (block << 16) | (offset & 0xFFFF); - - vent.size = htole32(strlen(value)); - - if (sqfs_meta_writer_append(mw, &vent, sizeof(vent))) - return -1; - - if (sqfs_meta_writer_append(mw, value, strlen(value))) - return -1; - - xattr->size += sizeof(vent) + strlen(value); - return 0; -} - -static int write_value_ool(sqfs_meta_writer_t *mw, sqfs_u64 location, - tree_xattr_t *xattr) -{ - sqfs_xattr_value_t vent; - sqfs_u64 ref; - - vent.size = htole32(sizeof(location)); - if (sqfs_meta_writer_append(mw, &vent, sizeof(vent))) - return -1; - - ref = htole64(location); - if (sqfs_meta_writer_append(mw, &ref, sizeof(ref))) - return -1; - - xattr->size += sizeof(vent) + sizeof(ref); - return 0; -} - -static bool should_store_ool(fstree_t *fs, const char *value, size_t index) -{ - size_t refcount; - - refcount = str_table_get_ref_count(&fs->xattr_values, index); - if (refcount < 2) - return false; - - /* - Storing in line needs this many bytes: refcount * len - - Storing out-of-line needs this many: len + (refcount - 1) * 8 - - Out-of-line prefereable if: - refcount * len > len + (refcount - 1) * 8 - => refcount * len - len > (refcount - 1) * 8 - => (refcount - 1) * len > (refcount - 1) * 8 - => len > 8 - - Note that this only holds iff refcount - 1 != 0, i.e. refcount > 1, - otherwise we would be dividing by 0 in the 3rd step. - */ - return strlen(value) > sizeof(sqfs_u64); -} - -static int write_kv_pairs(fstree_t *fs, sqfs_meta_writer_t *mw, - tree_xattr_t *xattr, sqfs_u64 *ool_locations) -{ - sqfs_u32 key_idx, val_idx; - const char *key, *value; - sqfs_u64 ref; - size_t i; - - for (i = 0; i < xattr->num_attr; ++i) { - key_idx = xattr->attr[i].key_index; - val_idx = xattr->attr[i].value_index; - - key = str_table_get_string(&fs->xattr_keys, key_idx); - value = str_table_get_string(&fs->xattr_values, val_idx); - - if (ool_locations[val_idx] == 0xFFFFFFFFFFFFFFFF) { - if (write_key(mw, key, xattr, false)) - return -1; - - if (write_value(mw, value, xattr, &ref)) - return -1; - - if (should_store_ool(fs, value, val_idx)) - ool_locations[val_idx] = ref; - } else { - if (write_key(mw, key, xattr, true)) - return -1; - - if (write_value_ool(mw, ool_locations[val_idx], xattr)) - return -1; - } - } - - return 0; -} - -static sqfs_u64 *create_ool_locations_table(fstree_t *fs) -{ - sqfs_u64 *table; - size_t i; - - table = alloc_array(sizeof(sqfs_u64), fs->xattr_values.num_strings); - - if (table == NULL) { - perror("allocating Xattr OOL locations table"); - return NULL; - } - - for (i = 0; i < fs->xattr_values.num_strings; ++i) { - table[i] = 0xFFFFFFFFFFFFFFFFUL; - } - - return table; -} - -int write_xattr(sqfs_file_t *file, fstree_t *fs, sqfs_super_t *super, - sqfs_compressor_t *cmp) -{ - sqfs_u64 kv_start, id_start, block, off, *tbl, *ool_locations; - size_t i = 0, count = 0, blocks; - sqfs_xattr_id_table_t idtbl; - sqfs_xattr_id_t id_ent; - sqfs_meta_writer_t *mw; - tree_xattr_t *it; - sqfs_u32 offset; - - if (fs->xattr == NULL) - return 0; - - ool_locations = create_ool_locations_table(fs); - if (ool_locations == NULL) - return -1; - - mw = sqfs_meta_writer_create(file, cmp, 0); - if (mw == NULL) - goto fail_ool; - - /* write xattr key-value pairs */ - kv_start = file->get_size(file); - - for (it = fs->xattr; it != NULL; it = it->next) { - sqfs_meta_writer_get_position(mw, &it->block, &it->offset); - it->size = 0; - - if (write_kv_pairs(fs, mw, it, ool_locations)) - goto fail_mw; - - ++count; - } - - if (sqfs_meta_writer_flush(mw)) - goto fail_mw; - - sqfs_meta_writer_reset(mw); - - /* allocate location table */ - blocks = (count * sizeof(id_ent)) / SQFS_META_BLOCK_SIZE; - - if ((count * sizeof(id_ent)) % SQFS_META_BLOCK_SIZE) - ++blocks; - - tbl = alloc_array(sizeof(sqfs_u64), blocks); - - if (tbl == NULL) { - perror("generating xattr ID table"); - goto fail_mw; - } - - /* write ID table referring to key value pairs, record offsets */ - id_start = 0; - off = file->get_size(file); - tbl[i++] = htole64(off); - - for (it = fs->xattr; it != NULL; it = it->next) { - id_ent.xattr = htole64((it->block << 16) | it->offset); - id_ent.count = htole32(it->num_attr); - id_ent.size = htole32(it->size); - - if (sqfs_meta_writer_append(mw, &id_ent, sizeof(id_ent))) - goto fail_tbl; - - sqfs_meta_writer_get_position(mw, &block, &offset); - - if (block != id_start) { - id_start = block; - tbl[i++] = htole64(off + id_start); - } - } - - if (sqfs_meta_writer_flush(mw)) - goto fail_tbl; - - /* write offset table */ - idtbl.xattr_table_start = htole64(kv_start); - idtbl.xattr_ids = htole32(count); - idtbl.unused = 0; - - super->xattr_id_table_start = file->get_size(file); - super->flags &= ~SQFS_FLAG_NO_XATTRS; - - if (file->write_at(file, super->xattr_id_table_start, - &idtbl, sizeof(idtbl))) { - perror("writing xattr ID table"); - goto fail_tbl; - } - - if (file->write_at(file, super->xattr_id_table_start + sizeof(idtbl), - tbl, sizeof(tbl[0]) * blocks)) { - perror("writing xattr ID table"); - goto fail_tbl; - } - - free(tbl); - sqfs_meta_writer_destroy(mw); - free(ool_locations); - return 0; -fail_tbl: - free(tbl); -fail_mw: - sqfs_meta_writer_destroy(mw); -fail_ool: - free(ool_locations); - return -1; -} |