summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2021-02-19 00:55:11 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2021-02-19 17:34:47 +0100
commit94269ff3c0166474c018c4973c481b2fcff00080 (patch)
tree7b5f38702fa4865599a6a3107071728580b99d05
parentd9549b3d288a9cb053ab5198f3bc2d277b72600f (diff)
libfstree: Add a filter callback to the directory scanning function
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--bin/gensquashfs/mkfs.c4
-rw-r--r--include/fstree.h14
-rw-r--r--lib/fstree/fstree_from_dir.c55
-rw-r--r--tests/fstree_from_file.c2
4 files changed, 62 insertions, 13 deletions
diff --git a/bin/gensquashfs/mkfs.c b/bin/gensquashfs/mkfs.c
index 2885d84..b25d325 100644
--- a/bin/gensquashfs/mkfs.c
+++ b/bin/gensquashfs/mkfs.c
@@ -160,8 +160,8 @@ int main(int argc, char **argv)
}
if (opt.infile == NULL) {
- if (fstree_from_dir(&sqfs.fs, sqfs.fs.root,
- opt.packdir, opt.dirscan_flags)) {
+ if (fstree_from_dir(&sqfs.fs, sqfs.fs.root, opt.packdir,
+ NULL, NULL, opt.dirscan_flags)) {
goto out;
}
} else {
diff --git a/include/fstree.h b/include/fstree.h
index e5fc966..35d6778 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -41,6 +41,15 @@ typedef struct file_info_t file_info_t;
typedef struct dir_info_t dir_info_t;
typedef struct fstree_t fstree_t;
+/*
+ Optionally used by fstree_from_dir and fstree_from_subdir to
+ execute custom actions for each discovered node.
+
+ If it returns a value > 0, the new node is discarded, if < 0, scanning is
+ aborted and returns a failure status.
+ */
+typedef int (*scan_node_callback)(void *user, fstree_t *fs, tree_node_t *node);
+
/* Additional meta data stored in a tree_node_t for regular files. */
struct file_info_t {
/* Linked list pointer for files in fstree_t */
@@ -252,7 +261,8 @@ int fstree_resolve_hard_link(fstree_t *fs, tree_node_t *node);
Returns 0 on success, prints to stderr on failure.
*/
int fstree_from_dir(fstree_t *fs, tree_node_t *root,
- const char *path, unsigned int flags);
+ const char *path, scan_node_callback cb, void *user,
+ unsigned int flags);
/*
Same as fstree_from_dir, but scans a sub-directory inside the specified path.
@@ -261,6 +271,6 @@ int fstree_from_dir(fstree_t *fs, tree_node_t *root,
*/
int fstree_from_subdir(fstree_t *fs, tree_node_t *root,
const char *path, const char *subdir,
- unsigned int flags);
+ scan_node_callback cb, void *user, unsigned int flags);
#endif /* FSTREE_H */
diff --git a/lib/fstree/fstree_from_dir.c b/lib/fstree/fstree_from_dir.c
index d3e188d..cb066b1 100644
--- a/lib/fstree/fstree_from_dir.c
+++ b/lib/fstree/fstree_from_dir.c
@@ -12,30 +12,53 @@
#include <string.h>
#include <errno.h>
+static void discard_node(tree_node_t *root, tree_node_t *n)
+{
+ tree_node_t *it;
+
+ if (n == root->data.dir.children) {
+ root->data.dir.children = n->next;
+ } else {
+ it = root->data.dir.children;
+
+ while (it != NULL && it->next != n)
+ it = it->next;
+
+ if (it != NULL)
+ it->next = n->next;
+ }
+
+ free(n);
+}
+
#ifdef _WIN32
int fstree_from_subdir(fstree_t *fs, tree_node_t *root,
const char *path, const char *subdir,
+ scan_node_callback cb, void *user,
unsigned int flags)
{
(void)fs; (void)root; (void)path; (void)subdir; (void)flags;
+ (void)cb; (void)user;
fputs("Packing a directory is not supported on Windows.\n", stderr);
return -1;
}
int fstree_from_dir(fstree_t *fs, tree_node_t *root,
- const char *path, unsigned int flags)
+ const char *path, scan_node_callback cb,
+ void *user, unsigned int flags)
{
- return fstree_from_subdir(fs, root, path, NULL, flags);
+ return fstree_from_subdir(fs, root, path, NULL, cb, user, flags);
}
#else
static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,
- dev_t devstart, unsigned int flags)
+ dev_t devstart, scan_node_callback cb,
+ void *user, unsigned int flags)
{
char *extra = NULL;
struct dirent *ent;
+ int ret, childfd;
struct stat sb;
tree_node_t *n;
- int childfd;
DIR *dir;
dir = fdopendir(dir_fd);
@@ -122,6 +145,8 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,
false, false);
if (n == NULL)
continue;
+
+ ret = 0;
} else {
n = fstree_mknode(root, ent->d_name,
strlen(ent->d_name), extra, &sb);
@@ -129,11 +154,21 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,
perror("creating tree node");
goto fail;
}
+
+ ret = (cb == NULL) ? 0 : cb(user, fs, n);
}
free(extra);
extra = NULL;
+ if (ret < 0)
+ goto fail;
+
+ if (ret > 0) {
+ discard_node(root, n);
+ continue;
+ }
+
if (S_ISDIR(n->mode) && !(flags & DIR_SCAN_NO_RECURSION)) {
childfd = openat(dir_fd, n->name, O_DIRECTORY |
O_RDONLY | O_CLOEXEC);
@@ -142,8 +177,10 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,
goto fail;
}
- if (populate_dir(childfd, fs, n, devstart, flags))
+ if (populate_dir(childfd, fs, n, devstart,
+ cb, user, flags)) {
goto fail;
+ }
}
}
@@ -159,6 +196,7 @@ fail:
int fstree_from_subdir(fstree_t *fs, tree_node_t *root,
const char *path, const char *subdir,
+ scan_node_callback cb, void *user,
unsigned int flags)
{
struct stat sb;
@@ -199,12 +237,13 @@ int fstree_from_subdir(fstree_t *fs, tree_node_t *root,
return -1;
}
- return populate_dir(fd, fs, root, sb.st_dev, flags);
+ return populate_dir(fd, fs, root, sb.st_dev, cb, user, flags);
}
int fstree_from_dir(fstree_t *fs, tree_node_t *root,
- const char *path, unsigned int flags)
+ const char *path, scan_node_callback cb,
+ void *user, unsigned int flags)
{
- return fstree_from_subdir(fs, root, path, NULL, flags);
+ return fstree_from_subdir(fs, root, path, NULL, cb, user, flags);
}
#endif
diff --git a/tests/fstree_from_file.c b/tests/fstree_from_file.c
index f8f0892..140ffd7 100644
--- a/tests/fstree_from_file.c
+++ b/tests/fstree_from_file.c
@@ -15,7 +15,7 @@ int main(void)
fstree_t fs;
TEST_ASSERT(fstree_init(&fs, NULL) == 0);
- TEST_ASSERT(fstree_from_file(&fs, TEST_PATH) == 0);
+ TEST_ASSERT(fstree_from_file(&fs, TEST_PATH, NULL) == 0);
fstree_post_process(&fs);
n = fs.root->data.dir.children;