diff options
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) && |