aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse
diff options
context:
space:
mode:
Diffstat (limited to 'internal/fusefrontend_reverse')
-rw-r--r--internal/fusefrontend_reverse/excluder.go3
-rw-r--r--internal/fusefrontend_reverse/excluder_test.go5
-rw-r--r--internal/fusefrontend_reverse/node.go4
-rw-r--r--internal/fusefrontend_reverse/node_helpers.go6
-rw-r--r--internal/fusefrontend_reverse/root_node.go27
-rw-r--r--internal/fusefrontend_reverse/virtualconf.go9
-rw-r--r--internal/fusefrontend_reverse/virtualnode.go13
7 files changed, 50 insertions, 17 deletions
diff --git a/internal/fusefrontend_reverse/excluder.go b/internal/fusefrontend_reverse/excluder.go
index 0faadfa..1cb4b80 100644
--- a/internal/fusefrontend_reverse/excluder.go
+++ b/internal/fusefrontend_reverse/excluder.go
@@ -1,7 +1,6 @@
package fusefrontend_reverse
import (
- "io/ioutil"
"log"
"os"
"strings"
@@ -50,7 +49,7 @@ func getExclusionPatterns(args fusefrontend.Args) []string {
// getLines reads a file and splits it into lines
func getLines(file string) ([]string, error) {
- buffer, err := ioutil.ReadFile(file)
+ buffer, err := os.ReadFile(file)
if err != nil {
return nil, err
}
diff --git a/internal/fusefrontend_reverse/excluder_test.go b/internal/fusefrontend_reverse/excluder_test.go
index bb041ce..b44ddce 100644
--- a/internal/fusefrontend_reverse/excluder_test.go
+++ b/internal/fusefrontend_reverse/excluder_test.go
@@ -1,7 +1,6 @@
package fusefrontend_reverse
import (
- "io/ioutil"
"os"
"reflect"
"testing"
@@ -23,7 +22,7 @@ func TestShouldPrefixExcludeValuesWithSlash(t *testing.T) {
}
func TestShouldReadExcludePatternsFromFiles(t *testing.T) {
- tmpfile1, err := ioutil.TempFile("", "excludetest")
+ tmpfile1, err := os.CreateTemp("", "excludetest")
if err != nil {
t.Fatal(err)
}
@@ -31,7 +30,7 @@ func TestShouldReadExcludePatternsFromFiles(t *testing.T) {
defer os.Remove(exclude1)
defer tmpfile1.Close()
- tmpfile2, err := ioutil.TempFile("", "excludetest")
+ tmpfile2, err := os.CreateTemp("", "excludetest")
if err != nil {
t.Fatal(err)
}
diff --git a/internal/fusefrontend_reverse/node.go b/internal/fusefrontend_reverse/node.go
index 22ad975..30654e0 100644
--- a/internal/fusefrontend_reverse/node.go
+++ b/internal/fusefrontend_reverse/node.go
@@ -69,6 +69,10 @@ func (n *Node) Lookup(ctx context.Context, cName string, out *fuse.EntryOut) (ch
n.translateSize(d.dirfd, cName, d.pName, &out.Attr)
}
+ if rn.args.ForceOwner != nil {
+ out.Owner = *rn.args.ForceOwner
+ }
+
// Usually we always create a new Node ID by always incrementing the generation
// number.
//
diff --git a/internal/fusefrontend_reverse/node_helpers.go b/internal/fusefrontend_reverse/node_helpers.go
index 6bba097..3165db6 100644
--- a/internal/fusefrontend_reverse/node_helpers.go
+++ b/internal/fusefrontend_reverse/node_helpers.go
@@ -24,7 +24,6 @@ const (
// * base64(192 bytes) = 256 bytes (over 255!)
// But the PKCS#7 padding is at least one byte. This means we can only use
// 175 bytes for the file name.
- shortNameMax = 175
)
// translateSize translates the ciphertext size in `out` into plaintext size.
@@ -175,7 +174,7 @@ func (n *Node) lookupDiriv(ctx context.Context, out *fuse.EntryOut) (ch *fs.Inod
errno = fs.ToErrno(err)
return
}
- content := pathiv.Derive(d.cPath, pathiv.PurposeDirIV)
+ content := rn.deriveDirIV(d.cPath)
var vf *VirtualMemNode
vf, errno = n.newVirtualMemNode(content, st, inoTagDirIV)
if errno != 0 {
@@ -201,6 +200,9 @@ func (n *Node) lookupConf(ctx context.Context, out *fuse.EntryOut) (ch *fs.Inode
// Get unique inode number
rn.inoMap.TranslateStat(&st)
out.Attr.FromStat(&st)
+ if rn.args.ForceOwner != nil {
+ out.Owner = *rn.args.ForceOwner
+ }
// Create child node
id := rn.uniqueStableAttr(uint32(st.Mode), st.Ino)
node := &VirtualConfNode{path: p}
diff --git a/internal/fusefrontend_reverse/root_node.go b/internal/fusefrontend_reverse/root_node.go
index 1a68ffd..9c2de28 100644
--- a/internal/fusefrontend_reverse/root_node.go
+++ b/internal/fusefrontend_reverse/root_node.go
@@ -8,22 +8,20 @@ import (
"sync/atomic"
"syscall"
- "github.com/rfjakob/gocryptfs/v2/internal/exitcodes"
-
- "github.com/rfjakob/gocryptfs/v2/internal/tlog"
-
"golang.org/x/sys/unix"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
"github.com/rfjakob/gocryptfs/v2/internal/contentenc"
+ "github.com/rfjakob/gocryptfs/v2/internal/exitcodes"
"github.com/rfjakob/gocryptfs/v2/internal/fusefrontend"
"github.com/rfjakob/gocryptfs/v2/internal/inomap"
"github.com/rfjakob/gocryptfs/v2/internal/nametransform"
"github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
+ "github.com/rfjakob/gocryptfs/v2/internal/tlog"
- "github.com/sabhiram/go-gitignore"
+ ignore "github.com/sabhiram/go-gitignore"
)
// RootNode is the root directory in a `gocryptfs -reverse` mount
@@ -52,7 +50,9 @@ type RootNode struct {
// makes go-fuse hand out separate FUSE Node IDs for each, and prevents
// bizarre problems when inode numbers are reused behind our back,
// like this one: https://github.com/rfjakob/gocryptfs/issues/802
- gen uint64
+ gen atomic.Uint64
+ // rootIno is the inode number that we report for the root node on mount
+ rootIno uint64
}
// NewRootNode returns an encrypted FUSE overlay filesystem.
@@ -61,9 +61,10 @@ type RootNode struct {
func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {
var rootDev uint64
var st syscall.Stat_t
+ var statErr error
var shortNameMax int
- if err := syscall.Stat(args.Cipherdir, &st); err != nil {
- tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err)
+ if statErr = syscall.Stat(args.Cipherdir, &st); statErr != nil {
+ tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, statErr)
if args.OneFileSystem {
tlog.Fatal.Printf("This is a fatal error in combination with -one-file-system")
os.Exit(exitcodes.CipherDir)
@@ -83,6 +84,10 @@ func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransf
rootDev: rootDev,
shortNameMax: shortNameMax,
}
+ if statErr == nil {
+ rn.inoMap.TranslateStat(&st)
+ rn.rootIno = st.Ino
+ }
if len(args.Exclude) > 0 || len(args.ExcludeWildcard) > 0 || len(args.ExcludeFrom) > 0 {
rn.excluder = prepareExcluder(args)
}
@@ -170,6 +175,10 @@ func (rn *RootNode) uniqueStableAttr(mode uint32, ino uint64) fs.StableAttr {
Ino: ino,
// Make each directory entry a unique node by using a unique generation
// value. Also see the comment at RootNode.gen for details.
- Gen: atomic.AddUint64(&rn.gen, 1),
+ Gen: rn.gen.Add(1),
}
}
+
+func (rn *RootNode) RootIno() uint64 {
+ return rn.rootIno
+}
diff --git a/internal/fusefrontend_reverse/virtualconf.go b/internal/fusefrontend_reverse/virtualconf.go
index 3643fad..ea358dd 100644
--- a/internal/fusefrontend_reverse/virtualconf.go
+++ b/internal/fusefrontend_reverse/virtualconf.go
@@ -18,6 +18,11 @@ type VirtualConfNode struct {
path string
}
+// rootNode returns the Root Node of the filesystem.
+func (n *VirtualConfNode) rootNode() *RootNode {
+ return n.Root().Operations().(*RootNode)
+}
+
func (n *VirtualConfNode) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
fd, err := syscall.Open(n.path, syscall.O_RDONLY, 0)
if err != nil {
@@ -35,6 +40,10 @@ func (n *VirtualConfNode) Getattr(ctx context.Context, fh fs.FileHandle, out *fu
return fs.ToErrno(err)
}
out.FromStat(&st)
+ rn := n.rootNode()
+ if rn.args.ForceOwner != nil {
+ out.Owner = *rn.args.ForceOwner
+ }
return 0
}
diff --git a/internal/fusefrontend_reverse/virtualnode.go b/internal/fusefrontend_reverse/virtualnode.go
index 922cfa7..95e71ab 100644
--- a/internal/fusefrontend_reverse/virtualnode.go
+++ b/internal/fusefrontend_reverse/virtualnode.go
@@ -100,7 +100,18 @@ func (n *Node) newVirtualMemNode(content []byte, parentStat *syscall.Stat_t, ino
st.Nlink = 1
var a fuse.Attr
a.FromStat(st)
-
+ // With inode number reuse and hard links, we could have returned
+ // wrong data for gocryptfs.diriv and gocryptfs.xyz.longname files, respectively
+ // (https://github.com/rfjakob/gocryptfs/issues/802).
+ //
+ // Now that this is fixed, ensure that rsync and similar tools pick up the new
+ // correct files by advancing mtime and ctime by 10 seconds, which should be more
+ // than any filesytems' timestamp granularity (FAT32 has 2 seconds).
+ a.Mtime += 10
+ a.Ctime += 10
+ if rn.args.ForceOwner != nil {
+ a.Owner = *rn.args.ForceOwner
+ }
vf = &VirtualMemNode{content: content, attr: a}
return
}