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

Implement and test hardlinks in UnionFs.

parent 1643d64c
......@@ -178,6 +178,10 @@ func (me *UnionFs) getBranchAttrNoCache(name string) branchResult {
a, s := fs.GetAttr(name, nil)
if s.Ok() {
if i > 0 {
// Needed to make hardlinks work.
a.Ino = 0
}
// Make all files appear writable
a.Mode |= 0222
return branchResult{
......@@ -306,6 +310,35 @@ func (me *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co
////////////////////////////////////////////////////////////////
// Below: implement interface for a FileSystem.
func (me *UnionFs) Link(orig string, newName string, context *fuse.Context) (code fuse.Status) {
origResult := me.getBranch(orig)
code = origResult.code
if code.Ok() && origResult.branch > 0 {
code = me.Promote(orig, origResult, context)
}
if code.Ok() && origResult.branch > 0 {
// Hairy: for the link to be hooked up to the existing
// inode, PathNodeFs must see a client inode for the
// original. We force a refresh of the attribute (so
// the Ino is filled in.), and then force PathNodeFs
// to see the Inode number.
me.branchCache.GetFresh(orig)
inode := me.nodeFs.Node(orig)
inode.FsNode().GetAttr(nil, nil)
}
if code.Ok() {
code = me.promoteDirsTo(newName)
}
if code.Ok() {
code = me.fileSystems[0].Link(orig, newName, context)
}
if code.Ok() {
me.removeDeletion(newName)
me.branchCache.GetFresh(newName)
}
return code
}
func (me *UnionFs) Rmdir(path string, context *fuse.Context) (code fuse.Status) {
r := me.getBranch(path)
if r.code != fuse.OK {
......
......@@ -579,6 +579,32 @@ func TestWriteAccess(t *testing.T) {
}
}
func TestLink(t *testing.T) {
wd, clean := setupUfs(t)
defer clean()
content := "blabla"
fn := wd + "/ro/file"
err := ioutil.WriteFile(fn, []byte(content), 0666)
CheckSuccess(err)
err = os.Link(wd+"/mount/file", wd + "/mount/linked")
CheckSuccess(err)
fi2, err := os.Lstat(wd + "/mount/linked")
CheckSuccess(err)
fi1, err := os.Lstat(wd + "/mount/file")
CheckSuccess(err)
if fi1.Ino != fi2.Ino {
t.Errorf("inode numbers should be equal for linked files %v, %v", fi1.Ino, fi2.Ino)
}
c, err := ioutil.ReadFile(wd + "/mount/linked")
if string(c) != content {
t.Errorf("content mismatch got %q want %q", string(c), content)
}
}
func TestTruncate(t *testing.T) {
t.Log("TestTruncate")
wd, clean := setupUfs(t)
......
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