Commit a0c52d0e authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Implement rename for symlinks.

Add disabled test for renaming directories.
parent b0a1c934
......@@ -248,20 +248,30 @@ func (me *UnionFs) putDeletion(name string) (code fuse.Status) {
////////////////
// Promotion.
func (me *UnionFs) Promote(name string, srcResult branchResult) fuse.Status {
if !srcResult.attr.IsRegular() {
// TODO - implement rename for dirs, links, etc.
log.Println("Can only promote normal files: ", name, srcResult.attr)
return fuse.ENOSYS
}
func (me *UnionFs) Promote(name string, srcResult branchResult) (code fuse.Status) {
writable := me.fileSystems[0]
sourceFs := me.fileSystems[srcResult.branch]
// Promote directories.
me.promoteDirsTo(name)
code := fuse.CopyFile(sourceFs, writable, name, name)
if srcResult.attr.IsRegular() {
code = fuse.CopyFile(sourceFs, writable, name, name)
} else if srcResult.attr.IsDirectory() {
code = writable.Mkdir(name, 0755)
} else if srcResult.attr.IsSymlink() {
link := ""
link, code = sourceFs.Readlink(name)
if !code.Ok() {
log.Println("can't read link in source fs", name)
} else {
code = writable.Symlink(link, name)
}
} else {
log.Println("Unknown file type:", srcResult.attr)
return fuse.ENOSYS
}
if !code.Ok() {
me.branchCache.GetFresh(name)
return code
......@@ -683,12 +693,21 @@ func (me *UnionFs) OpenDir(directory string) (stream chan fuse.DirEntry, status
return stream, fuse.OK
}
func (me *UnionFs) Rename(src string, dst string) (code fuse.Status) {
srcResult := me.getBranch(src)
code = srcResult.code
if code.Ok() {
code = srcResult.code
}
if srcResult.attr.IsDirectory() {
log.Println("rename directories unimplemented.")
// TODO - to rename a directory:
// * promote all files below the directory
// * execute a move in writable layer
// * issue invalidations against all promoted files.
return fuse.ENOSYS
}
if code.Ok() && srcResult.branch > 0 {
code = me.Promote(src, srcResult)
}
......
......@@ -350,6 +350,7 @@ func TestMkdirPromote(t *testing.T) {
t.Error("is not a directory: ", fi)
}
}
func TestRename(t *testing.T) {
type Config struct {
f1_ro bool
......@@ -408,6 +409,54 @@ func TestRename(t *testing.T) {
}
}
func disabledTestRenameDir(t *testing.T) {
wd, clean := setupUfs(t)
defer clean()
err := os.MkdirAll(wd + "/ro/dir/subdir", 0755)
CheckSuccess(err)
err = os.Rename(wd + "/mount/dir", wd + "/mount/renamed")
CheckSuccess(err)
if fi, _ := os.Lstat(wd + "/mount/dir"); fi != nil {
t.Fatalf("%s/mount/dir should have disappeared: %v", wd, fi)
}
if fi, _ := os.Lstat(wd + "/mount/renamed"); fi == nil || !fi.IsDirectory() {
t.Fatalf("%s/mount/renamed should be directory: %v", wd, fi)
}
entries, err := ioutil.ReadDir(wd + "/mount/renamed")
if err != nil || len(entries) != 1 || entries[0].Name != "subdir" {
t.Errorf("readdir(%s/mount/renamed) should have one entry: %v, err %v", wd, entries, err)
}
}
func TestRenameSymlink(t *testing.T) {
wd, clean := setupUfs(t)
defer clean()
err := os.Symlink("linktarget", wd + "/ro/link")
CheckSuccess(err)
err = os.Rename(wd + "/mount/link", wd + "/mount/renamed")
CheckSuccess(err)
if fi, _ := os.Lstat(wd + "/mount/link"); fi != nil {
t.Fatalf("%s/mount/link should have disappeared: %v", wd, fi)
}
if fi, _ := os.Lstat(wd + "/mount/renamed"); fi == nil || !fi.IsSymlink() {
t.Fatalf("%s/mount/renamed should be link: %v", wd, fi)
}
if link, err := os.Readlink(wd + "/mount/renamed"); err != nil || link != "linktarget" {
t.Fatalf("readlink(%s/mount/renamed) should point to 'linktarget': %v, err %v", wd, link, err)
}
}
func TestWritableDir(t *testing.T) {
t.Log("TestWritableDir")
wd, clean := setupUfs(t)
......@@ -681,3 +730,4 @@ func TestDisappearing(t *testing.T) {
t.Fatal("write should succeed", err)
}
}
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