mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-10 15:56:25 -04:00
fuse-overlayfs: support also mv to empty directory with whiteouts
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
0cc1b77696
commit
85d1a08cf2
65
main.c
65
main.c
@ -1742,6 +1742,36 @@ update_paths (struct ovl_node *node)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
empty_dir (struct ovl_data *lo, struct ovl_node *node)
|
||||||
|
{
|
||||||
|
DIR *dp;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = TEMP_FAILURE_RETRY (openat (get_upper_layer (lo)->fd, node->path, O_DIRECTORY));
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dp = fdopendir (fd);
|
||||||
|
if (dp)
|
||||||
|
{
|
||||||
|
struct dirent *dent;
|
||||||
|
|
||||||
|
while (dp && ((dent = readdir (dp)) != NULL))
|
||||||
|
{
|
||||||
|
if (strcmp (dent->d_name, ".") == 0)
|
||||||
|
continue;
|
||||||
|
if (strcmp (dent->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
if (unlinkat (dirfd (dp), dent->d_name, 0) < 0)
|
||||||
|
unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir (dp);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
|
do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
|
||||||
{
|
{
|
||||||
@ -1786,37 +1816,12 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
|
|||||||
node->do_unlink = 1;
|
node->do_unlink = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DIR *dp;
|
if (empty_dir (lo, node) < 0)
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = TEMP_FAILURE_RETRY (openat (get_upper_layer (lo)->fd, node->path, O_DIRECTORY));
|
|
||||||
if (fd < 0)
|
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, errno);
|
fuse_reply_err (req, errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd >= 0)
|
|
||||||
{
|
|
||||||
dp = fdopendir (fd);
|
|
||||||
if (dp)
|
|
||||||
{
|
|
||||||
struct dirent *dent;
|
|
||||||
|
|
||||||
while (dp && ((dent = readdir (dp)) != NULL))
|
|
||||||
{
|
|
||||||
if (strcmp (dent->d_name, ".") == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp (dent->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (unlinkat (dirfd (dp), dent->d_name, 0) < 0)
|
|
||||||
unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir (dp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node->do_rmdir = 1;
|
node->do_rmdir = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2627,12 +2632,8 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We support only the case where the destination is completely empty. */
|
if (whiteouts && empty_dir (lo, destnode) < 0)
|
||||||
if (whiteouts)
|
goto error;
|
||||||
{
|
|
||||||
errno = EXDEV;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (create_missing_whiteouts (lo, node, destnode->path) < 0)
|
if (create_missing_whiteouts (lo, node, destnode->path) < 0)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user