* [PATCH 1/5] mkfs.ubifs: change add_directory argument to 'existing'
2015-10-16 15:15 [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Marc Kleine-Budde
@ 2015-10-16 15:15 ` Marc Kleine-Budde
2015-10-16 15:15 ` [PATCH 2/5] mkfs.ubifs: use xmalloc/xzalloc for allocating memory Marc Kleine-Budde
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2015-10-16 15:15 UTC (permalink / raw)
To: linux-mtd; +Cc: kernel, Sascha Hauer, Marc Kleine-Budde
From: Sascha Hauer <s.hauer@pengutronix.de>
A 'non_existing' argument which is only used with !non_existing
is just too confusing. Change this to positive logic.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
mkfs.ubifs/mkfs.ubifs.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index ca17e2bca3ac..1b816ae483e0 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -1395,12 +1395,12 @@ static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink,
* @dir_name: directory path name
* @dir_inum: UBIFS inode number of directory
* @st: directory inode statistics
- * @non_existing: non-zero if this function is called for a directory which
- * does not exist on the host file-system and it is being
- * created because it is defined in the device table file.
+ * @existing: zero if this function is called for a directory which
+ * does not exist on the host file-system and it is being
+ * created because it is defined in the device table file.
*/
static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
- int non_existing)
+ int existing)
{
struct dirent *entry;
DIR *dir = NULL;
@@ -1416,7 +1416,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
unsigned long long dir_creat_sqnum = ++c->max_sqnum;
dbg_msg(2, "%s", dir_name);
- if (!non_existing) {
+ if (existing) {
dir = opendir(dir_name);
if (dir == NULL)
return sys_err_msg("cannot open directory '%s'",
@@ -1434,7 +1434,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
* Before adding the directory itself, we have to iterate over all the
* entries the device table adds to this directory and create them.
*/
- for (; !non_existing;) {
+ for (; existing;) {
struct stat dent_st;
errno = 0;
@@ -1492,7 +1492,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
inum = ++c->highest_inum;
if (S_ISDIR(dent_st.st_mode)) {
- err = add_directory(name, inum, &dent_st, 0);
+ err = add_directory(name, inum, &dent_st, 1);
if (err)
goto out_free;
nlink += 1;
@@ -1544,7 +1544,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
inum = ++c->highest_inum;
if (S_ISDIR(nh_elt->mode)) {
- err = add_directory(name, inum, &fake_st, 1);
+ err = add_directory(name, inum, &fake_st, 0);
if (err)
goto out_free;
nlink += 1;
@@ -1570,14 +1570,14 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
goto out_free;
free(name);
- if (!non_existing && closedir(dir) == -1)
+ if (existing && closedir(dir) == -1)
return sys_err_msg("error closing directory '%s'", dir_name);
return 0;
out_free:
free(name);
- if (!non_existing)
+ if (existing)
closedir(dir);
return -1;
}
@@ -1624,7 +1624,7 @@ static int write_data(void)
}
head_flags = 0;
- err = add_directory(root, UBIFS_ROOT_INO, &root_st, !root);
+ err = add_directory(root, UBIFS_ROOT_INO, &root_st, !!root);
if (err)
return err;
err = add_multi_linked_files();
--
2.6.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 2/5] mkfs.ubifs: use xmalloc/xzalloc for allocating memory
2015-10-16 15:15 [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Marc Kleine-Budde
2015-10-16 15:15 ` [PATCH 1/5] mkfs.ubifs: change add_directory argument to 'existing' Marc Kleine-Budde
@ 2015-10-16 15:15 ` Marc Kleine-Budde
2015-10-16 15:15 ` [PATCH 3/5] mkfs.ubifs: simplify make_path with xasprintf Marc Kleine-Budde
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2015-10-16 15:15 UTC (permalink / raw)
To: linux-mtd; +Cc: kernel, Sascha Hauer, Marc Kleine-Budde
From: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
mkfs.ubifs/mkfs.ubifs.c | 64 +++++++++++--------------------------------------
1 file changed, 14 insertions(+), 50 deletions(-)
diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index 1b816ae483e0..049219b52cc5 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -259,13 +259,8 @@ static int is_contained(const char *file, const char *dir)
file_base = dirname(copy);
/* Turn the paths into the canonical form */
- real_file = malloc(PATH_MAX);
- if (!real_file)
- goto out_free;
-
- real_dir = malloc(PATH_MAX);
- if (!real_dir)
- goto out_free;
+ real_file = xmalloc(PATH_MAX);
+ real_dir = xmalloc(PATH_MAX);
if (!realpath(file_base, real_file)) {
perror("Could not canonicalize file path");
@@ -500,9 +495,7 @@ static int get_options(int argc, char**argv)
case 'r':
case 'd':
root_len = strlen(optarg);
- root = malloc(root_len + 2);
- if (!root)
- return err_msg("cannot allocate memory");
+ root = xmalloc(root_len + 2);
/*
* The further code expects '/' at the end of the root
@@ -910,9 +903,7 @@ static int add_to_index(union ubifs_key *key, char *name, int lnum, int offs,
struct idx_entry *e;
dbg_msg(3, "LEB %d offs %d len %d", lnum, offs, len);
- e = malloc(sizeof(struct idx_entry));
- if (!e)
- return err_msg("out of memory");
+ e = xmalloc(sizeof(struct idx_entry));
e->next = NULL;
e->prev = idx_list_last;
e->key = *key;
@@ -1193,9 +1184,7 @@ static struct inum_mapping *lookup_inum_mapping(dev_t dev, ino_t inum)
return im;
im = im->next;
}
- im = malloc(sizeof(struct inum_mapping));
- if (!im)
- return NULL;
+ im = xmalloc(sizeof(struct inum_mapping));
im->next = hash_table[k];
im->prev = NULL;
im->dev = dev;
@@ -1355,9 +1344,7 @@ static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink,
/* New entry */
im->use_inum = *inum;
im->use_nlink = 1;
- im->path_name = malloc(strlen(path_name) + 1);
- if (!im->path_name)
- return err_msg("out of memory");
+ im->path_name = xmalloc(strlen(path_name) + 1);
strcpy(im->path_name, path_name);
} else {
/* Existing entry */
@@ -1707,21 +1694,14 @@ static int write_index(void)
head_flags = LPROPS_INDEX;
/* Allocate index node */
idx_sz = ubifs_idx_node_sz(c, c->fanout);
- idx = malloc(idx_sz);
- if (!idx)
- return err_msg("out of memory");
+ idx = xmalloc(idx_sz);
/* Make an array of pointers to sort the index list */
sz = idx_cnt * sizeof(struct idx_entry *);
if (sz / sizeof(struct idx_entry *) != idx_cnt) {
free(idx);
return err_msg("index is too big (%zu entries)", idx_cnt);
}
- idx_ptr = malloc(sz);
- if (!idx_ptr) {
- free(idx);
- return err_msg("out of memory - needed %zu bytes for index",
- sz);
- }
+ idx_ptr = xmalloc(sz);
idx_ptr[0] = idx_list_first;
for (i = 1; i < idx_cnt; i++)
idx_ptr[i] = idx_ptr[i - 1]->next;
@@ -2164,13 +2144,8 @@ static int init(void)
c->lpt_first = UBIFS_LOG_LNUM + c->log_lebs;
c->lpt_last = c->lpt_first + c->lpt_lebs - 1;
- c->lpt = malloc(c->main_lebs * sizeof(struct ubifs_lprops));
- if (!c->lpt)
- return err_msg("unable to allocate LPT");
-
- c->ltab = malloc(c->lpt_lebs * sizeof(struct ubifs_lprops));
- if (!c->ltab)
- return err_msg("unable to allocate LPT ltab");
+ c->lpt = xmalloc(c->main_lebs * sizeof(struct ubifs_lprops));
+ c->ltab = xmalloc(c->lpt_lebs * sizeof(struct ubifs_lprops));
/* Initialize LPT's own lprops */
for (i = 0; i < c->lpt_lebs; i++) {
@@ -2182,23 +2157,12 @@ static int init(void)
c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size);
dbg_msg(1, "dead_wm %d dark_wm %d", c->dead_wm, c->dark_wm);
- leb_buf = malloc(c->leb_size);
- if (!leb_buf)
- return err_msg("out of memory");
-
- node_buf = malloc(NODE_BUFFER_SIZE);
- if (!node_buf)
- return err_msg("out of memory");
-
- block_buf = malloc(UBIFS_BLOCK_SIZE);
- if (!block_buf)
- return err_msg("out of memory");
+ leb_buf = xmalloc(c->leb_size);
+ node_buf = xmalloc(NODE_BUFFER_SIZE);
+ block_buf = xmalloc(UBIFS_BLOCK_SIZE);
sz = sizeof(struct inum_mapping *) * HASH_TABLE_SIZE;
- hash_table = malloc(sz);
- if (!hash_table)
- return err_msg("out of memory");
- memset(hash_table, 0, sz);
+ hash_table = xzalloc(sz);
err = init_compression();
if (err)
--
2.6.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/5] mkfs.ubifs: simplify make_path with xasprintf
2015-10-16 15:15 [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Marc Kleine-Budde
2015-10-16 15:15 ` [PATCH 1/5] mkfs.ubifs: change add_directory argument to 'existing' Marc Kleine-Budde
2015-10-16 15:15 ` [PATCH 2/5] mkfs.ubifs: use xmalloc/xzalloc for allocating memory Marc Kleine-Budde
@ 2015-10-16 15:15 ` Marc Kleine-Budde
2015-10-16 15:15 ` [PATCH 4/5] mkfs.ubifs: Add extended attribute support Marc Kleine-Budde
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2015-10-16 15:15 UTC (permalink / raw)
To: linux-mtd; +Cc: kernel, Sascha Hauer, Marc Kleine-Budde
From: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
mkfs.ubifs/mkfs.ubifs.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index 049219b52cc5..a99c61382304 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -227,13 +227,9 @@ static char *make_path(const char *dir, const char *name)
{
char *s;
- s = malloc(strlen(dir) + strlen(name) + 2);
- if (!s)
- return NULL;
- strcpy(s, dir);
- if (dir[strlen(dir) - 1] != '/')
- strcat(s, "/");
- strcat(s, name);
+ xasprintf(&s, "%s%s%s",
+ dir, dir[strlen(dir) - 1] == '/' ? "" : "/", name);
+
return s;
}
--
2.6.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 4/5] mkfs.ubifs: Add extended attribute support
2015-10-16 15:15 [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Marc Kleine-Budde
` (2 preceding siblings ...)
2015-10-16 15:15 ` [PATCH 3/5] mkfs.ubifs: simplify make_path with xasprintf Marc Kleine-Budde
@ 2015-10-16 15:15 ` Marc Kleine-Budde
2015-10-16 15:15 ` [PATCH 5/5] mkfs.ubifs: Optionally create extended attribute with inode number Marc Kleine-Budde
2015-11-11 14:56 ` [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Daniel Walter
5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2015-10-16 15:15 UTC (permalink / raw)
To: linux-mtd; +Cc: kernel, Sascha Hauer, Marc Kleine-Budde
From: Sascha Hauer <s.hauer@pengutronix.de>
This adds extended attribute support to mkfs.ubifs. When creating
an image from a directory tree the existing extended attributes are
added to the UBIFS image.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
mkfs.ubifs/key.h | 18 +++++
mkfs.ubifs/mkfs.ubifs.c | 201 +++++++++++++++++++++++++++++++++++++++++-------
mkfs.ubifs/ubifs.h | 9 +++
3 files changed, 201 insertions(+), 27 deletions(-)
diff --git a/mkfs.ubifs/key.h b/mkfs.ubifs/key.h
index d3a02d4ff1a6..39379fd48178 100644
--- a/mkfs.ubifs/key.h
+++ b/mkfs.ubifs/key.h
@@ -119,6 +119,24 @@ static inline void dent_key_init(const struct ubifs_info *c,
}
/**
+ * xent_key_init - initialize extended attribute entry key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ * @inum: host inode number
+ * @nm: extended attribute entry name and length
+ */
+static inline void xent_key_init(const struct ubifs_info *c,
+ union ubifs_key *key, ino_t inum,
+ const struct qstr *nm)
+{
+ uint32_t hash = c->key_hash(nm->name, nm->len);
+
+ ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
+ key->u32[0] = inum;
+ key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
+}
+
+/**
* data_key_init - initialize data key.
* @c: UBIFS file-system description object
* @key: key to initialize
diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index a99c61382304..30f80cf14992 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -25,6 +25,8 @@
#include "mkfs.ubifs.h"
#include <crc32.h>
#include "common.h"
+#include <sys/types.h>
+#include <attr/xattr.h>
/* Size (prime number) of hash table for link counting */
#define HASH_TABLE_SIZE 10099
@@ -980,20 +982,168 @@ static int add_node(union ubifs_key *key, char *name, void *node, int len)
return 0;
}
+int add_xattr(struct stat *st, ino_t inum, const void *data, unsigned int data_len,
+ struct qstr *nm)
+{
+ struct ubifs_ino_node *ino;
+ struct ubifs_dent_node *xent;
+ union ubifs_key xkey, nkey;
+ int len, ret;
+
+ xent = xzalloc(sizeof(*xent) + nm->len + 1);
+ ino = xzalloc(sizeof(*ino) + data_len);
+
+ xent_key_init(c, &xkey, inum, nm);
+ xent->ch.node_type = UBIFS_XENT_NODE;
+ key_write(&xkey, &xent->key);
+
+ len = UBIFS_XENT_NODE_SZ + nm->len + 1;
+
+ xent->ch.len = len;
+ xent->padding1 = 0;
+ xent->type = UBIFS_ITYPE_DIR;
+ xent->nlen = cpu_to_le16(nm->len);
+
+ memcpy(xent->name, nm->name, nm->len + 1);
+
+ inum = ++c->highest_inum;
+ creat_sqnum = ++c->max_sqnum;
+
+ xent->inum = cpu_to_le64(inum);
+
+ ret = add_node(&xkey, nm->name, xent, len);
+ if (ret)
+ goto out;
+
+ ino->creat_sqnum = cpu_to_le64(creat_sqnum);
+ ino->nlink = cpu_to_le32(st->st_nlink);
+ /*
+ * The time fields are updated assuming the default time granularity
+ * of 1 second. To support finer granularities, utime() would be needed.
+ */
+ ino->atime_sec = cpu_to_le64(st->st_atime);
+ ino->ctime_sec = cpu_to_le64(st->st_ctime);
+ ino->mtime_sec = cpu_to_le64(st->st_mtime);
+ ino->atime_nsec = 0;
+ ino->ctime_nsec = 0;
+ ino->mtime_nsec = 0;
+ ino->uid = cpu_to_le32(st->st_uid);
+ ino->gid = cpu_to_le32(st->st_gid);
+ ino->compr_type = cpu_to_le16(c->default_compr);
+ ino->ch.node_type = UBIFS_INO_NODE;
+
+ ino_key_init(&nkey, inum);
+ key_write(&nkey, &ino->key);
+
+ ino->size = cpu_to_le64(data_len);
+ ino->mode = cpu_to_le32(S_IFREG);
+ ino->data_len = cpu_to_le32(data_len);
+ ino->flags = cpu_to_le32(UBIFS_XATTR_FL);
+
+ if (data_len)
+ memcpy(&ino->data, data, data_len);
+
+ ret = add_node(&nkey, nm->name, ino, UBIFS_INO_NODE_SZ + data_len) ;
+
+out:
+ free(xent);
+ free(ino);
+
+ return ret;
+}
+
+static int inode_add_xattr(struct ubifs_ino_node *host_ino,
+ const char *path_name, struct stat *st, ino_t inum)
+{
+ int ret;
+ struct qstr nm;
+ void *buf = NULL;
+ ssize_t len;
+ ssize_t pos = 0;
+ void *attrval = NULL;
+
+ len = llistxattr(path_name, NULL, 0);
+ if (len < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ sys_err_msg("llistxattr failed on %s", path_name);
+
+ return len;
+ }
+
+ if (len == 0)
+ goto noxattr;
+
+ buf = xmalloc(len);
+
+ len = llistxattr(path_name, buf, len);
+ if (len < 0) {
+ sys_err_msg("llistxattr failed on %s", path_name);
+ goto out_free;
+ }
+
+ while (pos < len) {
+ char *name;
+ ssize_t attrsize;
+
+ name = buf + pos;
+ pos += strlen(name) + 1;
+
+ attrsize = lgetxattr(path_name, name, NULL, 0);
+ if (attrsize < 0) {
+ sys_err_msg("lgetxattr failed on %s", path_name);
+ goto out_free;
+ }
+
+ attrval = xmalloc(attrsize);
+ attrsize = lgetxattr(path_name, name, attrval, attrsize);
+ if (attrsize < 0) {
+ sys_err_msg("lgetxattr failed on %s", path_name);
+ goto out_free;
+ }
+
+ nm.name = name;
+ nm.len = strlen(name);
+
+ host_ino->xattr_cnt++;
+ host_ino->xattr_size += CALC_DENT_SIZE(nm.len);
+ host_ino->xattr_size += CALC_XATTR_BYTES(attrsize);
+ host_ino->xattr_names += nm.len;
+
+ ret = add_xattr(st, inum, attrval, attrsize, &nm);
+ if (ret < 0)
+ goto out_free;
+
+ free(attrval);
+ attrval = NULL;
+ }
+
+noxattr:
+ free(buf);
+ return 0;
+
+out_free:
+ free(buf);
+ free(attrval);
+
+ return -1;
+}
+
/**
- * add_inode_with_data - write an inode.
+ * add_inode - write an inode.
* @st: stat information of source inode
* @inum: target inode number
* @data: inode data (for special inodes e.g. symlink path etc)
* @data_len: inode data length
* @flags: source inode flags
*/
-static int add_inode_with_data(struct stat *st, ino_t inum, void *data,
- unsigned int data_len, int flags)
+static int add_inode(struct stat *st, ino_t inum, void *data,
+ unsigned int data_len, int flags, const char *xattr_path)
{
struct ubifs_ino_node *ino = node_buf;
union ubifs_key key;
- int len, use_flags = 0;
+ int len, use_flags = 0, ret;
if (c->default_compr != UBIFS_COMPR_NONE)
use_flags |= UBIFS_COMPR_FL;
@@ -1037,18 +1187,13 @@ static int add_inode_with_data(struct stat *st, ino_t inum, void *data,
len = UBIFS_INO_NODE_SZ + data_len;
- return add_node(&key, NULL, ino, len);
-}
+ if (xattr_path) {
+ ret = inode_add_xattr(ino, xattr_path, st, inum);
+ if (ret < 0)
+ return ret;
+ }
-/**
- * add_inode - write an inode.
- * @st: stat information of source inode
- * @inum: target inode number
- * @flags: source inode flags
- */
-static int add_inode(struct stat *st, ino_t inum, int flags)
-{
- return add_inode_with_data(st, inum, NULL, 0, flags);
+ return add_node(&key, NULL, ino, len);
}
/**
@@ -1064,8 +1209,8 @@ static int add_inode(struct stat *st, ino_t inum, int flags)
* is being created does not exist at the host file system, but is defined by
* the device table.
*/
-static int add_dir_inode(DIR *dir, ino_t inum, loff_t size, unsigned int nlink,
- struct stat *st)
+static int add_dir_inode(const char *path_name, DIR *dir, ino_t inum, loff_t size,
+ unsigned int nlink, struct stat *st)
{
int fd, flags = 0;
@@ -1080,7 +1225,7 @@ static int add_dir_inode(DIR *dir, ino_t inum, loff_t size, unsigned int nlink,
flags = 0;
}
- return add_inode(st, inum, flags);
+ return add_inode(st, inum, NULL, 0, flags, path_name);
}
/**
@@ -1089,12 +1234,12 @@ static int add_dir_inode(DIR *dir, ino_t inum, loff_t size, unsigned int nlink,
* @inum: target inode number
* @flags: source inode flags
*/
-static int add_dev_inode(struct stat *st, ino_t inum, int flags)
+static int add_dev_inode(const char *path_name, struct stat *st, ino_t inum, int flags)
{
union ubifs_dev_desc dev;
dev.huge = cpu_to_le64(makedev(major(st->st_rdev), minor(st->st_rdev)));
- return add_inode_with_data(st, inum, &dev, 8, flags);
+ return add_inode(st, inum, &dev, 8, flags, path_name);
}
/**
@@ -1117,7 +1262,7 @@ static int add_symlink_inode(const char *path_name, struct stat *st, ino_t inum,
if (len > UBIFS_MAX_INO_DATA)
return err_msg("symlink too long for %s", path_name);
- return add_inode_with_data(st, inum, buf, len, flags);
+ return add_inode(st, inum, buf, len, flags, path_name);
}
/**
@@ -1275,12 +1420,14 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
return err;
}
} while (ret != 0);
+
if (close(fd) == -1)
return sys_err_msg("failed to close file '%s'", path_name);
if (file_size != st->st_size)
return err_msg("file size changed during writing file '%s'",
path_name);
- return add_inode(st, inum, flags);
+
+ return add_inode(st, inum, NULL, 0, flags, path_name);
}
/**
@@ -1360,15 +1507,15 @@ static int add_non_dir(const char *path_name, ino_t *inum, unsigned int nlink,
if (S_ISREG(st->st_mode))
return add_file(path_name, st, *inum, flags);
if (S_ISCHR(st->st_mode))
- return add_dev_inode(st, *inum, flags);
+ return add_dev_inode(path_name, st, *inum, flags);
if (S_ISBLK(st->st_mode))
- return add_dev_inode(st, *inum, flags);
+ return add_dev_inode(path_name, st, *inum, flags);
if (S_ISLNK(st->st_mode))
return add_symlink_inode(path_name, st, *inum, flags);
if (S_ISSOCK(st->st_mode))
- return add_inode(st, *inum, flags);
+ return add_inode(st, *inum, NULL, 0, flags, NULL);
if (S_ISFIFO(st->st_mode))
- return add_inode(st, *inum, flags);
+ return add_inode(st, *inum, NULL, 0, flags, NULL);
return err_msg("file '%s' has unknown inode type", path_name);
}
@@ -1548,7 +1695,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
creat_sqnum = dir_creat_sqnum;
- err = add_dir_inode(dir, dir_inum, size, nlink, st);
+ err = add_dir_inode(dir ? dir_name : NULL, dir, dir_inum, size, nlink, st);
if (err)
goto out_free;
diff --git a/mkfs.ubifs/ubifs.h b/mkfs.ubifs/ubifs.h
index 434b651859b3..2f080a8ce708 100644
--- a/mkfs.ubifs/ubifs.h
+++ b/mkfs.ubifs/ubifs.h
@@ -42,6 +42,15 @@
*/
#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT
+/*
+ * How much a directory entry/extended attribute entry adds to the parent/host
+ * inode.
+ */
+#define CALC_DENT_SIZE(name_len) ALIGN(UBIFS_DENT_NODE_SZ + (name_len) + 1, 8)
+
+/* How much an extended attribute adds to the host inode */
+#define CALC_XATTR_BYTES(data_len) ALIGN(UBIFS_INO_NODE_SZ + (data_len) + 1, 8)
+
/* The below union makes it easier to deal with keys */
union ubifs_key
{
--
2.6.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 5/5] mkfs.ubifs: Optionally create extended attribute with inode number
2015-10-16 15:15 [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Marc Kleine-Budde
` (3 preceding siblings ...)
2015-10-16 15:15 ` [PATCH 4/5] mkfs.ubifs: Add extended attribute support Marc Kleine-Budde
@ 2015-10-16 15:15 ` Marc Kleine-Budde
2015-11-11 14:56 ` [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Daniel Walter
5 siblings, 0 replies; 7+ messages in thread
From: Marc Kleine-Budde @ 2015-10-16 15:15 UTC (permalink / raw)
To: linux-mtd; +Cc: kernel, Sascha Hauer, Marc Kleine-Budde
From: Sascha Hauer <s.hauer@pengutronix.de>
This is done to allow creating images suitable for IMA directory
appraisal. IMA creates a hash for directories and attaches this
hash to the directory itself as an extended attribute. Among other
things the inode numbers of the files are hashed. So, to create
a valid hash in the UBIFS image the evmctl tool needs to know
the inode numbers which the files in the UBIFS image will have.
evmctl will read the inode numbers from the user.image-inode-number
extended attribute. Since extended attributes are inodes themselves
the inode numbers for the generated image will change when the
extended attributes change, so to generate a correctly hashed
UBIFS image, both evmctl and mkfs.ubifs must be run twice:
1) execute evmctl to iterate over the directory tree. This will
create the security.ima and security.evm extended attributes.
The existence of the attributes makes sure that subsequent
calls to mkfs.ubifs will use the same inode numbers. evmctl
will use the inode numbers from the host filesystem in this
step which makes the resulting image unusable
2) execute mkfs.ubifs -a. This will create the user.image-inode-number
extended attributes on files/directories added to the image.
3) execture evmctl again. This time evmctl will pick the inode
numbers from the user.image-inode-number extended attribute
instead of the ones from the host filesystem
4) execute mkfs.ubifs again. This will create the correct image.
The now existing user.image-inode-number extended attributes
are ignored and not added to the image.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
mkfs.ubifs/mkfs.ubifs.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index 30f80cf14992..cbc9db9b185a 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -113,6 +113,7 @@ static char *output;
static int out_fd;
static int out_ubi;
static int squash_owner;
+static int do_create_inum_attr;
/* The 'head' (position) which nodes are written */
static int head_lnum;
@@ -135,7 +136,7 @@ static struct inum_mapping **hash_table;
/* Inode creation sequence number */
static unsigned long long creat_sqnum;
-static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQq";
+static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQqa";
static const struct option longopts[] = {
{"root", 1, NULL, 'r'},
@@ -159,6 +160,7 @@ static const struct option longopts[] = {
{"log-lebs", 1, NULL, 'l'},
{"orph-lebs", 1, NULL, 'p'},
{"squash-uids" , 0, NULL, 'U'},
+ {"set-inode-attr", 0, NULL, 'a'},
{NULL, 0, NULL, 0}
};
@@ -199,6 +201,9 @@ static const char *helptext =
"-V, --version display version information\n"
"-g, --debug=LEVEL display debug information (0 - none, 1 - statistics,\n"
" 2 - files, 3 - more details)\n"
+"-a, --set-inum-attr create user.image-inode-number extended attribute on files\n"
+" added to the image. The attribute will contain the inode\n"
+" number the file has in the generated image.\n"
"-h, --help display this help text\n\n"
"Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
"Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n\n"
@@ -220,6 +225,25 @@ static const char *helptext =
"flag may make the first mount very slow, because the \"free space fixup\" procedure\n"
"takes time. This feature is supported by the Linux kernel starting from version 3.0.\n";
+static int create_inum_attr(ino_t inum, const char *name)
+{
+ char *str;
+ int ret;
+
+ if (!do_create_inum_attr)
+ return 0;
+
+ ret = asprintf(&str, "%llu", (unsigned long long)inum);
+ if (ret < 0)
+ return -1;
+
+ ret = lsetxattr(name, "user.image-inode-number", str, ret, 0);
+
+ free(str);
+
+ return ret;
+}
+
/**
* make_path - make a path name from a directory and a name.
* @dir: directory path name
@@ -614,6 +638,10 @@ static int get_options(int argc, char**argv)
case 'U':
squash_owner = 1;
break;
+ case 'a':
+ do_create_inum_attr = 1;
+ break;
+
}
}
@@ -1103,6 +1131,24 @@ static int inode_add_xattr(struct ubifs_ino_node *host_ino,
goto out_free;
}
+ if (!strcmp(name, "user.image-inode-number")) {
+ ino_t inum_from_xattr;
+
+ inum_from_xattr = strtoull(attrval, NULL, 10);
+ if (inum != inum_from_xattr) {
+ errno = EINVAL;
+ sys_err_msg("calculated inum (%llu) doesn't match inum from xattr (%llu) on %s",
+ (unsigned long long)inum,
+ (unsigned long long)inum_from_xattr,
+ path_name);
+ goto out_free;
+ }
+
+ free(attrval);
+ attrval = NULL;
+ continue;
+ }
+
nm.name = name;
nm.len = strlen(name);
@@ -1633,6 +1679,10 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
goto out_free;
}
+ err = create_inum_attr(inum, name);
+ if (err)
+ goto out_free;
+
err = add_dent_node(dir_inum, entry->d_name, inum, type);
if (err)
goto out_free;
@@ -1685,6 +1735,10 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
goto out_free;
}
+ err = create_inum_attr(inum, name);
+ if (err)
+ goto out_free;
+
err = add_dent_node(dir_inum, nh_elt->name, inum, type);
if (err)
goto out_free;
@@ -1754,6 +1808,11 @@ static int write_data(void)
}
head_flags = 0;
+
+ err = create_inum_attr(UBIFS_ROOT_INO, root);
+ if (err)
+ return err;
+
err = add_directory(root, UBIFS_ROOT_INO, &root_st, !!root);
if (err)
return err;
--
2.6.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support
2015-10-16 15:15 [PATCH 0/5] mkfs.ubifs: cleanups + extended attribute support Marc Kleine-Budde
` (4 preceding siblings ...)
2015-10-16 15:15 ` [PATCH 5/5] mkfs.ubifs: Optionally create extended attribute with inode number Marc Kleine-Budde
@ 2015-11-11 14:56 ` Daniel Walter
5 siblings, 0 replies; 7+ messages in thread
From: Daniel Walter @ 2015-11-11 14:56 UTC (permalink / raw)
To: linux-mtd; +Cc: mkl
On Fri, Oct 16, 2015 at 05:15:14PM +0200, Marc Kleine-Budde wrote:
> Hello,
>
> this series applies to current git master. The first 3 patches are cleanup
> patches, in the 4th adds extended attributes support. Patch 5 adds a option to
> write the used inode number to a extended attribute, so that other offline
> tools like IMA, that process the inode number can work. See description of
> patch 5 for a detailed explanation.
>
> regards,
> Marc
>
Hi Marc,
I had a quick look at the first 3 patches and they all seem fine, so
feel free to add a reviewed-by from me.
Since there is already a WITHOUT_XATTR build flag (to disable xattr
support) for mkfs.jffs2, would you mind using it for mkfs.ubi as well ?
cheers,
daniel
^ permalink raw reply [flat|nested] 7+ messages in thread