Source File
file.go
Belonging Package
os
// 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])//// Note: 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 osimport ()// Name returns the name of the file as presented to Open.func ( *File) () string { return .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 fileSEEK_CUR int = 1 // seek relative to the current offsetSEEK_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 stringOld stringNew stringErr error}func ( *LinkError) () string {return .Op + " " + .Old + " " + .New + ": " + .Err.Error()}func ( *LinkError) () error {return .Err}// Read reads up to len(b) bytes from the File.// It returns the number of bytes read and any error encountered.// At end of file, Read returns 0, io.EOF.func ( *File) ( []byte) ( int, error) {if := .checkValid("read"); != nil {return 0,}, := .read()return , .wrapErr("read", )}// 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 ( *File) ( []byte, int64) ( int, error) {if := .checkValid("read"); != nil {return 0,}if < 0 {return 0, &PathError{Op: "readat", Path: .name, Err: errors.New("negative offset")}}for len() > 0 {, := .pread(, )if != nil {= .wrapErr("read", )break}+== [:]+= int64()}return}// ReadFrom implements io.ReaderFrom.func ( *File) ( io.Reader) ( int64, error) {if := .checkValid("write"); != nil {return 0,}, , := .readFrom()if ! {return genericReadFrom(, ) // without wrapping}return , .wrapErr("write", )}func ( *File, io.Reader) (int64, error) {return io.Copy(onlyWriter{}, )}type onlyWriter struct {io.Writer}// Write writes len(b) bytes 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 ( *File) ( []byte) ( int, error) {if := .checkValid("write"); != nil {return 0,}, := .write()if < 0 {= 0}if != len() {= io.ErrShortWrite}epipecheck(, )if != nil {= .wrapErr("write", )}return ,}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 ( *File) ( []byte, int64) ( int, error) {if := .checkValid("write"); != nil {return 0,}if .appendMode {return 0, errWriteAtInAppendMode}if < 0 {return 0, &PathError{Op: "writeat", Path: .name, Err: errors.New("negative offset")}}for len() > 0 {, := .pwrite(, )if != nil {= .wrapErr("write", )break}+== [:]+= int64()}return}// 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.//// If f is a directory, the behavior of Seek varies by operating// system; you can seek to the beginning of the directory on Unix-like// operating systems, but not on Windows.func ( *File) ( int64, int) ( int64, error) {if := .checkValid("seek"); != nil {return 0,}, := .seek(, )if == nil && .dirinfo != nil && != 0 {= syscall.EISDIR}if != nil {return 0, .wrapErr("seek", )}return , nil}// WriteString is like Write, but writes the contents of string s rather than// a slice of bytes.func ( *File) ( string) ( int, error) {return .Write([]byte())}// 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 ( string, FileMode) error {if runtime.GOOS == "windows" && isWindowsNulName() {return &PathError{Op: "mkdir", Path: , Err: syscall.ENOTDIR}}:= fixLongPath():= ignoringEINTR(func() error {return syscall.Mkdir(, syscallMode())})if != nil {return &PathError{Op: "mkdir", Path: , Err: }}// mkdir(2) itself won't handle the sticky bit on *BSD and Solarisif !supportsCreateWithStickyBit && &ModeSticky != 0 {= setStickyBit()if != nil {Remove()return}}return nil}// setStickyBit adds ModeSticky to the permission bits of path, non atomic.func ( string) error {, := Stat()if != nil {return}return Chmod(, .Mode()|ModeSticky)}// Chdir changes the current working directory to the named directory.// If there is an error, it will be of type *PathError.func ( string) error {if := syscall.Chdir(); != nil {testlog.Open() // observe likely non-existent directoryreturn &PathError{Op: "chdir", Path: , Err: }}if := testlog.Logger(); != nil {, := Getwd()if == nil {.Chdir()}}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 ( string) (*File, error) {return OpenFile(, 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 0666// (before umask). If successful, methods on the returned File can// be used for I/O; the associated file descriptor has mode O_RDWR.// If there is an error, it will be of type *PathError.func ( string) (*File, error) {return OpenFile(, 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). 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 ( string, int, FileMode) (*File, error) {testlog.Open(), := openFileNolog(, , )if != nil {return nil,}.appendMode = &O_APPEND != 0return , nil}// lstat is overridden in tests.var lstat = Lstat// Rename renames (moves) oldpath to newpath.// If newpath already exists and is not a directory, Rename replaces it.// OS-specific restrictions may apply when oldpath and newpath are in different directories.// If there is an error, it will be of type *LinkError.func (, string) error {return rename(, )}// Many functions in package syscall return a count of -1 instead of 0.// Using fixCount(call()) instead of call() corrects the count.func ( int, error) (int, error) {if < 0 {= 0}return ,}// 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 ( *File) ( string, error) error {if == nil || == io.EOF {return}if == poll.ErrFileClosing {= ErrClosed}return &PathError{Op: , Path: .name, 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 () 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),// then it will return an error.func () (string, error) {var stringswitch runtime.GOOS {case "windows":= Getenv("LocalAppData")if == "" {return "", errors.New("%LocalAppData% is not defined")}case "darwin", "ios":= Getenv("HOME")if == "" {return "", errors.New("$HOME is not defined")}+= "/Library/Caches"case "plan9":= Getenv("home")if == "" {return "", errors.New("$home is not defined")}+= "/lib/cache"default: // Unix= Getenv("XDG_CACHE_HOME")if == "" {= Getenv("HOME")if == "" {return "", errors.New("neither $XDG_CACHE_HOME nor $HOME are defined")}+= "/.cache"}}return , 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),// then it will return an error.func () (string, error) {var stringswitch runtime.GOOS {case "windows":= Getenv("AppData")if == "" {return "", errors.New("%AppData% is not defined")}case "darwin", "ios":= Getenv("HOME")if == "" {return "", errors.New("$HOME is not defined")}+= "/Library/Application Support"case "plan9":= Getenv("home")if == "" {return "", errors.New("$home is not defined")}+= "/lib"default: // Unix= Getenv("XDG_CONFIG_HOME")if == "" {= Getenv("HOME")if == "" {return "", errors.New("neither $XDG_CONFIG_HOME nor $HOME are defined")}+= "/.config"}}return , 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.func () (string, error) {, := "HOME", "$HOME"switch runtime.GOOS {case "windows":, = "USERPROFILE", "%userprofile%"case "plan9":, = "home", "$home"}if := Getenv(); != "" {return , nil}// On some geese the home directory is not always defined.switch runtime.GOOS {case "android":return "/sdcard", nilcase "ios":return "/", nil}return "", errors.New( + " 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 0200 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 0400 for a read-only// file and 0600 for a readable+writable file.//// On Plan 9, the mode's permission bits, ModeAppend, ModeExclusive,// and ModeTemporary are used.func ( string, FileMode) error { return chmod(, ) }// Chmod changes the mode of the file to mode.// If there is an error, it will be of type *PathError.func ( *File) ( FileMode) error { return .chmod() }// 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 ( *File) ( time.Time) error {return .setDeadline()}// 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 ( *File) ( time.Time) error {return .setReadDeadline()}// 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 ( *File) ( time.Time) error {return .setWriteDeadline()}// SyscallConn returns a raw file.// This implements the syscall.Conn interface.func ( *File) () (syscall.RawConn, error) {if := .checkValid("SyscallConn"); != nil {return nil,}return newRawConn()}// isWindowsNulName reports whether name is os.DevNull ('NUL') on Windows.// True is returned if name is 'NUL' whatever the case.func ( string) bool {if len() != 3 {return false}if [0] != 'n' && [0] != 'N' {return false}if [1] != 'u' && [1] != 'U' {return false}if [2] != 'l' && [2] != 'L' {return false}return true}// 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. DirFS is therefore not a general substitute for a chroot-style security// mechanism when the directory tree contains arbitrary content.func ( string) fs.FS {return dirFS()}func (, string) bool {for := 0; < len(); ++ {for := 0; < len(); ++ {if [] == [] {return true}}}return false}type dirFS stringfunc ( dirFS) ( string) (fs.File, error) {if !fs.ValidPath() || runtime.GOOS == "windows" && containsAny(, `\:`) {return nil, &PathError{Op: "open", Path: , Err: ErrInvalid}}, := Open(string() + "/" + )if != nil {return nil, // nil fs.File}return , 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 ( string) ([]byte, error) {, := Open()if != nil {return nil,}defer .Close()var intif , := .Stat(); == nil {:= .Size()if int64(int()) == {= int()}}++ // one byte for final read at EOF// 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 < 512 {= 512}:= make([]byte, 0, )for {if len() >= cap() {:= append([:cap()], 0)= [:len()]}, := .Read([len():cap()])= [:len()+]if != nil {if == io.EOF {= nil}return ,}}}// 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.func ( string, []byte, FileMode) error {, := OpenFile(, O_WRONLY|O_CREATE|O_TRUNC, )if != nil {return}_, = .Write()if := .Close(); != nil && == nil {=}return}