]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/sync-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
11 int fsync_directory_of_file(int fd
) {
12 _cleanup_close_
int dfd
= -EBADF
;
18 /* We only reasonably can do this for regular files and directories, or for O_PATH fds, hence check
19 * for the inode type first */
20 if (fstat(fd
, &st
) < 0)
23 if (S_ISDIR(st
.st_mode
)) {
24 dfd
= openat(fd
, "..", O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
, 0);
28 } else if (!S_ISREG(st
.st_mode
)) { /* Regular files are OK regardless if O_PATH or not, for all other
29 * types check O_PATH flag */
32 flags
= fcntl(fd
, F_GETFL
);
36 if (!FLAGS_SET(flags
, O_PATH
)) /* If O_PATH this refers to the inode in the fs, in which case
37 * we can sensibly do what is requested. Otherwise this refers
38 * to a socket, fifo or device node, where the concept of a
39 * containing directory doesn't make too much sense. */
44 _cleanup_free_
char *path
= NULL
;
46 r
= fd_get_path(fd
, &path
);
48 log_debug_errno(r
, "Failed to query /proc/self/fd/%d%s: %m",
50 r
== -ENOSYS
? ", ignoring" : "");
53 /* If /proc is not available, we're most likely running in some
54 * chroot environment, and syncing the directory is not very
55 * important in that case. Let's just silently do nothing. */
61 if (!path_is_absolute(path
))
64 dfd
= open_parent(path
, O_CLOEXEC
|O_NOFOLLOW
, 0);
69 return RET_NERRNO(fsync(dfd
));
72 int fsync_full(int fd
) {
75 /* Sync both the file and the directory */
77 r
= RET_NERRNO(fsync(fd
));
79 q
= fsync_directory_of_file(fd
);
80 if (r
< 0) /* Return earlier error */
82 if (q
== -ENOTTY
) /* Ignore if the 'fd' refers to a block device or so which doesn't really have a
88 int fsync_path_at(int at_fd
, const char *path
) {
89 _cleanup_close_
int opened_fd
= -EBADF
;
93 if (at_fd
== AT_FDCWD
) {
94 opened_fd
= open(".", O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
);
102 opened_fd
= openat(at_fd
, path
, O_RDONLY
|O_CLOEXEC
|O_NONBLOCK
);
109 return RET_NERRNO(fsync(fd
));
112 int fsync_parent_at(int at_fd
, const char *path
) {
113 _cleanup_close_
int opened_fd
= -EBADF
;
116 if (at_fd
!= AT_FDCWD
)
117 return fsync_directory_of_file(at_fd
);
119 opened_fd
= open("..", O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
);
123 return RET_NERRNO(fsync(opened_fd
));
126 opened_fd
= openat(at_fd
, path
, O_PATH
|O_CLOEXEC
|O_NOFOLLOW
);
130 return fsync_directory_of_file(opened_fd
);
133 int fsync_path_and_parent_at(int at_fd
, const char *path
) {
134 _cleanup_close_
int opened_fd
= -EBADF
;
137 if (at_fd
!= AT_FDCWD
)
138 return fsync_full(at_fd
);
140 opened_fd
= open(".", O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
);
142 opened_fd
= openat(at_fd
, path
, O_RDONLY
|O_NOFOLLOW
|O_NONBLOCK
|O_CLOEXEC
);
146 return fsync_full(opened_fd
);
149 int syncfs_path(int at_fd
, const char *path
) {
150 _cleanup_close_
int fd
= -EBADF
;
153 if (at_fd
!= AT_FDCWD
)
154 return RET_NERRNO(syncfs(at_fd
));
156 fd
= open(".", O_RDONLY
|O_DIRECTORY
|O_CLOEXEC
);
158 fd
= openat(at_fd
, path
, O_RDONLY
|O_CLOEXEC
|O_NONBLOCK
);
162 return RET_NERRNO(syncfs(fd
));