recurse-dir: coding style cleanups; mount-util: teach open_tree_attr_fallback() our usual AT_EMPTY_PATH trick (#38130)

This commit is contained in:
Yu Watanabe
2025-07-10 03:32:33 +09:00
committed by GitHub
4 changed files with 51 additions and 44 deletions

View File

@@ -175,7 +175,7 @@ int recurse_dir(
r = func(RECURSE_DIR_ENTER,
path,
-1, /* we have no parent fd */
-EBADF, /* we have no parent fd */
dir_fd,
NULL, /* we have no dirent */
statx_mask != 0 ? &root_sx : NULL,
@@ -191,7 +191,8 @@ int recurse_dir(
if (r < 0)
return r;
for (size_t i = 0; i < de->n_entries; i++) {
FOREACH_ARRAY(entry, de->entries, de->n_entries) {
struct dirent *i = *entry;
_cleanup_close_ int inode_fd = -EBADF, subdir_fd = -EBADF;
_cleanup_free_ char *joined = NULL;
struct statx sx;
@@ -206,16 +207,16 @@ int recurse_dir(
*/
if (path) {
joined = path_join(path, de->entries[i]->d_name);
joined = path_join(path, i->d_name);
if (!joined)
return -ENOMEM;
p = joined;
} else
p = de->entries[i]->d_name;
p = i->d_name;
if (IN_SET(de->entries[i]->d_type, DT_UNKNOWN, DT_DIR)) {
subdir_fd = openat(dir_fd, de->entries[i]->d_name, O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (IN_SET(i->d_type, DT_UNKNOWN, DT_DIR)) {
subdir_fd = openat(dir_fd, i->d_name, O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (subdir_fd < 0) {
if (errno == ENOENT) /* Vanished by now, go for next file immediately */
continue;
@@ -229,9 +230,9 @@ int recurse_dir(
r = func(RECURSE_DIR_SKIP_OPEN_DIR_ERROR_BASE + errno,
p,
dir_fd,
-1,
de->entries[i],
NULL,
/* inode_fd = */ -EBADF,
i,
/* sx = */ NULL,
userdata);
if (r == RECURSE_DIR_LEAVE_DIRECTORY)
break;
@@ -245,7 +246,7 @@ int recurse_dir(
} else {
/* If we managed to get a DIR* off the inode, it's definitely a directory. */
de->entries[i]->d_type = DT_DIR;
i->d_type = DT_DIR;
if (statx_mask != 0 || (flags & RECURSE_DIR_SAME_MOUNT)) {
if (statx(subdir_fd, "", AT_EMPTY_PATH, statx_mask, &sx) < 0)
@@ -261,7 +262,7 @@ int recurse_dir(
if (flags & RECURSE_DIR_INODE_FD) {
inode_fd = openat(dir_fd, de->entries[i]->d_name, O_PATH|O_NOFOLLOW|O_CLOEXEC);
inode_fd = openat(dir_fd, i->d_name, O_PATH|O_NOFOLLOW|O_CLOEXEC);
if (inode_fd < 0) {
if (errno == ENOENT) /* Vanished by now, go for next file immediately */
continue;
@@ -273,9 +274,9 @@ int recurse_dir(
r = func(RECURSE_DIR_SKIP_OPEN_INODE_ERROR_BASE + errno,
p,
dir_fd,
-1,
de->entries[i],
NULL,
/* inode_fd = */ -EBADF,
i,
/* sx = */ NULL,
userdata);
if (r == RECURSE_DIR_LEAVE_DIRECTORY)
break;
@@ -308,9 +309,9 @@ int recurse_dir(
inode_fd = safe_close(inode_fd);
}
} else if (statx_mask != 0 || (de->entries[i]->d_type == DT_UNKNOWN && (flags & RECURSE_DIR_ENSURE_TYPE))) {
} else if (statx_mask != 0 || (i->d_type == DT_UNKNOWN && (flags & RECURSE_DIR_ENSURE_TYPE))) {
if (statx(dir_fd, de->entries[i]->d_name, AT_SYMLINK_NOFOLLOW, statx_mask | STATX_TYPE, &sx) < 0) {
if (statx(dir_fd, i->d_name, AT_SYMLINK_NOFOLLOW, statx_mask | STATX_TYPE, &sx) < 0) {
if (errno == ENOENT) /* Vanished by now? Go for next file immediately */
continue;
@@ -321,9 +322,9 @@ int recurse_dir(
r = func(RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE + errno,
p,
dir_fd,
-1,
de->entries[i],
NULL,
/* inode_fd = */ -EBADF,
i,
/* sx = */ NULL,
userdata);
if (r == RECURSE_DIR_LEAVE_DIRECTORY)
break;
@@ -351,9 +352,9 @@ int recurse_dir(
r = func(RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE + EISDIR,
p,
dir_fd,
-1,
de->entries[i],
NULL,
/* inode_fd = */ -EBADF,
i,
/* sx = */ NULL,
userdata);
if (r == RECURSE_DIR_LEAVE_DIRECTORY)
break;
@@ -369,11 +370,11 @@ int recurse_dir(
/* Copy over the data we acquired through statx() if we acquired any */
if (sx.stx_mask & STATX_TYPE) {
assert((subdir_fd < 0) == !S_ISDIR(sx.stx_mode));
de->entries[i]->d_type = IFTODT(sx.stx_mode);
i->d_type = IFTODT(sx.stx_mode);
}
if (sx.stx_mask & STATX_INO)
de->entries[i]->d_ino = sx.stx_ino;
i->d_ino = sx.stx_ino;
}
if (subdir_fd >= 0) {
@@ -383,7 +384,7 @@ int recurse_dir(
if (sx_valid && FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT))
is_mount = FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
else {
r = is_mount_point_at(dir_fd, de->entries[i]->d_name, 0);
r = is_mount_point_at(dir_fd, i->d_name, /* flags = */ 0);
if (r < 0)
log_debug_errno(r, "Failed to determine whether %s is a submount, assuming not: %m", p);
@@ -395,7 +396,7 @@ int recurse_dir(
p,
dir_fd,
subdir_fd,
de->entries[i],
i,
statx_mask != 0 ? &sx : NULL, /* only pass sx if user asked for it */
userdata);
if (r == RECURSE_DIR_LEAVE_DIRECTORY)
@@ -414,7 +415,7 @@ int recurse_dir(
p,
dir_fd,
subdir_fd,
de->entries[i],
i,
statx_mask != 0 ? &sx : NULL, /* only pass sx if user asked for it */
userdata);
if (r == RECURSE_DIR_LEAVE_DIRECTORY)
@@ -429,7 +430,7 @@ int recurse_dir(
p,
dir_fd,
subdir_fd,
de->entries[i],
i,
statx_mask != 0 ? &sx : NULL, /* only pass sx if user asked for it */
userdata);
if (r == RECURSE_DIR_LEAVE_DIRECTORY)
@@ -443,7 +444,7 @@ int recurse_dir(
p,
statx_mask,
n_depth_max - 1,
flags &~ RECURSE_DIR_TOPLEVEL, /* we already called the callback for this entry */
flags & ~RECURSE_DIR_TOPLEVEL, /* we already called the callback for this entry */
func,
userdata);
if (r != 0)
@@ -453,7 +454,7 @@ int recurse_dir(
p,
dir_fd,
subdir_fd,
de->entries[i],
i,
statx_mask != 0 ? &sx : NULL, /* only pass sx if user asked for it */
userdata);
} else
@@ -462,7 +463,7 @@ int recurse_dir(
p,
dir_fd,
inode_fd,
de->entries[i],
i,
statx_mask != 0 ? &sx : NULL, /* only pass sx if user asked for it */
userdata);
@@ -476,9 +477,9 @@ int recurse_dir(
r = func(RECURSE_DIR_LEAVE,
path,
-1,
-EBADF, /* we have no parent fd */
dir_fd,
NULL,
NULL, /* we have no dirent */
statx_mask != 0 ? &root_sx : NULL,
userdata);
if (!IN_SET(r, RECURSE_DIR_LEAVE_DIRECTORY, RECURSE_DIR_SKIP_ENTRY, RECURSE_DIR_CONTINUE))

View File

@@ -824,7 +824,7 @@ static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t u
* caller's userns *without* any mount idmapping in place. To get that uid, we clone the
* mount source tree and clear any existing idmapping and temporarily mount that tree over
* the mount source before we stat the mount source to figure out the source uid. */
_cleanup_close_ int fd_clone = open_tree_attr_fallback(
_cleanup_close_ int fd_clone = open_tree_attr_with_fallback(
AT_FDCWD,
m->source,
OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC,

View File

@@ -1441,10 +1441,18 @@ int make_userns(uid_t uid_shift,
return TAKE_FD(userns_fd);
}
int open_tree_attr_fallback(int dir_fd, const char *path, unsigned int flags, struct mount_attr *attr) {
int open_tree_attr_with_fallback(int dir_fd, const char *path, unsigned int flags, struct mount_attr *attr) {
_cleanup_close_ int fd = -EBADF;
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(attr);
_cleanup_close_ int fd = open_tree_attr(dir_fd, path, flags, attr, sizeof(struct mount_attr));
if (isempty(path)) {
path = "";
flags |= AT_EMPTY_PATH;
}
fd = open_tree_attr(dir_fd, path, flags, attr, sizeof(struct mount_attr));
if (fd >= 0)
return TAKE_FD(fd);
if (!ERRNO_IS_NOT_SUPPORTED(errno))
@@ -1492,8 +1500,8 @@ int remount_idmap_fd(
for (size_t i = 0; i < n; i++) {
/* Clone the mount point and et the user namespace mapping attribute on the cloned mount point. */
mount_fds[n_mounts_fds] = open_tree_attr_fallback(
/* dir_fd= */ -EBADF,
mount_fds[n_mounts_fds] = open_tree_attr_with_fallback(
AT_FDCWD,
paths[i],
OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC,
&(struct mount_attr) {

View File

@@ -13,11 +13,13 @@ typedef struct SubMount {
void sub_mount_array_free(SubMount *s, size_t n);
int get_sub_mounts(const char *prefix, SubMount **ret_mounts, size_t *ret_n_mounts);
int bind_mount_submounts(
const char *source,
const char *target);
int repeat_unmount(const char *path, int flags);
int umount_recursive_full(const char *target, int flags, char **keep);
static inline int umount_recursive(const char *target, int flags) {
return umount_recursive_full(target, flags, NULL);
}
@@ -148,16 +150,12 @@ typedef enum RemountIdmapping {
_REMOUNT_IDMAPPING_INVALID = -EINVAL,
} RemountIdmapping;
int open_tree_attr_fallback(int dir_fd, const char *path, unsigned int flags, struct mount_attr *attr);
int open_tree_attr_with_fallback(int dir_fd, const char *path, unsigned int flags, struct mount_attr *attr);
int make_userns(uid_t uid_shift, uid_t uid_range, uid_t host_owner, uid_t dest_owner, RemountIdmapping idmapping);
int remount_idmap_fd(char **p, int userns_fd, uint64_t extra_mount_attr_set);
int remount_idmap(char **p, uid_t uid_shift, uid_t uid_range, uid_t host_owner, uid_t dest_owner, RemountIdmapping idmapping);
int bind_mount_submounts(
const char *source,
const char *target);
/* Creates a mount point (without any parents) based on the source path or mode - i.e., a file or a directory */
int make_mount_point_inode_from_mode(int dir_fd, const char *dest, mode_t source_mode, mode_t target_mode);
int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode);