syscallcompat: switch from syscall.Getdents to unix.Getdents
On mips64le, syscall.Getdents() and struct syscall.Dirent do not fit together, causing our Getdents implementation to return garbage ( https://github.com/rfjakob/gocryptfs/issues/200 and https://github.com/golang/go/issues/23624 ). Switch to unix.Getdents which does not have this problem - the next Go release with the syscall package fixes is too far away, and will take time to trickle into distros.
This commit is contained in:
parent
b611e01035
commit
26ba8103bf
@ -19,14 +19,14 @@ import (
|
|||||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sizeofDirent = int(unsafe.Sizeof(syscall.Dirent{}))
|
const sizeofDirent = int(unsafe.Sizeof(unix.Dirent{}))
|
||||||
|
|
||||||
// maxReclen sanity check: Reclen should never be larger than this.
|
// maxReclen sanity check: Reclen should never be larger than this.
|
||||||
// Due to padding between entries, it is 280 even on 32-bit architectures.
|
// Due to padding between entries, it is 280 even on 32-bit architectures.
|
||||||
// See https://github.com/rfjakob/gocryptfs/issues/197 for details.
|
// See https://github.com/rfjakob/gocryptfs/issues/197 for details.
|
||||||
const maxReclen = 280
|
const maxReclen = 280
|
||||||
|
|
||||||
// getdents wraps syscall.Getdents and converts the result to []fuse.DirEntry.
|
// getdents wraps unix.Getdents and converts the result to []fuse.DirEntry.
|
||||||
func getdents(fd int) ([]fuse.DirEntry, error) {
|
func getdents(fd int) ([]fuse.DirEntry, error) {
|
||||||
// Collect syscall result in smartBuf.
|
// Collect syscall result in smartBuf.
|
||||||
// "bytes.Buffer" is smart about expanding the capacity and avoids the
|
// "bytes.Buffer" is smart about expanding the capacity and avoids the
|
||||||
@ -34,7 +34,7 @@ func getdents(fd int) ([]fuse.DirEntry, error) {
|
|||||||
var smartBuf bytes.Buffer
|
var smartBuf bytes.Buffer
|
||||||
tmp := make([]byte, 10000)
|
tmp := make([]byte, 10000)
|
||||||
for {
|
for {
|
||||||
n, err := syscall.Getdents(fd, tmp)
|
n, err := unix.Getdents(fd, tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ func getdents(fd int) ([]fuse.DirEntry, error) {
|
|||||||
// a fuse.DirEntry slice of the correct size at once.
|
// a fuse.DirEntry slice of the correct size at once.
|
||||||
var numEntries, offset int
|
var numEntries, offset int
|
||||||
for offset < len(buf) {
|
for offset < len(buf) {
|
||||||
s := *(*syscall.Dirent)(unsafe.Pointer(&buf[offset]))
|
s := *(*unix.Dirent)(unsafe.Pointer(&buf[offset]))
|
||||||
if s.Reclen == 0 {
|
if s.Reclen == 0 {
|
||||||
tlog.Warn.Printf("Getdents: corrupt entry #%d: Reclen=0 at offset=%d. Returning EBADR",
|
tlog.Warn.Printf("Getdents: corrupt entry #%d: Reclen=0 at offset=%d. Returning EBADR",
|
||||||
numEntries, offset)
|
numEntries, offset)
|
||||||
@ -73,7 +73,7 @@ func getdents(fd int) ([]fuse.DirEntry, error) {
|
|||||||
entries := make([]fuse.DirEntry, 0, numEntries)
|
entries := make([]fuse.DirEntry, 0, numEntries)
|
||||||
offset = 0
|
offset = 0
|
||||||
for offset < len(buf) {
|
for offset < len(buf) {
|
||||||
s := *(*syscall.Dirent)(unsafe.Pointer(&buf[offset]))
|
s := *(*unix.Dirent)(unsafe.Pointer(&buf[offset]))
|
||||||
name, err := getdentsName(s)
|
name, err := getdentsName(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -100,7 +100,7 @@ func getdents(fd int) ([]fuse.DirEntry, error) {
|
|||||||
|
|
||||||
// getdentsName extracts the filename from a Dirent struct and returns it as
|
// getdentsName extracts the filename from a Dirent struct and returns it as
|
||||||
// a Go string.
|
// a Go string.
|
||||||
func getdentsName(s syscall.Dirent) (string, error) {
|
func getdentsName(s unix.Dirent) (string, error) {
|
||||||
// After the loop, l contains the index of the first '\0'.
|
// After the loop, l contains the index of the first '\0'.
|
||||||
l := 0
|
l := 0
|
||||||
for l = range s.Name {
|
for l = range s.Name {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user