}
int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) {
- char fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
bool do_chown, do_chmod;
struct stat st;
* unaffected if the uid/gid is changed, i.e. it undoes implicit suid/sgid dropping the kernel does
* on chown().
*
- * This call is happy with O_PATH fds, since we always go via /proc/self/fd/ to change
- * ownership/access mode. */
+ * This call is happy with O_PATH fds. */
- xsprintf(fd_path, "/proc/self/fd/%i", fd);
- if (stat(fd_path, &st) < 0)
+ if (fstat(fd, &st) < 0)
return -errno;
do_chown =
mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */
if (((minimal ^ st.st_mode) & 07777) != 0)
- if (chmod(fd_path, minimal & 07777) < 0)
+ if (fchmod_opath(fd, minimal & 07777) < 0)
return -errno;
}
if (do_chown)
- if (chown(fd_path, uid, gid) < 0)
+ if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0)
return -errno;
if (do_chmod)
- if (chmod(fd_path, mode & 07777) < 0)
+ if (fchmod_opath(fd, mode & 07777) < 0)
return -errno;
return do_chown || do_chmod;
/* Prefix what's left to do with what we just read, and start the loop again, but
* remain in the current directory. */
- joined = strjoin(destination, todo);
+ joined = path_join(destination, todo);
} else
- joined = strjoin("/", destination, todo);
+ joined = path_join("/", destination, todo);
if (!joined)
return -ENOMEM;
return 0;
}
+int fsync_full(int fd) {
+ int r, q;
+
+ /* Sync both the file and the directory */
+
+ r = fsync(fd) < 0 ? -errno : 0;
+ q = fsync_directory_of_file(fd);
+
+ return r < 0 ? r : q;
+}
+
int fsync_path_at(int at_fd, const char *path) {
_cleanup_close_ int opened_fd = -1;
int fd;