summaryrefslogtreecommitdiff
path: root/internal/syscallcompat/getdents_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/syscallcompat/getdents_linux.go')
-rw-r--r--internal/syscallcompat/getdents_linux.go29
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
}