diff --git a/doc/Manual.md b/doc/Manual.md index 65b304b11..7398c23da 100644 --- a/doc/Manual.md +++ b/doc/Manual.md @@ -426,6 +426,11 @@ Don't forget to umount after quitting! Mounting repositories via FUSE is not possible on Windows and OpenBSD. +Restic supports storage and preservation of hard links. However, since hard links +exist in the scope of a filesystem by definition, restoring hard links from a fuse +mount should be done by a program that preserves hard links. A program that does so +is rsync, used with the option --hard-links. + # Create an SFTP repository In order to backup data via SFTP, you must first set up a server with SSH and diff --git a/src/restic/fuse/dir.go b/src/restic/fuse/dir.go index e5f68a9d1..9cdefaa3c 100644 --- a/src/restic/fuse/dir.go +++ b/src/restic/fuse/dir.go @@ -114,9 +114,25 @@ func (d *dir) Attr(ctx context.Context, a *fuse.Attr) error { a.Atime = d.node.AccessTime a.Ctime = d.node.ChangeTime a.Mtime = d.node.ModTime + + a.Nlink = d.calcNumberOfLinks() + return nil } +func (d *dir) calcNumberOfLinks() uint32 { + // a directory d has 2 hardlinks + the number + // of directories contained by d + var count uint32 + count = 2 + for _, node := range d.items { + if node.Type == "dir" { + count++ + } + } + return count +} + func (d *dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { debug.Log("called") ret := make([]fuse.Dirent, 0, len(d.items)) diff --git a/src/restic/fuse/file.go b/src/restic/fuse/file.go index b57e0d663..95bf0c074 100644 --- a/src/restic/fuse/file.go +++ b/src/restic/fuse/file.go @@ -83,7 +83,9 @@ func (f *file) Attr(ctx context.Context, a *fuse.Attr) error { a.Atime = f.node.AccessTime a.Ctime = f.node.ChangeTime a.Mtime = f.node.ModTime + return nil + } func (f *file) getBlobAt(i int) (blob []byte, err error) { diff --git a/src/restic/fuse/link.go b/src/restic/fuse/link.go index 43fb35020..e230acb07 100644 --- a/src/restic/fuse/link.go +++ b/src/restic/fuse/link.go @@ -38,5 +38,8 @@ func (l *link) Attr(ctx context.Context, a *fuse.Attr) error { a.Atime = l.node.AccessTime a.Ctime = l.node.ChangeTime a.Mtime = l.node.ModTime + + a.Nlink = uint32(l.node.Links) + return nil }