int btrfs_subvol_make(int dir_fd, const char *path) {
struct btrfs_ioctl_vol_args args = {};
- _cleanup_free_ char *subvolume = NULL;
+ _cleanup_free_ char *subvolume = NULL, *parent = NULL;
_cleanup_close_ int fd = -EBADF;
int r;
if (r < 0)
return r;
- r = path_extract_directory(path, NULL);
- if (r >= 0) {
- fd = open_parent_at(dir_fd, path, O_RDONLY|O_CLOEXEC|O_CLOEXEC, 0);
+ r = path_extract_directory(path, &parent);
+ if (r < 0) {
+ if (r != -EDESTADDRREQ) /* Propagate error, unless only a filename was specified, which is OK */
+ return r;
+
+ dir_fd = fd_reopen_condition(dir_fd, O_CLOEXEC, O_PATH, &fd); /* drop O_PATH if it is set */
+ if (dir_fd < 0)
+ return dir_fd;
+ } else {
+ fd = openat(dir_fd, parent, O_DIRECTORY|O_RDONLY|O_CLOEXEC, 0);
if (fd < 0)
- return fd;
+ return -errno;
dir_fd = fd;
}