Commit 38077f24 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

UnionFs: Create should mkdir up to the file in the writable branch.

parent 9f60272a
...@@ -262,7 +262,7 @@ func (me *UnionFs) Rmdir(path string) (code fuse.Status) { ...@@ -262,7 +262,7 @@ func (me *UnionFs) Rmdir(path string) (code fuse.Status) {
if r.code != fuse.OK { if r.code != fuse.OK {
return r.code return r.code
} }
if r.attr.Mode & fuse.S_IFDIR == 0 { if r.attr.Mode&fuse.S_IFDIR == 0 {
return syscall.ENOTDIR return syscall.ENOTDIR
} }
if r.branch > 0 { if r.branch > 0 {
...@@ -289,7 +289,7 @@ func (me *UnionFs) Rmdir(path string) (code fuse.Status) { ...@@ -289,7 +289,7 @@ func (me *UnionFs) Rmdir(path string) (code fuse.Status) {
} }
return code return code
} }
func (me *UnionFs) Mkdir(path string, mode uint32) (code fuse.Status) { func (me *UnionFs) Mkdir(path string, mode uint32) (code fuse.Status) {
r := me.branchCache.Get(path).(getBranchResult) r := me.branchCache.Get(path).(getBranchResult)
if r.code != fuse.ENOENT { if r.code != fuse.ENOENT {
...@@ -321,7 +321,7 @@ func (me *UnionFs) Chmod(name string, mode uint32) (code fuse.Status) { ...@@ -321,7 +321,7 @@ func (me *UnionFs) Chmod(name string, mode uint32) (code fuse.Status) {
return r.code return r.code
} }
if r.attr.Mode & fuse.S_IFREG == 0 { if r.attr.Mode&fuse.S_IFREG == 0 {
return fuse.EPERM return fuse.EPERM
} }
...@@ -375,10 +375,30 @@ func (me *UnionFs) Readlink(name string) (out string, code fuse.Status) { ...@@ -375,10 +375,30 @@ func (me *UnionFs) Readlink(name string) (out string, code fuse.Status) {
return "", fuse.ENOENT return "", fuse.ENOENT
} }
func IsDir(fs fuse.FileSystem, name string) bool {
a, code := fs.GetAttr(name)
return code == fuse.OK && a.Mode & fuse.S_IFDIR != 0
}
func (me *UnionFs) makeDirTo(name string) fuse.Status {
dir, base := filepath.Split(name)
if base != "" && !IsDir(me.fileSystems[0], dir) {
err := os.MkdirAll(me.branches[0].GetPath(dir), 0755)
if err != nil {
log.Println("Error creating dir leading to path", name, err)
return fuse.EPERM
}
}
return fuse.OK
}
func (me *UnionFs) Create(name string, flags uint32, mode uint32) (fuseFile fuse.File, code fuse.Status) { func (me *UnionFs) Create(name string, flags uint32, mode uint32) (fuseFile fuse.File, code fuse.Status) {
// TODO(hanwen) - we should check that the name is not a
// directory in another branch.
writable := me.fileSystems[0] writable := me.fileSystems[0]
code = me.makeDirTo(name)
if code != fuse.OK {
return nil, code
}
fuseFile, code = writable.Create(name, flags, mode) fuseFile, code = writable.Create(name, flags, mode)
if code == fuse.OK { if code == fuse.OK {
me.removeDeletion(name) me.removeDeletion(name)
...@@ -528,7 +548,7 @@ func (me *UnionFs) Rename(src string, dst string) (status fuse.Status) { ...@@ -528,7 +548,7 @@ func (me *UnionFs) Rename(src string, dst string) (status fuse.Status) {
me.removeDeletion(dst) me.removeDeletion(dst)
srcResult.branch = 0 srcResult.branch = 0
me.branchCache.Set(dst, srcResult) me.branchCache.Set(dst, srcResult)
if srcResult.branch == 0 { if srcResult.branch == 0 {
srcResult := me.branchCache.getDataNoCache(src) srcResult := me.branchCache.getDataNoCache(src)
if srcResult.(getBranchResult).branch > 0 { if srcResult.(getBranchResult).branch > 0 {
......
...@@ -17,7 +17,6 @@ func TestFilePathHash(t *testing.T) { ...@@ -17,7 +17,6 @@ func TestFilePathHash(t *testing.T) {
t.Log(filePathHash("xyz/abc")) t.Log(filePathHash("xyz/abc"))
} }
var testOpts = UnionFsOptions{ var testOpts = UnionFsOptions{
DeletionCacheTTLSecs: 0.01, DeletionCacheTTLSecs: 0.01,
DeletionDirName: "DELETIONS", DeletionDirName: "DELETIONS",
...@@ -237,6 +236,19 @@ func TestPromote(t *testing.T) { ...@@ -237,6 +236,19 @@ func TestPromote(t *testing.T) {
writeToFile(wd + "/mount/subdir/file", "other-content", false) writeToFile(wd + "/mount/subdir/file", "other-content", false)
} }
func TestCreate(t *testing.T) {
wd, state := setup(t)
defer state.Unmount()
err := os.MkdirAll(wd + "/ro/subdir/sub2", 0755)
CheckSuccess(err)
writeToFile(wd + "/mount/subdir/sub2/file", "other-content", true)
_, err = os.Lstat(wd + "/mount/subdir/sub2/file")
CheckSuccess(err)
}
func TestMkdir(t *testing.T) { func TestMkdir(t *testing.T) {
wd, state := setup(t) wd, state := setup(t)
defer state.Unmount() defer state.Unmount()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment