diff options
author | Brian Kendall <brian@briankendall.net> | 2022-03-31 16:05:31 -0400 |
---|---|---|
committer | Radek Podgorny <radek@podgorny.cz> | 2022-07-02 18:36:54 +0200 |
commit | fead5105e3bbbe57d18a8a0d1bb8e2c1b8637824 (patch) | |
tree | 2cf92dbe6b72c7616c95ad6d4ed8640d9b9e5b44 | |
parent | 222d01ef8612f33a55cbd6e7326517d0ba8e8652 (diff) | |
download | unionfs-fuse-git-fead5105e3bbbe57d18a8a0d1bb8e2c1b8637824.tar.gz |
Change rename behavior so that a file stays in the same branch if possible
-rw-r--r-- | src/findbranch.c | 40 | ||||
-rw-r--r-- | src/findbranch.h | 1 | ||||
-rw-r--r-- | src/fuse_ops.c | 5 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/findbranch.c b/src/findbranch.c index 843c44f..af526ea 100644 --- a/src/findbranch.c +++ b/src/findbranch.c @@ -51,6 +51,46 @@ #include "debug.h" #include "usyslog.h" +static bool branch_contains_path(int branch, const char *path, bool *is_dir) { + if (branch < 0 || branch >= uopt.nbranches) + RETURN(false); + + char p[PATHLEN_MAX]; + if (BUILD_PATH(p, uopt.branches[branch].path, path)) { + errno = ENAMETOOLONG; + RETURN(false); + } + + printf("***** p: %s\n", p); + struct stat stbuf; + int res = lstat(p, &stbuf); + + if (res == 0) { + (*is_dir) = S_ISDIR(stbuf.st_mode); + RETURN(true); + } else + RETURN(false); +} + +bool branch_contains_file_or_parent_dir(int branch, const char *path) { + bool is_dir = false; + bool found = branch_contains_path(branch, path, &is_dir); + + if (found) + RETURN(true); + + char *dname = u_dirname(path); + if (dname == NULL) { + errno = ENOMEM; + RETURN(false); + } + + found = branch_contains_path(branch, dname, &is_dir); + + free(dname); + RETURN(found && is_dir); +} + /** * Find a branch that has "path". Return the branch number. */ diff --git a/src/findbranch.h b/src/findbranch.h index 0636285..8393602 100644 --- a/src/findbranch.h +++ b/src/findbranch.h @@ -12,6 +12,7 @@ typedef enum searchflag { RWONLY } searchflag_t; +bool branch_contains_file_or_parent_dir(int branch, const char *path); int find_rorw_branch(const char *path); int find_lowest_rw_branch(int branch_ro); int find_rw_branch_cutlast(const char *path); diff --git a/src/fuse_ops.c b/src/fuse_ops.c index 915ceaa..a5a5851 100644 --- a/src/fuse_ops.c +++ b/src/fuse_ops.c @@ -490,6 +490,11 @@ static int unionfs_rename(const char *from, const char *to, unsigned int flags) int i = find_rorw_branch(from); if (i == -1) RETURN(-errno); + if (uopt.branches[i].rw && branch_contains_file_or_parent_dir(i, to)) { + DBG("file can stay in same branch\n"); + j = i; + } + if (!uopt.branches[i].rw) { i = find_rw_branch_cow_common(from, true); if (i == -1) RETURN(-errno); |