From 65cefb4cffadbd3b7adb9ff4a80db2914b0da4fd Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Fri, 31 Mar 2023 23:33:04 +0100 Subject: [PATCH] mkfs.jffs2: add --graft option Allows creation of image from more than one source directory tree, using --graft src:dest to graft new subtrees into the output. For example mkfs.jffs2 -r ./rootfs --graft $HOME/Pictures:/pictures to add your photo collection into the filesystem at /pictures without first copying it to rootfs --- jffsX-utils/mkfs.jffs2.c | 76 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/jffsX-utils/mkfs.jffs2.c b/jffsX-utils/mkfs.jffs2.c index bd67634..a33f4b4 100644 --- a/jffsX-utils/mkfs.jffs2.c +++ b/jffsX-utils/mkfs.jffs2.c @@ -112,6 +112,14 @@ static int squash_perms = 0; static int fake_times = 0; int target_endian = __BYTE_ORDER; +struct graft { + struct graft *next; + const char * source; + const char * dest; + struct stat st; +} * grafts = 0; + + static uint32_t find_hardlink(struct filesystem_entry *e) { struct filesystem_entry *f; @@ -597,6 +605,16 @@ static void cleanup(struct filesystem_entry *dir) } } +static void free_grafts(struct graft *graft) +{ + if(graft) { + if(graft->next) free_grafts(graft->next); + free((char *)graft->source); + free((char *)graft); + } +} + + /* Here is where we do the actual creation of the file system */ #include "mtd/jffs2-user.h" @@ -1359,6 +1377,7 @@ static void create_target_filesystem(struct filesystem_entry *root) static struct option long_options[] = { {"pad", 2, NULL, 'p'}, {"root", 1, NULL, 'r'}, + {"graft", 1, NULL, 'G'}, {"pagesize", 1, NULL, 's'}, {"eraseblock", 1, NULL, 'e'}, {"output", 1, NULL, 'o'}, @@ -1396,6 +1415,9 @@ static const char helptext[] = " not specified, the output is padded to the end of\n" " the final erase block\n" " -r, -d, --root=DIR Build file system from directory DIR (default: cwd)\n" +" -G, --graft=SOURCE:DEST Add contents of SOURCE directory at DEST in image.\n" +" May be given more than once. DEST must exist in\n" +" root DIR or a previous graft. \n" " -s, --pagesize=SIZE Use page size (max data node size) SIZE.\n" " Set according to target system's memory management\n" " page size (default: 4KiB)\n" @@ -1430,6 +1452,25 @@ static const char helptext[] = " -V, --version Display version information\n" " -i, --incremental=FILE Parse FILE and generate appendage output for it\n\n"; +static int add_graft(const char * source, const char *dest) +{ + struct graft * graft; + struct stat st; + + if (stat(source, &st)) { + errmsg_die("bad graft source '%s'", source); + } + + if(!grafts) grafts = calloc(sizeof (struct graft), 1); + for(graft = grafts; graft->next; graft = graft->next) + ; + graft->source = source; + graft->dest = dest; + memcpy((void *) &(graft->st), (void *) &st, sizeof st); + graft->next = calloc(sizeof (struct graft), 1); + return 0; +} + static int load_next_block(void) { int ret; @@ -1579,7 +1620,7 @@ int main(int argc, char **argv) jffs2_compressors_init(); while ((opt = getopt_long(argc, argv, - "D:d:r:s:o:qUPfh?vVe:lbp::nc:m:x:X:Lty:i:", long_options, &c)) >= 0) + "D:d:r:G:s:o:qUPfh?vVe:lbp::nc:m:x:X:Lty:i:", long_options, &c)) >= 0) { switch (opt) { case 'D': @@ -1598,6 +1639,18 @@ int main(int argc, char **argv) rootdir = xstrdup(optarg); break; + case 'G': + if(strchr(optarg, ':')) { + char * src_name, * dest_name; + src_name = xstrdup(optarg); + dest_name = strchr(src_name, ':'); + *dest_name = '\0'; + dest_name++; + add_graft(src_name, dest_name); + } else + errmsg_die("bad graft specification '%s', expecting source:dest", + optarg); + break; case 's': page_size = strtol(optarg, NULL, 0); warn_page_size = 0; /* set by user, so don't need to warn */ @@ -1784,13 +1837,34 @@ int main(int argc, char **argv) parse_image(); root = recursive_add_host_directory(NULL, "/", cwd); + for(struct graft *g = grafts; g && g->source; g=g->next) { + char *tmp = xstrdup(g->dest); + struct filesystem_entry * entry = + find_filesystem_entry(root, dirname(tmp), S_IFDIR); + free(tmp); + if(!entry) + errmsg_die("missing directory %s for graft point %s", + g->dest, g->source); + if (S_ISDIR(g->st.st_mode)) { + recursive_add_host_directory(entry, g->dest, g->source); + } else { + add_host_filesystem_entry(g->dest, + g->source, + g->st.st_uid, + g->st.st_gid, + g->st.st_mode, + g->st.st_rdev, + entry); + } + } if (devtable) parse_device_table(root, devtable); create_target_filesystem(root); cleanup(root); + free_grafts(grafts); if (rootdir != default_rootdir) free(rootdir); -- 2.38.1