mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-08-31 07:59:58 -04:00
fuse-overlayfs: mkdir creates the directory in the workdir first
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
996f297f9d
commit
b8f90ec1f6
92
main.c
92
main.c
@ -1281,33 +1281,20 @@ copy_xattr (int sfd, int dfd, char *buf, size_t buf_size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int create_node_directory (struct ovl_data *lo, struct ovl_node *src);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_directory (struct ovl_data *lo, struct ovl_node *src)
|
create_directory (struct ovl_data *lo, int dirfd, const char *name, const struct timespec *times,
|
||||||
|
struct ovl_node *parent, int xattr_sfd, uid_t uid, gid_t gid, mode_t mode)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct stat st;
|
int dfd = -1;
|
||||||
int sfd = -1, dfd = -1;
|
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
char wd_tmp_file_name[32];
|
char wd_tmp_file_name[32];
|
||||||
struct timespec times[2];
|
|
||||||
|
|
||||||
if (src == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (src->layer == get_upper_layer (lo))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
||||||
|
|
||||||
ret = sfd = TEMP_FAILURE_RETRY (openat (node_dirfd (src), src->path, O_RDONLY));
|
ret = mkdirat (lo->workdir_fd, wd_tmp_file_name, mode);
|
||||||
if (ret < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = TEMP_FAILURE_RETRY (fstat (sfd, &st));
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = mkdirat (lo->workdir_fd, wd_tmp_file_name, st.st_mode);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -1315,17 +1302,18 @@ create_directory (struct ovl_data *lo, struct ovl_node *src)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = fchown (dfd, st.st_uid, st.st_gid);
|
ret = fchown (dfd, uid, gid);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
times[0] = st.st_atim;
|
if (times)
|
||||||
times[1] = st.st_mtim;
|
{
|
||||||
ret = futimens (dfd, times);
|
ret = futimens (dfd, times);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0 && xattr_sfd >= 0)
|
||||||
{
|
{
|
||||||
const size_t buf_size = 1 << 20;
|
const size_t buf_size = 1 << 20;
|
||||||
char *buf = malloc (buf_size);
|
char *buf = malloc (buf_size);
|
||||||
@ -1335,26 +1323,26 @@ create_directory (struct ovl_data *lo, struct ovl_node *src)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = copy_xattr (sfd, dfd, buf, buf_size);
|
ret = copy_xattr (xattr_sfd, dfd, buf, buf_size);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = renameat (lo->workdir_fd, wd_tmp_file_name, get_upper_layer (lo)->fd, src->path);
|
unlinkat (dirfd, name, 0);
|
||||||
|
|
||||||
|
ret = renameat (lo->workdir_fd, wd_tmp_file_name, dirfd, name);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
if (errno == ENOENT && src->parent)
|
if (errno == ENOENT && parent)
|
||||||
{
|
{
|
||||||
ret = create_directory (lo, src->parent);
|
ret = create_node_directory (lo, parent);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = renameat (lo->workdir_fd, wd_tmp_file_name, get_upper_layer (lo)->fd, src->path);
|
ret = renameat (lo->workdir_fd, wd_tmp_file_name, dirfd, name);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (sfd >= 0)
|
|
||||||
close (sfd);
|
|
||||||
if (dfd >= 0)
|
if (dfd >= 0)
|
||||||
close (dfd);
|
close (dfd);
|
||||||
if (buf)
|
if (buf)
|
||||||
@ -1362,7 +1350,40 @@ out:
|
|||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
unlinkat (lo->workdir_fd, wd_tmp_file_name, AT_REMOVEDIR);
|
unlinkat (lo->workdir_fd, wd_tmp_file_name, AT_REMOVEDIR);
|
||||||
else
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
create_node_directory (struct ovl_data *lo, struct ovl_node *src)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct stat st;
|
||||||
|
int sfd = -1;
|
||||||
|
struct timespec times[2];
|
||||||
|
|
||||||
|
if (src == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (src->layer == get_upper_layer (lo))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = sfd = TEMP_FAILURE_RETRY (openat (node_dirfd (src), src->path, O_RDONLY));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = TEMP_FAILURE_RETRY (fstat (sfd, &st));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
times[0] = st.st_atim;
|
||||||
|
times[1] = st.st_mtim;
|
||||||
|
|
||||||
|
ret = create_directory (lo, get_upper_layer (lo)->fd, src->path, times, src->parent, sfd, st.st_uid, st.st_gid, st.st_mode);
|
||||||
|
|
||||||
|
close (sfd);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
src->layer = get_upper_layer (lo);
|
src->layer = get_upper_layer (lo);
|
||||||
|
|
||||||
@ -1393,7 +1414,7 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
|
|||||||
|
|
||||||
if (node->parent)
|
if (node->parent)
|
||||||
{
|
{
|
||||||
ret = create_directory (lo, node->parent);
|
ret = create_node_directory (lo, node->parent);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1405,7 +1426,7 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
|
|||||||
|
|
||||||
if ((st.st_mode & S_IFMT) == S_IFDIR)
|
if ((st.st_mode & S_IFMT) == S_IFDIR)
|
||||||
{
|
{
|
||||||
ret = create_directory (lo, node);
|
ret = create_node_directory (lo, node);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
goto success;
|
goto success;
|
||||||
@ -2625,6 +2646,7 @@ ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
char path[PATH_MAX + 10];
|
char path[PATH_MAX + 10];
|
||||||
struct fuse_entry_param e;
|
struct fuse_entry_param e;
|
||||||
|
const struct fuse_ctx *ctx = fuse_req_ctx (req);
|
||||||
|
|
||||||
if (ovl_debug (req))
|
if (ovl_debug (req))
|
||||||
fprintf (stderr, "ovl_mkdir(ino=%" PRIu64 ", name=%s, mode=%d)\n",
|
fprintf (stderr, "ovl_mkdir(ino=%" PRIu64 ", name=%s, mode=%d)\n",
|
||||||
@ -2652,8 +2674,8 @@ ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
|
|||||||
}
|
}
|
||||||
sprintf (path, "%s/%s", pnode->path, name);
|
sprintf (path, "%s/%s", pnode->path, name);
|
||||||
|
|
||||||
unlinkat (get_upper_layer (lo)->fd, path, AT_REMOVEDIR);
|
ret = create_directory (lo, get_upper_layer (lo)->fd, path, NULL, pnode, -1,
|
||||||
ret = mkdirat (get_upper_layer (lo)->fd, path, mode);
|
get_uid (lo, ctx->uid), get_gid (lo, ctx->gid), mode);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
fuse_reply_err (req, errno);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user