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, 0755);
+ child = xopenat(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)) {
/* 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));
r = chase(path, root, CHASE_PARENT|chase_flags, &p, &path_fd);
return r;
}
- r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, mode);
+ r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
if (r < 0)
return r;
/* 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));
r = chaseat(dir_fd, path, chase_flags|CHASE_PARENT, &p, &path_fd);
return r;
}
- r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, mode);
+ r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
if (r < 0)
return r;
#include "fileio.h"
#include "fs-util.h"
#include "hostname-util.h"
+#include "label.h"
#include "lock-util.h"
#include "log.h"
#include "macro.h"
path = fname;
}
- fd = xopenat(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, mode);
+ fd = xopenat(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
if (IN_SET(fd, -ELOOP, -ENOTDIR))
return -EEXIST;
if (fd < 0)
}
}
-int xopenat(int dir_fd, const char *path, int flags, mode_t mode) {
+int xopenat(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;
assert(path);
if (isempty(path)) {
- assert(!FLAGS_SET(flags, O_CREAT|O_EXCL));
- return fd_reopen(dir_fd, flags & ~O_NOFOLLOW);
+ assert(!FLAGS_SET(open_flags, O_CREAT|O_EXCL));
+ return fd_reopen(dir_fd, open_flags & ~O_NOFOLLOW);
}
- if (FLAGS_SET(flags, O_DIRECTORY|O_CREAT)) {
+ if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) {
+ r = label_ops_pre(dir_fd, path, FLAGS_SET(open_flags, O_DIRECTORY) ? S_IFDIR : S_IFREG);
+ if (r < 0)
+ return r;
+ }
+
+ if (FLAGS_SET(open_flags, O_DIRECTORY|O_CREAT)) {
r = RET_NERRNO(mkdirat(dir_fd, path, mode));
if (r == -EEXIST) {
- if (FLAGS_SET(flags, O_EXCL))
+ if (FLAGS_SET(open_flags, O_EXCL))
return -EEXIST;
made = false;
else
made = true;
- flags &= ~(O_EXCL|O_CREAT);
+ if (FLAGS_SET(xopen_flags, XO_LABEL)) {
+ r = label_ops_post(dir_fd, path);
+ if (r < 0)
+ return r;
+ }
+
+ open_flags &= ~(O_EXCL|O_CREAT);
+ xopen_flags &= ~XO_LABEL;
}
- fd = RET_NERRNO(openat(dir_fd, path, flags, mode));
+ fd = RET_NERRNO(openat(dir_fd, path, open_flags, mode));
if (fd < 0) {
if (IN_SET(fd,
/* We got ENOENT? then someone else immediately removed it after we
return fd;
}
+ if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) {
+ r = label_ops_post(dir_fd, path);
+ if (r < 0)
+ return r;
+ }
+
return TAKE_FD(fd);
}
-int xopenat_lock(int dir_fd, const char *path, int flags, mode_t mode, LockType locktype, int operation) {
+int xopenat_lock(
+ int dir_fd,
+ const char *path,
+ int open_flags,
+ XOpenFlags xopen_flags,
+ mode_t mode,
+ LockType locktype,
+ int operation) {
+
_cleanup_close_ int fd = -EBADF;
int r;
/* POSIX/UNPOSIX locks don't work on directories (errno is set to -EBADF so let's return early with
* the same error here). */
- if (FLAGS_SET(flags, O_DIRECTORY) && locktype != LOCK_BSD)
+ if (FLAGS_SET(open_flags, O_DIRECTORY) && locktype != LOCK_BSD)
return -EBADF;
for (;;) {
struct stat st;
- fd = xopenat(dir_fd, path, flags, mode);
+ fd = xopenat(dir_fd, path, open_flags, xopen_flags, mode);
if (fd < 0)
return fd;
int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, bool *ret_newly_created);
-int xopenat(int dir_fd, const char *path, int flags, mode_t mode);
+typedef enum XOpenFlags {
+ XO_LABEL = 1 << 0,
+} XOpenFlags;
-int xopenat_lock(int dir_fd, const char *path, int flags, mode_t mode, LockType locktype, int operation);
+int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode);
+
+int xopenat_lock(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation);
if (!t)
return -ENOMEM;
- fd = xopenat_lock(dfd, p, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600, LOCK_UNPOSIX, operation);
+ fd = xopenat_lock(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;
assert(path);
assert(ret);
- fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY, 0);
+ fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
if (fd < 0)
return fd;
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(path);
- fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY, 0);
+ fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
if (fd < 0)
return fd;
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, 0444);
+ fd = xopenat(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, /* xopen_flags = */ 0, 0444);
if (fd < 0)
return fd;
assert(path);
assert(ret);
- fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, 0);
+ fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
if (fd < 0)
return fd;
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, 0);
+ fd = xopenat(dir_fd, path, basic_flags|direct_flags|rdwr_flags, /* xopen_flags = */ 0, /* mode = */ 0);
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, 0);
+ fd = xopenat(dir_fd, path, basic_flags|rdwr_flags, /* xopen_flags = */ 0, /* mode = */ 0);
else
direct = direct_flags != 0;
if (fd < 0) {
if (open_flags >= 0 || !(ERRNO_IS_PRIVILEGE(r) || r == -EROFS))
return r;
- fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY, 0);
+ fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY, /* xopen_flags = */ 0, /* mode = */ 0);
if (fd < 0 && direct_flags != 0) /* as above */
- fd = xopenat(dir_fd, path, basic_flags|O_RDONLY, 0);
+ fd = xopenat(dir_fd, path, basic_flags|O_RDONLY, /* xopen_flags = */ 0, /* mode = */ 0);
else
direct = direct_flags != 0;
if (fd < 0)
/* Test that xopenat() creates directories if O_DIRECTORY is specified. */
- assert_se((fd = xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0755)) >= 0);
+ assert_se((fd = xopenat(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, 0755) == -EEXIST);
+ assert_se(xopenat(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, 0755)) >= 0);
+ assert_se((fd = xopenat(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. */
- assert_se((fd = xopenat(tfd, "def", O_CREAT|O_EXCL|O_CLOEXEC, 0644)) >= 0);
+ assert_se((fd = xopenat(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. */
- assert_se((fd = xopenat(tfd, "def", O_PATH|O_CLOEXEC, 0)) >= 0);
- assert_se((fd2 = xopenat(fd, "", O_RDWR|O_CLOEXEC, 0644)) >= 0);
+ 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);
}
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, 0755, LOCK_BSD, LOCK_EX);
+ fd = xopenat_lock(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, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
+ assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
pid_t pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
safe_close(fd);
- fd = xopenat_lock(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0755, LOCK_BSD, LOCK_EX);
+ fd = xopenat_lock(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, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
+ assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate(pid, &si) >= 0);
assert_se(si.si_code == CLD_EXITED);
- assert_se(xopenat_lock(tfd, "abc", 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
- assert_se(xopenat_lock(tfd, "def", O_DIRECTORY, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
+ 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);
}
static int intro(void) {
cutoff_nsec, sub_path, age_by_file, false))
continue;
- fd = xopenat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME, 0);
+ fd = xopenat(dirfd(d),
+ de->d_name,
+ O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME,
+ /* xopen_flags = */ 0,
+ /* mode = */ 0);
if (fd < 0 && fd != -ENOENT)
log_warning_errno(fd, "Opening file \"%s\" failed, ignoring: %m", sub_path);
if (fd >= 0 && flock(fd, LOCK_EX|LOCK_NB) < 0 && errno == EAGAIN) {