syscallcompat: Getdents: warn once if we get DT_UNKNOWN

...and if Getdents is not available at all.

Due to this warning I now know that SSHFS always returns DT_UNKNOWN:

    gocryptfs[8129]: Getdents: convertDType: received DT_UNKNOWN, falling back to Lstat

This behavoir is confirmed at http://ahefner.livejournal.com/16875.html:

    "With sshfs, I finally found that obscure case. The dtype is always set to DT_UNKNOWN [...]"
This commit is contained in:
Jakob Unterwurzacher 2017-09-03 15:05:54 +02:00
parent a710451d92
commit 538cae610c
2 changed files with 12 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import (
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"sync"
"syscall" "syscall"
"github.com/hanwen/go-fuse/fuse" "github.com/hanwen/go-fuse/fuse"
@ -234,6 +235,8 @@ func (fs *FS) Rmdir(path string, context *fuse.Context) (code fuse.Status) {
return fuse.OK return fuse.OK
} }
var haveGetdentsWarnOnce sync.Once
// OpenDir implements pathfs.FileSystem // OpenDir implements pathfs.FileSystem
func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) { func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
tlog.Debug.Printf("OpenDir(%s)", dirName) tlog.Debug.Printf("OpenDir(%s)", dirName)
@ -252,6 +255,9 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f
return nil, fuse.ToStatus(err) return nil, fuse.ToStatus(err)
} }
} else { } else {
haveGetdentsWarnOnce.Do(func() {
tlog.Warn.Printf("OpenDir: Getdents not available, falling back to OpenDir")
})
cipherEntries, status = fs.FileSystem.OpenDir(cDirName, context) cipherEntries, status = fs.FileSystem.OpenDir(cDirName, context)
if !status.Ok() { if !status.Ok() {
return nil, status return nil, status

View File

@ -8,6 +8,7 @@ package syscallcompat
import ( import (
"bytes" "bytes"
"sync"
"syscall" "syscall"
"unsafe" "unsafe"
@ -121,6 +122,8 @@ func getdentsName(s syscall.Dirent) (string, error) {
return string(name), nil return string(name), nil
} }
var dtUnknownWarnOnce sync.Once
// convertDType converts a Dirent.Type to at Stat_t.Mode value. // convertDType converts a Dirent.Type to at Stat_t.Mode value.
func convertDType(dtype uint8, file string) (uint32, error) { func convertDType(dtype uint8, file string) (uint32, error) {
if dtype != syscall.DT_UNKNOWN { if dtype != syscall.DT_UNKNOWN {
@ -128,6 +131,9 @@ func convertDType(dtype uint8, file string) (uint32, error) {
return uint32(dtype) << 12, nil return uint32(dtype) << 12, nil
} }
// DT_UNKNOWN: we have to call Lstat() // DT_UNKNOWN: we have to call Lstat()
dtUnknownWarnOnce.Do(func() {
tlog.Warn.Printf("Getdents: convertDType: received DT_UNKNOWN, falling back to Lstat")
})
var st syscall.Stat_t var st syscall.Stat_t
err := syscall.Lstat(file, &st) err := syscall.Lstat(file, &st)
if err != nil { if err != nil {