[RFC PATCH] AOSP: erofs-utils: add fs_config support
Gao Xiang
hsiangkao at aol.com
Tue Sep 29 07:35:49 AEST 2020
So that mkfs can directly generate images with fs_config.
All code for AOSP is wraped up with WITH_ANDROID macro.
Signed-off-by: Gao Xiang <hsiangkao at aol.com>
---
originated from:
https://github.com/hsiangkao/erofs-utils/commit/e30bee2993d35350406ed8b0e0bfd6e580edc734
with some cleanup, and haven't rebuilt with
Android environment yet.
include/erofs/config.h | 12 +++++++++
include/erofs/internal.h | 3 +++
lib/inode.c | 49 +++++++++++++++++++++++++++++++++++
lib/xattr.c | 56 ++++++++++++++++++++++++++++++++++++++++
mkfs/main.c | 29 ++++++++++++++++++++-
5 files changed, 148 insertions(+), 1 deletion(-)
diff --git a/include/erofs/config.h b/include/erofs/config.h
index 2f0974900be1..9902a089ab46 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -17,6 +17,13 @@
#include <selinux/label.h>
#endif
+#ifdef WITH_ANDROID
+#include <selinux/android.h>
+#include <private/android_filesystem_config.h>
+#include <private/canned_fs_config.h>
+#include <private/fs_config.h>
+#endif
+
enum {
FORCE_INODE_COMPACT = 1,
FORCE_INODE_EXTENDED,
@@ -40,6 +47,11 @@ struct erofs_configure {
/* < 0, xattr disabled and INT_MAX, always use inline xattrs */
int c_inline_xattr_tolerance;
u64 c_unix_timestamp;
+#ifdef WITH_ANDROID
+ char *mount_point;
+ char *target_out_path;
+ char *fs_config_file;
+#endif
};
extern struct erofs_configure cfg;
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 41da189ffac1..bc77c43719e8 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -127,6 +127,9 @@ struct erofs_inode {
void *idata;
void *compressmeta;
+#ifdef WITH_ANDROID
+ uint64_t capabilities;
+#endif
};
static inline bool is_inode_layout_compression(struct erofs_inode *inode)
diff --git a/lib/inode.c b/lib/inode.c
index 5013184e66bf..597cbc7fc6dd 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -673,10 +673,59 @@ static u32 erofs_new_encode_dev(dev_t dev)
return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
}
+#ifdef WITH_ANDROID
+int erofs_droid_inode_fsconfig(struct erofs_inode *inode,
+ struct stat64 *st,
+ const char *path)
+{
+ /* filesystem_config does not preserve file type bits */
+ mode_t stat_file_type_mask = st->st_mode & S_IFMT;
+ unsigned int uid = 0, gid = 0, mode = 0;
+ char *fspath;
+
+ inode->capabilities = 0;
+ if (cfg.fs_config_file)
+ canned_fs_config(erofs_fspath(path),
+ S_ISDIR(st->st_mode),
+ cfg.target_out_path,
+ &uid, &gid, &mode, &inode->capabilities);
+ else if (cfg.mount_point) {
+ if (asprintf(&fspath, "%s/%s", cfg.mount_point,
+ erofs_fspath(path)) <= 0)
+ return -ENOMEM;
+
+ fs_config(fspath, S_ISDIR(st->st_mode),
+ cfg.target_out_path,
+ &uid, &gid, &mode, &inode->capabilities);
+ free(fspath);
+ }
+ st->st_uid = uid;
+ st->st_gid = gid;
+ st->st_mode = mode | stat_file_type_mask;
+
+ erofs_dbg("/%s -> mode = 0x%x, uid = 0x%x, gid = 0x%x, "
+ "capabilities = 0x%" PRIx64 "\n",
+ erofs_fspath(path),
+ mode, uid, gid, inode->capabilities);
+ return 0;
+}
+#else
+static int erofs_droid_inode_fsconfig(struct erofs_inode *inode,
+ struct stat64 *st,
+ const char *path)
+{
+ return 0;
+}
+#endif
+
int erofs_fill_inode(struct erofs_inode *inode,
struct stat64 *st,
const char *path)
{
+ int err = erofs_droid_inode_fsconfig(inode, st, path);
+ if (err)
+ return err;
+
inode->i_mode = st->st_mode;
inode->i_uid = st->st_uid;
inode->i_gid = st->st_gid;
diff --git a/lib/xattr.c b/lib/xattr.c
index 769ab9c716d0..0986e4674d81 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -196,6 +196,12 @@ static struct xattr_item *erofs_get_selabel_xattr(const char *srcpath,
unsigned int len[2];
char *kvbuf, *fspath;
+#ifdef WITH_ANDROID
+ if (cfg.mount_point)
+ ret = asprintf(&fspath, "/%s/%s", cfg.mount_point,
+ erofs_fspath(srcpath));
+ else
+#endif
ret = asprintf(&fspath, "/%s", erofs_fspath(srcpath));
if (ret <= 0)
return ERR_PTR(-ENOMEM);
@@ -352,6 +358,52 @@ err:
return ret;
}
+#ifdef WITH_ANDROID
+static struct vfs_cap_data __set_caps(uint64_t capabilities)
+{
+ struct vfs_cap_data cap_data = {0};
+
+ if (capabilities == 0)
+ return cap_data;
+
+ cap_data.magic_etc = VFS_CAP_REVISION_2 | VFS_CAP_FLAGS_EFFECTIVE;
+ cap_data.data[0].permitted = (uint32_t) capabilities;
+ cap_data.data[0].inheritable = 0;
+ cap_data.data[1].permitted = (uint32_t) (capabilities >> 32);
+ cap_data.data[1].inheritable = 0;
+ return cap_data;
+}
+
+static int erofs_droid_xattr_set_caps(struct erofs_inode *inode)
+{
+ if (inode->capabilities) {
+ unsigned int len[2];
+ char *kvbuf;
+ struct vfs_cap_data caps;
+ struct xattr_item *item;
+
+ len[0] = sizeof("capability") - 1;
+ len[1] = sizeof(struct vfs_cap_data);
+ kvbuf = malloc(len[0] + len[1]);
+ if (!kvbuf)
+ return -ENOMEM;
+
+ memcpy(kvbuf, "capability", len[0]);
+ caps = __set_caps(inode->capabilities);
+ memcpy(kvbuf + len[0], &caps, len[1]);
+ item = get_xattritem(EROFS_XATTR_INDEX_SECURITY, kvbuf, len);
+ if (IS_ERR(item))
+ return PTR_ERR(item);
+ if (item) {
+ ret = erofs_xattr_add(ixattrs, item);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ return 0;
+}
+#endif
+
int erofs_prepare_xattr_ibody(struct erofs_inode *inode)
{
int ret;
@@ -366,6 +418,10 @@ int erofs_prepare_xattr_ibody(struct erofs_inode *inode)
if (ret < 0)
return ret;
+ ret = erofs_droid_xattr_set_caps(inode);
+ if (ret < 0)
+ return ret;
+
if (list_empty(ixattrs))
return 0;
diff --git a/mkfs/main.c b/mkfs/main.c
index 94bf1e6a2425..191003409b2f 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -35,6 +35,11 @@ static struct option long_options[] = {
{"exclude-regex", required_argument, NULL, 3},
#ifdef HAVE_LIBSELINUX
{"file-contexts", required_argument, NULL, 4},
+#endif
+#ifdef WITH_ANDROID
+ {"mount-point", required_argument, NULL, 10},
+ {"product-out", required_argument, NULL, 11},
+ {"fs-config-file", required_argument, NULL, 12},
#endif
{0, 0, 0, 0},
};
@@ -210,7 +215,21 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
if (opt && opt != -EBUSY)
return opt;
break;
-
+#ifdef WITH_ANDROID
+ case 10:
+ cfg.mount_point = optarg;
+ /* all trailing '/' should be deleted */
+ opt = strlen(cfg.mount_point);
+ if (opt && optarg[opt - 1] == '/')
+ optarg[opt - 1] = '\0';
+ break;
+ case 11:
+ cfg.target_out_path = optarg;
+ break;
+ case 12:
+ cfg.fs_config_file = optarg;
+ break;
+#endif
case 1:
usage();
exit(0);
@@ -404,6 +423,14 @@ int main(int argc, char **argv)
return 1;
}
+#ifdef WITH_ANDROID
+ if (cfg.fs_config_file &&
+ load_canned_fs_config(cfg.fs_config_file) < 0) {
+ erofs_err("failed to load fs config %s", cfg.fs_config_file);
+ return 1;
+ }
+#endif
+
erofs_show_config();
erofs_set_fs_root(cfg.c_src_path);
--
2.24.0
More information about the Linux-erofs
mailing list