0
1
mirror of https://github.com/golang/go synced 2025-05-25 15:00:09 +00:00

os: consolidate and clarify File.Fd docs

Change-Id: Id062b969fe7d6908a0797b36a4a379e4d46ba557
Reviewed-on: https://go-review.googlesource.com/c/go/+/648516
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
Ian Lance Taylor
2025-02-11 12:56:27 -08:00
committed by Gopher Robot
parent 89c2f282dc
commit 0044bc614a
5 changed files with 37 additions and 43 deletions

@ -685,6 +685,23 @@ func (f *File) SyscallConn() (syscall.RawConn, error) {
return newRawConn(f)
}
// Fd returns the system file descriptor or handle referencing the open file.
// If f is closed, the descriptor becomes invalid.
// If f is garbage collected, a cleanup may close the descriptor,
// making it invalid; see [runtime.AddCleanup] for more information on when
// a cleanup might be run.
//
// Do not close the returned descriptor; that could cause a later
// close of f to close an unrelated descriptor.
//
// On Unix systems this will cause the [File.SetDeadline]
// methods to stop working.
//
// For most uses prefer the f.SyscallConn method.
func (f *File) Fd() uintptr {
return f.fd()
}
// DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir.
//
// Note that DirFS("/prefix") only guarantees that the Open calls it makes to the

