diff options
| -rw-r--r-- | internal/fusefrontend/root_node.go | 12 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/root_node.go | 17 | ||||
| -rw-r--r-- | internal/inomap/inomap.go | 13 | ||||
| -rw-r--r-- | internal/inomap/inomap_test.go | 17 | 
4 files changed, 39 insertions, 20 deletions
| diff --git a/internal/fusefrontend/root_node.go b/internal/fusefrontend/root_node.go index 7d37520..7221be6 100644 --- a/internal/fusefrontend/root_node.go +++ b/internal/fusefrontend/root_node.go @@ -62,18 +62,28 @@ type RootNode struct {  }  func NewRootNode(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode { +	var rootDev uint64 +	var st syscall.Stat_t +	if err := syscall.Stat(args.Cipherdir, &st); err != nil { +		tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err) +	} else { +		rootDev = uint64(st.Dev) +	} +  	if len(args.Exclude) > 0 {  		tlog.Warn.Printf("Forward mode does not support -exclude")  	} +  	ivLen := nametransform.DirIVLen  	if args.PlaintextNames {  		ivLen = 0  	} +  	rn := &RootNode{  		args:          args,  		nameTransform: n,  		contentEnc:    c, -		inoMap:        inomap.New(), +		inoMap:        inomap.New(rootDev),  		dirCache:      dirCache{ivLen: ivLen},  		quirks:        syscallcompat.DetectQuirks(args.Cipherdir),  	} diff --git a/internal/fusefrontend_reverse/root_node.go b/internal/fusefrontend_reverse/root_node.go index d4c1e37..e15ddb0 100644 --- a/internal/fusefrontend_reverse/root_node.go +++ b/internal/fusefrontend_reverse/root_node.go @@ -2,10 +2,13 @@ package fusefrontend_reverse  import (  	"log" +	"os"  	"path/filepath"  	"strings"  	"syscall" +	"github.com/rfjakob/gocryptfs/v2/internal/exitcodes" +  	"github.com/rfjakob/gocryptfs/v2/internal/tlog"  	"golang.org/x/sys/unix" @@ -46,12 +49,14 @@ type RootNode struct {  // ReverseFS provides an encrypted view.  func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *RootNode {  	var rootDev uint64 -	if args.OneFileSystem { -		var st syscall.Stat_t -		err := syscall.Stat(args.Cipherdir, &st) -		if err != nil { -			log.Panicf("Could not stat backing directory %q: %v", args.Cipherdir, err) +	var st syscall.Stat_t +	if err := syscall.Stat(args.Cipherdir, &st); err != nil { +		tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, err) +		if args.OneFileSystem { +			tlog.Fatal.Printf("This is a fatal error in combination with -one-file-system") +			os.Exit(exitcodes.CipherDir)  		} +	} else {  		rootDev = uint64(st.Dev)  	} @@ -59,7 +64,7 @@ func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransf  		args:          args,  		nameTransform: n,  		contentEnc:    c, -		inoMap:        inomap.New(), +		inoMap:        inomap.New(rootDev),  		rootDev:       rootDev,  	}  	if len(args.Exclude) > 0 || len(args.ExcludeWildcard) > 0 || len(args.ExcludeFrom) > 0 { diff --git a/internal/inomap/inomap.go b/internal/inomap/inomap.go index 97f9b61..997ea9b 100644 --- a/internal/inomap/inomap.go +++ b/internal/inomap/inomap.go @@ -49,13 +49,22 @@ type InoMap struct {  }  // New returns a new InoMap. -func New() *InoMap { -	return &InoMap{ +// Inode numbers on device `rootDev` will be passed through as-is. +// If `rootDev` is zero, the first Translate() call decides the effective +// rootDev. +func New(rootDev uint64) *InoMap { +	m := &InoMap{  		namespaceMap:  make(map[namespaceData]uint16),  		namespaceNext: 0,  		spillMap:      make(map[QIno]uint64),  		spillNext:     0,  	} +	if rootDev > 0 { +		// Reserve namespace 0 for rootDev +		m.namespaceMap[namespaceData{rootDev, 0}] = 0 +		m.namespaceNext = 1 +	} +	return m  }  var spillWarn sync.Once diff --git a/internal/inomap/inomap_test.go b/internal/inomap/inomap_test.go index 6fbb4ef..9ec2932 100644 --- a/internal/inomap/inomap_test.go +++ b/internal/inomap/inomap_test.go @@ -6,7 +6,7 @@ import (  )  func TestTranslate(t *testing.T) { -	m := New() +	m := New(0)  	q := QIno{Ino: 1}  	out := m.Translate(q)  	if out != 1 { @@ -25,12 +25,7 @@ func TestTranslate(t *testing.T) {  func TestTranslateStress(t *testing.T) {  	const baseDev = 12345 -	m := New() - -	// Make sure baseDev gets namespace id zero -	var q QIno -	q.Dev = baseDev -	m.Translate(q) +	m := New(baseDev)  	var wg sync.WaitGroup  	wg.Add(4) @@ -100,7 +95,7 @@ func TestTranslateStress(t *testing.T) {  }  func TestSpill(t *testing.T) { -	m := New() +	m := New(0)  	var q QIno  	q.Ino = maxPassthruIno + 1  	out1 := m.Translate(q) @@ -119,7 +114,7 @@ func TestSpill(t *testing.T) {  // TestUniqueness checks that unique (Dev, Flags, Ino) tuples get unique inode  // numbers  func TestUniqueness(t *testing.T) { -	m := New() +	m := New(0)  	var q QIno  	outMap := make(map[uint64]struct{})  	for q.Dev = 0; q.Dev < 10; q.Dev++ { @@ -141,7 +136,7 @@ func TestUniqueness(t *testing.T) {  }  func BenchmarkTranslateSingleDev(b *testing.B) { -	m := New() +	m := New(0)  	var q QIno  	for n := 0; n < b.N; n++ {  		q.Ino = uint64(n % 1000) @@ -150,7 +145,7 @@ func BenchmarkTranslateSingleDev(b *testing.B) {  }  func BenchmarkTranslateManyDevs(b *testing.B) { -	m := New() +	m := New(0)  	var q QIno  	for n := 0; n < b.N; n++ {  		q.Dev = uint64(n % 10) | 
