From 9c5acf4bf2e57d039cb1f8e7ad5a882a83301895 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 12 Jul 2018 14:49:04 +0200 Subject: [PATCH] fuse-overlayfs: attempt to delete node whiteout first Signed-off-by: Giuseppe Scrivano --- main.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/main.c b/main.c index 241584e..f617d14 100644 --- a/main.c +++ b/main.c @@ -318,8 +318,34 @@ create_whiteout (struct ovl_data *lo, struct ovl_node *parent, const char *name) static int delete_whiteout (struct ovl_data *lo, int dirfd, struct ovl_node *parent, const char *name) { + struct stat st; char whiteout_path[PATH_MAX + 10]; + if (dirfd >= 0) + { + if (TEMP_FAILURE_RETRY (fstatat (dirfd, name, &st, AT_SYMLINK_NOFOLLOW)) == 0 + && (st.st_mode & S_IFMT) == S_IFCHR + && major (st.st_rdev) == 0 + && minor (st.st_rdev) == 0) + { + return unlinkat (dirfd, name, 0); + } + } + else + { + sprintf (whiteout_path, "%s/.wh.%s", parent->path, name); + + if (TEMP_FAILURE_RETRY (fstatat (get_upper_layer (lo)->fd, whiteout_path, &st, AT_SYMLINK_NOFOLLOW)) == 0 + && (st.st_mode & S_IFMT) == S_IFCHR + && major (st.st_rdev) == 0 + && minor (st.st_rdev) == 0) + { + return unlinkat (get_upper_layer (lo)->fd, whiteout_path, 0); + } + } + + /* If the whiteout was not found, try the .wh. alternative used when running as non-root. */ + if (dirfd >= 0) { sprintf (whiteout_path, ".wh.%s", name);