Merge pull request #21784 from jtru/fuse-mount-hardlink-count

mount: Ensure a hard link count > 0 for all files
This commit is contained in:
Michael Eischer
2026-05-14 11:25:20 +02:00
committed by GitHub
3 changed files with 36 additions and 1 deletions
+9
View File
@@ -0,0 +1,9 @@
Bugfix: Support exporting a `restic mount` of a Windows system via Samba
A repository mounted using `restic mount` on a POSIX system, could not use
Samba to export files from restic backups of Windows systems. Backups of
other systems were not affected. This has been fixed.
https://github.com/restic/restic/pull/21784
https://github.com/restic/restic/issues/2034
https://github.com/restic/restic/issues/4382
+4 -1
View File
@@ -55,7 +55,10 @@ func (f *file) Attr(_ context.Context, a *fuse.Attr) error {
a.Size = f.node.Size
a.Blocks = (f.node.Size + blockSize - 1) / blockSize
a.BlockSize = blockSize
a.Nlink = uint32(f.node.Links)
// Windows (and other non-POSIX) backups may store a link count of 0.
// FUSE must still report a positive nlink so tools that validate stat()
// (e.g. Samba) accept the file.
a.Nlink = max(uint32(1), uint32(f.node.Links))
if !f.root.cfg.OwnerIsRoot {
a.Uid = f.node.UID
+23
View File
@@ -5,6 +5,7 @@ package fuse
import (
"bytes"
"context"
"fmt"
"math/rand"
"os"
"strings"
@@ -277,6 +278,28 @@ func TestBlocks(t *testing.T) {
}
}
// Windows (and other non-POSIX) backups may store a link count of 0; FUSE
// must still report a positive nlink so tools that validate stat() (e.g.
// Samba) accept the file.
func TestFileAttrNlink(t *testing.T) {
root := &Root{}
for _, tc := range []struct {
links uint64
want uint32
}{
{0, 1},
{1, 1},
{42, 42},
} {
t.Run(fmt.Sprintf("links_%d", tc.links), func(t *testing.T) {
f := &file{root: root, node: &data.Node{Links: tc.links}}
var a fuse.Attr
rtest.OK(t, f.Attr(context.TODO(), &a))
rtest.Equals(t, tc.want, a.Nlink)
})
}
}
func TestInodeFromNode(t *testing.T) {
node := &data.Node{Name: "foo.txt", Type: data.NodeTypeCharDev, Links: 2}
ino1 := inodeFromNode(1, node)