mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-08-03 18:05:58 -04:00
containerfs: use the workingdir to create a directory
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
c820997ed6
commit
78d72baaa4
84
main.c
84
main.c
@ -1214,6 +1214,10 @@ create_directory (struct lo_data *lo, struct lo_node *src)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
int sfd = -1, dfd = -1;
|
||||||
|
char *buf = NULL;
|
||||||
|
char wd_tmp_file_name[32];
|
||||||
|
struct timespec times[2];
|
||||||
|
|
||||||
if (src == NULL)
|
if (src == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1221,31 +1225,72 @@ create_directory (struct lo_data *lo, struct lo_node *src)
|
|||||||
if (src->layer == get_upper_layer (lo))
|
if (src->layer == get_upper_layer (lo))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = fstatat (node_dirfd (src), src->path, &st, AT_SYMLINK_NOFOLLOW);
|
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
||||||
|
|
||||||
|
ret = sfd = openat (node_dirfd (src), src->path, O_RDONLY);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = mkdirat (get_upper_layer (lo)->fd, src->path, st.st_mode);
|
ret = fstat (sfd, &st);
|
||||||
if (ret < 0 && errno == EEXIST)
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = mkdirat (lo->workdir_fd, wd_tmp_file_name, st.st_mode);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = dfd = openat (lo->workdir_fd, wd_tmp_file_name, O_RDONLY);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = fchown (dfd, st.st_uid, st.st_gid);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
times[0] = st.st_atim;
|
||||||
|
times[1] = st.st_mtim;
|
||||||
|
ret = futimens (dfd, times);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
ret = 0;
|
const size_t buf_size = 1 << 20;
|
||||||
|
char *buf = malloc (buf_size);
|
||||||
|
if (buf == NULL)
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
else if (ret < 0 && errno == ENOENT)
|
|
||||||
|
ret = copy_xattr (sfd, dfd, buf, buf_size);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = renameat (lo->workdir_fd, wd_tmp_file_name, get_upper_layer (lo)->fd, src->path);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
if (errno == ENOENT && src->parent)
|
||||||
{
|
{
|
||||||
ret = create_directory (lo, src->parent);
|
ret = create_directory (lo, src->parent);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = mkdirat (lo->layers[0].fd, src->path, st.st_mode);
|
|
||||||
if (ret < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = fchownat (lo->layers[0].fd, src->path, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = renameat (lo->workdir_fd, wd_tmp_file_name, get_upper_layer (lo)->fd, src->path);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
if (ret == 0)
|
if (sfd >= 0)
|
||||||
|
close (sfd);
|
||||||
|
if (dfd >= 0)
|
||||||
|
close (dfd);
|
||||||
|
if (buf)
|
||||||
|
free (buf);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
unlinkat (lo->workdir_fd, wd_tmp_file_name, AT_REMOVEDIR);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
src->layer = get_upper_layer (lo);
|
src->layer = get_upper_layer (lo);
|
||||||
|
|
||||||
@ -1272,20 +1317,18 @@ copyup (struct lo_data *lo, struct lo_node *node)
|
|||||||
struct timespec times[2];
|
struct timespec times[2];
|
||||||
char wd_tmp_file_name[32];
|
char wd_tmp_file_name[32];
|
||||||
|
|
||||||
|
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
||||||
|
|
||||||
|
ret = fstatat (node_dirfd (node), node->path, &st, AT_SYMLINK_NOFOLLOW);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (node->parent)
|
if (node->parent)
|
||||||
{
|
{
|
||||||
ret = create_directory (lo, node->parent);
|
ret = create_directory (lo, node->parent);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
|
|
||||||
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
|
||||||
|
|
||||||
if (fstatat (node_dirfd (node), node->path, &st, AT_SYMLINK_NOFOLLOW) < 0)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
if (node->parent)
|
|
||||||
{
|
|
||||||
char whpath[PATH_MAX + 10];
|
char whpath[PATH_MAX + 10];
|
||||||
sprintf (whpath, "%s/.wh.%s", node->parent->path, node->name);
|
sprintf (whpath, "%s/.wh.%s", node->parent->path, node->name);
|
||||||
if (unlinkat (get_upper_layer (lo)->fd, whpath, 0) < 0 && errno != ENOENT)
|
if (unlinkat (get_upper_layer (lo)->fd, whpath, 0) < 0 && errno != ENOENT)
|
||||||
@ -2058,7 +2101,6 @@ lo_link (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, const char *newna
|
|||||||
fsetxattr (dfd, REDIRECT_XATTR, node->path, strlen (node->path), 0);
|
fsetxattr (dfd, REDIRECT_XATTR, node->path, strlen (node->path), 0);
|
||||||
close (dfd);
|
close (dfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node = make_lo_node (path, get_upper_layer (lo), newname, node->ino, false);
|
node = make_lo_node (path, get_upper_layer (lo), newname, node->ino, false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user