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
// 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
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
}
// 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
}
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
}
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
}
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
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
}
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
}
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.
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
// 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.
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
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))
}