summaryrefslogtreecommitdiffstats
path: root/contrib/go/_std_1.25/src/os/file.go
diff options
context:
space:
mode:
authorYDBot <[email protected]>2026-06-10 06:27:27 +0000
committerYDBot <[email protected]>2026-06-10 06:27:27 +0000
commiteb8c7d3ee0c13034ecf5d8d35c24cefc40f0bb3f (patch)
treea1eba7fec49a258bb24bfa77808233496ac0047f /contrib/go/_std_1.25/src/os/file.go
parentc4011885693f041c96b035f368aae8a1baac8885 (diff)
parent72cfbf8958fa6fa5227e9ad6466abfc635fdeb15 (diff)
Merge pull request #43056 from ydb-platform/merge-rightlib-260610-0127HEADmain
Diffstat (limited to 'contrib/go/_std_1.25/src/os/file.go')
-rw-r--r--contrib/go/_std_1.25/src/os/file.go942
1 files changed, 0 insertions, 942 deletions
diff --git a/contrib/go/_std_1.25/src/os/file.go b/contrib/go/_std_1.25/src/os/file.go
deleted file mode 100644
index 80857240f5c..00000000000
--- a/contrib/go/_std_1.25/src/os/file.go
+++ /dev/null
@@ -1,942 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package os provides a platform-independent interface to operating system
-// functionality. The design is Unix-like, although the error handling is
-// Go-like; failing calls return values of type error rather than error numbers.
-// Often, more information is available within the error. For example,
-// if a call that takes a file name fails, such as [Open] or [Stat], the error
-// will include the failing file name when printed and will be of type
-// [*PathError], which may be unpacked for more information.
-//
-// The os interface is intended to be uniform across all operating systems.
-// Features not generally available appear in the system-specific package syscall.
-//
-// Here is a simple example, opening a file and reading some of it.
-//
-// file, err := os.Open("file.go") // For read access.
-// if err != nil {
-// log.Fatal(err)
-// }
-//
-// If the open fails, the error string will be self-explanatory, like
-//
-// open file.go: no such file or directory
-//
-// The file's data can then be read into a slice of bytes. Read and
-// Write take their byte counts from the length of the argument slice.
-//
-// data := make([]byte, 100)
-// count, err := file.Read(data)
-// if err != nil {
-// log.Fatal(err)
-// }
-// fmt.Printf("read %d bytes: %q\n", count, data[:count])
-//
-// # Concurrency
-//
-// The methods of [File] correspond to file system operations. All are
-// safe for concurrent use. The maximum number of concurrent
-// operations on a File may be limited by the OS or the system. The
-// number should be high, but exceeding it may degrade performance or
-// cause other issues.
-package os
-
-import (
- "errors"
- "internal/filepathlite"
- "internal/poll"
- "internal/testlog"
- "io"
- "io/fs"
- "runtime"
- "slices"
- "syscall"
- "time"
- "unsafe"
-)
-
-// Name returns the name of the file as presented to Open.
-//
-// It is safe to call Name after [Close].
-func (f *File) Name() string { return f.name }
-
-// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
-// standard output, and standard error file descriptors.
-//
-// Note that the Go runtime writes to standard error for panics and crashes;
-// closing Stderr may cause those messages to go elsewhere, perhaps
-// to a file opened later.
-var (
- Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
- Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
- Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
-)
-
-// Flags to OpenFile wrapping those of the underlying system. Not all
-// flags may be implemented on a given system.
-const (
- // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
- O_RDONLY int = syscall.O_RDONLY // open the file read-only.
- O_WRONLY int = syscall.O_WRONLY // open the file write-only.
- O_RDWR int = syscall.O_RDWR // open the file read-write.
- // The remaining values may be or'ed in to control behavior.
- O_APPEND int = syscall.O_APPEND // append data to the file when writing.
- O_CREATE int = syscall.O_CREAT // create a new file if none exists.
- O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist.
- O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
- O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened.
-)
-
-// Seek whence values.
-//
-// Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd.
-const (
- SEEK_SET int = 0 // seek relative to the origin of the file
- SEEK_CUR int = 1 // seek relative to the current offset
- SEEK_END int = 2 // seek relative to the end
-)
-
-// LinkError records an error during a link or symlink or rename
-// system call and the paths that caused it.
-type LinkError struct {
- Op string
- Old string
- New string
- Err error
-}
-
-func (e *LinkError) Error() string {
- return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
-}
-
-func (e *LinkError) Unwrap() error {
- return e.Err
-}
-
-// NewFile returns a new [File] with the given file descriptor and name.
-// The returned value will be nil if fd is not a valid file descriptor.
-//
-// NewFile's behavior differs on some platforms:
-//
-// - On Unix, if fd is in non-blocking mode, NewFile will attempt to return a pollable file.
-// - On Windows, if fd is opened for asynchronous I/O (that is, [syscall.FILE_FLAG_OVERLAPPED]
-// has been specified in the [syscall.CreateFile] call), NewFile will attempt to return a pollable
-// file by associating fd with the Go runtime I/O completion port.
-// The I/O operations will be performed synchronously if the association fails.
-//
-// Only pollable files support [File.SetDeadline], [File.SetReadDeadline], and [File.SetWriteDeadline].
-//
-// After passing it to NewFile, fd may become invalid under the same conditions described
-// in the comments of [File.Fd], and the same constraints apply.
-func NewFile(fd uintptr, name string) *File {
- return newFileFromNewFile(fd, name)
-}
-
-// Read reads up to len(b) bytes from the File and stores them in b.
-// It returns the number of bytes read and any error encountered.
-// At end of file, Read returns 0, io.EOF.
-func (f *File) Read(b []byte) (n int, err error) {
- if err := f.checkValid("read"); err != nil {
- return 0, err
- }
- n, e := f.read(b)
- return n, f.wrapErr("read", e)
-}
-
-// ReadAt reads len(b) bytes from the File starting at byte offset off.
-// It returns the number of bytes read and the error, if any.
-// ReadAt always returns a non-nil error when n < len(b).
-// At end of file, that error is io.EOF.
-func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
- if err := f.checkValid("read"); err != nil {
- return 0, err
- }
-
- if off < 0 {
- return 0, &PathError{Op: "readat", Path: f.name, Err: errors.New("negative offset")}
- }
-
- for len(b) > 0 {
- m, e := f.pread(b, off)
- if e != nil {
- err = f.wrapErr("read", e)
- break
- }
- n += m
- b = b[m:]
- off += int64(m)
- }
- return
-}
-
-// ReadFrom implements io.ReaderFrom.
-func (f *File) ReadFrom(r io.Reader) (n int64, err error) {
- if err := f.checkValid("write"); err != nil {
- return 0, err
- }
- n, handled, e := f.readFrom(r)
- if !handled {
- return genericReadFrom(f, r) // without wrapping
- }
- return n, f.wrapErr("write", e)
-}
-
-// noReadFrom can be embedded alongside another type to
-// hide the ReadFrom method of that other type.
-type noReadFrom struct{}
-
-// ReadFrom hides another ReadFrom method.
-// It should never be called.
-func (noReadFrom) ReadFrom(io.Reader) (int64, error) {
- panic("can't happen")
-}
-
-// fileWithoutReadFrom implements all the methods of *File other
-// than ReadFrom. This is used to permit ReadFrom to call io.Copy
-// without leading to a recursive call to ReadFrom.
-type fileWithoutReadFrom struct {
- noReadFrom
- *File
-}
-
-func genericReadFrom(f *File, r io.Reader) (int64, error) {
- return io.Copy(fileWithoutReadFrom{File: f}, r)
-}
-
-// Write writes len(b) bytes from b to the File.
-// It returns the number of bytes written and an error, if any.
-// Write returns a non-nil error when n != len(b).
-func (f *File) Write(b []byte) (n int, err error) {
- if err := f.checkValid("write"); err != nil {
- return 0, err
- }
- n, e := f.write(b)
- if n < 0 {
- n = 0
- }
- if n != len(b) {
- err = io.ErrShortWrite
- }
-
- epipecheck(f, e)
-
- if e != nil {
- err = f.wrapErr("write", e)
- }
-
- return n, err
-}
-
-var errWriteAtInAppendMode = errors.New("os: invalid use of WriteAt on file opened with O_APPEND")
-
-// WriteAt writes len(b) bytes to the File starting at byte offset off.
-// It returns the number of bytes written and an error, if any.
-// WriteAt returns a non-nil error when n != len(b).
-//
-// If file was opened with the [O_APPEND] flag, WriteAt returns an error.
-func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
- if err := f.checkValid("write"); err != nil {
- return 0, err
- }
- if f.appendMode {
- return 0, errWriteAtInAppendMode
- }
-
- if off < 0 {
- return 0, &PathError{Op: "writeat", Path: f.name, Err: errors.New("negative offset")}
- }
-
- for len(b) > 0 {
- m, e := f.pwrite(b, off)
- if e != nil {
- err = f.wrapErr("write", e)
- break
- }
- n += m
- b = b[m:]
- off += int64(m)
- }
- return
-}
-
-// WriteTo implements io.WriterTo.
-func (f *File) WriteTo(w io.Writer) (n int64, err error) {
- if err := f.checkValid("read"); err != nil {
- return 0, err
- }
- n, handled, e := f.writeTo(w)
- if handled {
- return n, f.wrapErr("read", e)
- }
- return genericWriteTo(f, w) // without wrapping
-}
-
-// noWriteTo can be embedded alongside another type to
-// hide the WriteTo method of that other type.
-type noWriteTo struct{}
-
-// WriteTo hides another WriteTo method.
-// It should never be called.
-func (noWriteTo) WriteTo(io.Writer) (int64, error) {
- panic("can't happen")
-}
-
-// fileWithoutWriteTo implements all the methods of *File other
-// than WriteTo. This is used to permit WriteTo to call io.Copy
-// without leading to a recursive call to WriteTo.
-type fileWithoutWriteTo struct {
- noWriteTo
- *File
-}
-
-func genericWriteTo(f *File, w io.Writer) (int64, error) {
- return io.Copy(w, fileWithoutWriteTo{File: f})
-}
-
-// Seek sets the offset for the next Read or Write on file to offset, interpreted
-// according to whence: 0 means relative to the origin of the file, 1 means
-// relative to the current offset, and 2 means relative to the end.
-// It returns the new offset and an error, if any.
-// The behavior of Seek on a file opened with [O_APPEND] is not specified.
-func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
- if err := f.checkValid("seek"); err != nil {
- return 0, err
- }
- r, e := f.seek(offset, whence)
- if e == nil && f.dirinfo.Load() != nil && r != 0 {
- e = syscall.EISDIR
- }
- if e != nil {
- return 0, f.wrapErr("seek", e)
- }
- return r, nil
-}
-
-// WriteString is like Write, but writes the contents of string s rather than
-// a slice of bytes.
-func (f *File) WriteString(s string) (n int, err error) {
- b := unsafe.Slice(unsafe.StringData(s), len(s))
- return f.Write(b)
-}
-
-// Mkdir creates a new directory with the specified name and permission
-// bits (before umask).
-// If there is an error, it will be of type [*PathError].
-func Mkdir(name string, perm FileMode) error {
- longName := fixLongPath(name)
- e := ignoringEINTR(func() error {
- return syscall.Mkdir(longName, syscallMode(perm))
- })
-
- if e != nil {
- return &PathError{Op: "mkdir", Path: name, Err: e}
- }
-
- // mkdir(2) itself won't handle the sticky bit on *BSD and Solaris
- if !supportsCreateWithStickyBit && perm&ModeSticky != 0 {
- e = setStickyBit(name)
-
- if e != nil {
- Remove(name)
- return e
- }
- }
-
- return nil
-}
-
-// setStickyBit adds ModeSticky to the permission bits of path, non atomic.
-func setStickyBit(name string) error {
- fi, err := Stat(name)
- if err != nil {
- return err
- }
- return Chmod(name, fi.Mode()|ModeSticky)
-}
-
-// Chdir changes the current working directory to the named directory.
-// If there is an error, it will be of type [*PathError].
-func Chdir(dir string) error {
- if e := syscall.Chdir(dir); e != nil {
- testlog.Open(dir) // observe likely non-existent directory
- return &PathError{Op: "chdir", Path: dir, Err: e}
- }
- if runtime.GOOS == "windows" {
- abs := filepathlite.IsAbs(dir)
- getwdCache.Lock()
- if abs {
- getwdCache.dir = dir
- } else {
- getwdCache.dir = ""
- }
- getwdCache.Unlock()
- }
- if log := testlog.Logger(); log != nil {
- wd, err := Getwd()
- if err == nil {
- log.Chdir(wd)
- }
- }
- return nil
-}
-
-// Open opens the named file for reading. If successful, methods on
-// the returned file can be used for reading; the associated file
-// descriptor has mode [O_RDONLY].
-// If there is an error, it will be of type [*PathError].
-func Open(name string) (*File, error) {
- return OpenFile(name, O_RDONLY, 0)
-}
-
-// Create creates or truncates the named file. If the file already exists,
-// it is truncated. If the file does not exist, it is created with mode 0o666
-// (before umask). If successful, methods on the returned File can
-// be used for I/O; the associated file descriptor has mode [O_RDWR].
-// The directory containing the file must already exist.
-// If there is an error, it will be of type [*PathError].
-func Create(name string) (*File, error) {
- return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
-}
-
-// OpenFile is the generalized open call; most users will use Open
-// or Create instead. It opens the named file with specified flag
-// ([O_RDONLY] etc.). If the file does not exist, and the [O_CREATE] flag
-// is passed, it is created with mode perm (before umask);
-// the containing directory must exist. If successful,
-// methods on the returned File can be used for I/O.
-// If there is an error, it will be of type [*PathError].
-func OpenFile(name string, flag int, perm FileMode) (*File, error) {
- testlog.Open(name)
- f, err := openFileNolog(name, flag, perm)
- if err != nil {
- return nil, err
- }
- f.appendMode = flag&O_APPEND != 0
-
- return f, nil
-}
-
-var errPathEscapes = errors.New("path escapes from parent")
-
-// openDir opens a file which is assumed to be a directory. As such, it skips
-// the syscalls that make the file descriptor non-blocking as these take time
-// and will fail on file descriptors for directories.
-func openDir(name string) (*File, error) {
- testlog.Open(name)
- return openDirNolog(name)
-}
-
-// Rename renames (moves) oldpath to newpath.
-// If newpath already exists and is not a directory, Rename replaces it.
-// If newpath already exists and is a directory, Rename returns an error.
-// OS-specific restrictions may apply when oldpath and newpath are in different directories.
-// Even within the same directory, on non-Unix platforms Rename is not an atomic operation.
-// If there is an error, it will be of type *LinkError.
-func Rename(oldpath, newpath string) error {
- return rename(oldpath, newpath)
-}
-
-// Readlink returns the destination of the named symbolic link.
-// If there is an error, it will be of type [*PathError].
-//
-// If the link destination is relative, Readlink returns the relative path
-// without resolving it to an absolute one.
-func Readlink(name string) (string, error) {
- return readlink(name)
-}
-
-// Many functions in package syscall return a count of -1 instead of 0.
-// Using fixCount(call()) instead of call() corrects the count.
-func fixCount(n int, err error) (int, error) {
- if n < 0 {
- n = 0
- }
- return n, err
-}
-
-// checkWrapErr is the test hook to enable checking unexpected wrapped errors of poll.ErrFileClosing.
-// It is set to true in the export_test.go for tests (including fuzz tests).
-var checkWrapErr = false
-
-// wrapErr wraps an error that occurred during an operation on an open file.
-// It passes io.EOF through unchanged, otherwise converts
-// poll.ErrFileClosing to ErrClosed and wraps the error in a PathError.
-func (f *File) wrapErr(op string, err error) error {
- if err == nil || err == io.EOF {
- return err
- }
- if err == poll.ErrFileClosing {
- err = ErrClosed
- } else if checkWrapErr && errors.Is(err, poll.ErrFileClosing) {
- panic("unexpected error wrapping poll.ErrFileClosing: " + err.Error())
- }
- return &PathError{Op: op, Path: f.name, Err: err}
-}
-
-// TempDir returns the default directory to use for temporary files.
-//
-// On Unix systems, it returns $TMPDIR if non-empty, else /tmp.
-// On Windows, it uses GetTempPath, returning the first non-empty
-// value from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory.
-// On Plan 9, it returns /tmp.
-//
-// The directory is neither guaranteed to exist nor have accessible
-// permissions.
-func TempDir() string {
- return tempDir()
-}
-
-// UserCacheDir returns the default root directory to use for user-specific
-// cached data. Users should create their own application-specific subdirectory
-// within this one and use that.
-//
-// On Unix systems, it returns $XDG_CACHE_HOME as specified by
-// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if
-// non-empty, else $HOME/.cache.
-// On Darwin, it returns $HOME/Library/Caches.
-// On Windows, it returns %LocalAppData%.
-// On Plan 9, it returns $home/lib/cache.
-//
-// If the location cannot be determined (for example, $HOME is not defined) or
-// the path in $XDG_CACHE_HOME is relative, then it will return an error.
-func UserCacheDir() (string, error) {
- var dir string
-
- switch runtime.GOOS {
- case "windows":
- dir = Getenv("LocalAppData")
- if dir == "" {
- return "", errors.New("%LocalAppData% is not defined")
- }
-
- case "darwin", "ios":
- dir = Getenv("HOME")
- if dir == "" {
- return "", errors.New("$HOME is not defined")
- }
- dir += "/Library/Caches"
-
- case "plan9":
- dir = Getenv("home")
- if dir == "" {
- return "", errors.New("$home is not defined")
- }
- dir += "/lib/cache"
-
- default: // Unix
- dir = Getenv("XDG_CACHE_HOME")
- if dir == "" {
- dir = Getenv("HOME")
- if dir == "" {
- return "", errors.New("neither $XDG_CACHE_HOME nor $HOME are defined")
- }
- dir += "/.cache"
- } else if !filepathlite.IsAbs(dir) {
- return "", errors.New("path in $XDG_CACHE_HOME is relative")
- }
- }
-
- return dir, nil
-}
-
-// UserConfigDir returns the default root directory to use for user-specific
-// configuration data. Users should create their own application-specific
-// subdirectory within this one and use that.
-//
-// On Unix systems, it returns $XDG_CONFIG_HOME as specified by
-// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html if
-// non-empty, else $HOME/.config.
-// On Darwin, it returns $HOME/Library/Application Support.
-// On Windows, it returns %AppData%.
-// On Plan 9, it returns $home/lib.
-//
-// If the location cannot be determined (for example, $HOME is not defined) or
-// the path in $XDG_CONFIG_HOME is relative, then it will return an error.
-func UserConfigDir() (string, error) {
- var dir string
-
- switch runtime.GOOS {
- case "windows":
- dir = Getenv("AppData")
- if dir == "" {
- return "", errors.New("%AppData% is not defined")
- }
-
- case "darwin", "ios":
- dir = Getenv("HOME")
- if dir == "" {
- return "", errors.New("$HOME is not defined")
- }
- dir += "/Library/Application Support"
-
- case "plan9":
- dir = Getenv("home")
- if dir == "" {
- return "", errors.New("$home is not defined")
- }
- dir += "/lib"
-
- default: // Unix
- dir = Getenv("XDG_CONFIG_HOME")
- if dir == "" {
- dir = Getenv("HOME")
- if dir == "" {
- return "", errors.New("neither $XDG_CONFIG_HOME nor $HOME are defined")
- }
- dir += "/.config"
- } else if !filepathlite.IsAbs(dir) {
- return "", errors.New("path in $XDG_CONFIG_HOME is relative")
- }
- }
-
- return dir, nil
-}
-
-// UserHomeDir returns the current user's home directory.
-//
-// On Unix, including macOS, it returns the $HOME environment variable.
-// On Windows, it returns %USERPROFILE%.
-// On Plan 9, it returns the $home environment variable.
-//
-// If the expected variable is not set in the environment, UserHomeDir
-// returns either a platform-specific default value or a non-nil error.
-func UserHomeDir() (string, error) {
- env, enverr := "HOME", "$HOME"
- switch runtime.GOOS {
- case "windows":
- env, enverr = "USERPROFILE", "%userprofile%"
- case "plan9":
- env, enverr = "home", "$home"
- }
- if v := Getenv(env); v != "" {
- return v, nil
- }
- // On some operating systems the home directory is not always defined.
- switch runtime.GOOS {
- case "android":
- return "/sdcard", nil
- case "ios":
- return "/", nil
- }
- return "", errors.New(enverr + " is not defined")
-}
-
-// Chmod changes the mode of the named file to mode.
-// If the file is a symbolic link, it changes the mode of the link's target.
-// If there is an error, it will be of type [*PathError].
-//
-// A different subset of the mode bits are used, depending on the
-// operating system.
-//
-// On Unix, the mode's permission bits, [ModeSetuid], [ModeSetgid], and
-// [ModeSticky] are used.
-//
-// On Windows, only the 0o200 bit (owner writable) of mode is used; it
-// controls whether the file's read-only attribute is set or cleared.
-// The other bits are currently unused. For compatibility with Go 1.12
-// and earlier, use a non-zero mode. Use mode 0o400 for a read-only
-// file and 0o600 for a readable+writable file.
-//
-// On Plan 9, the mode's permission bits, [ModeAppend], [ModeExclusive],
-// and [ModeTemporary] are used.
-func Chmod(name string, mode FileMode) error { return chmod(name, mode) }
-
-// Chmod changes the mode of the file to mode.
-// If there is an error, it will be of type [*PathError].
-func (f *File) Chmod(mode FileMode) error { return f.chmod(mode) }
-
-// SetDeadline sets the read and write deadlines for a File.
-// It is equivalent to calling both SetReadDeadline and SetWriteDeadline.
-//
-// Only some kinds of files support setting a deadline. Calls to SetDeadline
-// for files that do not support deadlines will return ErrNoDeadline.
-// On most systems ordinary files do not support deadlines, but pipes do.
-//
-// A deadline is an absolute time after which I/O operations fail with an
-// error instead of blocking. The deadline applies to all future and pending
-// I/O, not just the immediately following call to Read or Write.
-// After a deadline has been exceeded, the connection can be refreshed
-// by setting a deadline in the future.
-//
-// If the deadline is exceeded a call to Read or Write or to other I/O
-// methods will return an error that wraps ErrDeadlineExceeded.
-// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
-// That error implements the Timeout method, and calling the Timeout
-// method will return true, but there are other possible errors for which
-// the Timeout will return true even if the deadline has not been exceeded.
-//
-// An idle timeout can be implemented by repeatedly extending
-// the deadline after successful Read or Write calls.
-//
-// A zero value for t means I/O operations will not time out.
-func (f *File) SetDeadline(t time.Time) error {
- return f.setDeadline(t)
-}
-
-// SetReadDeadline sets the deadline for future Read calls and any
-// currently-blocked Read call.
-// A zero value for t means Read will not time out.
-// Not all files support setting deadlines; see SetDeadline.
-func (f *File) SetReadDeadline(t time.Time) error {
- return f.setReadDeadline(t)
-}
-
-// SetWriteDeadline sets the deadline for any future Write calls and any
-// currently-blocked Write call.
-// Even if Write times out, it may return n > 0, indicating that
-// some of the data was successfully written.
-// A zero value for t means Write will not time out.
-// Not all files support setting deadlines; see SetDeadline.
-func (f *File) SetWriteDeadline(t time.Time) error {
- return f.setWriteDeadline(t)
-}
-
-// SyscallConn returns a raw file.
-// This implements the syscall.Conn interface.
-func (f *File) SyscallConn() (syscall.RawConn, error) {
- if err := f.checkValid("SyscallConn"); err != nil {
- return nil, err
- }
- 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 finalizer may close the descriptor,
-// making it invalid; see [runtime.SetFinalizer] for more information on when
-// a finalizer might be run.
-//
-// Do not close the returned descriptor; that could cause a later
-// close of f to close an unrelated descriptor.
-//
-// Fd's behavior differs on some platforms:
-//
-// - On Unix and Windows, [File.SetDeadline] methods will stop working.
-// - On Windows, the file descriptor will be disassociated from the
-// Go runtime I/O completion port if there are no concurrent I/O
-// operations on the file.
-//
-// 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
-// operating system will begin with "/prefix": DirFS("/prefix").Open("file") is the
-// same as os.Open("/prefix/file"). So if /prefix/file is a symbolic link pointing outside
-// the /prefix tree, then using DirFS does not stop the access any more than using
-// os.Open does. Additionally, the root of the fs.FS returned for a relative path,
-// DirFS("prefix"), will be affected by later calls to Chdir. DirFS is therefore not
-// a general substitute for a chroot-style security mechanism when the directory tree
-// contains arbitrary content.
-//
-// Use [Root.FS] to obtain a fs.FS that prevents escapes from the tree via symbolic links.
-//
-// The directory dir must not be "".
-//
-// The result implements [io/fs.StatFS], [io/fs.ReadFileFS], [io/fs.ReadDirFS], and
-// [io/fs.ReadLinkFS].
-func DirFS(dir string) fs.FS {
- return dirFS(dir)
-}
-
-var _ fs.StatFS = dirFS("")
-var _ fs.ReadFileFS = dirFS("")
-var _ fs.ReadDirFS = dirFS("")
-var _ fs.ReadLinkFS = dirFS("")
-
-type dirFS string
-
-func (dir dirFS) Open(name string) (fs.File, error) {
- fullname, err := dir.join(name)
- if err != nil {
- return nil, &PathError{Op: "open", Path: name, Err: err}
- }
- f, err := Open(fullname)
- if err != nil {
- // DirFS takes a string appropriate for GOOS,
- // while the name argument here is always slash separated.
- // dir.join will have mixed the two; undo that for
- // error reporting.
- err.(*PathError).Path = name
- return nil, err
- }
- return f, nil
-}
-
-// The ReadFile method calls the [ReadFile] function for the file
-// with the given name in the directory. The function provides
-// robust handling for small files and special file systems.
-// Through this method, dirFS implements [io/fs.ReadFileFS].
-func (dir dirFS) ReadFile(name string) ([]byte, error) {
- fullname, err := dir.join(name)
- if err != nil {
- return nil, &PathError{Op: "readfile", Path: name, Err: err}
- }
- b, err := ReadFile(fullname)
- if err != nil {
- if e, ok := err.(*PathError); ok {
- // See comment in dirFS.Open.
- e.Path = name
- }
- return nil, err
- }
- return b, nil
-}
-
-// ReadDir reads the named directory, returning all its directory entries sorted
-// by filename. Through this method, dirFS implements [io/fs.ReadDirFS].
-func (dir dirFS) ReadDir(name string) ([]DirEntry, error) {
- fullname, err := dir.join(name)
- if err != nil {
- return nil, &PathError{Op: "readdir", Path: name, Err: err}
- }
- entries, err := ReadDir(fullname)
- if err != nil {
- if e, ok := err.(*PathError); ok {
- // See comment in dirFS.Open.
- e.Path = name
- }
- return nil, err
- }
- return entries, nil
-}
-
-func (dir dirFS) Stat(name string) (fs.FileInfo, error) {
- fullname, err := dir.join(name)
- if err != nil {
- return nil, &PathError{Op: "stat", Path: name, Err: err}
- }
- f, err := Stat(fullname)
- if err != nil {
- // See comment in dirFS.Open.
- err.(*PathError).Path = name
- return nil, err
- }
- return f, nil
-}
-
-func (dir dirFS) Lstat(name string) (fs.FileInfo, error) {
- fullname, err := dir.join(name)
- if err != nil {
- return nil, &PathError{Op: "lstat", Path: name, Err: err}
- }
- f, err := Lstat(fullname)
- if err != nil {
- // See comment in dirFS.Open.
- err.(*PathError).Path = name
- return nil, err
- }
- return f, nil
-}
-
-func (dir dirFS) ReadLink(name string) (string, error) {
- fullname, err := dir.join(name)
- if err != nil {
- return "", &PathError{Op: "readlink", Path: name, Err: err}
- }
- return Readlink(fullname)
-}
-
-// join returns the path for name in dir.
-func (dir dirFS) join(name string) (string, error) {
- if dir == "" {
- return "", errors.New("os: DirFS with empty root")
- }
- name, err := filepathlite.Localize(name)
- if err != nil {
- return "", ErrInvalid
- }
- if IsPathSeparator(dir[len(dir)-1]) {
- return string(dir) + name, nil
- }
- return string(dir) + string(PathSeparator) + name, nil
-}
-
-// ReadFile reads the named file and returns the contents.
-// A successful call returns err == nil, not err == EOF.
-// Because ReadFile reads the whole file, it does not treat an EOF from Read
-// as an error to be reported.
-func ReadFile(name string) ([]byte, error) {
- f, err := Open(name)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- return readFileContents(statOrZero(f), f.Read)
-}
-
-func statOrZero(f *File) int64 {
- if fi, err := f.Stat(); err == nil {
- return fi.Size()
- }
- return 0
-}
-
-// readFileContents reads the contents of a file using the provided read function
-// (*os.File.Read, except in tests) one or more times, until an error is seen.
-//
-// The provided size is the stat size of the file, which might be 0 for a
-// /proc-like file that doesn't report a size.
-func readFileContents(statSize int64, read func([]byte) (int, error)) ([]byte, error) {
- zeroSize := statSize == 0
-
- // Figure out how big to make the initial slice. For files with known size
- // that fit in memory, use that size + 1. Otherwise, use a small buffer and
- // we'll grow.
- var size int
- if int64(int(statSize)) == statSize {
- size = int(statSize)
- }
- size++ // one byte for final read at EOF
-
- const minBuf = 512
- // If a file claims a small size, read at least 512 bytes. In particular,
- // files in Linux's /proc claim size 0 but then do not work right if read in
- // small pieces, so an initial read of 1 byte would not work correctly.
- if size < minBuf {
- size = minBuf
- }
-
- data := make([]byte, 0, size)
- for {
- n, err := read(data[len(data):cap(data)])
- data = data[:len(data)+n]
- if err != nil {
- if err == io.EOF {
- err = nil
- }
- return data, err
- }
-
- // If we're either out of capacity or if the file was a /proc-like zero
- // sized file, grow the buffer. Per Issue 72080, we always want to issue
- // Read calls on zero-length files with a non-tiny buffer size.
- capRemain := cap(data) - len(data)
- if capRemain == 0 || (zeroSize && capRemain < minBuf) {
- data = slices.Grow(data, minBuf)
- }
- }
-}
-
-// WriteFile writes data to the named file, creating it if necessary.
-// If the file does not exist, WriteFile creates it with permissions perm (before umask);
-// otherwise WriteFile truncates it before writing, without changing permissions.
-// Since WriteFile requires multiple system calls to complete, a failure mid-operation
-// can leave the file in a partially written state.
-func WriteFile(name string, data []byte, perm FileMode) error {
- f, err := OpenFile(name, O_WRONLY|O_CREATE|O_TRUNC, perm)
- if err != nil {
- return err
- }
- _, err = f.Write(data)
- if err1 := f.Close(); err1 != nil && err == nil {
- err = err1
- }
- return err
-}