summaryrefslogtreecommitdiff
path: root/internal/fusefrontend/node.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2021-07-31 13:24:25 +0200
committerJakob Unterwurzacher2021-07-31 13:24:25 +0200
commit1bc1db620b061aabf59469a5eb4fb60e3e1701a3 (patch)
treed569e213c3a046cdb1fa01fe089fbab048a6fdfe /internal/fusefrontend/node.go
parenteecbcbb0905320fc8a030fb716bee259bf6dd00f (diff)
fusefrontend: -sharedstorage: present stable inode numbers
Use the Gen field (inode generation) to distinguish hard links while passing the real inode numbers to userspace. Fixes https://github.com/rfjakob/gocryptfs/issues/584
Diffstat (limited to 'internal/fusefrontend/node.go')
-rw-r--r--internal/fusefrontend/node.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/internal/fusefrontend/node.go b/internal/fusefrontend/node.go
index 5d3c178..8a3cfa2 100644
--- a/internal/fusefrontend/node.go
+++ b/internal/fusefrontend/node.go
@@ -40,6 +40,24 @@ func (n *Node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (ch
// Translate ciphertext size in `out.Attr.Size` to plaintext size
n.translateSize(dirfd, cName, &out.Attr)
+ rn := n.rootNode()
+ if rn.args.SharedStorage {
+ // If we already have a child node that matches what we found on disk*
+ // (as reflected in `ch`), return it here.
+ //
+ // This keeps the Node ID for each directory entry stable
+ // (until forgotten).
+ //
+ // *We compare `name`, `Ino`, `Mode` (but not `Gen`!)
+ old := n.Inode.GetChild(name)
+ if old != nil &&
+ old.StableAttr().Ino == ch.StableAttr().Ino &&
+ // `Mode` has already been masked with syscall.S_IFMT by n.newChild()
+ old.StableAttr().Mode == ch.StableAttr().Mode {
+ return old, 0
+ }
+ }
+
return ch, 0
}