[PATCH 1/2] erofs-utils: lib: record source paths for external data

Gao Xiang hsiangkao at linux.alibaba.com
Thu Jun 12 17:31:02 AEST 2025


...which will be filled into VMDK descriptor files.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 include/erofs/internal.h |   1 +
 lib/super.c              |   5 +
 mkfs/main.c              | 217 ++++++++++++++++++++++-----------------
 3 files changed, 129 insertions(+), 94 deletions(-)

diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 5e86943..8916be1 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -61,6 +61,7 @@ struct erofs_buffer_head;
 struct erofs_bufmgr;
 
 struct erofs_device_info {
+	char *src_path;
 	u8 tag[64];
 	u32 blocks;
 	u32 mapped_blkaddr;
diff --git a/lib/super.c b/lib/super.c
index 1541838..beab74e 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -145,6 +145,11 @@ int erofs_read_superblock(struct erofs_sb_info *sbi)
 void erofs_put_super(struct erofs_sb_info *sbi)
 {
 	if (sbi->devs) {
+		int i;
+
+		DBG_BUGON(!sbi->extra_devices);
+		for (i = 0; i < sbi->extra_devices; ++i)
+			free(sbi->devs[i].src_path);
 		free(sbi->devs);
 		sbi->devs = NULL;
 	}
diff --git a/mkfs/main.c b/mkfs/main.c
index 16de894..ef83f2e 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -253,6 +253,7 @@ static u8 fixeduuid[16];
 static bool valid_fixeduuid;
 static unsigned int dsunit;
 static unsigned int fsalignblks = 1;
+static int tarerofs_decoder;
 
 static int erofs_mkfs_feat_set_legacy_compress(bool en, const char *val,
 					       unsigned int vallen)
@@ -577,12 +578,93 @@ static void erofs_rebuild_cleanup(void)
 	rebuild_src_count = 0;
 }
 
+static int mkfs_parse_sources(int argc, char *argv[], int optind)
+{
+	struct stat st;
+	int err, fd;
+	char *s;
+
+	if (tar_mode) {
+		cfg.c_src_path = strdup(argv[optind++]);
+		if (!cfg.c_src_path)
+			return -ENOMEM;
+		fd = open(cfg.c_src_path, O_RDONLY);
+		if (fd < 0) {
+			erofs_err("failed to open tar file: %s", cfg.c_src_path);
+			return -errno;
+		}
+		err = erofs_iostream_open(&erofstar.ios, fd,
+					  tarerofs_decoder);
+		if (err)
+			return err;
+
+		if (erofstar.dumpfile) {
+			fd = open(erofstar.dumpfile,
+				  O_WRONLY | O_CREAT | O_TRUNC, 0644);
+			if (fd < 0) {
+				erofs_err("failed to open dumpfile: %s",
+					  erofstar.dumpfile);
+				return -errno;
+			}
+			erofstar.ios.dumpfd = fd;
+		}
+	} else {
+		err = lstat((s = argv[optind++]), &st);
+		if (err) {
+			erofs_err("failed to stat %s: %s", s,
+				  erofs_strerror(-errno));
+			return -ENOENT;
+		}
+		if (S_ISDIR(st.st_mode)) {
+			cfg.c_src_path = realpath(s, NULL);
+			if (!cfg.c_src_path) {
+				erofs_err("failed to parse source directory: %s",
+					  erofs_strerror(-errno));
+				return -ENOENT;
+			}
+			erofs_set_fs_root(cfg.c_src_path);
+		} else {
+			cfg.c_src_path = strdup(s);
+			if (!cfg.c_src_path)
+				return -ENOMEM;
+			rebuild_mode = true;
+		}
+	}
+
+	if (rebuild_mode) {
+		char *srcpath = cfg.c_src_path;
+		struct erofs_sb_info *src;
+
+		do {
+			src = calloc(1, sizeof(struct erofs_sb_info));
+			if (!src) {
+				erofs_rebuild_cleanup();
+				return -ENOMEM;
+			}
+
+			err = erofs_dev_open(src, srcpath, O_RDONLY);
+			if (err) {
+				free(src);
+				erofs_rebuild_cleanup();
+				return err;
+			}
+
+			/* extra device index starts from 1 */
+			src->dev = ++rebuild_src_count;
+			list_add(&src->list, &rebuild_src_list);
+		} while (optind < argc && (srcpath = argv[optind++]));
+	} else if (optind < argc) {
+		erofs_err("unexpected argument: %s\n", argv[optind]);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int mkfs_parse_options_cfg(int argc, char *argv[])
 {
 	char *endptr;
 	int opt, i, err;
 	bool quiet = false;
-	int tarerofs_decoder = 0;
 	bool has_timestamp = false;
 
 	while ((opt = getopt_long(argc, argv, "C:E:L:T:U:b:d:x:z:Vh",
@@ -939,93 +1021,28 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 	if (!cfg.c_img_path)
 		return -ENOMEM;
 
-	if (optind >= argc) {
-		if (!tar_mode) {
-			erofs_err("missing argument: SOURCE(s)");
-			return -EINVAL;
-		} else {
-			int dupfd;
-
-			dupfd = dup(STDIN_FILENO);
-			if (dupfd < 0) {
-				erofs_err("failed to duplicate STDIN_FILENO: %s",
-					  strerror(errno));
-				return -errno;
-			}
-			err = erofs_iostream_open(&erofstar.ios, dupfd,
-						  tarerofs_decoder);
-			if (err)
-				return err;
-		}
+	if (optind < argc) {
+		err = mkfs_parse_sources(argc, argv, optind);
+		if (err)
+			return err;
+	} else if (!tar_mode) {
+		erofs_err("missing argument: SOURCE(s)");
+		return -EINVAL;
 	} else {
-		struct stat st;
-
-		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 (tar_mode) {
-			int fd = open(cfg.c_src_path, O_RDONLY);
-
-			if (fd < 0) {
-				erofs_err("failed to open file: %s", cfg.c_src_path);
-				return -errno;
-			}
-			err = erofs_iostream_open(&erofstar.ios, fd,
-						  tarerofs_decoder);
-			if (err)
-				return err;
+		int dupfd;
 
-			if (erofstar.dumpfile) {
-				fd = open(erofstar.dumpfile,
-					  O_WRONLY | O_CREAT | O_TRUNC, 0644);
-				if (fd < 0) {
-					erofs_err("failed to open dumpfile: %s",
-						  erofstar.dumpfile);
-					return -errno;
-				}
-				erofstar.ios.dumpfd = fd;
-			}
-		} else {
-			err = lstat(cfg.c_src_path, &st);
-			if (err)
-				return -errno;
-			if (S_ISDIR(st.st_mode))
-				erofs_set_fs_root(cfg.c_src_path);
-			else
-				rebuild_mode = true;
-		}
-
-		if (rebuild_mode) {
-			char *srcpath = cfg.c_src_path;
-			struct erofs_sb_info *src;
-
-			do {
-				src = calloc(1, sizeof(struct erofs_sb_info));
-				if (!src) {
-					erofs_rebuild_cleanup();
-					return -ENOMEM;
-				}
-
-				err = erofs_dev_open(src, srcpath, O_RDONLY);
-				if (err) {
-					free(src);
-					erofs_rebuild_cleanup();
-					return err;
-				}
-
-				/* extra device index starts from 1 */
-				src->dev = ++rebuild_src_count;
-				list_add(&src->list, &rebuild_src_list);
-			} while (optind < argc && (srcpath = argv[optind++]));
-		} else if (optind < argc) {
-			erofs_err("unexpected argument: %s\n", argv[optind]);
-			return -EINVAL;
+		dupfd = dup(STDIN_FILENO);
+		if (dupfd < 0) {
+			erofs_err("failed to duplicate STDIN_FILENO: %s",
+				  strerror(errno));
+			return -errno;
 		}
+		err = erofs_iostream_open(&erofstar.ios, dupfd,
+					  tarerofs_decoder);
+		if (err)
+			return err;
 	}
+
 	if (quiet) {
 		cfg.c_dbg_lvl = EROFS_ERR;
 		cfg.c_showprogress = false;
@@ -1115,6 +1132,7 @@ void erofs_show_progs(int argc, char *argv[])
 
 static int erofs_mkfs_rebuild_load_trees(struct erofs_inode *root)
 {
+	struct erofs_device_info *devs;
 	struct erofs_sb_info *src;
 	unsigned int extra_devices = 0;
 	erofs_blk_t nblocks;
@@ -1163,20 +1181,22 @@ static int erofs_mkfs_rebuild_load_trees(struct erofs_inode *root)
 	if (ret)
 		return ret;
 
+	devs = g_sbi.devs;
 	list_for_each_entry(src, &rebuild_src_list, list) {
 		u8 *tag = NULL;
 
+		DBG_BUGON(src->dev < 1);
+		idx = src->dev - 1;
 		if (extra_devices) {
 			nblocks = src->devs[0].blocks;
 			tag = src->devs[0].tag;
 		} else {
 			nblocks = src->primarydevice_blocks;
+			devs[idx].src_path = strdup(src->devname);
 		}
-		DBG_BUGON(src->dev < 1);
-		idx = src->dev - 1;
-		g_sbi.devs[idx].blocks = nblocks;
+		devs[idx].blocks = nblocks;
 		if (tag && *tag)
-			memcpy(g_sbi.devs[idx].tag, tag, sizeof(g_sbi.devs[0].tag));
+			memcpy(devs[idx].tag, tag, sizeof(devs[0].tag));
 		else
 			/* convert UUID of the source image to a hex string */
 			sprintf((char *)g_sbi.devs[idx].tag,
@@ -1216,11 +1236,12 @@ static void erofs_mkfs_showsummaries(void)
 
 int main(int argc, char **argv)
 {
-	int err = 0;
 	struct erofs_buffer_head *sb_bh;
 	struct erofs_inode *root = NULL;
+	bool tar_index_512b = false;
 	struct timeval t;
 	FILE *blklst = NULL;
+	int err = 0;
 	u32 crc;
 
 	erofs_init_configure();
@@ -1291,12 +1312,13 @@ int main(int argc, char **argv)
 				erofs_err("failed to open %s", erofstar.mapfile);
 				goto exit;
 			}
-		} else if (erofstar.index_mode) {
+		} else if (erofstar.index_mode && !erofstar.headeronly_mode) {
 			/*
 			 * If mapfile is unspecified for tarfs index mode,
 			 * 512-byte block size is enforced here.
 			 */
 			g_sbi.blkszbits = 9;
+			tar_index_512b = true;
 		}
 	}
 
@@ -1412,8 +1434,7 @@ int main(int argc, char **argv)
 			return 1;
 	}
 
-	if (((erofstar.index_mode && !erofstar.headeronly_mode) &&
-	    !erofstar.mapfile) || cfg.c_blobdev_path) {
+	if (tar_index_512b || cfg.c_blobdev_path) {
 		err = erofs_mkfs_init_devices(&g_sbi, 1);
 		if (err) {
 			erofs_err("failed to generate device table: %s",
@@ -1471,8 +1492,16 @@ int main(int argc, char **argv)
 		}
 	}
 
-	if (erofstar.index_mode && g_sbi.extra_devices && !erofstar.mapfile)
-		g_sbi.devs[0].blocks = BLK_ROUND_UP(&g_sbi, erofstar.offset);
+	if (tar_index_512b) {
+		if (!g_sbi.extra_devices) {
+			DBG_BUGON(1);
+		} else {
+			if (cfg.c_src_path)
+				g_sbi.devs[0].src_path = strdup(cfg.c_src_path);
+			g_sbi.devs[0].blocks =
+				BLK_ROUND_UP(&g_sbi, erofstar.offset);
+		}
+	}
 
 	if ((cfg.c_fragments || cfg.c_extra_ea_name_prefixes) &&
 	    erofs_sb_has_fragments(&g_sbi)) {
-- 
2.43.5



More information about the Linux-erofs mailing list