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 <[email protected]> --- changes since v1: - fix compile issues on Android / Linux build; - tested with Android system booting; include/erofs/config.h | 12 ++++++++++ include/erofs/internal.h | 3 +++ lib/inode.c | 49 +++++++++++++++++++++++++++++++++++++ lib/xattr.c | 52 ++++++++++++++++++++++++++++++++++++++++ mkfs/main.c | 29 +++++++++++++++++++++- 5 files changed, 144 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..b9ac223cc746 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,48 @@ err: return ret; } +#ifdef WITH_ANDROID +static int erofs_droid_xattr_set_caps(struct erofs_inode *inode) +{ + const u64 capabilities = inode->capabilities; + char *kvbuf; + unsigned int len[2]; + struct vfs_cap_data caps; + struct xattr_item *item; + + if (!capabilities) + return 0; + + len[0] = sizeof("capability") - 1; + len[1] = sizeof(caps); + + kvbuf = malloc(len[0] + len[1]); + if (!kvbuf) + return -ENOMEM; + + memcpy(kvbuf, "capability", len[0]); + caps.magic_etc = VFS_CAP_REVISION_2 | VFS_CAP_FLAGS_EFFECTIVE; + caps.data[0].permitted = (u32) capabilities; + caps.data[0].inheritable = 0; + caps.data[1].permitted = (u32) (capabilities >> 32); + caps.data[1].inheritable = 0; + 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) + return 0; + + return erofs_xattr_add(&inode->i_xattrs, item); +} +#else +static int erofs_droid_xattr_set_caps(struct erofs_inode *inode) +{ + return 0; +} +#endif + int erofs_prepare_xattr_ibody(struct erofs_inode *inode) { int ret; @@ -366,6 +414,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
