From 223dcc487cb0115d3ccb0dd6464d20346253a43e Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Tue, 11 Jun 2019 12:48:51 +0200 Subject: Move write_xattr to libsqfs.a Signed-off-by: David Oberhollenzer --- include/highlevel.h | 8 ++ lib/Makemodule.am | 2 +- lib/sqfs/write_xattr.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++ mkfs/Makemodule.am | 3 +- mkfs/mkfs.h | 3 - mkfs/xattr.c | 202 ------------------------------------------------ 6 files changed, 215 insertions(+), 208 deletions(-) create mode 100644 lib/sqfs/write_xattr.c delete mode 100644 mkfs/xattr.c diff --git a/include/highlevel.h b/include/highlevel.h index f61ad0b..4bc3b7a 100644 --- a/include/highlevel.h +++ b/include/highlevel.h @@ -67,4 +67,12 @@ tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode, int deserialize_fstree(fstree_t *out, sqfs_super_t *super, compressor_t *cmp, int fd, int flags); +/* + Generate a squahfs xattr table from a file system tree. + + Returns 0 on success. Prints error messages to stderr on failure. + */ +int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, + compressor_t *cmp); + #endif /* HIGHLEVEL_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index 1b99a05..3c1ef12 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -22,7 +22,7 @@ libsquashfs_a_SOURCES += lib/sqfs/write_dir.c lib/sqfs/write_inode.c libsquashfs_a_SOURCES += lib/sqfs/serialize_fstree.c libsquashfs_a_SOURCES += lib/sqfs/tree_node_from_inode.c libsquashfs_a_SOURCES += lib/sqfs/deserialize_fstree.c -libsquashfs_a_SOURCES += lib/sqfs/data_writer.c +libsquashfs_a_SOURCES += lib/sqfs/data_writer.c lib/sqfs/write_xattr.c libsquashfs_a_SOURCES += include/data_writer.h libsquashfs_a_SOURCES += include/frag_reader.h diff --git a/lib/sqfs/write_xattr.c b/lib/sqfs/write_xattr.c new file mode 100644 index 0000000..b6198b4 --- /dev/null +++ b/lib/sqfs/write_xattr.c @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "meta_writer.h" +#include "highlevel.h" +#include "util.h" + +#include +#include +#include +#include + +static const struct { + const char *prefix; + E_SQFS_XATTR_TYPE type; +} xattr_types[] = { + { "user.", SQUASHFS_XATTR_USER }, + { "trusted.", SQUASHFS_XATTR_TRUSTED }, + { "security.", SQUASHFS_XATTR_SECURITY }, +}; + +static int get_prefix(const char *key) +{ + size_t i, len; + + for (i = 0; i < sizeof(xattr_types) / sizeof(xattr_types[0]); ++i) { + len = strlen(xattr_types[i].prefix); + + if (strncmp(key, xattr_types[i].prefix, len) == 0 && + strlen(key) > len) { + return xattr_types[i].type; + } + } + + fprintf(stderr, "unknown xattr key '%s'\n", key); + return -1; +} + +static int write_pair(meta_writer_t *mw, const char *key, const char *value) +{ + sqfs_xattr_entry_t kent; + sqfs_xattr_value_t vent; + int type; + + type = get_prefix(key); + if (type < 0) + return -1; + + key = strchr(key, '.'); + assert(key != NULL); + ++key; + + kent.type = htole16(type); + kent.size = htole16(strlen(key)); + + if (meta_writer_append(mw, &kent, sizeof(kent))) + return -1; + if (meta_writer_append(mw, key, strlen(key))) + return -1; + + vent.size = htole32(strlen(value)); + + if (meta_writer_append(mw, &vent, sizeof(vent))) + return -1; + if (meta_writer_append(mw, value, strlen(value))) + return -1; + + return 0; +} + +static int write_kv_pairs(fstree_t *fs, meta_writer_t *mw, tree_xattr_t *xattr) +{ + uint32_t key_idx, val_idx; + const char *key, *value; + size_t i; + + for (i = 0; i < xattr->num_attr; ++i) { + key_idx = (xattr->ref[i] >> 32) & 0xFFFFFFFF; + val_idx = xattr->ref[i] & 0xFFFFFFFF; + + key = str_table_get_string(&fs->xattr_keys, key_idx); + value = str_table_get_string(&fs->xattr_values, val_idx); + + if (write_pair(mw, key, value)) + return -1; + + xattr->size += sizeof(sqfs_xattr_entry_t) + strlen(key); + xattr->size += sizeof(sqfs_xattr_value_t) + strlen(value); + } + + return 0; +} + +int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, + compressor_t *cmp) +{ + uint64_t kv_start, id_start, block, *tbl; + size_t i = 0, count = 0, blocks; + sqfs_xattr_id_table_t idtbl; + sqfs_xattr_id_t id_ent; + meta_writer_t *mw; + tree_xattr_t *it; + uint32_t offset; + ssize_t ret; + + if (fs->xattr == NULL) + return 0; + + mw = meta_writer_create(outfd, cmp); + if (mw == NULL) + return -1; + + /* write xattr key-value pairs */ + kv_start = super->bytes_used; + + for (it = fs->xattr; it != NULL; it = it->next) { + meta_writer_get_position(mw, &it->block, &it->offset); + it->size = 0; + + if (write_kv_pairs(fs, mw, it)) + goto fail_mw; + + ++count; + } + + if (meta_writer_flush(mw)) + goto fail_mw; + + meta_writer_get_position(mw, &block, &offset); + meta_writer_reset(mw); + + super->bytes_used += block; + + /* allocate location table */ + blocks = (count * sizeof(id_ent)) / SQFS_META_BLOCK_SIZE; + + if ((count * sizeof(id_ent)) % SQFS_META_BLOCK_SIZE) + ++blocks; + + tbl = calloc(sizeof(uint64_t), 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; + tbl[i++] = htole64(super->bytes_used); + + 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 (meta_writer_append(mw, &id_ent, sizeof(id_ent))) + goto fail_tbl; + + meta_writer_get_position(mw, &block, &offset); + + if (block != id_start) { + id_start = block; + tbl[i++] = htole64(super->bytes_used + id_start); + } + } + + if (meta_writer_flush(mw)) + goto fail_tbl; + + meta_writer_get_position(mw, &block, &offset); + super->bytes_used += block; + + /* write offset table */ + idtbl.xattr_table_start = htole64(kv_start); + idtbl.xattr_ids = htole32(count); + idtbl.unused = 0; + + ret = write_retry(outfd, &idtbl, sizeof(idtbl)); + if (ret < 0) + goto fail_wr; + if ((size_t)ret < sizeof(idtbl)) + goto fail_trunc; + + write_retry(outfd, tbl, sizeof(tbl[0]) * blocks); + if (ret < 0) + goto fail_wr; + if ((size_t)ret < sizeof(tbl[0]) * blocks) + goto fail_trunc; + + super->xattr_id_table_start = super->bytes_used; + super->bytes_used += sizeof(idtbl) + sizeof(tbl[0]) * blocks; + + free(tbl); + meta_writer_destroy(mw); + return 0; +fail_wr: + perror("writing xattr ID table"); + goto fail_tbl; +fail_trunc: + fputs("writing xattr ID table: truncated write\n", stderr); + goto fail_tbl; +fail_tbl: + free(tbl); +fail_mw: + meta_writer_destroy(mw); + return -1; +} diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am index 3dd639d..fac5eec 100644 --- a/mkfs/Makemodule.am +++ b/mkfs/Makemodule.am @@ -1,5 +1,4 @@ -gensquashfs_SOURCES = mkfs/mkfs.c mkfs/mkfs.h mkfs/block.c -gensquashfs_SOURCES += mkfs/options.c mkfs/xattr.c +gensquashfs_SOURCES = mkfs/mkfs.c mkfs/mkfs.h mkfs/block.c mkfs/options.c gensquashfs_LDADD = libsquashfs.a libfstree.a libcompress.a libutil.a gensquashfs_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h index f08ef5a..e7a339f 100644 --- a/mkfs/mkfs.h +++ b/mkfs/mkfs.h @@ -49,9 +49,6 @@ typedef struct { void process_command_line(options_t *opt, int argc, char **argv); -int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, - compressor_t *cmp); - int write_data_to_image(data_writer_t *data, sqfs_info_t *info); #endif /* MKFS_H */ diff --git a/mkfs/xattr.c b/mkfs/xattr.c deleted file mode 100644 index 237f5d4..0000000 --- a/mkfs/xattr.c +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -#include "meta_writer.h" -#include "mkfs.h" -#include "util.h" - -#include - -static const struct { - const char *prefix; - E_SQFS_XATTR_TYPE type; -} xattr_types[] = { - { "user.", SQUASHFS_XATTR_USER }, - { "trusted.", SQUASHFS_XATTR_TRUSTED }, - { "security.", SQUASHFS_XATTR_SECURITY }, -}; - -static int get_prefix(const char *key) -{ - size_t i, len; - - for (i = 0; i < sizeof(xattr_types) / sizeof(xattr_types[0]); ++i) { - len = strlen(xattr_types[i].prefix); - - if (strncmp(key, xattr_types[i].prefix, len) == 0 && - strlen(key) > len) { - return xattr_types[i].type; - } - } - - fprintf(stderr, "unknown xattr key '%s'\n", key); - return -1; -} - -static int write_pair(meta_writer_t *mw, const char *key, const char *value) -{ - sqfs_xattr_entry_t kent; - sqfs_xattr_value_t vent; - int type; - - type = get_prefix(key); - if (type < 0) - return -1; - - key = strchr(key, '.'); - assert(key != NULL); - ++key; - - kent.type = htole16(type); - kent.size = htole16(strlen(key)); - - if (meta_writer_append(mw, &kent, sizeof(kent))) - return -1; - if (meta_writer_append(mw, key, strlen(key))) - return -1; - - vent.size = htole32(strlen(value)); - - if (meta_writer_append(mw, &vent, sizeof(vent))) - return -1; - if (meta_writer_append(mw, value, strlen(value))) - return -1; - - return 0; -} - -static int write_kv_pairs(fstree_t *fs, meta_writer_t *mw, tree_xattr_t *xattr) -{ - uint32_t key_idx, val_idx; - const char *key, *value; - size_t i; - - for (i = 0; i < xattr->num_attr; ++i) { - key_idx = (xattr->ref[i] >> 32) & 0xFFFFFFFF; - val_idx = xattr->ref[i] & 0xFFFFFFFF; - - key = str_table_get_string(&fs->xattr_keys, key_idx); - value = str_table_get_string(&fs->xattr_values, val_idx); - - if (write_pair(mw, key, value)) - return -1; - - xattr->size += sizeof(sqfs_xattr_entry_t) + strlen(key); - xattr->size += sizeof(sqfs_xattr_value_t) + strlen(value); - } - - return 0; -} - -int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, - compressor_t *cmp) -{ - uint64_t kv_start, id_start, block, *tbl; - size_t i = 0, count = 0, blocks; - sqfs_xattr_id_table_t idtbl; - sqfs_xattr_id_t id_ent; - meta_writer_t *mw; - tree_xattr_t *it; - uint32_t offset; - ssize_t ret; - - if (fs->xattr == NULL) - return 0; - - mw = meta_writer_create(outfd, cmp); - if (mw == NULL) - return -1; - - /* write xattr key-value pairs */ - kv_start = super->bytes_used; - - for (it = fs->xattr; it != NULL; it = it->next) { - meta_writer_get_position(mw, &it->block, &it->offset); - it->size = 0; - - if (write_kv_pairs(fs, mw, it)) - goto fail_mw; - - ++count; - } - - if (meta_writer_flush(mw)) - goto fail_mw; - - meta_writer_get_position(mw, &block, &offset); - meta_writer_reset(mw); - - super->bytes_used += block; - - /* allocate location table */ - blocks = (count * sizeof(id_ent)) / SQFS_META_BLOCK_SIZE; - - if ((count * sizeof(id_ent)) % SQFS_META_BLOCK_SIZE) - ++blocks; - - tbl = calloc(sizeof(uint64_t), 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; - tbl[i++] = htole64(super->bytes_used); - - 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 (meta_writer_append(mw, &id_ent, sizeof(id_ent))) - goto fail_tbl; - - meta_writer_get_position(mw, &block, &offset); - - if (block != id_start) { - id_start = block; - tbl[i++] = htole64(super->bytes_used + id_start); - } - } - - if (meta_writer_flush(mw)) - goto fail_tbl; - - meta_writer_get_position(mw, &block, &offset); - super->bytes_used += block; - - /* write offset table */ - idtbl.xattr_table_start = htole64(kv_start); - idtbl.xattr_ids = htole32(count); - idtbl.unused = 0; - - ret = write_retry(outfd, &idtbl, sizeof(idtbl)); - if (ret < 0) - goto fail_wr; - if ((size_t)ret < sizeof(idtbl)) - goto fail_trunc; - - write_retry(outfd, tbl, sizeof(tbl[0]) * blocks); - if (ret < 0) - goto fail_wr; - if ((size_t)ret < sizeof(tbl[0]) * blocks) - goto fail_trunc; - - super->xattr_id_table_start = super->bytes_used; - super->bytes_used += sizeof(idtbl) + sizeof(tbl[0]) * blocks; - - free(tbl); - meta_writer_destroy(mw); - return 0; -fail_wr: - perror("writing xattr ID table"); - goto fail_tbl; -fail_trunc: - fputs("writing xattr ID table: truncated write\n", stderr); - goto fail_tbl; -fail_tbl: - free(tbl); -fail_mw: - meta_writer_destroy(mw); - return -1; -} -- cgit v1.2.3