diff options
author | Jakob Unterwurzacher | 2017-12-03 17:57:08 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2017-12-03 19:33:26 +0100 |
commit | 70bcf58a9bda5f95a3037fb785858f5d7ce3f930 (patch) | |
tree | 15122949d8adede1b6e8a68e7e2a2b19d42a1660 /internal/syscallcompat/getdents_linux.go | |
parent | e33593d30d9dee6fd6b0e7c0d01832e478815d88 (diff) |
syscallcompat: convert Getdents to fd input, add emulation
Now that we have Fstatat we can use it in Getdents to
get rid of the path name.
Also, add an emulated version of getdents for MacOS. This allows
to drop the !HaveGetdents special cases from fusefrontend.
Modify the getdents test to test both native getdents and the emulated
version.
Diffstat (limited to 'internal/syscallcompat/getdents_linux.go')
-rw-r--r-- | internal/syscallcompat/getdents_linux.go | 29 |
1 files changed, 10 insertions, 19 deletions
diff --git a/internal/syscallcompat/getdents_linux.go b/internal/syscallcompat/getdents_linux.go index 55bffff..49f9233 100644 --- a/internal/syscallcompat/getdents_linux.go +++ b/internal/syscallcompat/getdents_linux.go @@ -12,26 +12,17 @@ import ( "syscall" "unsafe" + "golang.org/x/sys/unix" + "github.com/hanwen/go-fuse/fuse" "github.com/rfjakob/gocryptfs/internal/tlog" ) -// HaveGetdents is true if we have a working implementation of Getdents -const HaveGetdents = true - const sizeofDirent = int(unsafe.Sizeof(syscall.Dirent{})) -// Getdents wraps syscall.Getdents and converts the result to []fuse.DirEntry. -// The function takes a path instead of an fd because we need to be able to -// call Lstat on files. Fstatat is not yet available in Go as of v1.9: -// https://github.com/golang/go/issues/14216 -func Getdents(dir string) ([]fuse.DirEntry, error) { - fd, err := syscall.Open(dir, syscall.O_RDONLY, 0) - if err != nil { - return nil, err - } - defer syscall.Close(fd) +// getdents wraps syscall.Getdents and converts the result to []fuse.DirEntry. +func getdents(fd int) ([]fuse.DirEntry, error) { // Collect syscall result in smartBuf. // "bytes.Buffer" is smart about expanding the capacity and avoids the // exponential runtime of simple append(). @@ -84,7 +75,7 @@ func Getdents(dir string) ([]fuse.DirEntry, error) { // os.File.Readdir() drops "." and "..". Let's be compatible. continue } - mode, err := convertDType(s.Type, dir+"/"+name) + mode, err := convertDType(fd, name, s.Type) if err != nil { // The file may have been deleted in the meantime. Just skip it // and go on. @@ -125,17 +116,17 @@ func getdentsName(s syscall.Dirent) (string, error) { var dtUnknownWarnOnce sync.Once // convertDType converts a Dirent.Type to at Stat_t.Mode value. -func convertDType(dtype uint8, file string) (uint32, error) { +func convertDType(dirfd int, name string, dtype uint8) (uint32, error) { if dtype != syscall.DT_UNKNOWN { // Shift up by four octal digits = 12 bits return uint32(dtype) << 12, nil } - // DT_UNKNOWN: we have to call Lstat() + // DT_UNKNOWN: we have to call stat() dtUnknownWarnOnce.Do(func() { - tlog.Warn.Printf("Getdents: convertDType: received DT_UNKNOWN, falling back to Lstat") + tlog.Warn.Printf("Getdents: convertDType: received DT_UNKNOWN, falling back to stat") }) - var st syscall.Stat_t - err := syscall.Lstat(file, &st) + var st unix.Stat_t + err := Fstatat(dirfd, name, &st, unix.AT_SYMLINK_NOFOLLOW) if err != nil { return 0, err } |