From 5197d47639146111bfb365fd543c83c539c8a9c5 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sun, 28 May 2023 16:33:21 +0200 Subject: gensquashfs: split glob related code from fstree_from_file.c The glob function and everything associated is moved to a separate file, the entry point exposed any the special case handling is removed from the other callbacks in fstree_from_file.c Signed-off-by: David Oberhollenzer --- bin/gensquashfs/Makemodule.am | 6 +- bin/gensquashfs/src/fstree_from_file.c | 312 ++++----------------------------- bin/gensquashfs/src/glob.c | 233 ++++++++++++++++++++++++ bin/gensquashfs/src/mkfs.h | 5 + 4 files changed, 278 insertions(+), 278 deletions(-) create mode 100644 bin/gensquashfs/src/glob.c (limited to 'bin/gensquashfs') diff --git a/bin/gensquashfs/Makemodule.am b/bin/gensquashfs/Makemodule.am index fd39aaf..0bb2122 100644 --- a/bin/gensquashfs/Makemodule.am +++ b/bin/gensquashfs/Makemodule.am @@ -3,7 +3,7 @@ gensquashfs_SOURCES = bin/gensquashfs/src/mkfs.c bin/gensquashfs/src/mkfs.h \ bin/gensquashfs/src/dirscan_xattr.c bin/gensquashfs/src/filemap_xattr.c\ bin/gensquashfs/src/fstree_from_file.c \ bin/gensquashfs/src/fstree_from_dir.c \ - bin/gensquashfs/src/sort_by_file.c + bin/gensquashfs/src/sort_by_file.c bin/gensquashfs/src/glob.c gensquashfs_LDADD = libcommon.a libsquashfs.la libfstree.a libio.a gensquashfs_LDADD += libutil.a libcompat.a $(LZO_LIBS) $(PTHREAD_LIBS) gensquashfs_CPPFLAGS = $(AM_CPPFLAGS) @@ -31,6 +31,7 @@ test_filemap_xattr_LDADD += libio.a libcompat.a test_fstree_from_file_SOURCES = bin/gensquashfs/test/fstree_from_file.c \ bin/gensquashfs/src/fstree_from_file.c \ bin/gensquashfs/src/fstree_from_dir.c \ + bin/gensquashfs/src/glob.c \ bin/gensquashfs/src/mkfs.h test_fstree_from_file_CPPFLAGS = $(AM_CPPFLAGS) test_fstree_from_file_CPPFLAGS += -I$(top_srcdir)/bin/gensquashfs/src @@ -41,6 +42,7 @@ test_fstree_from_file_LDADD = libcommon.a libfstree.a libio.a libutil.a \ test_fstree_glob1_SOURCES = bin/gensquashfs/test/fstree_glob1.c \ bin/gensquashfs/src/fstree_from_file.c \ bin/gensquashfs/src/fstree_from_dir.c \ + bin/gensquashfs/src/glob.c \ bin/gensquashfs/src/mkfs.h test_fstree_glob1_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/bin/gensquashfs/src test_fstree_glob1_CPPFLAGS += -DTESTPATH=$(GENDATADIR) @@ -50,6 +52,7 @@ test_sort_file_SOURCES = bin/gensquashfs/test/sort_file.c \ bin/gensquashfs/src/fstree_from_file.c \ bin/gensquashfs/src/fstree_from_dir.c \ bin/gensquashfs/src/sort_by_file.c \ + bin/gensquashfs/src/glob.c \ bin/gensquashfs/src/mkfs.h test_sort_file_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/bin/gensquashfs/src test_sort_file_LDADD = libcommon.a libfstree.a libio.a libutil.a libcompat.a @@ -57,6 +60,7 @@ test_sort_file_LDADD = libcommon.a libfstree.a libio.a libutil.a libcompat.a fstree_fuzz_SOURCES = bin/gensquashfs/test/fstree_fuzz.c \ bin/gensquashfs/src/fstree_from_file.c \ bin/gensquashfs/src/fstree_from_dir.c \ + bin/gensquashfs/src/glob.c \ bin/gensquashfs/src/mkfs.h fstree_fuzz_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/bin/gensquashfs/src fstree_fuzz_LDADD = libcommon.a libfstree.a libio.a libutil.a libcompat.a diff --git a/bin/gensquashfs/src/fstree_from_file.c b/bin/gensquashfs/src/fstree_from_file.c index 318c129..d4d77a7 100644 --- a/bin/gensquashfs/src/fstree_from_file.c +++ b/bin/gensquashfs/src/fstree_from_file.c @@ -4,45 +4,11 @@ * * Copyright (C) 2019 David Oberhollenzer */ -#include "config.h" - -#include "util/util.h" -#include "io/file.h" -#include "compat.h" #include "mkfs.h" -#include -#include -#include -#include -#include - -static const struct { - const char *name; - unsigned int clear_flag; - unsigned int set_flag; -} glob_scan_flags[] = { - { "-type b", DIR_SCAN_NO_BLK, 0 }, - { "-type c", DIR_SCAN_NO_CHR, 0 }, - { "-type d", DIR_SCAN_NO_DIR, 0 }, - { "-type p", DIR_SCAN_NO_FIFO, 0 }, - { "-type f", DIR_SCAN_NO_FILE, 0 }, - { "-type l", DIR_SCAN_NO_SLINK, 0 }, - { "-type s", DIR_SCAN_NO_SOCK, 0 }, - { "-xdev", 0, DIR_SCAN_ONE_FILESYSTEM }, - { "-mount", 0, DIR_SCAN_ONE_FILESYSTEM }, - { "-keeptime", 0, DIR_SCAN_KEEP_TIME }, - { "-nonrecursive", 0, DIR_SCAN_NO_RECURSION }, -}; - static int add_generic(fstree_t *fs, const char *filename, size_t line_num, - const char *path, struct stat *sb, - const char *basepath, unsigned int glob_flags, - const char *extra) + const char *path, struct stat *sb, const char *extra) { - (void)basepath; - (void)glob_flags; - if (fstree_add_generic(fs, path, sb, extra) == NULL) { fprintf(stderr, "%s: " PRI_SZ ": %s: %s\n", filename, line_num, path, strerror(errno)); @@ -53,8 +19,7 @@ static int add_generic(fstree_t *fs, const char *filename, size_t line_num, } static int add_device(fstree_t *fs, const char *filename, size_t line_num, - const char *path, struct stat *sb, const char *basepath, - unsigned int glob_flags, const char *extra) + const char *path, struct stat *sb, const char *extra) { unsigned int maj, min; char c; @@ -77,28 +42,22 @@ static int add_device(fstree_t *fs, const char *filename, size_t line_num, } sb->st_rdev = makedev(maj, min); - return add_generic(fs, filename, line_num, path, sb, basepath, - glob_flags, NULL); + return add_generic(fs, filename, line_num, path, sb, NULL); } static int add_file(fstree_t *fs, const char *filename, size_t line_num, - const char *path, struct stat *basic, const char *basepath, - unsigned int glob_flags, const char *extra) + const char *path, struct stat *basic, const char *extra) { if (extra == NULL || *extra == '\0') extra = path; - return add_generic(fs, filename, line_num, path, basic, - basepath, glob_flags, extra); + return add_generic(fs, filename, line_num, path, basic, extra); } static int add_hard_link(fstree_t *fs, const char *filename, size_t line_num, const char *path, struct stat *basic, - const char *basepath, unsigned int glob_flags, const char *extra) { - (void)basepath; - (void)glob_flags; (void)basic; if (fstree_add_hard_link(fs, path, extra) == NULL) { @@ -109,233 +68,21 @@ static int add_hard_link(fstree_t *fs, const char *filename, size_t line_num, return 0; } -static size_t name_string_length(const char *str) -{ - size_t len = 0; - int start; - - if (*str == '"' || *str == '\'') { - start = *str; - ++len; - - while (str[len] != '\0' && str[len] != start) - ++len; - - if (str[len] == start) - ++len; - } else { - while (str[len] != '\0' && !isspace(str[len])) - ++len; - } - - return len; -} - -static void quote_remove(char *str) -{ - char *dst = str; - int start = *(str++); - - if (start != '\'' && start != '"') - return; - - while (*str != start && *str != '\0') - *(dst++) = *(str++); - - *(dst++) = '\0'; -} - -static int glob_files(fstree_t *fs, const char *filename, size_t line_num, - const char *path, struct stat *basic, - const char *basepath, unsigned int glob_flags, - const char *extra) -{ - char *name_pattern = NULL, *prefix = NULL; - unsigned int scan_flags = 0, all_flags; - dir_iterator_t *dir = NULL; - bool first_clear_flag; - size_t i, count, len; - dir_tree_cfg_t cfg; - tree_node_t *root; - int ret; - - /* fetch the actual target node */ - root = fstree_get_node_by_path(fs, fs->root, path, true, false); - if (root == NULL) { - fprintf(stderr, "%s: " PRI_SZ ": %s: %s\n", - filename, line_num, path, strerror(errno)); - return -1; - } - - if (!S_ISDIR(root->mode)) { - fprintf(stderr, "%s: " PRI_SZ ": %s is not a directoy!\n", - filename, line_num, path); - return -1; - } - - prefix = fstree_get_path(root); - if (canonicalize_name(prefix) != 0) { - fprintf(stderr, "%s: " PRI_SZ ": error cannonicalizing `%s`!\n", - filename, line_num, prefix); - free(prefix); - return -1; - } - - /* process options */ - first_clear_flag = true; - - all_flags = DIR_SCAN_NO_BLK | DIR_SCAN_NO_CHR | DIR_SCAN_NO_DIR | - DIR_SCAN_NO_FIFO | DIR_SCAN_NO_FILE | DIR_SCAN_NO_SLINK | - DIR_SCAN_NO_SOCK; - - while (extra != NULL && *extra != '\0') { - count = sizeof(glob_scan_flags) / sizeof(glob_scan_flags[0]); - - for (i = 0; i < count; ++i) { - len = strlen(glob_scan_flags[i].name); - if (strncmp(extra, glob_scan_flags[i].name, len) != 0) - continue; - - if (isspace(extra[len])) { - extra += len; - while (isspace(*extra)) - ++extra; - break; - } - } - - if (i < count) { - if (glob_scan_flags[i].clear_flag != 0 && - first_clear_flag) { - scan_flags |= all_flags; - first_clear_flag = false; - } - - scan_flags &= ~(glob_scan_flags[i].clear_flag); - scan_flags |= glob_scan_flags[i].set_flag; - continue; - } - - if (strncmp(extra, "-name", 5) == 0 && isspace(extra[5])) { - for (extra += 5; isspace(*extra); ++extra) - ; - - len = name_string_length(extra); - - free(name_pattern); - name_pattern = strndup(extra, len); - extra += len; - - while (isspace(*extra)) - ++extra; - - quote_remove(name_pattern); - continue; - } - - if (strncmp(extra, "-path", 5) == 0 && isspace(extra[5])) { - for (extra += 5; isspace(*extra); ++extra) - ; - - len = name_string_length(extra); - - free(name_pattern); - name_pattern = strndup(extra, len); - extra += len; - - while (isspace(*extra)) - ++extra; - - quote_remove(name_pattern); - glob_flags |= DIR_SCAN_MATCH_FULL_PATH; - continue; - } - - if (extra[0] == '-') { - if (extra[1] == '-' && isspace(extra[2])) { - extra += 2; - while (isspace(*extra)) - ++extra; - break; - } - - fprintf(stderr, "%s: " PRI_SZ ": unknown option.\n", - filename, line_num); - free(name_pattern); - free(prefix); - return -1; - } else { - break; - } - } - - if (extra != NULL && *extra == '\0') - extra = NULL; - - /* do the scan */ - memset(&cfg, 0, sizeof(cfg)); - cfg.flags = scan_flags | glob_flags; - cfg.def_mtime = basic->st_mtime; - cfg.def_uid = basic->st_uid; - cfg.def_gid = basic->st_gid; - cfg.def_mode = basic->st_mode; - cfg.prefix = prefix; - cfg.name_pattern = name_pattern; - - if (basepath == NULL) { - dir = dir_tree_iterator_create(extra == NULL ? "." : extra, - &cfg); - } else { - size_t plen = strlen(basepath); - size_t slen = strlen(extra); - char *temp = calloc(1, plen + 1 + slen + 1); - - if (temp == NULL) { - fprintf(stderr, "%s: " PRI_SZ ": allocation failure.\n", - filename, line_num); - } else { - memcpy(temp, basepath, plen); - temp[plen] = '/'; - memcpy(temp + plen + 1, extra, slen); - temp[plen + 1 + slen] = '\0'; - - dir = dir_tree_iterator_create(temp, &cfg); - } - - free(temp); - } - - if (dir != NULL) { - ret = fstree_from_dir(fs, dir); - sqfs_drop(dir); - } else { - ret = -1; - } - - free(name_pattern); - free(prefix); - return ret; -} - static const struct callback_t { const char *keyword; unsigned int mode; bool need_extra; - bool is_glob; bool allow_root; int (*callback)(fstree_t *fs, const char *filename, size_t line_num, - const char *path, struct stat *sb, - const char *basepath, unsigned int glob_flags, - const char *extra); + const char *path, struct stat *sb, const char *extra); } file_list_hooks[] = { - { "dir", S_IFDIR, false, false, true, add_generic }, - { "slink", S_IFLNK, true, false, false, add_generic }, - { "link", 0, true, false, false, add_hard_link }, - { "nod", 0, true, false, false, add_device }, - { "pipe", S_IFIFO, false, false, false, add_generic }, - { "sock", S_IFSOCK, false, false, false, add_generic }, - { "file", S_IFREG, false, false, false, add_file }, - { "glob", 0, false, true, true, glob_files }, + { "dir", S_IFDIR, false, true, add_generic }, + { "slink", S_IFLNK, true, false, add_generic }, + { "link", 0, true, false, add_hard_link }, + { "nod", 0, true, false, add_device }, + { "pipe", S_IFIFO, false, false, add_generic }, + { "sock", S_IFSOCK, false, false, add_generic }, + { "file", S_IFREG, false, false, add_file }, }; #define NUM_HOOKS (sizeof(file_list_hooks) / sizeof(file_list_hooks[0])) @@ -414,6 +161,7 @@ static int handle_line(fstree_t *fs, const char *filename, const struct callback_t *cb = NULL; unsigned int glob_flags = 0; sqfs_u32 uid, gid, mode; + bool is_glob = false; struct stat sb; char *path; @@ -429,8 +177,14 @@ static int handle_line(fstree_t *fs, const char *filename, } } - if (cb == NULL) - goto fail_kw; + if (cb == NULL) { + if (strncmp("glob", line, 4) == 0 && isspace(line[4])) { + line = skip_space(line + 4); + is_glob = true; + } else { + goto fail_kw; + } + } if ((line = read_str(line, &path)) == NULL) goto fail_ent; @@ -438,10 +192,10 @@ static int handle_line(fstree_t *fs, const char *filename, if (canonicalize_name(path)) goto fail_ent; - if (*path == '\0' && !cb->allow_root) + if (*path == '\0' && !(is_glob || cb->allow_root)) goto fail_root; - if (cb->is_glob && *line == '*') { + if (is_glob && *line == '*') { ++line; mode = 0; glob_flags |= DIR_SCAN_KEEP_MODE; @@ -453,7 +207,7 @@ static int handle_line(fstree_t *fs, const char *filename, if ((line = skip_space(line)) == NULL) goto fail_ent; - if (cb->is_glob && *line == '*') { + if (is_glob && *line == '*') { ++line; uid = 0; glob_flags |= DIR_SCAN_KEEP_UID; @@ -465,7 +219,7 @@ static int handle_line(fstree_t *fs, const char *filename, if ((line = skip_space(line)) == NULL) goto fail_ent; - if (cb->is_glob && *line == '*') { + if (is_glob && *line == '*') { ++line; gid = 0; glob_flags |= DIR_SCAN_KEEP_GID; @@ -477,21 +231,25 @@ static int handle_line(fstree_t *fs, const char *filename, if ((line = skip_space(line)) != NULL && *line != '\0') extra = line; - if (cb->need_extra && extra == NULL) + if (!is_glob && cb->need_extra && extra == NULL) goto fail_no_extra; /* forward to callback */ memset(&sb, 0, sizeof(sb)); sb.st_mtime = fs->defaults.mtime; - sb.st_mode = mode | cb->mode; + sb.st_mode = mode | (is_glob ? 0 : cb->mode); sb.st_uid = uid; sb.st_gid = gid; - return cb->callback(fs, filename, line_num, path, - &sb, basepath, glob_flags, extra); + if (is_glob) { + return glob_files(fs, filename, line_num, path, &sb, + basepath, glob_flags, extra); + } + + return cb->callback(fs, filename, line_num, path, &sb, extra); fail_root: fprintf(stderr, "%s: " PRI_SZ ": cannot use / as argument for %s.\n", - filename, line_num, cb->keyword); + filename, line_num, is_glob ? "glob" : cb->keyword); return -1; fail_no_extra: fprintf(stderr, "%s: " PRI_SZ ": missing argument for %s.\n", diff --git a/bin/gensquashfs/src/glob.c b/bin/gensquashfs/src/glob.c new file mode 100644 index 0000000..c95d06d --- /dev/null +++ b/bin/gensquashfs/src/glob.c @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * glob.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "mkfs.h" + +static const struct { + const char *name; + unsigned int clear_flag; + unsigned int set_flag; +} glob_scan_flags[] = { + { "-type b", DIR_SCAN_NO_BLK, 0 }, + { "-type c", DIR_SCAN_NO_CHR, 0 }, + { "-type d", DIR_SCAN_NO_DIR, 0 }, + { "-type p", DIR_SCAN_NO_FIFO, 0 }, + { "-type f", DIR_SCAN_NO_FILE, 0 }, + { "-type l", DIR_SCAN_NO_SLINK, 0 }, + { "-type s", DIR_SCAN_NO_SOCK, 0 }, + { "-xdev", 0, DIR_SCAN_ONE_FILESYSTEM }, + { "-mount", 0, DIR_SCAN_ONE_FILESYSTEM }, + { "-keeptime", 0, DIR_SCAN_KEEP_TIME }, + { "-nonrecursive", 0, DIR_SCAN_NO_RECURSION }, +}; + +static size_t name_string_length(const char *str) +{ + size_t len = 0; + int start; + + if (*str == '"' || *str == '\'') { + start = *str; + ++len; + + while (str[len] != '\0' && str[len] != start) + ++len; + + if (str[len] == start) + ++len; + } else { + while (str[len] != '\0' && !isspace(str[len])) + ++len; + } + + return len; +} + +static void quote_remove(char *str) +{ + char *dst = str; + int start = *(str++); + + if (start != '\'' && start != '"') + return; + + while (*str != start && *str != '\0') + *(dst++) = *(str++); + + *(dst++) = '\0'; +} + +int glob_files(fstree_t *fs, const char *filename, size_t line_num, + const char *path, struct stat *basic, + const char *basepath, unsigned int glob_flags, + const char *extra) +{ + char *name_pattern = NULL, *prefix = NULL; + unsigned int scan_flags = 0, all_flags; + dir_iterator_t *dir = NULL; + bool first_clear_flag; + size_t i, count, len; + dir_tree_cfg_t cfg; + tree_node_t *root; + int ret; + + /* fetch the actual target node */ + root = fstree_get_node_by_path(fs, fs->root, path, true, false); + if (root == NULL) { + fprintf(stderr, "%s: " PRI_SZ ": %s: %s\n", + filename, line_num, path, strerror(errno)); + return -1; + } + + if (!S_ISDIR(root->mode)) { + fprintf(stderr, "%s: " PRI_SZ ": %s is not a directoy!\n", + filename, line_num, path); + return -1; + } + + prefix = fstree_get_path(root); + if (canonicalize_name(prefix) != 0) { + fprintf(stderr, "%s: " PRI_SZ ": error cannonicalizing `%s`!\n", + filename, line_num, prefix); + free(prefix); + return -1; + } + + /* process options */ + first_clear_flag = true; + + all_flags = DIR_SCAN_NO_BLK | DIR_SCAN_NO_CHR | DIR_SCAN_NO_DIR | + DIR_SCAN_NO_FIFO | DIR_SCAN_NO_FILE | DIR_SCAN_NO_SLINK | + DIR_SCAN_NO_SOCK; + + while (extra != NULL && *extra != '\0') { + count = sizeof(glob_scan_flags) / sizeof(glob_scan_flags[0]); + + for (i = 0; i < count; ++i) { + len = strlen(glob_scan_flags[i].name); + if (strncmp(extra, glob_scan_flags[i].name, len) != 0) + continue; + + if (isspace(extra[len])) { + extra += len; + while (isspace(*extra)) + ++extra; + break; + } + } + + if (i < count) { + if (glob_scan_flags[i].clear_flag != 0 && + first_clear_flag) { + scan_flags |= all_flags; + first_clear_flag = false; + } + + scan_flags &= ~(glob_scan_flags[i].clear_flag); + scan_flags |= glob_scan_flags[i].set_flag; + continue; + } + + if (strncmp(extra, "-name", 5) == 0 && isspace(extra[5])) { + for (extra += 5; isspace(*extra); ++extra) + ; + + len = name_string_length(extra); + + free(name_pattern); + name_pattern = strndup(extra, len); + extra += len; + + while (isspace(*extra)) + ++extra; + + quote_remove(name_pattern); + continue; + } + + if (strncmp(extra, "-path", 5) == 0 && isspace(extra[5])) { + for (extra += 5; isspace(*extra); ++extra) + ; + + len = name_string_length(extra); + + free(name_pattern); + name_pattern = strndup(extra, len); + extra += len; + + while (isspace(*extra)) + ++extra; + + quote_remove(name_pattern); + glob_flags |= DIR_SCAN_MATCH_FULL_PATH; + continue; + } + + if (extra[0] == '-') { + if (extra[1] == '-' && isspace(extra[2])) { + extra += 2; + while (isspace(*extra)) + ++extra; + break; + } + + fprintf(stderr, "%s: " PRI_SZ ": unknown option.\n", + filename, line_num); + free(name_pattern); + free(prefix); + return -1; + } else { + break; + } + } + + if (extra != NULL && *extra == '\0') + extra = NULL; + + /* do the scan */ + memset(&cfg, 0, sizeof(cfg)); + cfg.flags = scan_flags | glob_flags; + cfg.def_mtime = basic->st_mtime; + cfg.def_uid = basic->st_uid; + cfg.def_gid = basic->st_gid; + cfg.def_mode = basic->st_mode; + cfg.prefix = prefix; + cfg.name_pattern = name_pattern; + + if (basepath == NULL) { + dir = dir_tree_iterator_create(extra == NULL ? "." : extra, + &cfg); + } else { + size_t plen = strlen(basepath); + size_t slen = strlen(extra); + char *temp = calloc(1, plen + 1 + slen + 1); + + if (temp == NULL) { + fprintf(stderr, "%s: " PRI_SZ ": allocation failure.\n", + filename, line_num); + } else { + memcpy(temp, basepath, plen); + temp[plen] = '/'; + memcpy(temp + plen + 1, extra, slen); + temp[plen + 1 + slen] = '\0'; + + dir = dir_tree_iterator_create(temp, &cfg); + } + + free(temp); + } + + if (dir != NULL) { + ret = fstree_from_dir(fs, dir); + sqfs_drop(dir); + } else { + ret = -1; + } + + free(name_pattern); + free(prefix); + return ret; +} diff --git a/bin/gensquashfs/src/mkfs.h b/bin/gensquashfs/src/mkfs.h index 9205b7b..6c95588 100644 --- a/bin/gensquashfs/src/mkfs.h +++ b/bin/gensquashfs/src/mkfs.h @@ -124,4 +124,9 @@ int fstree_from_dir(fstree_t *fs, dir_iterator_t *dir); int fstree_sort_files(fstree_t *fs, istream_t *sortfile); +int glob_files(fstree_t *fs, const char *filename, size_t line_num, + const char *path, struct stat *basic, + const char *basepath, unsigned int glob_flags, + const char *extra); + #endif /* MKFS_H */ -- cgit v1.2.3