Merge pull request #31331 from yuwata/xopenat

tree-wide: several cleanups related to xopenat()
This commit is contained in:
Yu Watanabe
2024-02-16 01:32:21 +09:00
committed by GitHub
16 changed files with 196 additions and 122 deletions
+15 -15
View File
@@ -374,11 +374,11 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
return r;
if (FLAGS_SET(flags, CHASE_MKDIR_0755) && !isempty(todo)) {
child = xopenat(fd,
first,
O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,
/* xopen_flags = */ 0,
0755);
child = xopenat_full(fd,
first,
O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,
/* xopen_flags = */ 0,
0755);
if (child < 0)
return child;
} else if (FLAGS_SET(flags, CHASE_PARENT) && isempty(todo)) {
@@ -760,10 +760,10 @@ int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, i
if (empty_or_root(root) && !ret_path &&
(chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return RET_NERRNO(xopenat(AT_FDCWD, path,
open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
/* xopen_flags = */ 0,
mode));
return xopenat_full(AT_FDCWD, path,
open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
/* xopen_flags = */ 0,
mode);
r = chase(path, root, CHASE_PARENT|chase_flags, &p, &path_fd);
if (r < 0)
@@ -777,7 +777,7 @@ int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, i
return r;
}
r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
r = xopenat_full(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
if (r < 0)
return r;
@@ -964,10 +964,10 @@ int chase_and_openat(int dir_fd, const char *path, ChaseFlags chase_flags, int o
if (dir_fd == AT_FDCWD && !ret_path &&
(chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_PROHIBIT_SYMLINKS|CHASE_PARENT|CHASE_MKDIR_0755)) == 0)
/* Shortcut this call if none of the special features of this call are requested */
return RET_NERRNO(xopenat(dir_fd, path,
open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
/* xopen_flags = */ 0,
mode));
return xopenat_full(dir_fd, path,
open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
/* xopen_flags = */ 0,
mode);
r = chaseat(dir_fd, path, chase_flags|CHASE_PARENT, &p, &path_fd);
if (r < 0)
@@ -979,7 +979,7 @@ int chase_and_openat(int dir_fd, const char *path, ChaseFlags chase_flags, int o
return r;
}
r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
r = xopenat_full(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
if (r < 0)
return r;
+2 -2
View File
@@ -29,9 +29,9 @@ int chattr_full(
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
if (fd < 0)
return -errno;
return fd;
if (fstat(fd, &st) < 0)
return -errno;
+10 -6
View File
@@ -116,7 +116,11 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
int readlinkat_malloc(int fd, const char *p, char **ret) {
size_t l = PATH_MAX;
assert(p);
assert(fd >= 0 || fd == AT_FDCWD);
if (fd < 0 && isempty(p))
return -EISDIR; /* In this case, the fd points to the current working directory, and is
* definitely not a symlink. Let's return earlier. */
for (;;) {
_cleanup_free_ char *c = NULL;
@@ -126,7 +130,7 @@ int readlinkat_malloc(int fd, const char *p, char **ret) {
if (!c)
return -ENOMEM;
n = readlinkat(fd, p, c, l);
n = readlinkat(fd, strempty(p), c, l);
if (n < 0)
return -errno;
@@ -1050,7 +1054,7 @@ int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) {
path = fname;
}
fd = xopenat(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
fd = xopenat_full(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
if (IN_SET(fd, -ELOOP, -ENOTDIR))
return -EEXIST;
if (fd < 0)
@@ -1106,7 +1110,7 @@ int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, b
}
}
int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) {
int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) {
_cleanup_close_ int fd = -EBADF;
bool made = false;
int r;
@@ -1187,7 +1191,7 @@ int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags
return TAKE_FD(fd);
}
int xopenat_lock(
int xopenat_lock_full(
int dir_fd,
const char *path,
int open_flags,
@@ -1210,7 +1214,7 @@ int xopenat_lock(
for (;;) {
struct stat st;
fd = xopenat(dir_fd, path, open_flags, xopen_flags, mode);
fd = xopenat_full(dir_fd, path, open_flags, xopen_flags, mode);
if (fd < 0)
return fd;
+8 -2
View File
@@ -137,6 +137,12 @@ typedef enum XOpenFlags {
XO_SUBVOLUME = 1 << 1,
} XOpenFlags;
int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode);
int xopenat_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode);
static inline int xopenat(int dir_fd, const char *path, int open_flags) {
return xopenat_full(dir_fd, path, open_flags, 0, 0);
}
int xopenat_lock(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation);
int xopenat_lock_full(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation);
static inline int xopenat_lock(int dir_fd, const char *path, int open_flags, LockType locktype, int operation) {
return xopenat_lock_full(dir_fd, path, open_flags, 0, 0, locktype, operation);
}
+7 -7
View File
@@ -40,13 +40,13 @@ int make_lock_file_at(int dir_fd, const char *p, int operation, LockFile *ret) {
if (!t)
return -ENOMEM;
fd = xopenat_lock(dfd,
p,
O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY,
/* xopen_flags = */ 0,
0600,
LOCK_UNPOSIX,
operation);
fd = xopenat_lock_full(dfd,
p,
O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY,
/* xopen_flags = */ 0,
0600,
LOCK_UNPOSIX,
operation);
if (fd < 0)
return fd == -EAGAIN ? -EBUSY : fd;
+1 -1
View File
@@ -138,7 +138,7 @@ int readdir_all_at(int fd, const char *path, RecurseDirFlags flags, DirectoryEnt
assert(fd >= 0 || fd == AT_FDCWD);
dir_fd = xopenat(fd, path, O_DIRECTORY|O_CLOEXEC, /* xopen_flags= */ 0, /* mode= */ 0);
dir_fd = xopenat(fd, path, O_DIRECTORY|O_CLOEXEC);
if (dir_fd < 0)
return dir_fd;
+1 -1
View File
@@ -468,7 +468,7 @@ int xstatfsat(int dir_fd, const char *path, struct statfs *ret) {
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(ret);
fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return fd;
+2 -2
View File
@@ -139,7 +139,7 @@ int id128_read_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t *ret) {
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(path);
fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return fd;
@@ -185,7 +185,7 @@ int id128_write_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t id) {
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(path);
fd = xopenat(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, /* xopen_flags = */ 0, 0444);
fd = xopenat_full(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, /* xopen_flags = */ 0, 0444);
if (fd < 0)
return fd;
+3 -7
View File
@@ -65,7 +65,7 @@ int btrfs_subvol_set_read_only_at(int dir_fd, const char *path, bool b) {
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
fd = xopenat(dir_fd, path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
if (fd < 0)
return fd;
@@ -113,7 +113,7 @@ int btrfs_get_block_device_at(int dir_fd, const char *path, dev_t *ret) {
assert(path);
assert(ret);
fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
if (fd < 0)
return fd;
@@ -1276,8 +1276,6 @@ static int subvol_snapshot_children(
if (FLAGS_SET(flags, BTRFS_SNAPSHOT_LOCK_BSD)) {
subvolume_fd = xopenat_lock(new_fd, subvolume,
O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW,
/* xopen_flags = */ 0,
/* mode = */ 0,
LOCK_BSD,
LOCK_EX);
if (subvolume_fd < 0)
@@ -1445,7 +1443,7 @@ int btrfs_subvol_snapshot_at_full(
assert(dir_fdt >= 0 || dir_fdt == AT_FDCWD);
assert(to);
old_fd = xopenat(dir_fdf, from, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY, /* xopen_flags = */ 0, /* mode = */ 0);
old_fd = xopenat(dir_fdf, from, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
if (old_fd < 0)
return old_fd;
@@ -1482,8 +1480,6 @@ int btrfs_subvol_snapshot_at_full(
if (FLAGS_SET(flags, BTRFS_SNAPSHOT_LOCK_BSD)) {
subvolume_fd = xopenat_lock(new_fd, subvolume,
O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW,
/* xopen_flags = */ 0,
/* mode = */ 0,
LOCK_BSD,
LOCK_EX);
if (subvolume_fd < 0)
+37 -38
View File
@@ -509,7 +509,6 @@ static int fd_copy_symlink(
_cleanup_free_ char *target = NULL;
int r;
assert(from);
assert(st);
assert(to);
@@ -527,7 +526,10 @@ static int fd_copy_symlink(
mac_selinux_create_file_clear();
if (r < 0) {
if (FLAGS_SET(copy_flags, COPY_GRACEFUL_WARN) && (ERRNO_IS_PRIVILEGE(r) || ERRNO_IS_NOT_SUPPORTED(r))) {
log_notice_errno(r, "Failed to copy symlink '%s', ignoring: %m", from);
log_notice_errno(r, "Failed to copy symlink%s%s%s, ignoring: %m",
isempty(from) ? "" : " '",
strempty(from),
isempty(from) ? "" : "'");
return 0;
}
@@ -758,7 +760,6 @@ static int fd_copy_regular(
_cleanup_close_ int fdf = -EBADF, fdt = -EBADF;
int r, q;
assert(from);
assert(st);
assert(to);
@@ -768,9 +769,9 @@ static int fd_copy_regular(
if (r > 0) /* worked! */
return 0;
fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
fdf = xopenat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
if (fdf < 0)
return -errno;
return fdf;
if (copy_flags & COPY_MAC_CREATE) {
r = mac_selinux_create_file_prepare_at(dt, to, S_IFREG);
@@ -831,7 +832,6 @@ static int fd_copy_fifo(
HardlinkContext *hardlink_context) {
int r;
assert(from);
assert(st);
assert(to);
@@ -850,7 +850,10 @@ static int fd_copy_fifo(
if (copy_flags & COPY_MAC_CREATE)
mac_selinux_create_file_clear();
if (FLAGS_SET(copy_flags, COPY_GRACEFUL_WARN) && (ERRNO_IS_NEG_PRIVILEGE(r) || ERRNO_IS_NEG_NOT_SUPPORTED(r))) {
log_notice_errno(r, "Failed to copy fifo '%s', ignoring: %m", from);
log_notice_errno(r, "Failed to copy fifo%s%s%s, ignoring: %m",
isempty(from) ? "" : " '",
strempty(from),
isempty(from) ? "" : "'");
return 0;
} else if (r < 0)
return r;
@@ -882,7 +885,6 @@ static int fd_copy_node(
HardlinkContext *hardlink_context) {
int r;
assert(from);
assert(st);
assert(to);
@@ -901,7 +903,10 @@ static int fd_copy_node(
if (copy_flags & COPY_MAC_CREATE)
mac_selinux_create_file_clear();
if (FLAGS_SET(copy_flags, COPY_GRACEFUL_WARN) && (ERRNO_IS_NEG_PRIVILEGE(r) || ERRNO_IS_NEG_NOT_SUPPORTED(r))) {
log_notice_errno(r, "Failed to copy node '%s', ignoring: %m", from);
log_notice_errno(r, "Failed to copy node%s%s%s, ignoring: %m",
isempty(from) ? "" : " '",
strempty(from),
isempty(from) ? "" : "'");
return 0;
} else if (r < 0)
return r;
@@ -956,12 +961,9 @@ static int fd_copy_directory(
if (depth_left == 0)
return -ENAMETOOLONG;
if (from)
fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
else
fdf = fcntl(df, F_DUPFD_CLOEXEC, 3);
fdf = xopenat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
if (fdf < 0)
return -errno;
return fdf;
if (!hardlink_context) {
/* If recreating hardlinks is requested let's set up a context for that now. */
@@ -985,19 +987,19 @@ static int fd_copy_directory(
exists = r >= 0;
fdt = xopenat_lock(dt, to,
O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|(exists ? 0 : O_CREAT|O_EXCL),
(copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0)|(set_contains(subvolumes, st) ? XO_SUBVOLUME : 0),
st->st_mode & 07777,
copy_flags & COPY_LOCK_BSD ? LOCK_BSD : LOCK_NONE,
LOCK_EX);
fdt = xopenat_lock_full(dt, to,
O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|(exists ? 0 : O_CREAT|O_EXCL),
(copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0)|(set_contains(subvolumes, st) ? XO_SUBVOLUME : 0),
st->st_mode & 07777,
copy_flags & COPY_LOCK_BSD ? LOCK_BSD : LOCK_NONE,
LOCK_EX);
if (fdt < 0)
return fdt;
r = 0;
if (PTR_TO_INT(hashmap_get(denylist, st)) == DENY_CONTENTS) {
log_debug("%s is in the denylist, not recursing", from);
log_debug("%s is in the denylist, not recursing", from ?: "file to copy");
goto finish;
}
@@ -1031,7 +1033,8 @@ static int fd_copy_directory(
}
if (PTR_TO_INT(hashmap_get(denylist, &buf)) == DENY_INODE) {
log_debug("%s/%s is in the denylist, ignoring", from, de->d_name);
log_debug("%s%s%s is in the denylist, ignoring",
strempty(from), isempty(from) ? "" : "/", de->d_name);
continue;
}
@@ -1164,10 +1167,10 @@ static int fd_copy_tree_generic(
DenyType t = PTR_TO_INT(hashmap_get(denylist, st));
if (t == DENY_INODE) {
log_debug("%s is in the denylist, ignoring", from);
log_debug("%s is in the denylist, ignoring", from ?: "file to copy");
return 0;
} else if (t == DENY_CONTENTS)
log_debug("%s is configured to have its contents excluded, but is not a directory", from);
log_debug("%s is configured to have its contents excluded, but is not a directory", from ?: "file to copy");
r = fd_copy_leaf(df, from, st, dt, to, override_uid, override_gid, copy_flags, hardlink_context, display_path, progress_bytes, userdata);
/* We just tried to copy a leaf node of the tree. If it failed because the node already exists *and* the COPY_REPLACE flag has been provided, we should unlink the node and re-copy. */
@@ -1199,11 +1202,10 @@ int copy_tree_at_full(
struct stat st;
int r;
assert(from);
assert(to);
assert(!FLAGS_SET(copy_flags, COPY_LOCK_BSD));
if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0)
if (fstatat(fdf, strempty(from), &st, AT_SYMLINK_NOFOLLOW | (isempty(from) ? AT_EMPTY_PATH : 0)) < 0)
return -errno;
r = fd_copy_tree_generic(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid,
@@ -1306,13 +1308,12 @@ int copy_file_fd_at_full(
int r;
assert(dir_fdf >= 0 || dir_fdf == AT_FDCWD);
assert(from);
assert(fdt >= 0);
assert(!FLAGS_SET(copy_flags, COPY_LOCK_BSD));
fdf = openat(dir_fdf, from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
fdf = xopenat(dir_fdf, from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fdf < 0)
return -errno;
return fdf;
r = fd_verify_regular(fdf);
if (r < 0)
@@ -1364,12 +1365,11 @@ int copy_file_at_full(
assert(dir_fdf >= 0 || dir_fdf == AT_FDCWD);
assert(dir_fdt >= 0 || dir_fdt == AT_FDCWD);
assert(from);
assert(to);
fdf = openat(dir_fdf, from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
fdf = xopenat(dir_fdf, from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fdf < 0)
return -errno;
return fdf;
if (fstat(fdf, &st) < 0)
return -errno;
@@ -1379,11 +1379,11 @@ int copy_file_at_full(
return r;
WITH_UMASK(0000) {
fdt = xopenat_lock(dir_fdt, to,
flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
(copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0),
mode != MODE_INVALID ? mode : st.st_mode,
copy_flags & COPY_LOCK_BSD ? LOCK_BSD : LOCK_NONE, LOCK_EX);
fdt = xopenat_lock_full(dir_fdt, to,
flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
(copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0),
mode != MODE_INVALID ? mode : st.st_mode,
copy_flags & COPY_LOCK_BSD ? LOCK_BSD : LOCK_NONE, LOCK_EX);
if (fdt < 0)
return fdt;
}
@@ -1452,7 +1452,6 @@ int copy_file_atomic_at_full(
_cleanup_close_ int fdt = -EBADF;
int r;
assert(from);
assert(to);
assert(!FLAGS_SET(copy_flags, COPY_LOCK_BSD));
+6 -5
View File
@@ -210,11 +210,12 @@ static void journal_file_set_offline_internal(JournalFile *f) {
log_debug_errno(r, "Failed to re-enable copy-on-write for %s: %m, rewriting file", f->path);
r = copy_file_atomic_full(FORMAT_PROC_FD_PATH(f->fd), f->path, f->mode,
0,
FS_NOCOW_FL,
COPY_REPLACE | COPY_FSYNC | COPY_HOLES | COPY_ALL_XATTRS,
NULL, NULL);
r = copy_file_atomic_at_full(
f->fd, NULL, AT_FDCWD, f->path, f->mode,
0,
FS_NOCOW_FL,
COPY_REPLACE | COPY_FSYNC | COPY_HOLES | COPY_ALL_XATTRS,
NULL, NULL);
if (r < 0) {
log_debug_errno(r, "Failed to rewrite %s: %m", f->path);
continue;
+5 -5
View File
@@ -673,21 +673,21 @@ int loop_device_make_by_path_at(
direct_flags = FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO) ? O_DIRECT : 0;
rdwr_flags = open_flags >= 0 ? open_flags : O_RDWR;
fd = xopenat(dir_fd, path, basic_flags|direct_flags|rdwr_flags, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, basic_flags|direct_flags|rdwr_flags);
if (fd < 0 && direct_flags != 0) /* If we had O_DIRECT on, and things failed with that, let's immediately try again without */
fd = xopenat(dir_fd, path, basic_flags|rdwr_flags, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, basic_flags|rdwr_flags);
else
direct = direct_flags != 0;
if (fd < 0) {
r = -errno;
r = fd;
/* Retry read-only? */
if (open_flags >= 0 || !(ERRNO_IS_PRIVILEGE(r) || r == -EROFS))
return r;
fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY);
if (fd < 0 && direct_flags != 0) /* as above */
fd = xopenat(dir_fd, path, basic_flags|O_RDONLY, /* xopen_flags = */ 0, /* mode = */ 0);
fd = xopenat(dir_fd, path, basic_flags|O_RDONLY);
else
direct = direct_flags != 0;
if (fd < 0)
+1 -1
View File
@@ -71,7 +71,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
log_error_errno(r, "Failed to make snapshot: %m");
if (r >= 0)
assert_se(xopenat_lock(AT_FDCWD, "/xxxtest4", 0, 0, 0, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
assert_se(xopenat_lock(AT_FDCWD, "/xxxtest4", 0, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
safe_close(r);
+39 -2
View File
@@ -253,6 +253,43 @@ TEST(copy_tree) {
(void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
}
TEST(copy_tree_at_symlink) {
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_close_ int tfd = -EBADF, fd = -EBADF;
_cleanup_free_ char *p = NULL, *q = NULL;
const char *expect = "hgoehogefoobar";
tfd = mkdtemp_open(NULL, O_PATH, &t);
assert_se(tfd >= 0);
assert_se(symlinkat(expect, tfd, "from") >= 0);
assert_se(copy_tree_at(tfd, "from", tfd, "to_1", UID_INVALID, GID_INVALID, 0, NULL, NULL) >= 0);
assert_se(readlinkat_malloc(tfd, "to_1", &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
assert_se(q = path_join(t, "from"));
assert_se(copy_tree_at(AT_FDCWD, q, tfd, "to_2", UID_INVALID, GID_INVALID, 0, NULL, NULL) >= 0);
assert_se(readlinkat_malloc(tfd, "to_2", &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
q = mfree(q);
fd = openat(tfd, "from", O_CLOEXEC | O_PATH | O_NOFOLLOW);
assert_se(fd >= 0);
assert_se(copy_tree_at(fd, NULL, tfd, "to_3", UID_INVALID, GID_INVALID, 0, NULL, NULL) >= 0);
assert_se(readlinkat_malloc(tfd, "to_3", &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
assert_se(copy_tree_at(fd, "", tfd, "to_4", UID_INVALID, GID_INVALID, 0, NULL, NULL) >= 0);
assert_se(readlinkat_malloc(tfd, "to_4", &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
fd = safe_close(fd);
}
TEST(copy_bytes) {
_cleanup_close_pair_ int pipefd[2] = EBADF_PAIR;
_cleanup_close_ int infd = -EBADF;
@@ -520,12 +557,12 @@ TEST(copy_lock) {
assert_se((fd = copy_directory_at(tfd, "abc", tfd, "qed", COPY_LOCK_BSD)) >= 0);
assert_se(faccessat(tfd, "qed", F_OK, 0) >= 0);
assert_se(faccessat(tfd, "qed/def", F_OK, 0) >= 0);
assert_se(xopenat_lock(tfd, "qed", 0, 0, 0, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
assert_se(xopenat_lock(tfd, "qed", 0, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
fd = safe_close(fd);
assert_se((fd = copy_file_at(tfd, "abc/def", tfd, "poi", 0, 0644, COPY_LOCK_BSD)));
assert_se(read_file_at_and_streq(tfd, "poi", "abc\n"));
assert_se(xopenat_lock(tfd, "poi", 0, 0, 0, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
assert_se(xopenat_lock(tfd, "poi", 0, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
fd = safe_close(fd);
}
+58 -23
View File
@@ -673,37 +673,37 @@ TEST(openat_report_new) {
assert_se(b);
}
TEST(xopenat) {
TEST(xopenat_full) {
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_close_ int tfd = -EBADF, fd = -EBADF, fd2 = -EBADF;
assert_se((tfd = mkdtemp_open(NULL, 0, &t)) >= 0);
/* Test that xopenat() creates directories if O_DIRECTORY is specified. */
/* Test that xopenat_full() creates directories if O_DIRECTORY is specified. */
assert_se((fd = xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0, 0755)) >= 0);
assert_se((fd = xopenat_full(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0, 0755)) >= 0);
assert_se((fd_verify_directory(fd) >= 0));
fd = safe_close(fd);
assert_se(xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0, 0755) == -EEXIST);
assert_se(xopenat_full(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0, 0755) == -EEXIST);
assert_se((fd = xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_CLOEXEC, 0, 0755)) >= 0);
assert_se((fd = xopenat_full(tfd, "abc", O_DIRECTORY|O_CREAT|O_CLOEXEC, 0, 0755)) >= 0);
assert_se((fd_verify_directory(fd) >= 0));
fd = safe_close(fd);
/* Test that xopenat() creates regular files if O_DIRECTORY is not specified. */
/* Test that xopenat_full() creates regular files if O_DIRECTORY is not specified. */
assert_se((fd = xopenat(tfd, "def", O_CREAT|O_EXCL|O_CLOEXEC, 0, 0644)) >= 0);
assert_se((fd = xopenat_full(tfd, "def", O_CREAT|O_EXCL|O_CLOEXEC, 0, 0644)) >= 0);
assert_se(fd_verify_regular(fd) >= 0);
fd = safe_close(fd);
/* Test that we can reopen an existing fd with xopenat() by specifying an empty path. */
/* Test that we can reopen an existing fd with xopenat_full() by specifying an empty path. */
assert_se((fd = xopenat(tfd, "def", O_PATH|O_CLOEXEC, 0, 0)) >= 0);
assert_se((fd2 = xopenat(fd, "", O_RDWR|O_CLOEXEC, 0, 0644)) >= 0);
assert_se((fd = xopenat_full(tfd, "def", O_PATH|O_CLOEXEC, 0, 0)) >= 0);
assert_se((fd2 = xopenat_full(fd, "", O_RDWR|O_CLOEXEC, 0, 0644)) >= 0);
}
TEST(xopenat_lock) {
TEST(xopenat_lock_full) {
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_close_ int tfd = -EBADF, fd = -EBADF;
siginfo_t si;
@@ -714,11 +714,11 @@ TEST(xopenat_lock) {
* and close the file descriptor and still properly create the directory and acquire the lock in
* another process. */
fd = xopenat_lock(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
assert_se(fd >= 0);
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
assert_se(fd_verify_directory(fd) >= 0);
assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
pid_t pid = fork();
assert_se(pid >= 0);
@@ -726,21 +726,21 @@ TEST(xopenat_lock) {
if (pid == 0) {
safe_close(fd);
fd = xopenat_lock(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
fd = xopenat_lock_full(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
assert_se(fd >= 0);
assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
assert_se(fd_verify_directory(fd) >= 0);
assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
assert_se(xopenat_lock_full(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
_exit(EXIT_SUCCESS);
}
/* We need to give the child process some time to get past the xopenat() call in xopenat_lock() and
* block in the call to lock_generic() waiting for the lock to become free. We can't modify
* xopenat_lock() to signal an eventfd to let us know when that has happened, so we just sleep for a
* little and assume that's enough time for the child process to get along far enough. It doesn't
* matter if it doesn't get far enough, in that case we just won't trigger the fallback logic in
* xopenat_lock(), but the test will still succeed. */
/* We need to give the child process some time to get past the xopenat() call in xopenat_lock_full()
* and block in the call to lock_generic() waiting for the lock to become free. We can't modify
* xopenat_lock_full() to signal an eventfd to let us know when that has happened, so we just sleep
* for a little and assume that's enough time for the child process to get along far enough. It
* doesn't matter if it doesn't get far enough, in that case we just won't trigger the fallback logic
* in xopenat_lock_full(), but the test will still succeed. */
assert_se(usleep_safe(20 * USEC_PER_MSEC) >= 0);
assert_se(unlinkat(tfd, "abc", AT_REMOVEDIR) >= 0);
@@ -749,8 +749,8 @@ TEST(xopenat_lock) {
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
assert_se(xopenat_lock(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
assert_se(xopenat_lock(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
assert_se(xopenat_lock_full(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
assert_se(xopenat_lock_full(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
}
static int intro(void) {
@@ -758,4 +758,39 @@ static int intro(void) {
return EXIT_SUCCESS;
}
TEST(readlinkat_malloc) {
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_close_ int tfd = -EBADF, fd = -EBADF;
_cleanup_free_ char *p = NULL, *q = NULL;
const char *expect = "hgoehogefoobar";
tfd = mkdtemp_open(NULL, O_PATH, &t);
assert_se(tfd >= 0);
assert_se(symlinkat(expect, tfd, "linkname") >= 0);
assert_se(readlinkat_malloc(tfd, "linkname", &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
fd = openat(tfd, "linkname", O_PATH | O_NOFOLLOW | O_CLOEXEC);
assert_se(fd >= 0);
assert_se(readlinkat_malloc(fd, NULL, &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
assert_se(readlinkat_malloc(fd, "", &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
fd = safe_close(fd);
assert_se(q = path_join(t, "linkname"));
assert_se(readlinkat_malloc(AT_FDCWD, q, &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
assert_se(readlinkat_malloc(INT_MAX, q, &p) >= 0);
assert_se(streq(p, expect));
p = mfree(p);
q = mfree(q);
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
+1 -5
View File
@@ -892,11 +892,7 @@ static int dir_cleanup(
continue;
if (!arg_dry_run) {
fd = xopenat(dirfd(d),
de->d_name,
O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME|O_NONBLOCK,
/* xopen_flags = */ 0,
/* mode = */ 0);
fd = xopenat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME|O_NONBLOCK);
if (fd < 0 && !IN_SET(fd, -ENOENT, -ELOOP))
log_warning_errno(fd, "Opening file \"%s\" failed, ignoring: %m", sub_path);
if (fd >= 0 && flock(fd, LOCK_EX|LOCK_NB) < 0 && errno == EAGAIN) {