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/src/fstree_from_file.c | 312 ++++----------------------------- 1 file changed, 35 insertions(+), 277 deletions(-) (limited to 'bin/gensquashfs/src/fstree_from_file.c') 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", -- cgit v1.2.3