mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #20166 from poettering/fsync-more
various tweaks to existing fsync() helpers, and some new apis
This commit is contained in:
@@ -1378,18 +1378,39 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags) {
|
||||
}
|
||||
|
||||
int fsync_directory_of_file(int fd) {
|
||||
_cleanup_free_ char *path = NULL;
|
||||
_cleanup_close_ int dfd = -1;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
/* We only reasonably can do this for regular files and directories, hence check for that */
|
||||
/* We only reasonably can do this for regular files and directories, or for O_PATH fds, hence check
|
||||
* for the inode type first */
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
dfd = openat(fd, "..", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0);
|
||||
if (dfd < 0)
|
||||
return -errno;
|
||||
|
||||
} else if (!S_ISREG(st.st_mode)) { /* Regular files are OK regardless if O_PATH or not, for all other
|
||||
* types check O_PATH flag */
|
||||
int flags;
|
||||
|
||||
flags = fcntl(fd, F_GETFL);
|
||||
if (flags < 0)
|
||||
return -errno;
|
||||
|
||||
if (!FLAGS_SET(flags, O_PATH)) /* If O_PATH this refers to the inode in the fs, in which case
|
||||
* we can sensibly do what is requested. Otherwise this refers
|
||||
* to a socket, fifo or device node, where the concept of a
|
||||
* containing directory doesn't make too much sense. */
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
if (dfd < 0) {
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
r = fd_get_path(fd, &path);
|
||||
if (r < 0) {
|
||||
@@ -1412,13 +1433,7 @@ int fsync_directory_of_file(int fd) {
|
||||
dfd = open_parent(path, O_CLOEXEC|O_NOFOLLOW, 0);
|
||||
if (dfd < 0)
|
||||
return dfd;
|
||||
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
dfd = openat(fd, "..", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0);
|
||||
if (dfd < 0)
|
||||
return -errno;
|
||||
} else
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
if (fsync(dfd) < 0)
|
||||
return -errno;
|
||||
@@ -1469,12 +1484,56 @@ int fsync_path_at(int at_fd, const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fsync_parent_at(int at_fd, const char *path) {
|
||||
_cleanup_close_ int opened_fd = -1;
|
||||
|
||||
if (isempty(path)) {
|
||||
if (at_fd != AT_FDCWD)
|
||||
return fsync_directory_of_file(at_fd);
|
||||
|
||||
opened_fd = open("..", O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
if (opened_fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (fsync(opened_fd) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
opened_fd = openat(at_fd, path, O_PATH|O_CLOEXEC|O_NOFOLLOW);
|
||||
if (opened_fd < 0)
|
||||
return -errno;
|
||||
|
||||
return fsync_directory_of_file(opened_fd);
|
||||
}
|
||||
|
||||
int fsync_path_and_parent_at(int at_fd, const char *path) {
|
||||
_cleanup_close_ int opened_fd = -1;
|
||||
|
||||
if (isempty(path)) {
|
||||
if (at_fd != AT_FDCWD)
|
||||
return fsync_full(at_fd);
|
||||
|
||||
opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
} else
|
||||
opened_fd = openat(at_fd, path, O_RDONLY|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC);
|
||||
if (opened_fd < 0)
|
||||
return -errno;
|
||||
|
||||
return fsync_full(opened_fd);
|
||||
}
|
||||
|
||||
int syncfs_path(int atfd, const char *path) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
assert(path);
|
||||
if (isempty(path)) {
|
||||
if (atfd != AT_FDCWD)
|
||||
return syncfs(atfd) < 0 ? -errno : 0;
|
||||
|
||||
fd = openat(atfd, path, O_CLOEXEC|O_RDONLY|O_NONBLOCK);
|
||||
fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC);
|
||||
} else
|
||||
fd = openat(atfd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
|
||||
@@ -140,6 +140,8 @@ int unlinkat_deallocate(int fd, const char *name, UnlinkDeallocateFlags flags);
|
||||
int fsync_directory_of_file(int fd);
|
||||
int fsync_full(int fd);
|
||||
int fsync_path_at(int at_fd, const char *path);
|
||||
int fsync_parent_at(int at_fd, const char *path);
|
||||
int fsync_path_and_parent_at(int at_fd, const char *path);
|
||||
|
||||
int syncfs_path(int atfd, const char *path);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user