From df806266c539c25bc23b78b4fe376a155fb7f74f Mon Sep 17 00:00:00 2001 From: database64128 Date: Thu, 24 Jul 2025 15:24:23 +0800 Subject: [PATCH] Call SyscallConn() instead of Fd() to use file's fd [os.File.SyscallConn] is the safer alternative to [os.File.Fd], without the pitfalls mentioned in Fd's doc comment. The SyscallConn method is implemented on all platforms except Plan 9, where it returns [syscall.EPLAN9], which matches [errors.ErrUnsupported] and goes to the fallback path. --- reader.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/reader.go b/reader.go index 639e8bc..5933ecf 100644 --- a/reader.go +++ b/reader.go @@ -234,7 +234,7 @@ func Open(file string, options ...ReaderOption) (*Reader, error) { return nil, errors.New("file too large") } - data, err := mmap(int(mapFile.Fd()), size) + data, err := openMmap(mapFile, size) if err != nil { if errors.Is(err, errors.ErrUnsupported) { data, err = openFallback(mapFile, size) @@ -257,6 +257,21 @@ func Open(file string, options ...ReaderOption) (*Reader, error) { return reader, nil } +func openMmap(f *os.File, size int) (data []byte, err error) { + rawConn, err := f.SyscallConn() + if err != nil { + return nil, err + } + + if cerr := rawConn.Control(func(fd uintptr) { + data, err = mmap(int(fd), size) + }); cerr != nil { + return nil, cerr + } + + return data, err +} + func openFallback(f *os.File, size int) (data []byte, err error) { data = make([]byte, size) _, err = io.ReadFull(f, data)