diff options
Diffstat (limited to 'libgo/go/os/file.go')
-rw-r--r-- | libgo/go/os/file.go | 104 |
1 files changed, 89 insertions, 15 deletions
diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go index fdead63..96df3fb 100644 --- a/libgo/go/os/file.go +++ b/libgo/go/os/file.go @@ -98,6 +98,10 @@ func (e *LinkError) Error() string { return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error() } +func (e *LinkError) Unwrap() error { + return e.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. @@ -159,13 +163,20 @@ func (f *File) Write(b []byte) (n int, err error) { 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{"writeat", f.name, errors.New("negative offset")} @@ -265,10 +276,10 @@ func Open(name string) (*File, error) { return OpenFile(name, O_RDONLY, 0) } -// Create creates the named file with mode 0666 (before umask), truncating -// it if it already exists. If successful, methods on the returned -// File can be used for I/O; the associated file descriptor has mode -// O_RDWR. +// 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 Create(name string) (*File, error) { return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666) @@ -276,12 +287,19 @@ func Create(name string) (*File, error) { // 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.) and perm (before umask), if applicable. If successful, +// (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 OpenFile(name string, flag int, perm FileMode) (*File, error) { testlog.Open(name) - return openFileNolog(name, flag, perm) + f, err := openFileNolog(name, flag, perm) + if err != nil { + return nil, err + } + f.appendMode = flag&O_APPEND != 0 + + return f, nil } // lstat is overridden in tests. @@ -381,6 +399,57 @@ func UserCacheDir() (string, error) { 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://standards.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 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": + 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" + } + } + + return dir, nil +} + // UserHomeDir returns the current user's home directory. // // On Unix, including macOS, it returns the $HOME environment variable. @@ -393,16 +462,21 @@ func UserHomeDir() (string, error) { env, enverr = "USERPROFILE", "%userprofile%" case "plan9": env, enverr = "home", "$home" - case "nacl", "android": + } + if v := Getenv(env); v != "" { + return v, nil + } + // On some geese the home directory is not always defined. + switch runtime.GOOS { + case "nacl": return "/", nil + case "android": + return "/sdcard", nil case "darwin": if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { return "/", nil } } - if v := Getenv(env); v != "" { - return v, nil - } return "", errors.New(enverr + " is not defined") } @@ -416,11 +490,11 @@ func UserHomeDir() (string, error) { // On Unix, the mode's permission bits, ModeSetuid, ModeSetgid, and // ModeSticky are used. // -// On Windows, the mode must be non-zero but otherwise only the 0200 -// bit (owner writable) of mode is used; it controls whether the -// file's read-only attribute is set or cleared. attribute. The other -// bits are currently unused. Use mode 0400 for a read-only file and -// 0600 for a readable+writable file. +// 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. |