#include "fd-util.h"
#include "fs-util.h"
#include "log.h"
+#include "recurse-dir.h"
#include "string-util.h"
int chattr_full(
return read_attr_fd(fd, ret);
}
+
+int read_fs_xattr_fd(int fd, uint32_t *ret_xflags, uint32_t *ret_projid) {
+ struct fsxattr attrs;
+ _cleanup_close_ int fd_reopened = -EBADF;
+
+ assert(fd >= 0);
+
+ fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_reopened);
+ if (fd < 0)
+ return fd;
+
+ if (ioctl(fd, FS_IOC_FSGETXATTR, &attrs) < 0)
+ return -errno;
+
+ if (ret_xflags)
+ *ret_xflags = attrs.fsx_xflags;
+
+ if (ret_projid)
+ *ret_projid = attrs.fsx_projid;
+
+ return 0;
+}
+
+int set_proj_id(int fd, uint32_t proj_id) {
+ struct fsxattr attrs;
+ _cleanup_close_ int fd_reopened = -EBADF;
+
+ assert(fd >= 0);
+
+ fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_reopened);
+ if (fd < 0)
+ return fd;
+
+ if (ioctl(fd, FS_IOC_FSGETXATTR, &attrs) < 0)
+ return -errno;
+
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) < 0)
+ return -errno;
+
+ if (attrs.fsx_projid == proj_id && (!S_ISDIR(statbuf.st_mode) || FLAGS_SET(attrs.fsx_xflags, FS_XFLAG_PROJINHERIT)))
+ return 0;
+
+ attrs.fsx_projid = proj_id;
+ if (S_ISDIR(statbuf.st_mode))
+ attrs.fsx_xflags |= FS_XFLAG_PROJINHERIT;
+
+ return RET_NERRNO(ioctl(fd, FS_IOC_FSSETXATTR, &attrs));
+}
+
+static int set_proj_id_cb(
+ RecurseDirEvent event,
+ const char *path,
+ int dir_fd,
+ int inode_fd,
+ const struct dirent *de,
+ const struct statx *sx,
+ void *userdata) {
+
+ if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY))
+ return RECURSE_DIR_CONTINUE;
+
+ if (de && !IN_SET(de->d_type, DT_DIR, DT_REG))
+ return RECURSE_DIR_CONTINUE;
+
+ return set_proj_id(inode_fd, PTR_TO_UINT32(userdata));
+}
+
+int set_proj_id_recursive(int fd, uint32_t proj_id) {
+ return recurse_dir_at(
+ fd,
+ /* path = */ NULL,
+ /* statx_mask = */ 0,
+ /* n_depth_max = */ UINT_MAX,
+ RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_TOPLEVEL|RECURSE_DIR_INODE_FD,
+ set_proj_id_cb,
+ UINT32_TO_PTR(proj_id));
+}
int read_attr_fd(int fd, unsigned *ret);
int read_attr_at(int dir_fd, const char *path, unsigned *ret);
+int read_fs_xattr_fd(int fd, uint32_t *ret_xflags, uint32_t *ret_projid);
+
+int set_proj_id(int fd, uint32_t proj_id);
+int set_proj_id_recursive(int fd, uint32_t proj_id);
/* Combination of chattr flags, that should be appropriate for secrets stored on disk: Secure Remove +
* Exclusion from Dumping + Synchronous Writing (i.e. not caching in memory) + In-Place Updating (i.e. not