summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBaeuerle, Florian <Florian.Baeuerle@allegion.com>2018-12-19 14:02:03 +0000
committerSascha Hauer <s.hauer@pengutronix.de>2019-01-08 16:37:40 +0100
commit99c1263dce3902a8961bcdcac9398bce51fccd1b (patch)
tree0e014ee901e55dad8c2cd74d074622baea4d0be1 /lib
parentbaf8fc002ce67ca80f3bd7456b52a9bd2f10402d (diff)
downloadbarebox-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.c3
-rw-r--r--lib/recursive_action.c71
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) &&