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

Reply via email to