aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-07-11 13:08:06 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-07-11 13:27:49 +0200
commit59e17afe291f9df52d2334b92e88a889c2fe8f6a (patch)
treeadd5674ebd1b8441cacab11afdd1a6fabb6fe79a
parent48b171335c213091cdf682c98ad784dc5c8456da (diff)
downloadslcl-59e17afe291f9df52d2334b92e88a889c2fe8f6a.tar.gz
cftw: Allow user callback to stop recursive search
So far, cftw would search through all directories and files recursively, until all objects are processed. However, it is interesting for the user callback to be able to stop this process under specific circumstances. Now, cftw will pass a pointer to a bool, initialised to false by default, that can be optionally assigned to true by the user callback. Future commits will make use of this feature. For example, this will be used to limit the number of search results when a user enters a search term that is too generic and would otherwise generate a large amount of search results.
-rw-r--r--cftw.c20
-rw-r--r--cftw.h3
-rw-r--r--main.c6
3 files changed, 19 insertions, 10 deletions
diff --git a/cftw.c b/cftw.c
index 8fb1d67..4b8b013 100644
--- a/cftw.c
+++ b/cftw.c
@@ -9,8 +9,8 @@
#include <stdint.h>
#include <string.h>
-int cftw(const char *const dirpath, int (*const fn)(const char *,
- const struct stat *, void *), void *const user)
+static int do_cftw(const char *const dirpath, int (*const fn)(const char *,
+ const struct stat *, bool *, void *), bool *const done, void *const user)
{
int ret = -1;
DIR *const d = opendir(dirpath);
@@ -58,20 +58,20 @@ int cftw(const char *const dirpath, int (*const fn)(const char *,
__func__, path, strerror(errno));
else if (S_ISDIR(sb.st_mode))
{
- if ((ret = cftw(d.str, fn, user)))
+ if ((ret = do_cftw(d.str, fn, done, user)))
;
- else if ((ret = fn(d.str, &sb, user)))
+ else if ((ret = fn(d.str, &sb, done, user)))
;
}
else if (S_ISREG(sb.st_mode))
- ret = fn(d.str, &sb, user);
+ ret = fn(d.str, &sb, done, user);
else
fprintf(stderr, "%s: unexpected st_mode %ju\n",
__func__, (uintmax_t)sb.st_mode);
dynstr_free(&d);
- if (ret)
+ if (ret || *done)
goto end;
}
@@ -87,3 +87,11 @@ end:
return ret;
}
+
+int cftw(const char *const dirpath, int (*const fn)(const char *,
+ const struct stat *, bool *, void *), void *const user)
+{
+ bool done = false;
+
+ return do_cftw(dirpath, fn, &done, user);
+}
diff --git a/cftw.h b/cftw.h
index 612451e..663960c 100644
--- a/cftw.h
+++ b/cftw.h
@@ -1,11 +1,12 @@
#ifndef CFTW_H
#define CFTW_H
+#include <stdbool.h>
#include <sys/stat.h>
/* Thread-safe variant of ftw(3) and nftw(3) that allows passing an
* opaque pointer and removes some unneeded parameters. */
int cftw(const char *dirpath, int (*fn)(const char *fpath,
- const struct stat *sb, void *user), void *user);
+ const struct stat *sb, bool *done, void *user), void *user);
#endif /* CFTW_H */
diff --git a/main.c b/main.c
index b75d556..19178f4 100644
--- a/main.c
+++ b/main.c
@@ -619,7 +619,7 @@ struct search_args
};
static int search_fn(const char *const fpath, const struct stat *const sb,
- void *const user)
+ bool *const done, void *const user)
{
const struct search_args *const sa = user;
const char *rel = fpath + strlen(sa->root);
@@ -810,7 +810,7 @@ end:
}
static int add_length(const char *const fpath, const struct stat *const sb,
- void *const user)
+ bool *const done, void *const user)
{
if (!S_ISREG(sb->st_mode))
return 0;
@@ -1481,7 +1481,7 @@ static const char *find_rm_dir(const struct form *const forms, const size_t n,
}
static int rm_dir_contents(const char *const fpath,
- const struct stat *const sb, void *const user)
+ const struct stat *const sb, bool *const done, void *const user)
{
if (S_ISDIR(sb->st_mode) && rmdir(fpath))
{