diff options
author | Baeuerle, Florian <Florian.Baeuerle@allegion.com> | 2018-12-19 14:02:03 +0000 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-01-08 16:37:40 +0100 |
commit | 99c1263dce3902a8961bcdcac9398bce51fccd1b (patch) | |
tree | 0e014ee901e55dad8c2cd74d074622baea4d0be1 /lib | |
parent | baf8fc002ce67ca80f3bd7456b52a9bd2f10402d (diff) | |
download | barebox-99c1263dce3902a8961bcdcac9398bce51fccd1b.tar.gz barebox-99c1263dce3902a8961bcdcac9398bce51fccd1b.tar.xz |
recursive_action: add ACTION_SORT flag
Add a flag to sort directory entries before recursing into them.
Since this part of lib/ is used inside barebox as well as in
scripts/bareboxenv.c, we cannot easily use stringlists from lib/, which
would have made the code a bit nicer.
Signed-off-by: Florian Bäuerle <florian.baeuerle@allegion.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/list_sort.c | 3 | ||||
-rw-r--r-- | lib/recursive_action.c | 71 |
2 files changed, 64 insertions, 10 deletions
diff --git a/lib/list_sort.c b/lib/list_sort.c index b7e74f260d..84c6f6465b 100644 --- a/lib/list_sort.c +++ b/lib/list_sort.c @@ -1,7 +1,6 @@ #ifndef __BAREBOX__ #include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> +#define EXPORT_SYMBOL(x) #else #include <common.h> #include <malloc.h> diff --git a/lib/recursive_action.c b/lib/recursive_action.c index 345d3db0ce..9505c86284 100644 --- a/lib/recursive_action.c +++ b/lib/recursive_action.c @@ -13,9 +13,28 @@ #include <linux/stat.h> #include <malloc.h> #include <libbb.h> +#include <xfuncs.h> + +/* + * Sorting not required for barebox itself currently, support for it is only added + * for generating reproducible envfs images on the build host. + */ +#define DO_SORT(flags) 0 + +#else + +#define DO_SORT(flags) ((flags) & ACTION_SORT) #endif +#include <linux/list.h> +#include <linux/list_sort.h> + +struct dirlist { + char *dirname; + struct list_head list; +}; + /* * Walk down all the directories under the specified * location, and do something (something specified @@ -33,6 +52,19 @@ static int true_action(const char *fileName, struct stat *statbuf, return 1; } +static int cmp_dirlist(void *priv, struct list_head *a, struct list_head *b) +{ + struct dirlist *ra, *rb; + + if (a == b) + return 0; + + ra = list_entry(a, struct dirlist, list); + rb = list_entry(b, struct dirlist, list); + + return strcmp(ra->dirname, rb->dirname); +} + /* fileAction return value of 0 on any file in directory will make * recursive_action() return 0, but it doesn't stop directory traversal * (fileAction/dirAction will be called on each file). @@ -58,6 +90,8 @@ int recursive_action(const char *fileName, int status; DIR *dir; struct dirent *next; + struct dirlist *entry, *entry_tmp; + LIST_HEAD(dirs); if (!fileAction) fileAction = true_action; if (!dirAction) dirAction = true_action; @@ -106,19 +140,40 @@ int recursive_action(const char *fileName, /* To trigger: "find -exec rm -rf {} \;" */ goto done_nak_warn; } + status = 1; while ((next = readdir(dir)) != NULL) { - char *nextFile; - - nextFile = concat_subpath_file(fileName, next->d_name); + char *nextFile = concat_subpath_file(fileName, next->d_name); if (nextFile == NULL) continue; - /* now descend into it, forcing recursion. */ - if (!recursive_action(nextFile, flags | ACTION_RECURSE, - fileAction, dirAction, userData, depth+1)) { - status = 0; + + if (DO_SORT(flags)) { + struct dirlist *e = xmalloc(sizeof(*e)); + e->dirname = nextFile; + list_add(&e->list, &dirs); + } else { + /* descend into it, forcing recursion. */ + if (!recursive_action(nextFile, flags | ACTION_RECURSE, + fileAction, dirAction, userData, depth+1)) { + status = 0; + } + free(nextFile); + } + } + + if (DO_SORT(flags)) { + list_sort(NULL, &dirs, &cmp_dirlist); + + list_for_each_entry_safe(entry, entry_tmp, &dirs, list){ + /* descend into it, forcing recursion. */ + if (!recursive_action(entry->dirname, flags | ACTION_RECURSE, + fileAction, dirAction, userData, depth+1)) { + status = 0; + } + + list_del(&entry->list); + free(entry->dirname); } - free(nextFile); } closedir(dir); if ((flags & ACTION_DEPTHFIRST) && |