@ -27,26 +27,19 @@ func fixLongPath(path string) string {
// to close the wrong file descriptor.
type file struct {
fdmu poll.FDMutex
fd int
sysfd int
name string
dirinfo atomic.Pointer[dirInfo] // nil unless directory being read
appendMode bool // whether file is opened for appending
cleanup runtime.Cleanup // cleanup closes the file when no longer referenced
}
// Fd returns the integer Plan 9 file descriptor referencing the open file.
// If f is closed, the file descriptor becomes invalid.
// If f is garbage collected, a cleanup may close the file descriptor,
// making it invalid; see [runtime.AddCleanup] for more information on when
// a cleanup might be run. On Unix systems this will cause the [File.SetDeadline]
// methods to stop working.
//
// As an alternative, see the f.SyscallConn method.
func (f *File) Fd() uintptr {
// fd is the Plan 9 implementation of Fd.
func (f *File) fd() uintptr {
if f == nil {
return ^(uintptr(0))
}
return uintptr(f.fd)
return uintptr(f.sysfd)
}
// NewFile returns a new File with the given file descriptor and
@ -57,7 +50,7 @@ func NewFile(fd uintptr, name string) *File {
if fdi < 0 {
return nil
}
f := &File{&file{fd: fdi, name: name}}
f := &File{&file{sysfd: fdi, name: name}}
f.cleanup = runtime.AddCleanup(f, func(f *file) { f.close() }, f.file)
return f
}
@ -180,7 +173,7 @@ func (file *file) close() error {
// and writeUnlock methods.
func (file *file) destroy() error {
var err error
if e := syscall.Close(file.fd); e != nil {
if e := syscall.Close(file.sysfd); e != nil {
err = &PathError{Op: "close", Path: file.name, Err: e}
}
return err
@ -222,7 +215,7 @@ func (f *File) Truncate(size int64) error {
}
defer f.decref()
if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
if err = syscall.Fwstat(f.sysfd, buf[:n]); err != nil {
return &PathError{Op: "truncate", Path: f.name, Err: err}
}
return nil
@ -254,7 +247,7 @@ func (f *File) chmod(mode FileMode) error {
}
defer f.decref()
if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
if err = syscall.Fwstat(f.sysfd, buf[:n]); err != nil {
return &PathError{Op: "chmod", Path: f.name, Err: err}
}
return nil
@ -281,7 +274,7 @@ func (f *File) Sync() error {
}
defer f.decref()
if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
if err = syscall.Fwstat(f.sysfd, buf[:n]); err != nil {
return &PathError{Op: "sync", Path: f.name, Err: err}
}
return nil
@ -294,7 +287,7 @@ func (f *File) read(b []byte) (n int, err error) {
return 0, err
}
defer f.readUnlock()
n, e := fixCount(syscall.Read(f.fd, b))
n, e := fixCount(syscall.Read(f.sysfd, b))
if n == 0 && len(b) > 0 && e == nil {
return 0, io.EOF
}
@ -309,7 +302,7 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
return 0, err
}
defer f.readUnlock()
n, e := fixCount(syscall.Pread(f.fd, b, off))
n, e := fixCount(syscall.Pread(f.sysfd, b, off))
if n == 0 && len(b) > 0 && e == nil {
return 0, io.EOF
}
@ -328,7 +321,7 @@ func (f *File) write(b []byte) (n int, err error) {
if len(b) == 0 {
return 0, nil
}
return fixCount(syscall.Write(f.fd, b))
return fixCount(syscall.Write(f.sysfd, b))
}
// pwrite writes len(b) bytes to the File starting at byte offset off.
@ -343,7 +336,7 @@ func (f *File) pwrite(b []byte, off int64) (n int, err error) {
if len(b) == 0 {
return 0, nil
}
return fixCount(syscall.Pwrite(f.fd, b, off))
return fixCount(syscall.Pwrite(f.sysfd, b, off))
}
// seek sets the offset for the next Read or Write on file to offset, interpreted
@ -358,7 +351,7 @@ func (f *File) seek(offset int64, whence int) (ret int64, err error) {
// Free cached dirinfo, so we allocate a new one if we
// access this file as a directory again. See #35767 and #37161.
f.dirinfo.Store(nil)
return syscall.Seek(f.fd, offset, whence)
return syscall.Seek(f.sysfd, offset, whence)
}
// Truncate changes the size of the named file.
@ -555,7 +548,7 @@ func (f *File) Chdir() error {
return err
}
defer f.decref()
if e := syscall.Fchdir(f.fd); e != nil {
if e := syscall.Fchdir(f.sysfd); e != nil {
return &PathError{Op: "chdir", Path: f.name, Err: e}
}
return nil

@ -66,19 +66,8 @@ type file struct {
cleanup runtime.Cleanup // cleanup closes the file when no longer referenced
}
// Fd returns the integer Unix file descriptor referencing the open file.
// If f is closed, the file descriptor becomes invalid.
// If f is garbage collected, a cleanup may close the file descriptor,
// making it invalid; see [runtime.AddCleanup] for more information on when
// a cleanup might be run. On Unix systems this will cause the [File.SetDeadline]
// methods to stop working.
// Because file descriptors can be reused, the returned file descriptor may
// only be closed through the [File.Close] method of f, or by its cleanup during
// garbage collection. Otherwise, during garbage collection the cleanup
// may close an unrelated file descriptor with the same (reused) number.
//
// As an alternative, see the f.SyscallConn method.
func (f *File) Fd() uintptr {
// fd is the Unix implementation of Fd.
func (f *File) fd() uintptr {
if f == nil {
return ^(uintptr(0))
}

@ -32,13 +32,8 @@ type file struct {
cleanup runtime.Cleanup // cleanup closes the file when no longer referenced
}
// Fd returns the Windows handle referencing the open file.
// If f is closed, the file descriptor becomes invalid.
// If f is garbage collected, a cleanup may close the file descriptor,
// making it invalid; see [runtime.AddCleanup] for more information on when
// a cleanup might be run. On Unix systems this will cause the [File.SetDeadline]
// methods to stop working.
func (file *File) Fd() uintptr {
// fd is the Windows implementation of Fd.
func (file *File) fd() uintptr {
if file == nil {
return uintptr(syscall.InvalidHandle)
}

@ -59,7 +59,7 @@ func dirstat(arg any) (*syscall.Dir, error) {
if err := a.incref("fstat"); err != nil {
return nil, err
}
n, err = syscall.Fstat(a.fd, buf)
n, err = syscall.Fstat(a.sysfd, buf)
a.decref()
case string:
name = a