[PATCH 07/13] erofs-utils: introduce mkfs support

Gao Xiang hsiangkao at aol.com
Fri May 31 10:50:41 AEST 2019


From: Li Guifu <bluce.liguifu at 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.liguifu at huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25 at 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.liguifu at 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



More information about the Linux-erofs mailing list