summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/findbranch.c18
-rw-r--r--src/findbranch.h1
-rw-r--r--src/unionfs.c5
3 files changed, 20 insertions, 4 deletions
diff --git a/src/findbranch.c b/src/findbranch.c
index 145edf6..9581c3a 100644
--- a/src/findbranch.c
+++ b/src/findbranch.c
@@ -107,8 +107,10 @@ int find_rorw_branch(const char *path) {
/**
* Find a writable branch. If file does not exist, we check for
* the parent directory.
+ * @path - the path to find or to copy (with last element cut off)
+ * @ rw_hint - the rw branch to copy to, set to -1 to autodetect it
*/
-int find_rw_branch_cutlast(const char *path) {
+int __find_rw_branch_cutlast(const char *path, int rw_hint) {
DBG_IN();
int branch = find_rw_branch_cow(path);
@@ -136,8 +138,12 @@ int find_rw_branch_cutlast(const char *path) {
goto out;
}
+ int branch_rw;
// since it is a directory, any rw-branch is fine
- int branch_rw = find_lowest_rw_branch(uopt.nbranches);
+ if (rw_hint == -1)
+ branch_rw = find_lowest_rw_branch(uopt.nbranches);
+ else
+ branch_rw = rw_hint;
// no writable branch found, we must return an error
if (branch_rw < 0) {
@@ -155,6 +161,14 @@ out:
}
/**
+ * Call __find_rw_branch_cutlast()
+ */
+int find_rw_branch_cutlast(const char *path) {
+ int rw_hint = -1; // autodetect rw_branch
+ return __find_rw_branch_cutlast(path, rw_hint);
+}
+
+/**
* copy-on-write
* Find path in a union branch and if this branch is read-only,
* copy the file to a read-write branch.
diff --git a/src/findbranch.h b/src/findbranch.h
index 6378d86..56cfc08 100644
--- a/src/findbranch.h
+++ b/src/findbranch.h
@@ -15,6 +15,7 @@ typedef enum searchflag {
int find_rorw_branch(const char *path);
int find_lowest_rw_branch(int branch_ro);
int find_rw_branch_cutlast(const char *path);
+int __find_rw_branch_cutlast(const char *path, int rw_hint);
int find_rw_branch_cow(const char *path);
#endif
diff --git a/src/unionfs.c b/src/unionfs.c
index cd58a83..091f00d 100644
--- a/src/unionfs.c
+++ b/src/unionfs.c
@@ -241,10 +241,11 @@ static int unionfs_link(const char *from, const char *to) {
int i = find_rw_branch_cow(from);
if (i == -1) return -errno;
- // FIXME, we actually MUST COW to i
- int j = find_rw_branch_cutlast(to);
+ int j = __find_rw_branch_cutlast(to, i);
if (j == -1) return -errno;
+ DBG("from branch: %d to branch: %d\n", i, j);
+
char f[PATHLEN_MAX], t[PATHLEN_MAX];
if (BUILD_PATH(f, uopt.branches[i].path, from)) return -ENAMETOOLONG;
if (BUILD_PATH(t, uopt.branches[j].path, to)) return -ENAMETOOLONG;