recurse-dir: optionally, call callback when entering/leaving toplevel dir, too
So far recurse_dir() will call the callback whenever we enter a directory, and then pass the struct dirent for that directory, and an fd for the directory the dirent is part of (i.e. the parent of the directory we call things for). For the top-level dir the function is invoked for we will not call the callback however, because we have no dirent for that, and not fd for the directory the top-level dir is part of. Let's add a flag to call it anyway, and in that case pass a NULL dirent and -1 as directory fd. This is useful when we want to treat the top-level dir the same as any dir further down. This is done opt-in since the callback must be ablet to handle a NULL dirent and a -1 directory fd.
This commit is contained in:
+35
-1
@@ -126,6 +126,7 @@ int recurse_dir(
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_free_ DirectoryEntries *de = NULL;
|
||||
STRUCT_STATX_DEFINE(root_sx);
|
||||
int r;
|
||||
|
||||
assert(dir_fd >= 0);
|
||||
@@ -139,6 +140,26 @@ int recurse_dir(
|
||||
if (n_depth_max == UINT_MAX) /* special marker for "default" */
|
||||
n_depth_max = DEFAULT_RECURSION_MAX;
|
||||
|
||||
if (FLAGS_SET(flags, RECURSE_DIR_TOPLEVEL)) {
|
||||
if (statx_mask != 0) {
|
||||
r = statx_fallback(dir_fd, "", AT_EMPTY_PATH, statx_mask, &root_sx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = func(RECURSE_DIR_ENTER,
|
||||
path,
|
||||
-1, /* we have no parent fd */
|
||||
dir_fd,
|
||||
NULL, /* we have no dirent */
|
||||
statx_mask != 0 ? &root_sx : NULL,
|
||||
userdata);
|
||||
if (IN_SET(r, RECURSE_DIR_LEAVE_DIRECTORY, RECURSE_DIR_SKIP_ENTRY))
|
||||
return 0;
|
||||
if (r != RECURSE_DIR_CONTINUE)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = readdir_all(dir_fd, flags, &de);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -397,7 +418,7 @@ int recurse_dir(
|
||||
p,
|
||||
statx_mask,
|
||||
n_depth_max - 1,
|
||||
flags,
|
||||
flags &~ RECURSE_DIR_TOPLEVEL, /* we already called the callback for this entry */
|
||||
func,
|
||||
userdata);
|
||||
if (r != 0)
|
||||
@@ -427,6 +448,19 @@ int recurse_dir(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, RECURSE_DIR_TOPLEVEL)) {
|
||||
|
||||
r = func(RECURSE_DIR_LEAVE,
|
||||
path,
|
||||
-1,
|
||||
dir_fd,
|
||||
NULL,
|
||||
statx_mask != 0 ? &root_sx : NULL,
|
||||
userdata);
|
||||
if (!IN_SET(r, RECURSE_DIR_LEAVE_DIRECTORY, RECURSE_DIR_SKIP_ENTRY, RECURSE_DIR_CONTINUE))
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user