From: Li Guifu <bluce.ligu...@huawei.com> This patch adds mkfs support to erofs-utils, and it's able to build uncompressed images at the moment.
Signed-off-by: Li Guifu <bluce.ligu...@huawei.com> Signed-off-by: Gao Xiang <gaoxian...@huawei.com> --- Makefile.am | 2 +- configure.ac | 3 +- mkfs/Makefile.am | 9 +++ mkfs/main.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 mkfs/Makefile.am create mode 100644 mkfs/main.c diff --git a/Makefile.am b/Makefile.am index ee5fd92..d94ab73 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,4 +3,4 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS=lib +SUBDIRS=lib mkfs diff --git a/configure.ac b/configure.ac index 9c6d8bb..49f1a7d 100644 --- a/configure.ac +++ b/configure.ac @@ -103,5 +103,6 @@ AC_CHECK_DECL(lseek64,[AC_DEFINE(HAVE_LSEEK64_PROTOTYPE, 1, AC_CHECK_FUNCS([gettimeofday memset realpath strdup strerror strrchr strtoull]) AC_CONFIG_FILES([Makefile - lib/Makefile]) + lib/Makefile + mkfs/Makefile]) AC_OUTPUT diff --git a/mkfs/Makefile.am b/mkfs/Makefile.am new file mode 100644 index 0000000..257f864 --- /dev/null +++ b/mkfs/Makefile.am @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Makefile.am + +AUTOMAKE_OPTIONS = foreign +bin_PROGRAMS = mkfs.erofs +mkfs_erofs_SOURCES = main.c +mkfs_erofs_CFLAGS = -Wall -Werror -I$(top_srcdir)/include +mkfs_erofs_LDADD = $(top_builddir)/lib/liberofs.la + diff --git a/mkfs/main.c b/mkfs/main.c new file mode 100644 index 0000000..1ed15d2 --- /dev/null +++ b/mkfs/main.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * mkfs/main.c + * + * Copyright (C) 2018-2019 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Li Guifu <bluce.ligu...@huawei.com> + */ +#define _GNU_SOURCE +#include <time.h> +#include <sys/time.h> +#include <stdlib.h> +#include <limits.h> +#include <libgen.h> +#include "erofs/config.h" +#include "erofs/print.h" +#include "erofs/cache.h" +#include "erofs/inode.h" +#include "erofs/io.h" + +#define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block)) + +static void usage(char *execpath) +{ + fprintf(stderr, "%s %s\n", basename(execpath), cfg.c_version); + fprintf(stderr, "usage: [options] FILE DIRECTORY\n\n"); + fprintf(stderr, "Generate erofs image from DIRECTORY to FILE, and [options] are:\n"); + fprintf(stderr, " -d# set output message level to # (maximum 9)\n"); +} + +u64 parse_num_from_str(const char *str) +{ + u64 num = 0; + char *endptr = NULL; + + num = strtoull(str, &endptr, 10); + BUG_ON(num == ULLONG_MAX); + return num; +} + +static int mkfs_parse_options_cfg(int argc, char *argv[]) +{ + int opt, i; + + while ((opt = getopt(argc, argv, "d:z:")) != -1) { + switch (opt) { + case 'd': + cfg.c_dbg_lvl = parse_num_from_str(optarg); + break; + + default: /* '?' */ + return -EINVAL; + } + } + + if (optind >= argc) + return -EINVAL; + + cfg.c_img_path = strdup(argv[optind++]); + if (!cfg.c_img_path) + return -ENOMEM; + + if (optind > argc) { + erofs_err("Source directory is missing"); + return -EINVAL; + } + + cfg.c_src_path = realpath(argv[optind++], NULL); + if (!cfg.c_src_path) { + erofs_err("Failed to parse source directory: %s", + erofs_strerror(-errno)); + return -ENOENT; + } + + if (optind < argc) { + erofs_err("Unexpected argument: %s\n", argv[optind]); + return -EINVAL; + } + return 0; +} + +int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh, + erofs_nid_t root_nid) +{ + struct erofs_super_block sb = { + .magic = cpu_to_le32(EROFS_SUPER_MAGIC_V1), + .blkszbits = LOG_BLOCK_SIZE, + .inos = 0, + .blocks = 0, + .meta_blkaddr = sbi.meta_blkaddr, + .xattr_blkaddr = 0, + }; + const unsigned int sb_blksize = + round_up(EROFS_SUPER_END, EROFS_BLKSIZ); + char *buf; + struct timeval t; + + if (!gettimeofday(&t, NULL)) { + sb.build_time = cpu_to_le64(t.tv_sec); + sb.build_time_nsec = cpu_to_le32(t.tv_usec); + } + + sb.blocks = cpu_to_le32(erofs_mapbh(NULL, true)); + sb.root_nid = cpu_to_le16(root_nid); + + buf = calloc(sb_blksize, 1); + if (!buf) { + erofs_err("Failed to allocate memory for sb: %s", + erofs_strerror(-errno)); + return -ENOMEM; + } + memcpy(buf + EROFS_SUPER_OFFSET, &sb, sizeof(sb)); + + bh->fsprivate = buf; + bh->op = &erofs_buf_write_bhops; + return 0; +} + +int main(int argc, char **argv) +{ + int err = 0; + struct erofs_buffer_head *sb_bh; + struct erofs_inode *root_inode; + erofs_nid_t root_nid; + + erofs_init_configure(); + err = mkfs_parse_options_cfg(argc, argv); + if (err) { + if (err == -EINVAL) + usage(argv[0]); + return 1; + } + + err = dev_open(cfg.c_img_path); + if (err) { + usage(argv[0]); + return 1; + } + + erofs_err("%s %s\n", basename(argv[0]), cfg.c_version); + erofs_show_config(); + + sb_bh = erofs_buffer_init(); + err = erofs_bh_balloon(sb_bh, EROFS_SUPER_END); + if (err < 0) { + erofs_err("Failed to balloon erofs_super_block: %s", + erofs_strerror(err)); + goto exit; + } + + erofs_inode_manager_init(); + + root_inode = erofs_mkfs_build_tree_from_path(NULL, cfg.c_src_path); + if (IS_ERR(root_inode)) { + err = PTR_ERR(root_inode); + goto exit; + } + + root_nid = erofs_lookupnid(root_inode); + erofs_iput(root_inode); + + err = erofs_mkfs_update_super_block(sb_bh, root_nid); + if (err) + goto exit; + + /* flush all remaining buffers */ + if (!erofs_bflush(NULL)) + err = -EIO; +exit: + dev_close(); + erofs_exit_configure(); + + if (err) { + erofs_err("\tCould not format the device : %s\n", + erofs_strerror(err)); + return 1; + } + return err; +} -- 2.17.1