diff options
Diffstat (limited to 'src/pkg/os')
82 files changed, 0 insertions, 9582 deletions
diff --git a/src/pkg/os/dir_plan9.go b/src/pkg/os/dir_plan9.go deleted file mode 100644 index 8195c02a4..000000000 --- a/src/pkg/os/dir_plan9.go +++ /dev/null @@ -1,73 +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 - -import ( - "io" - "syscall" -) - -func (file *File) readdir(n int) ([]FileInfo, error) { - // If this file has no dirinfo, create one. - if file.dirinfo == nil { - file.dirinfo = new(dirInfo) - } - d := file.dirinfo - size := n - if size <= 0 { - size = 100 - n = -1 - } - fi := make([]FileInfo, 0, size) // Empty with room to grow. - for n != 0 { - // Refill the buffer if necessary. - if d.bufp >= d.nbuf { - nb, err := file.Read(d.buf[:]) - - // Update the buffer state before checking for errors. - d.bufp, d.nbuf = 0, nb - - if err != nil { - if err == io.EOF { - break - } - return fi, &PathError{"readdir", file.name, err} - } - if nb < syscall.STATFIXLEN { - return fi, &PathError{"readdir", file.name, syscall.ErrShortStat} - } - } - - // Get a record from the buffer. - b := d.buf[d.bufp:] - m := int(uint16(b[0])|uint16(b[1])<<8) + 2 - if m < syscall.STATFIXLEN { - return fi, &PathError{"readdir", file.name, syscall.ErrShortStat} - } - - dir, err := syscall.UnmarshalDir(b[:m]) - if err != nil { - return fi, &PathError{"readdir", file.name, err} - } - fi = append(fi, fileInfoFromStat(dir)) - - d.bufp += m - n-- - } - - if n >= 0 && len(fi) == 0 { - return fi, io.EOF - } - return fi, nil -} - -func (file *File) readdirnames(n int) (names []string, err error) { - fi, err := file.Readdir(n) - names = make([]string, len(fi)) - for i := range fi { - names[i] = fi[i].Name() - } - return -} diff --git a/src/pkg/os/dir_unix.go b/src/pkg/os/dir_unix.go deleted file mode 100644 index d353e405e..000000000 --- a/src/pkg/os/dir_unix.go +++ /dev/null @@ -1,58 +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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris - -package os - -import ( - "io" - "syscall" -) - -const ( - blockSize = 4096 -) - -func (f *File) readdirnames(n int) (names []string, err error) { - // If this file has no dirinfo, create one. - if f.dirinfo == nil { - f.dirinfo = new(dirInfo) - // The buffer must be at least a block long. - f.dirinfo.buf = make([]byte, blockSize) - } - d := f.dirinfo - - size := n - if size <= 0 { - size = 100 - n = -1 - } - - names = make([]string, 0, size) // Empty with room to grow. - for n != 0 { - // Refill the buffer if necessary - if d.bufp >= d.nbuf { - d.bufp = 0 - var errno error - d.nbuf, errno = syscall.ReadDirent(f.fd, d.buf) - if errno != nil { - return names, NewSyscallError("readdirent", errno) - } - if d.nbuf <= 0 { - break // EOF - } - } - - // Drain the buffer - var nb, nc int - nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], n, names) - d.bufp += nb - n -= nc - } - if n >= 0 && len(names) == 0 { - return names, io.EOF - } - return names, nil -} diff --git a/src/pkg/os/dir_windows.go b/src/pkg/os/dir_windows.go deleted file mode 100644 index 931316048..000000000 --- a/src/pkg/os/dir_windows.go +++ /dev/null @@ -1,14 +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 - -func (file *File) readdirnames(n int) (names []string, err error) { - fis, err := file.Readdir(n) - names = make([]string, len(fis)) - for i, fi := range fis { - names[i] = fi.Name() - } - return names, err -} diff --git a/src/pkg/os/doc.go b/src/pkg/os/doc.go deleted file mode 100644 index 389a8eb14..000000000 --- a/src/pkg/os/doc.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2012 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 - -import "time" - -// FindProcess looks for a running process by its pid. -// The Process it returns can be used to obtain information -// about the underlying operating system process. -func FindProcess(pid int) (p *Process, err error) { - return findProcess(pid) -} - -// StartProcess starts a new process with the program, arguments and attributes -// specified by name, argv and attr. -// -// StartProcess is a low-level interface. The os/exec package provides -// higher-level interfaces. -// -// If there is an error, it will be of type *PathError. -func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) { - return startProcess(name, argv, attr) -} - -// Release releases any resources associated with the Process p, -// rendering it unusable in the future. -// Release only needs to be called if Wait is not. -func (p *Process) Release() error { - return p.release() -} - -// Kill causes the Process to exit immediately. -func (p *Process) Kill() error { - return p.kill() -} - -// Wait waits for the Process to exit, and then returns a -// ProcessState describing its status and an error, if any. -// Wait releases any resources associated with the Process. -// On most operating systems, the Process must be a child -// of the current process or an error will be returned. -func (p *Process) Wait() (*ProcessState, error) { - return p.wait() -} - -// Signal sends a signal to the Process. -// Sending Interrupt on Windows is not implemented. -func (p *Process) Signal(sig Signal) error { - return p.signal(sig) -} - -// UserTime returns the user CPU time of the exited process and its children. -func (p *ProcessState) UserTime() time.Duration { - return p.userTime() -} - -// SystemTime returns the system CPU time of the exited process and its children. -func (p *ProcessState) SystemTime() time.Duration { - return p.systemTime() -} - -// Exited reports whether the program has exited. -func (p *ProcessState) Exited() bool { - return p.exited() -} - -// Success reports whether the program exited successfully, -// such as with exit status 0 on Unix. -func (p *ProcessState) Success() bool { - return p.success() -} - -// Sys returns system-dependent exit information about -// the process. Convert it to the appropriate underlying -// type, such as syscall.WaitStatus on Unix, to access its contents. -func (p *ProcessState) Sys() interface{} { - return p.sys() -} - -// SysUsage returns system-dependent resource usage information about -// the exited process. Convert it to the appropriate underlying -// type, such as *syscall.Rusage on Unix, to access its contents. -// (On Unix, *syscall.Rusage matches struct rusage as defined in the -// getrusage(2) manual page.) -func (p *ProcessState) SysUsage() interface{} { - return p.sysUsage() -} - -// Hostname returns the host name reported by the kernel. -func Hostname() (name string, err error) { - return hostname() -} - -// Readdir reads the contents of the directory associated with file and -// returns a slice of up to n FileInfo values, as would be returned -// by Lstat, in directory order. Subsequent calls on the same file will yield -// further FileInfos. -// -// If n > 0, Readdir returns at most n FileInfo structures. In this case, if -// Readdir returns an empty slice, it will return a non-nil error -// explaining why. At the end of a directory, the error is io.EOF. -// -// If n <= 0, Readdir returns all the FileInfo from the directory in -// a single slice. In this case, if Readdir succeeds (reads all -// the way to the end of the directory), it returns the slice and a -// nil error. If it encounters an error before the end of the -// directory, Readdir returns the FileInfo read until that point -// and a non-nil error. -func (f *File) Readdir(n int) (fi []FileInfo, err error) { - if f == nil { - return nil, ErrInvalid - } - return f.readdir(n) -} - -// Readdirnames reads and returns a slice of names from the directory f. -// -// If n > 0, Readdirnames returns at most n names. In this case, if -// Readdirnames returns an empty slice, it will return a non-nil error -// explaining why. At the end of a directory, the error is io.EOF. -// -// If n <= 0, Readdirnames returns all the names from the directory in -// a single slice. In this case, if Readdirnames succeeds (reads all -// the way to the end of the directory), it returns the slice and a -// nil error. If it encounters an error before the end of the -// directory, Readdirnames returns the names read until that point and -// a non-nil error. -func (f *File) Readdirnames(n int) (names []string, err error) { - if f == nil { - return nil, ErrInvalid - } - return f.readdirnames(n) -} diff --git a/src/pkg/os/env.go b/src/pkg/os/env.go deleted file mode 100644 index db7fc72b8..000000000 --- a/src/pkg/os/env.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2010 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. - -// General environment variables. - -package os - -import "syscall" - -// Expand replaces ${var} or $var in the string based on the mapping function. -// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv). -func Expand(s string, mapping func(string) string) string { - buf := make([]byte, 0, 2*len(s)) - // ${} is all ASCII, so bytes are fine for this operation. - i := 0 - for j := 0; j < len(s); j++ { - if s[j] == '$' && j+1 < len(s) { - buf = append(buf, s[i:j]...) - name, w := getShellName(s[j+1:]) - buf = append(buf, mapping(name)...) - j += w - i = j + 1 - } - } - return string(buf) + s[i:] -} - -// ExpandEnv replaces ${var} or $var in the string according to the values -// of the current environment variables. References to undefined -// variables are replaced by the empty string. -func ExpandEnv(s string) string { - return Expand(s, Getenv) -} - -// isSpellSpecialVar reports whether the character identifies a special -// shell variable such as $*. -func isShellSpecialVar(c uint8) bool { - switch c { - case '*', '#', '$', '@', '!', '?', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return true - } - return false -} - -// isAlphaNum reports whether the byte is an ASCII letter, number, or underscore -func isAlphaNum(c uint8) bool { - return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' -} - -// getName returns the name that begins the string and the number of bytes -// consumed to extract it. If the name is enclosed in {}, it's part of a ${} -// expansion and two more bytes are needed than the length of the name. -func getShellName(s string) (string, int) { - switch { - case s[0] == '{': - if len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' { - return s[1:2], 3 - } - // Scan to closing brace - for i := 1; i < len(s); i++ { - if s[i] == '}' { - return s[1:i], i + 1 - } - } - return "", 1 // Bad syntax; just eat the brace. - case isShellSpecialVar(s[0]): - return s[0:1], 1 - } - // Scan alphanumerics. - var i int - for i = 0; i < len(s) && isAlphaNum(s[i]); i++ { - } - return s[:i], i -} - -// Getenv retrieves the value of the environment variable named by the key. -// It returns the value, which will be empty if the variable is not present. -func Getenv(key string) string { - v, _ := syscall.Getenv(key) - return v -} - -// Setenv sets the value of the environment variable named by the key. -// It returns an error, if any. -func Setenv(key, value string) error { - err := syscall.Setenv(key, value) - if err != nil { - return NewSyscallError("setenv", err) - } - return nil -} - -// Clearenv deletes all environment variables. -func Clearenv() { - syscall.Clearenv() -} - -// Environ returns a copy of strings representing the environment, -// in the form "key=value". -func Environ() []string { - return syscall.Environ() -} diff --git a/src/pkg/os/env_test.go b/src/pkg/os/env_test.go deleted file mode 100644 index 991fa4d05..000000000 --- a/src/pkg/os/env_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2010 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_test - -import ( - . "os" - "reflect" - "testing" -) - -// testGetenv gives us a controlled set of variables for testing Expand. -func testGetenv(s string) string { - switch s { - case "*": - return "all the args" - case "#": - return "NARGS" - case "$": - return "PID" - case "1": - return "ARGUMENT1" - case "HOME": - return "/usr/gopher" - case "H": - return "(Value of H)" - case "home_1": - return "/usr/foo" - case "_": - return "underscore" - } - return "" -} - -var expandTests = []struct { - in, out string -}{ - {"", ""}, - {"$*", "all the args"}, - {"$$", "PID"}, - {"${*}", "all the args"}, - {"$1", "ARGUMENT1"}, - {"${1}", "ARGUMENT1"}, - {"now is the time", "now is the time"}, - {"$HOME", "/usr/gopher"}, - {"$home_1", "/usr/foo"}, - {"${HOME}", "/usr/gopher"}, - {"${H}OME", "(Value of H)OME"}, - {"A$$$#$1$H$home_1*B", "APIDNARGSARGUMENT1(Value of H)/usr/foo*B"}, -} - -func TestExpand(t *testing.T) { - for _, test := range expandTests { - result := Expand(test.in, testGetenv) - if result != test.out { - t.Errorf("Expand(%q)=%q; expected %q", test.in, result, test.out) - } - } -} - -func TestConsistentEnviron(t *testing.T) { - e0 := Environ() - for i := 0; i < 10; i++ { - e1 := Environ() - if !reflect.DeepEqual(e0, e1) { - t.Fatalf("environment changed") - } - } -} diff --git a/src/pkg/os/env_unix_test.go b/src/pkg/os/env_unix_test.go deleted file mode 100644 index 5ec07ee1b..000000000 --- a/src/pkg/os/env_unix_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 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. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package os_test - -import ( - . "os" - "testing" -) - -var setenvEinvalTests = []struct { - k, v string -}{ - {"", ""}, // empty key - {"k=v", ""}, // '=' in key - {"\x00", ""}, // '\x00' in key - {"k", "\x00"}, // '\x00' in value -} - -func TestSetenvUnixEinval(t *testing.T) { - for _, tt := range setenvEinvalTests { - err := Setenv(tt.k, tt.v) - if err == nil { - t.Errorf(`Setenv(%q, %q) == nil, want error`, tt.k, tt.v) - } - } -} diff --git a/src/pkg/os/error.go b/src/pkg/os/error.go deleted file mode 100644 index 8810e6930..000000000 --- a/src/pkg/os/error.go +++ /dev/null @@ -1,65 +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 - -import ( - "errors" -) - -// Portable analogs of some common system call errors. -var ( - ErrInvalid = errors.New("invalid argument") - ErrPermission = errors.New("permission denied") - ErrExist = errors.New("file already exists") - ErrNotExist = errors.New("file does not exist") -) - -// PathError records an error and the operation and file path that caused it. -type PathError struct { - Op string - Path string - Err error -} - -func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() } - -// SyscallError records an error from a specific system call. -type SyscallError struct { - Syscall string - Err error -} - -func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() } - -// NewSyscallError returns, as an error, a new SyscallError -// with the given system call name and error details. -// As a convenience, if err is nil, NewSyscallError returns nil. -func NewSyscallError(syscall string, err error) error { - if err == nil { - return nil - } - return &SyscallError{syscall, err} -} - -// IsExist returns a boolean indicating whether the error is known to report -// that a file or directory already exists. It is satisfied by ErrExist as -// well as some syscall errors. -func IsExist(err error) bool { - return isExist(err) -} - -// IsNotExist returns a boolean indicating whether the error is known to -// report that a file or directory does not exist. It is satisfied by -// ErrNotExist as well as some syscall errors. -func IsNotExist(err error) bool { - return isNotExist(err) -} - -// IsPermission returns a boolean indicating whether the error is known to -// report that permission is denied. It is satisfied by ErrPermission as well -// as some syscall errors. -func IsPermission(err error) bool { - return isPermission(err) -} diff --git a/src/pkg/os/error_plan9.go b/src/pkg/os/error_plan9.go deleted file mode 100644 index 85260c82a..000000000 --- a/src/pkg/os/error_plan9.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2011 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 - -func isExist(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return contains(err.Error(), " exists") -} - -func isNotExist(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return contains(err.Error(), "does not exist") -} - -func isPermission(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return contains(err.Error(), "permission denied") -} - -// contains is a local version of strings.Contains. It knows len(sep) > 1. -func contains(s, sep string) bool { - n := len(sep) - c := sep[0] - for i := 0; i+n <= len(s); i++ { - if s[i] == c && s[i:i+n] == sep { - return true - } - } - return false -} diff --git a/src/pkg/os/error_test.go b/src/pkg/os/error_test.go deleted file mode 100644 index 02ed2351c..000000000 --- a/src/pkg/os/error_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2012 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_test - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "testing" -) - -func TestErrIsExist(t *testing.T) { - f, err := ioutil.TempFile("", "_Go_ErrIsExist") - if err != nil { - t.Fatalf("open ErrIsExist tempfile: %s", err) - return - } - defer os.Remove(f.Name()) - defer f.Close() - f2, err := os.OpenFile(f.Name(), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if err == nil { - f2.Close() - t.Fatal("Open should have failed") - return - } - if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" { - t.Fatal(s) - return - } -} - -func testErrNotExist(name string) string { - f, err := os.Open(name) - if err == nil { - f.Close() - return "Open should have failed" - } - if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" { - return s - } - - err = os.Chdir(name) - if err == nil { - return "Chdir should have failed" - } - if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" { - return s - } - return "" -} - -func TestErrIsNotExist(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "_Go_ErrIsNotExist") - if err != nil { - t.Fatalf("create ErrIsNotExist tempdir: %s", err) - return - } - defer os.RemoveAll(tmpDir) - - name := filepath.Join(tmpDir, "NotExists") - if s := testErrNotExist(name); s != "" { - t.Fatal(s) - return - } - - name = filepath.Join(name, "NotExists2") - if s := testErrNotExist(name); s != "" { - t.Fatal(s) - return - } -} - -func checkErrorPredicate(predName string, pred func(error) bool, err error) string { - if !pred(err) { - return fmt.Sprintf("%s does not work as expected for %#v", predName, err) - } - return "" -} - -var isExistTests = []struct { - err error - is bool - isnot bool -}{ - {&os.PathError{Err: os.ErrInvalid}, false, false}, - {&os.PathError{Err: os.ErrPermission}, false, false}, - {&os.PathError{Err: os.ErrExist}, true, false}, - {&os.PathError{Err: os.ErrNotExist}, false, true}, - {&os.LinkError{Err: os.ErrInvalid}, false, false}, - {&os.LinkError{Err: os.ErrPermission}, false, false}, - {&os.LinkError{Err: os.ErrExist}, true, false}, - {&os.LinkError{Err: os.ErrNotExist}, false, true}, - {nil, false, false}, -} - -func TestIsExist(t *testing.T) { - for _, tt := range isExistTests { - if is := os.IsExist(tt.err); is != tt.is { - t.Errorf("os.IsExist(%T %v) = %v, want %v", tt.err, tt.err, is, tt.is) - } - if isnot := os.IsNotExist(tt.err); isnot != tt.isnot { - t.Errorf("os.IsNotExist(%T %v) = %v, want %v", tt.err, tt.err, isnot, tt.isnot) - } - } -} - -func TestErrPathNUL(t *testing.T) { - f, err := ioutil.TempFile("", "_Go_ErrPathNUL\x00") - if err == nil { - f.Close() - t.Fatal("TempFile should have failed") - } - f, err = ioutil.TempFile("", "_Go_ErrPathNUL") - if err != nil { - t.Fatalf("open ErrPathNUL tempfile: %s", err) - } - defer os.Remove(f.Name()) - defer f.Close() - f2, err := os.OpenFile(f.Name(), os.O_RDWR, 0600) - if err != nil { - t.Fatalf("open ErrPathNUL: %s", err) - } - f2.Close() - f2, err = os.OpenFile(f.Name()+"\x00", os.O_RDWR, 0600) - if err == nil { - f2.Close() - t.Fatal("Open should have failed") - } -} diff --git a/src/pkg/os/error_unix.go b/src/pkg/os/error_unix.go deleted file mode 100644 index f2aabbb45..000000000 --- a/src/pkg/os/error_unix.go +++ /dev/null @@ -1,45 +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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris - -package os - -import "syscall" - -func isExist(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return err == syscall.EEXIST || err == ErrExist -} - -func isNotExist(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return err == syscall.ENOENT || err == ErrNotExist -} - -func isPermission(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission -} diff --git a/src/pkg/os/error_windows.go b/src/pkg/os/error_windows.go deleted file mode 100644 index 83db6c078..000000000 --- a/src/pkg/os/error_windows.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 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 - -import "syscall" - -func isExist(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return err == syscall.ERROR_ALREADY_EXISTS || - err == syscall.ERROR_FILE_EXISTS || err == ErrExist -} - -func isNotExist(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return err == syscall.ERROR_FILE_NOT_FOUND || - err == syscall.ERROR_PATH_NOT_FOUND || err == ErrNotExist -} - -func isPermission(err error) bool { - switch pe := err.(type) { - case nil: - return false - case *PathError: - err = pe.Err - case *LinkError: - err = pe.Err - } - return err == syscall.ERROR_ACCESS_DENIED || err == ErrPermission -} diff --git a/src/pkg/os/error_windows_test.go b/src/pkg/os/error_windows_test.go deleted file mode 100644 index 3e6504f8d..000000000 --- a/src/pkg/os/error_windows_test.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 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_test - -import ( - "io/ioutil" - "os" - "path/filepath" - "testing" -) - -func TestErrIsExistAfterRename(t *testing.T) { - dir, err := ioutil.TempDir("", "go-build") - if err != nil { - t.Fatalf("Create temp directory: %v", err) - } - defer os.RemoveAll(dir) - - src := filepath.Join(dir, "src") - dest := filepath.Join(dir, "dest") - - f, err := os.Create(src) - if err != nil { - t.Fatalf("Create file %v: %v", src, err) - } - f.Close() - err = os.Rename(src, dest) - if err != nil { - t.Fatalf("Rename %v to %v: %v", src, dest, err) - } - - f, err = os.Create(src) - if err != nil { - t.Fatalf("Create file %v: %v", src, err) - } - f.Close() - err = os.Rename(src, dest) - if err == nil { - t.Fatal("Rename should have failed") - } - if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" { - t.Fatal(s) - return - } -} diff --git a/src/pkg/os/exec.go b/src/pkg/os/exec.go deleted file mode 100644 index 5aea3098b..000000000 --- a/src/pkg/os/exec.go +++ /dev/null @@ -1,70 +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 - -import ( - "runtime" - "sync/atomic" - "syscall" -) - -// Process stores the information about a process created by StartProcess. -type Process struct { - Pid int - handle uintptr - isdone uint32 // process has been successfully waited on, non zero if true -} - -func newProcess(pid int, handle uintptr) *Process { - p := &Process{Pid: pid, handle: handle} - runtime.SetFinalizer(p, (*Process).Release) - return p -} - -func (p *Process) setDone() { - atomic.StoreUint32(&p.isdone, 1) -} - -func (p *Process) done() bool { - return atomic.LoadUint32(&p.isdone) > 0 -} - -// ProcAttr holds the attributes that will be applied to a new process -// started by StartProcess. -type ProcAttr struct { - // If Dir is non-empty, the child changes into the directory before - // creating the process. - Dir string - // If Env is non-nil, it gives the environment variables for the - // new process in the form returned by Environ. - // If it is nil, the result of Environ will be used. - Env []string - // Files specifies the open files inherited by the new process. The - // first three entries correspond to standard input, standard output, and - // standard error. An implementation may support additional entries, - // depending on the underlying operating system. A nil entry corresponds - // to that file being closed when the process starts. - Files []*File - - // Operating system-specific process creation attributes. - // Note that setting this field means that your program - // may not execute properly or even compile on some - // operating systems. - Sys *syscall.SysProcAttr -} - -// A Signal represents an operating system signal. -// The usual underlying implementation is operating system-dependent: -// on Unix it is syscall.Signal. -type Signal interface { - String() string - Signal() // to distinguish from other Stringers -} - -// Getpid returns the process id of the caller. -func Getpid() int { return syscall.Getpid() } - -// Getppid returns the process id of the caller's parent. -func Getppid() int { return syscall.Getppid() } diff --git a/src/pkg/os/exec/example_test.go b/src/pkg/os/exec/example_test.go deleted file mode 100644 index 55eaac8ab..000000000 --- a/src/pkg/os/exec/example_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2012 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 exec_test - -import ( - "bytes" - "encoding/json" - "fmt" - "log" - "os/exec" - "strings" -) - -func ExampleLookPath() { - path, err := exec.LookPath("fortune") - if err != nil { - log.Fatal("installing fortune is in your future") - } - fmt.Printf("fortune is available at %s\n", path) -} - -func ExampleCommand() { - cmd := exec.Command("tr", "a-z", "A-Z") - cmd.Stdin = strings.NewReader("some input") - var out bytes.Buffer - cmd.Stdout = &out - err := cmd.Run() - if err != nil { - log.Fatal(err) - } - fmt.Printf("in all caps: %q\n", out.String()) -} - -func ExampleCmd_Output() { - out, err := exec.Command("date").Output() - if err != nil { - log.Fatal(err) - } - fmt.Printf("The date is %s\n", out) -} - -func ExampleCmd_Start() { - cmd := exec.Command("sleep", "5") - err := cmd.Start() - if err != nil { - log.Fatal(err) - } - log.Printf("Waiting for command to finish...") - err = cmd.Wait() - log.Printf("Command finished with error: %v", err) -} - -func ExampleCmd_StdoutPipe() { - cmd := exec.Command("echo", "-n", `{"Name": "Bob", "Age": 32}`) - stdout, err := cmd.StdoutPipe() - if err != nil { - log.Fatal(err) - } - if err := cmd.Start(); err != nil { - log.Fatal(err) - } - var person struct { - Name string - Age int - } - if err := json.NewDecoder(stdout).Decode(&person); err != nil { - log.Fatal(err) - } - if err := cmd.Wait(); err != nil { - log.Fatal(err) - } - fmt.Printf("%s is %d years old\n", person.Name, person.Age) -} diff --git a/src/pkg/os/exec/exec.go b/src/pkg/os/exec/exec.go deleted file mode 100644 index a70ed0d20..000000000 --- a/src/pkg/os/exec/exec.go +++ /dev/null @@ -1,493 +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 exec runs external commands. It wraps os.StartProcess to make it -// easier to remap stdin and stdout, connect I/O with pipes, and do other -// adjustments. -package exec - -import ( - "bytes" - "errors" - "io" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "sync" - "syscall" -) - -// Error records the name of a binary that failed to be executed -// and the reason it failed. -type Error struct { - Name string - Err error -} - -func (e *Error) Error() string { - return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error() -} - -// Cmd represents an external command being prepared or run. -type Cmd struct { - // Path is the path of the command to run. - // - // This is the only field that must be set to a non-zero - // value. If Path is relative, it is evaluated relative - // to Dir. - Path string - - // Args holds command line arguments, including the command as Args[0]. - // If the Args field is empty or nil, Run uses {Path}. - // - // In typical use, both Path and Args are set by calling Command. - Args []string - - // Env specifies the environment of the process. - // If Env is nil, Run uses the current process's environment. - Env []string - - // Dir specifies the working directory of the command. - // If Dir is the empty string, Run runs the command in the - // calling process's current directory. - Dir string - - // Stdin specifies the process's standard input. If Stdin is - // nil, the process reads from the null device (os.DevNull). - Stdin io.Reader - - // Stdout and Stderr specify the process's standard output and error. - // - // If either is nil, Run connects the corresponding file descriptor - // to the null device (os.DevNull). - // - // If Stdout and Stderr are the same writer, at most one - // goroutine at a time will call Write. - Stdout io.Writer - Stderr io.Writer - - // ExtraFiles specifies additional open files to be inherited by the - // new process. It does not include standard input, standard output, or - // standard error. If non-nil, entry i becomes file descriptor 3+i. - // - // BUG: on OS X 10.6, child processes may sometimes inherit unwanted fds. - // http://golang.org/issue/2603 - ExtraFiles []*os.File - - // SysProcAttr holds optional, operating system-specific attributes. - // Run passes it to os.StartProcess as the os.ProcAttr's Sys field. - SysProcAttr *syscall.SysProcAttr - - // Process is the underlying process, once started. - Process *os.Process - - // ProcessState contains information about an exited process, - // available after a call to Wait or Run. - ProcessState *os.ProcessState - - lookPathErr error // LookPath error, if any. - finished bool // when Wait was called - childFiles []*os.File - closeAfterStart []io.Closer - closeAfterWait []io.Closer - goroutine []func() error - errch chan error // one send per goroutine -} - -// Command returns the Cmd struct to execute the named program with -// the given arguments. -// -// It sets only the Path and Args in the returned structure. -// -// If name contains no path separators, Command uses LookPath to -// resolve the path to a complete name if possible. Otherwise it uses -// name directly. -// -// The returned Cmd's Args field is constructed from the command name -// followed by the elements of arg, so arg should not include the -// command name itself. For example, Command("echo", "hello") -func Command(name string, arg ...string) *Cmd { - cmd := &Cmd{ - Path: name, - Args: append([]string{name}, arg...), - } - if filepath.Base(name) == name { - if lp, err := LookPath(name); err != nil { - cmd.lookPathErr = err - } else { - cmd.Path = lp - } - } - return cmd -} - -// interfaceEqual protects against panics from doing equality tests on -// two interfaces with non-comparable underlying types. -func interfaceEqual(a, b interface{}) bool { - defer func() { - recover() - }() - return a == b -} - -func (c *Cmd) envv() []string { - if c.Env != nil { - return c.Env - } - return os.Environ() -} - -func (c *Cmd) argv() []string { - if len(c.Args) > 0 { - return c.Args - } - return []string{c.Path} -} - -func (c *Cmd) stdin() (f *os.File, err error) { - if c.Stdin == nil { - f, err = os.Open(os.DevNull) - if err != nil { - return - } - c.closeAfterStart = append(c.closeAfterStart, f) - return - } - - if f, ok := c.Stdin.(*os.File); ok { - return f, nil - } - - pr, pw, err := os.Pipe() - if err != nil { - return - } - - c.closeAfterStart = append(c.closeAfterStart, pr) - c.closeAfterWait = append(c.closeAfterWait, pw) - c.goroutine = append(c.goroutine, func() error { - _, err := io.Copy(pw, c.Stdin) - if err1 := pw.Close(); err == nil { - err = err1 - } - return err - }) - return pr, nil -} - -func (c *Cmd) stdout() (f *os.File, err error) { - return c.writerDescriptor(c.Stdout) -} - -func (c *Cmd) stderr() (f *os.File, err error) { - if c.Stderr != nil && interfaceEqual(c.Stderr, c.Stdout) { - return c.childFiles[1], nil - } - return c.writerDescriptor(c.Stderr) -} - -func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) { - if w == nil { - f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0) - if err != nil { - return - } - c.closeAfterStart = append(c.closeAfterStart, f) - return - } - - if f, ok := w.(*os.File); ok { - return f, nil - } - - pr, pw, err := os.Pipe() - if err != nil { - return - } - - c.closeAfterStart = append(c.closeAfterStart, pw) - c.closeAfterWait = append(c.closeAfterWait, pr) - c.goroutine = append(c.goroutine, func() error { - _, err := io.Copy(w, pr) - return err - }) - return pw, nil -} - -func (c *Cmd) closeDescriptors(closers []io.Closer) { - for _, fd := range closers { - fd.Close() - } -} - -// Run starts the specified command and waits for it to complete. -// -// The returned error is nil if the command runs, has no problems -// copying stdin, stdout, and stderr, and exits with a zero exit -// status. -// -// If the command fails to run or doesn't complete successfully, the -// error is of type *ExitError. Other error types may be -// returned for I/O problems. -func (c *Cmd) Run() error { - if err := c.Start(); err != nil { - return err - } - return c.Wait() -} - -// lookExtensions finds windows executable by its dir and path. -// It uses LookPath to try appropriate extensions. -// lookExtensions does not search PATH, instead it converts `prog` into `.\prog`. -func lookExtensions(path, dir string) (string, error) { - if filepath.Base(path) == path { - path = filepath.Join(".", path) - } - if dir == "" { - return LookPath(path) - } - if filepath.VolumeName(path) != "" { - return LookPath(path) - } - if len(path) > 1 && os.IsPathSeparator(path[0]) { - return LookPath(path) - } - dirandpath := filepath.Join(dir, path) - // We assume that LookPath will only add file extension. - lp, err := LookPath(dirandpath) - if err != nil { - return "", err - } - ext := strings.TrimPrefix(lp, dirandpath) - return path + ext, nil -} - -// Start starts the specified command but does not wait for it to complete. -// -// The Wait method will return the exit code and release associated resources -// once the command exits. -func (c *Cmd) Start() error { - if c.lookPathErr != nil { - c.closeDescriptors(c.closeAfterStart) - c.closeDescriptors(c.closeAfterWait) - return c.lookPathErr - } - if runtime.GOOS == "windows" { - lp, err := lookExtensions(c.Path, c.Dir) - if err != nil { - c.closeDescriptors(c.closeAfterStart) - c.closeDescriptors(c.closeAfterWait) - return err - } - c.Path = lp - } - if c.Process != nil { - return errors.New("exec: already started") - } - - type F func(*Cmd) (*os.File, error) - for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { - fd, err := setupFd(c) - if err != nil { - c.closeDescriptors(c.closeAfterStart) - c.closeDescriptors(c.closeAfterWait) - return err - } - c.childFiles = append(c.childFiles, fd) - } - c.childFiles = append(c.childFiles, c.ExtraFiles...) - - var err error - c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ - Dir: c.Dir, - Files: c.childFiles, - Env: c.envv(), - Sys: c.SysProcAttr, - }) - if err != nil { - c.closeDescriptors(c.closeAfterStart) - c.closeDescriptors(c.closeAfterWait) - return err - } - - c.closeDescriptors(c.closeAfterStart) - - c.errch = make(chan error, len(c.goroutine)) - for _, fn := range c.goroutine { - go func(fn func() error) { - c.errch <- fn() - }(fn) - } - - return nil -} - -// An ExitError reports an unsuccessful exit by a command. -type ExitError struct { - *os.ProcessState -} - -func (e *ExitError) Error() string { - return e.ProcessState.String() -} - -// Wait waits for the command to exit. -// It must have been started by Start. -// -// The returned error is nil if the command runs, has no problems -// copying stdin, stdout, and stderr, and exits with a zero exit -// status. -// -// If the command fails to run or doesn't complete successfully, the -// error is of type *ExitError. Other error types may be -// returned for I/O problems. -// -// Wait releases any resources associated with the Cmd. -func (c *Cmd) Wait() error { - if c.Process == nil { - return errors.New("exec: not started") - } - if c.finished { - return errors.New("exec: Wait was already called") - } - c.finished = true - state, err := c.Process.Wait() - c.ProcessState = state - - var copyError error - for _ = range c.goroutine { - if err := <-c.errch; err != nil && copyError == nil { - copyError = err - } - } - - c.closeDescriptors(c.closeAfterWait) - - if err != nil { - return err - } else if !state.Success() { - return &ExitError{state} - } - - return copyError -} - -// Output runs the command and returns its standard output. -func (c *Cmd) Output() ([]byte, error) { - if c.Stdout != nil { - return nil, errors.New("exec: Stdout already set") - } - var b bytes.Buffer - c.Stdout = &b - err := c.Run() - return b.Bytes(), err -} - -// CombinedOutput runs the command and returns its combined standard -// output and standard error. -func (c *Cmd) CombinedOutput() ([]byte, error) { - if c.Stdout != nil { - return nil, errors.New("exec: Stdout already set") - } - if c.Stderr != nil { - return nil, errors.New("exec: Stderr already set") - } - var b bytes.Buffer - c.Stdout = &b - c.Stderr = &b - err := c.Run() - return b.Bytes(), err -} - -// StdinPipe returns a pipe that will be connected to the command's -// standard input when the command starts. -// The pipe will be closed automatically after Wait sees the command exit. -// A caller need only call Close to force the pipe to close sooner. -// For example, if the command being run will not exit until standard input -// is closed, the caller must close the pipe. -func (c *Cmd) StdinPipe() (io.WriteCloser, error) { - if c.Stdin != nil { - return nil, errors.New("exec: Stdin already set") - } - if c.Process != nil { - return nil, errors.New("exec: StdinPipe after process started") - } - pr, pw, err := os.Pipe() - if err != nil { - return nil, err - } - c.Stdin = pr - c.closeAfterStart = append(c.closeAfterStart, pr) - wc := &closeOnce{File: pw} - c.closeAfterWait = append(c.closeAfterWait, wc) - return wc, nil -} - -type closeOnce struct { - *os.File - - once sync.Once - err error -} - -func (c *closeOnce) Close() error { - c.once.Do(c.close) - return c.err -} - -func (c *closeOnce) close() { - c.err = c.File.Close() -} - -// StdoutPipe returns a pipe that will be connected to the command's -// standard output when the command starts. -// -// Wait will close the pipe after seeing the command exit, so most callers -// need not close the pipe themselves; however, an implication is that -// it is incorrect to call Wait before all reads from the pipe have completed. -// For the same reason, it is incorrect to call Run when using StdoutPipe. -// See the example for idiomatic usage. -func (c *Cmd) StdoutPipe() (io.ReadCloser, error) { - if c.Stdout != nil { - return nil, errors.New("exec: Stdout already set") - } - if c.Process != nil { - return nil, errors.New("exec: StdoutPipe after process started") - } - pr, pw, err := os.Pipe() - if err != nil { - return nil, err - } - c.Stdout = pw - c.closeAfterStart = append(c.closeAfterStart, pw) - c.closeAfterWait = append(c.closeAfterWait, pr) - return pr, nil -} - -// StderrPipe returns a pipe that will be connected to the command's -// standard error when the command starts. -// -// Wait will close the pipe after seeing the command exit, so most callers -// need not close the pipe themselves; however, an implication is that -// it is incorrect to call Wait before all reads from the pipe have completed. -// For the same reason, it is incorrect to use Run when using StderrPipe. -// See the StdoutPipe example for idiomatic usage. -func (c *Cmd) StderrPipe() (io.ReadCloser, error) { - if c.Stderr != nil { - return nil, errors.New("exec: Stderr already set") - } - if c.Process != nil { - return nil, errors.New("exec: StderrPipe after process started") - } - pr, pw, err := os.Pipe() - if err != nil { - return nil, err - } - c.Stderr = pw - c.closeAfterStart = append(c.closeAfterStart, pw) - c.closeAfterWait = append(c.closeAfterWait, pr) - return pr, nil -} diff --git a/src/pkg/os/exec/exec_test.go b/src/pkg/os/exec/exec_test.go deleted file mode 100644 index 6f77ac38a..000000000 --- a/src/pkg/os/exec/exec_test.go +++ /dev/null @@ -1,726 +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. - -// Use an external test to avoid os/exec -> net/http -> crypto/x509 -> os/exec -// circular dependency on non-cgo darwin. - -package exec_test - -import ( - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/http/httptest" - "os" - "os/exec" - "path/filepath" - "runtime" - "strconv" - "strings" - "testing" - "time" -) - -func helperCommand(t *testing.T, s ...string) *exec.Cmd { - if runtime.GOOS == "nacl" { - t.Skip("skipping on nacl") - } - cs := []string{"-test.run=TestHelperProcess", "--"} - cs = append(cs, s...) - cmd := exec.Command(os.Args[0], cs...) - cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} - return cmd -} - -func TestEcho(t *testing.T) { - bs, err := helperCommand(t, "echo", "foo bar", "baz").Output() - if err != nil { - t.Errorf("echo: %v", err) - } - if g, e := string(bs), "foo bar baz\n"; g != e { - t.Errorf("echo: want %q, got %q", e, g) - } -} - -func TestCommandRelativeName(t *testing.T) { - // Run our own binary as a relative path - // (e.g. "_test/exec.test") our parent directory. - base := filepath.Base(os.Args[0]) // "exec.test" - dir := filepath.Dir(os.Args[0]) // "/tmp/go-buildNNNN/os/exec/_test" - if dir == "." { - t.Skip("skipping; running test at root somehow") - } - parentDir := filepath.Dir(dir) // "/tmp/go-buildNNNN/os/exec" - dirBase := filepath.Base(dir) // "_test" - if dirBase == "." { - t.Skipf("skipping; unexpected shallow dir of %q", dir) - } - - cmd := exec.Command(filepath.Join(dirBase, base), "-test.run=TestHelperProcess", "--", "echo", "foo") - cmd.Dir = parentDir - cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} - - out, err := cmd.Output() - if err != nil { - t.Errorf("echo: %v", err) - } - if g, e := string(out), "foo\n"; g != e { - t.Errorf("echo: want %q, got %q", e, g) - } -} - -func TestCatStdin(t *testing.T) { - // Cat, testing stdin and stdout. - input := "Input string\nLine 2" - p := helperCommand(t, "cat") - p.Stdin = strings.NewReader(input) - bs, err := p.Output() - if err != nil { - t.Errorf("cat: %v", err) - } - s := string(bs) - if s != input { - t.Errorf("cat: want %q, got %q", input, s) - } -} - -func TestCatGoodAndBadFile(t *testing.T) { - // Testing combined output and error values. - bs, err := helperCommand(t, "cat", "/bogus/file.foo", "exec_test.go").CombinedOutput() - if _, ok := err.(*exec.ExitError); !ok { - t.Errorf("expected *exec.ExitError from cat combined; got %T: %v", err, err) - } - s := string(bs) - sp := strings.SplitN(s, "\n", 2) - if len(sp) != 2 { - t.Fatalf("expected two lines from cat; got %q", s) - } - errLine, body := sp[0], sp[1] - if !strings.HasPrefix(errLine, "Error: open /bogus/file.foo") { - t.Errorf("expected stderr to complain about file; got %q", errLine) - } - if !strings.Contains(body, "func TestHelperProcess(t *testing.T)") { - t.Errorf("expected test code; got %q (len %d)", body, len(body)) - } -} - -func TestNoExistBinary(t *testing.T) { - // Can't run a non-existent binary - err := exec.Command("/no-exist-binary").Run() - if err == nil { - t.Error("expected error from /no-exist-binary") - } -} - -func TestExitStatus(t *testing.T) { - // Test that exit values are returned correctly - cmd := helperCommand(t, "exit", "42") - err := cmd.Run() - want := "exit status 42" - switch runtime.GOOS { - case "plan9": - want = fmt.Sprintf("exit status: '%s %d: 42'", filepath.Base(cmd.Path), cmd.ProcessState.Pid()) - } - if werr, ok := err.(*exec.ExitError); ok { - if s := werr.Error(); s != want { - t.Errorf("from exit 42 got exit %q, want %q", s, want) - } - } else { - t.Fatalf("expected *exec.ExitError from exit 42; got %T: %v", err, err) - } -} - -func TestPipes(t *testing.T) { - check := func(what string, err error) { - if err != nil { - t.Fatalf("%s: %v", what, err) - } - } - // Cat, testing stdin and stdout. - c := helperCommand(t, "pipetest") - stdin, err := c.StdinPipe() - check("StdinPipe", err) - stdout, err := c.StdoutPipe() - check("StdoutPipe", err) - stderr, err := c.StderrPipe() - check("StderrPipe", err) - - outbr := bufio.NewReader(stdout) - errbr := bufio.NewReader(stderr) - line := func(what string, br *bufio.Reader) string { - line, _, err := br.ReadLine() - if err != nil { - t.Fatalf("%s: %v", what, err) - } - return string(line) - } - - err = c.Start() - check("Start", err) - - _, err = stdin.Write([]byte("O:I am output\n")) - check("first stdin Write", err) - if g, e := line("first output line", outbr), "O:I am output"; g != e { - t.Errorf("got %q, want %q", g, e) - } - - _, err = stdin.Write([]byte("E:I am error\n")) - check("second stdin Write", err) - if g, e := line("first error line", errbr), "E:I am error"; g != e { - t.Errorf("got %q, want %q", g, e) - } - - _, err = stdin.Write([]byte("O:I am output2\n")) - check("third stdin Write 3", err) - if g, e := line("second output line", outbr), "O:I am output2"; g != e { - t.Errorf("got %q, want %q", g, e) - } - - stdin.Close() - err = c.Wait() - check("Wait", err) -} - -const stdinCloseTestString = "Some test string." - -// Issue 6270. -func TestStdinClose(t *testing.T) { - check := func(what string, err error) { - if err != nil { - t.Fatalf("%s: %v", what, err) - } - } - cmd := helperCommand(t, "stdinClose") - stdin, err := cmd.StdinPipe() - check("StdinPipe", err) - // Check that we can access methods of the underlying os.File.` - if _, ok := stdin.(interface { - Fd() uintptr - }); !ok { - t.Error("can't access methods of underlying *os.File") - } - check("Start", cmd.Start()) - go func() { - _, err := io.Copy(stdin, strings.NewReader(stdinCloseTestString)) - check("Copy", err) - // Before the fix, this next line would race with cmd.Wait. - check("Close", stdin.Close()) - }() - check("Wait", cmd.Wait()) -} - -// Issue 5071 -func TestPipeLookPathLeak(t *testing.T) { - fd0, lsof0 := numOpenFDS(t) - for i := 0; i < 4; i++ { - cmd := exec.Command("something-that-does-not-exist-binary") - cmd.StdoutPipe() - cmd.StderrPipe() - cmd.StdinPipe() - if err := cmd.Run(); err == nil { - t.Fatal("unexpected success") - } - } - for triesLeft := 3; triesLeft >= 0; triesLeft-- { - open, lsof := numOpenFDS(t) - fdGrowth := open - fd0 - if fdGrowth > 2 { - if triesLeft > 0 { - // Work around what appears to be a race with Linux's - // proc filesystem (as used by lsof). It seems to only - // be eventually consistent. Give it awhile to settle. - // See golang.org/issue/7808 - time.Sleep(100 * time.Millisecond) - continue - } - t.Errorf("leaked %d fds; want ~0; have:\n%s\noriginally:\n%s", fdGrowth, lsof, lsof0) - } - break - } -} - -func numOpenFDS(t *testing.T) (n int, lsof []byte) { - lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output() - if err != nil { - t.Skip("skipping test; error finding or running lsof") - } - return bytes.Count(lsof, []byte("\n")), lsof -} - -var testedAlreadyLeaked = false - -// basefds returns the number of expected file descriptors -// to be present in a process at start. -func basefds() uintptr { - n := os.Stderr.Fd() + 1 - - // Go runtime for 32-bit Plan 9 requires that /dev/bintime - // be kept open. - // See ../../runtime/time_plan9_386.c:/^runtime·nanotime - if runtime.GOOS == "plan9" && runtime.GOARCH == "386" { - n++ - } - return n -} - -func closeUnexpectedFds(t *testing.T, m string) { - for fd := basefds(); fd <= 101; fd++ { - err := os.NewFile(fd, "").Close() - if err == nil { - t.Logf("%s: Something already leaked - closed fd %d", m, fd) - } - } -} - -func TestExtraFilesFDShuffle(t *testing.T) { - t.Skip("flaky test; see http://golang.org/issue/5780") - switch runtime.GOOS { - case "darwin": - // TODO(cnicolaou): http://golang.org/issue/2603 - // leads to leaked file descriptors in this test when it's - // run from a builder. - closeUnexpectedFds(t, "TestExtraFilesFDShuffle") - case "netbsd": - // http://golang.org/issue/3955 - closeUnexpectedFds(t, "TestExtraFilesFDShuffle") - case "windows": - t.Skip("no operating system support; skipping") - } - - // syscall.StartProcess maps all the FDs passed to it in - // ProcAttr.Files (the concatenation of stdin,stdout,stderr and - // ExtraFiles) into consecutive FDs in the child, that is: - // Files{11, 12, 6, 7, 9, 3} should result in the file - // represented by FD 11 in the parent being made available as 0 - // in the child, 12 as 1, etc. - // - // We want to test that FDs in the child do not get overwritten - // by one another as this shuffle occurs. The original implementation - // was buggy in that in some data dependent cases it would ovewrite - // stderr in the child with one of the ExtraFile members. - // Testing for this case is difficult because it relies on using - // the same FD values as that case. In particular, an FD of 3 - // must be at an index of 4 or higher in ProcAttr.Files and - // the FD of the write end of the Stderr pipe (as obtained by - // StderrPipe()) must be the same as the size of ProcAttr.Files; - // therefore we test that the read end of this pipe (which is what - // is returned to the parent by StderrPipe() being one less than - // the size of ProcAttr.Files, i.e. 3+len(cmd.ExtraFiles). - // - // Moving this test case around within the overall tests may - // affect the FDs obtained and hence the checks to catch these cases. - npipes := 2 - c := helperCommand(t, "extraFilesAndPipes", strconv.Itoa(npipes+1)) - rd, wr, _ := os.Pipe() - defer rd.Close() - if rd.Fd() != 3 { - t.Errorf("bad test value for test pipe: fd %d", rd.Fd()) - } - stderr, _ := c.StderrPipe() - wr.WriteString("_LAST") - wr.Close() - - pipes := make([]struct { - r, w *os.File - }, npipes) - data := []string{"a", "b"} - - for i := 0; i < npipes; i++ { - r, w, err := os.Pipe() - if err != nil { - t.Fatalf("unexpected error creating pipe: %s", err) - } - pipes[i].r = r - pipes[i].w = w - w.WriteString(data[i]) - c.ExtraFiles = append(c.ExtraFiles, pipes[i].r) - defer func() { - r.Close() - w.Close() - }() - } - // Put fd 3 at the end. - c.ExtraFiles = append(c.ExtraFiles, rd) - - stderrFd := int(stderr.(*os.File).Fd()) - if stderrFd != ((len(c.ExtraFiles) + 3) - 1) { - t.Errorf("bad test value for stderr pipe") - } - - expected := "child: " + strings.Join(data, "") + "_LAST" - - err := c.Start() - if err != nil { - t.Fatalf("Run: %v", err) - } - ch := make(chan string, 1) - go func(ch chan string) { - buf := make([]byte, 512) - n, err := stderr.Read(buf) - if err != nil { - t.Fatalf("Read: %s", err) - ch <- err.Error() - } else { - ch <- string(buf[:n]) - } - close(ch) - }(ch) - select { - case m := <-ch: - if m != expected { - t.Errorf("Read: '%s' not '%s'", m, expected) - } - case <-time.After(5 * time.Second): - t.Errorf("Read timedout") - } - c.Wait() -} - -func TestExtraFiles(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("no operating system support; skipping") - } - - // Ensure that file descriptors have not already been leaked into - // our environment. - if !testedAlreadyLeaked { - testedAlreadyLeaked = true - closeUnexpectedFds(t, "TestExtraFiles") - } - - // Force network usage, to verify the epoll (or whatever) fd - // doesn't leak to the child, - ln, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer ln.Close() - - // Make sure duplicated fds don't leak to the child. - f, err := ln.(*net.TCPListener).File() - if err != nil { - t.Fatal(err) - } - defer f.Close() - ln2, err := net.FileListener(f) - if err != nil { - t.Fatal(err) - } - defer ln2.Close() - - // Force TLS root certs to be loaded (which might involve - // cgo), to make sure none of that potential C code leaks fds. - ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) - // quiet expected TLS handshake error "remote error: bad certificate" - ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0) - ts.StartTLS() - defer ts.Close() - _, err = http.Get(ts.URL) - if err == nil { - t.Errorf("success trying to fetch %s; want an error", ts.URL) - } - - tf, err := ioutil.TempFile("", "") - if err != nil { - t.Fatalf("TempFile: %v", err) - } - defer os.Remove(tf.Name()) - defer tf.Close() - - const text = "Hello, fd 3!" - _, err = tf.Write([]byte(text)) - if err != nil { - t.Fatalf("Write: %v", err) - } - _, err = tf.Seek(0, os.SEEK_SET) - if err != nil { - t.Fatalf("Seek: %v", err) - } - - c := helperCommand(t, "read3") - var stdout, stderr bytes.Buffer - c.Stdout = &stdout - c.Stderr = &stderr - c.ExtraFiles = []*os.File{tf} - err = c.Run() - if err != nil { - t.Fatalf("Run: %v; stdout %q, stderr %q", err, stdout.Bytes(), stderr.Bytes()) - } - if stdout.String() != text { - t.Errorf("got stdout %q, stderr %q; want %q on stdout", stdout.String(), stderr.String(), text) - } -} - -func TestExtraFilesRace(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("no operating system support; skipping") - } - listen := func() net.Listener { - ln, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - return ln - } - listenerFile := func(ln net.Listener) *os.File { - f, err := ln.(*net.TCPListener).File() - if err != nil { - t.Fatal(err) - } - return f - } - runCommand := func(c *exec.Cmd, out chan<- string) { - bout, err := c.CombinedOutput() - if err != nil { - out <- "ERROR:" + err.Error() - } else { - out <- string(bout) - } - } - - for i := 0; i < 10; i++ { - la := listen() - ca := helperCommand(t, "describefiles") - ca.ExtraFiles = []*os.File{listenerFile(la)} - lb := listen() - cb := helperCommand(t, "describefiles") - cb.ExtraFiles = []*os.File{listenerFile(lb)} - ares := make(chan string) - bres := make(chan string) - go runCommand(ca, ares) - go runCommand(cb, bres) - if got, want := <-ares, fmt.Sprintf("fd3: listener %s\n", la.Addr()); got != want { - t.Errorf("iteration %d, process A got:\n%s\nwant:\n%s\n", i, got, want) - } - if got, want := <-bres, fmt.Sprintf("fd3: listener %s\n", lb.Addr()); got != want { - t.Errorf("iteration %d, process B got:\n%s\nwant:\n%s\n", i, got, want) - } - la.Close() - lb.Close() - for _, f := range ca.ExtraFiles { - f.Close() - } - for _, f := range cb.ExtraFiles { - f.Close() - } - - } -} - -// TestHelperProcess isn't a real test. It's used as a helper process -// for TestParameterRun. -func TestHelperProcess(*testing.T) { - if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" { - return - } - defer os.Exit(0) - - // Determine which command to use to display open files. - ofcmd := "lsof" - switch runtime.GOOS { - case "dragonfly", "freebsd", "netbsd", "openbsd": - ofcmd = "fstat" - case "plan9": - ofcmd = "/bin/cat" - } - - args := os.Args - for len(args) > 0 { - if args[0] == "--" { - args = args[1:] - break - } - args = args[1:] - } - if len(args) == 0 { - fmt.Fprintf(os.Stderr, "No command\n") - os.Exit(2) - } - - cmd, args := args[0], args[1:] - switch cmd { - case "echo": - iargs := []interface{}{} - for _, s := range args { - iargs = append(iargs, s) - } - fmt.Println(iargs...) - case "cat": - if len(args) == 0 { - io.Copy(os.Stdout, os.Stdin) - return - } - exit := 0 - for _, fn := range args { - f, err := os.Open(fn) - if err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - exit = 2 - } else { - defer f.Close() - io.Copy(os.Stdout, f) - } - } - os.Exit(exit) - case "pipetest": - bufr := bufio.NewReader(os.Stdin) - for { - line, _, err := bufr.ReadLine() - if err == io.EOF { - break - } else if err != nil { - os.Exit(1) - } - if bytes.HasPrefix(line, []byte("O:")) { - os.Stdout.Write(line) - os.Stdout.Write([]byte{'\n'}) - } else if bytes.HasPrefix(line, []byte("E:")) { - os.Stderr.Write(line) - os.Stderr.Write([]byte{'\n'}) - } else { - os.Exit(1) - } - } - case "stdinClose": - b, err := ioutil.ReadAll(os.Stdin) - if err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } - if s := string(b); s != stdinCloseTestString { - fmt.Fprintf(os.Stderr, "Error: Read %q, want %q", s, stdinCloseTestString) - os.Exit(1) - } - os.Exit(0) - case "read3": // read fd 3 - fd3 := os.NewFile(3, "fd3") - bs, err := ioutil.ReadAll(fd3) - if err != nil { - fmt.Printf("ReadAll from fd 3: %v", err) - os.Exit(1) - } - switch runtime.GOOS { - case "dragonfly": - // TODO(jsing): Determine why DragonFly is leaking - // file descriptors... - case "darwin": - // TODO(bradfitz): broken? Sometimes. - // http://golang.org/issue/2603 - // Skip this additional part of the test for now. - case "netbsd": - // TODO(jsing): This currently fails on NetBSD due to - // the cloned file descriptors that result from opening - // /dev/urandom. - // http://golang.org/issue/3955 - case "plan9": - // TODO(0intro): Determine why Plan 9 is leaking - // file descriptors. - // http://golang.org/issue/7118 - case "solaris": - // TODO(aram): This fails on Solaris because libc opens - // its own files, as it sees fit. Darwin does the same, - // see: http://golang.org/issue/2603 - default: - // Now verify that there are no other open fds. - var files []*os.File - for wantfd := basefds() + 1; wantfd <= 100; wantfd++ { - f, err := os.Open(os.Args[0]) - if err != nil { - fmt.Printf("error opening file with expected fd %d: %v", wantfd, err) - os.Exit(1) - } - if got := f.Fd(); got != wantfd { - fmt.Printf("leaked parent file. fd = %d; want %d\n", got, wantfd) - var args []string - switch runtime.GOOS { - case "plan9": - args = []string{fmt.Sprintf("/proc/%d/fd", os.Getpid())} - default: - args = []string{"-p", fmt.Sprint(os.Getpid())} - } - out, _ := exec.Command(ofcmd, args...).CombinedOutput() - fmt.Print(string(out)) - os.Exit(1) - } - files = append(files, f) - } - for _, f := range files { - f.Close() - } - } - // Referring to fd3 here ensures that it is not - // garbage collected, and therefore closed, while - // executing the wantfd loop above. It doesn't matter - // what we do with fd3 as long as we refer to it; - // closing it is the easy choice. - fd3.Close() - os.Stdout.Write(bs) - case "exit": - n, _ := strconv.Atoi(args[0]) - os.Exit(n) - case "describefiles": - f := os.NewFile(3, fmt.Sprintf("fd3")) - ln, err := net.FileListener(f) - if err == nil { - fmt.Printf("fd3: listener %s\n", ln.Addr()) - ln.Close() - } - os.Exit(0) - case "extraFilesAndPipes": - n, _ := strconv.Atoi(args[0]) - pipes := make([]*os.File, n) - for i := 0; i < n; i++ { - pipes[i] = os.NewFile(uintptr(3+i), strconv.Itoa(i)) - } - response := "" - for i, r := range pipes { - ch := make(chan string, 1) - go func(c chan string) { - buf := make([]byte, 10) - n, err := r.Read(buf) - if err != nil { - fmt.Fprintf(os.Stderr, "Child: read error: %v on pipe %d\n", err, i) - os.Exit(1) - } - c <- string(buf[:n]) - close(c) - }(ch) - select { - case m := <-ch: - response = response + m - case <-time.After(5 * time.Second): - fmt.Fprintf(os.Stderr, "Child: Timeout reading from pipe: %d\n", i) - os.Exit(1) - } - } - fmt.Fprintf(os.Stderr, "child: %s", response) - os.Exit(0) - case "exec": - cmd := exec.Command(args[1]) - cmd.Dir = args[0] - output, err := cmd.CombinedOutput() - if err != nil { - fmt.Fprintf(os.Stderr, "Child: %s %s", err, string(output)) - os.Exit(1) - } - fmt.Printf("%s", string(output)) - os.Exit(0) - case "lookpath": - p, err := exec.LookPath(args[0]) - if err != nil { - fmt.Fprintf(os.Stderr, "LookPath failed: %v\n", err) - os.Exit(1) - } - fmt.Print(p) - os.Exit(0) - default: - fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd) - os.Exit(2) - } -} diff --git a/src/pkg/os/exec/lp_plan9.go b/src/pkg/os/exec/lp_plan9.go deleted file mode 100644 index 5aa8a54ed..000000000 --- a/src/pkg/os/exec/lp_plan9.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2011 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 exec - -import ( - "errors" - "os" - "strings" -) - -// ErrNotFound is the error resulting if a path search failed to find an executable file. -var ErrNotFound = errors.New("executable file not found in $path") - -func findExecutable(file string) error { - d, err := os.Stat(file) - if err != nil { - return err - } - if m := d.Mode(); !m.IsDir() && m&0111 != 0 { - return nil - } - return os.ErrPermission -} - -// LookPath searches for an executable binary named file -// in the directories named by the path environment variable. -// If file begins with "/", "#", "./", or "../", it is tried -// directly and the path is not consulted. -// The result may be an absolute path or a path relative to the current directory. -func LookPath(file string) (string, error) { - // skip the path lookup for these prefixes - skip := []string{"/", "#", "./", "../"} - - for _, p := range skip { - if strings.HasPrefix(file, p) { - err := findExecutable(file) - if err == nil { - return file, nil - } - return "", &Error{file, err} - } - } - - path := os.Getenv("path") - for _, dir := range strings.Split(path, "\000") { - if err := findExecutable(dir + "/" + file); err == nil { - return dir + "/" + file, nil - } - } - return "", &Error{file, ErrNotFound} -} diff --git a/src/pkg/os/exec/lp_test.go b/src/pkg/os/exec/lp_test.go deleted file mode 100644 index 77d8e848c..000000000 --- a/src/pkg/os/exec/lp_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2011 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 exec - -import ( - "testing" -) - -var nonExistentPaths = []string{ - "some-non-existent-path", - "non-existent-path/slashed", -} - -func TestLookPathNotFound(t *testing.T) { - for _, name := range nonExistentPaths { - path, err := LookPath(name) - if err == nil { - t.Fatalf("LookPath found %q in $PATH", name) - } - if path != "" { - t.Fatalf("LookPath path == %q when err != nil", path) - } - perr, ok := err.(*Error) - if !ok { - t.Fatal("LookPath error is not an exec.Error") - } - if perr.Name != name { - t.Fatalf("want Error name %q, got %q", name, perr.Name) - } - } -} diff --git a/src/pkg/os/exec/lp_unix.go b/src/pkg/os/exec/lp_unix.go deleted file mode 100644 index 3f895d5b3..000000000 --- a/src/pkg/os/exec/lp_unix.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2010 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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris - -package exec - -import ( - "errors" - "os" - "strings" -) - -// ErrNotFound is the error resulting if a path search failed to find an executable file. -var ErrNotFound = errors.New("executable file not found in $PATH") - -func findExecutable(file string) error { - d, err := os.Stat(file) - if err != nil { - return err - } - if m := d.Mode(); !m.IsDir() && m&0111 != 0 { - return nil - } - return os.ErrPermission -} - -// LookPath searches for an executable binary named file -// in the directories named by the PATH environment variable. -// If file contains a slash, it is tried directly and the PATH is not consulted. -// The result may be an absolute path or a path relative to the current directory. -func LookPath(file string) (string, error) { - // NOTE(rsc): I wish we could use the Plan 9 behavior here - // (only bypass the path if file begins with / or ./ or ../) - // but that would not match all the Unix shells. - - if strings.Contains(file, "/") { - err := findExecutable(file) - if err == nil { - return file, nil - } - return "", &Error{file, err} - } - pathenv := os.Getenv("PATH") - if pathenv == "" { - return "", &Error{file, ErrNotFound} - } - for _, dir := range strings.Split(pathenv, ":") { - if dir == "" { - // Unix shell semantics: path element "" means "." - dir = "." - } - path := dir + "/" + file - if err := findExecutable(path); err == nil { - return path, nil - } - } - return "", &Error{file, ErrNotFound} -} diff --git a/src/pkg/os/exec/lp_unix_test.go b/src/pkg/os/exec/lp_unix_test.go deleted file mode 100644 index 051db664a..000000000 --- a/src/pkg/os/exec/lp_unix_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 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. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package exec - -import ( - "io/ioutil" - "os" - "testing" -) - -func TestLookPathUnixEmptyPath(t *testing.T) { - tmp, err := ioutil.TempDir("", "TestLookPathUnixEmptyPath") - if err != nil { - t.Fatal("TempDir failed: ", err) - } - defer os.RemoveAll(tmp) - wd, err := os.Getwd() - if err != nil { - t.Fatal("Getwd failed: ", err) - } - err = os.Chdir(tmp) - if err != nil { - t.Fatal("Chdir failed: ", err) - } - defer os.Chdir(wd) - - f, err := os.OpenFile("exec_me", os.O_CREATE|os.O_EXCL, 0700) - if err != nil { - t.Fatal("OpenFile failed: ", err) - } - err = f.Close() - if err != nil { - t.Fatal("Close failed: ", err) - } - - pathenv := os.Getenv("PATH") - defer os.Setenv("PATH", pathenv) - - err = os.Setenv("PATH", "") - if err != nil { - t.Fatal("Setenv failed: ", err) - } - - path, err := LookPath("exec_me") - if err == nil { - t.Fatal("LookPath found exec_me in empty $PATH") - } - if path != "" { - t.Fatalf("LookPath path == %q when err != nil", path) - } -} diff --git a/src/pkg/os/exec/lp_windows.go b/src/pkg/os/exec/lp_windows.go deleted file mode 100644 index c3efd67e9..000000000 --- a/src/pkg/os/exec/lp_windows.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2010 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 exec - -import ( - "errors" - "os" - "strings" -) - -// ErrNotFound is the error resulting if a path search failed to find an executable file. -var ErrNotFound = errors.New("executable file not found in %PATH%") - -func chkStat(file string) error { - d, err := os.Stat(file) - if err != nil { - return err - } - if d.IsDir() { - return os.ErrPermission - } - return nil -} - -func hasExt(file string) bool { - i := strings.LastIndex(file, ".") - if i < 0 { - return false - } - return strings.LastIndexAny(file, `:\/`) < i -} - -func findExecutable(file string, exts []string) (string, error) { - if len(exts) == 0 { - return file, chkStat(file) - } - if hasExt(file) { - if chkStat(file) == nil { - return file, nil - } - } - for _, e := range exts { - if f := file + e; chkStat(f) == nil { - return f, nil - } - } - return ``, os.ErrNotExist -} - -// LookPath searches for an executable binary named file -// in the directories named by the PATH environment variable. -// If file contains a slash, it is tried directly and the PATH is not consulted. -// LookPath also uses PATHEXT environment variable to match -// a suitable candidate. -// The result may be an absolute path or a path relative to the current directory. -func LookPath(file string) (f string, err error) { - x := os.Getenv(`PATHEXT`) - if x == `` { - x = `.COM;.EXE;.BAT;.CMD` - } - exts := []string{} - for _, e := range strings.Split(strings.ToLower(x), `;`) { - if e == "" { - continue - } - if e[0] != '.' { - e = "." + e - } - exts = append(exts, e) - } - if strings.IndexAny(file, `:\/`) != -1 { - if f, err = findExecutable(file, exts); err == nil { - return - } - return ``, &Error{file, err} - } - if f, err = findExecutable(`.\`+file, exts); err == nil { - return - } - if pathenv := os.Getenv(`PATH`); pathenv != `` { - for _, dir := range splitList(pathenv) { - if f, err = findExecutable(dir+`\`+file, exts); err == nil { - return - } - } - } - return ``, &Error{file, ErrNotFound} -} - -func splitList(path string) []string { - // The same implementation is used in SplitList in path/filepath; - // consider changing path/filepath when changing this. - - if path == "" { - return []string{} - } - - // Split path, respecting but preserving quotes. - list := []string{} - start := 0 - quo := false - for i := 0; i < len(path); i++ { - switch c := path[i]; { - case c == '"': - quo = !quo - case c == os.PathListSeparator && !quo: - list = append(list, path[start:i]) - start = i + 1 - } - } - list = append(list, path[start:]) - - // Remove quotes. - for i, s := range list { - if strings.Contains(s, `"`) { - list[i] = strings.Replace(s, `"`, ``, -1) - } - } - - return list -} diff --git a/src/pkg/os/exec/lp_windows_test.go b/src/pkg/os/exec/lp_windows_test.go deleted file mode 100644 index 72df03ed2..000000000 --- a/src/pkg/os/exec/lp_windows_test.go +++ /dev/null @@ -1,573 +0,0 @@ -// Copyright 2013 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 exec - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - "testing" -) - -func installExe(t *testing.T, dest, src string) { - fsrc, err := os.Open(src) - if err != nil { - t.Fatal("os.Open failed: ", err) - } - defer fsrc.Close() - fdest, err := os.Create(dest) - if err != nil { - t.Fatal("os.Create failed: ", err) - } - defer fdest.Close() - _, err = io.Copy(fdest, fsrc) - if err != nil { - t.Fatal("io.Copy failed: ", err) - } -} - -func installBat(t *testing.T, dest string) { - f, err := os.Create(dest) - if err != nil { - t.Fatalf("failed to create batch file: %v", err) - } - defer f.Close() - fmt.Fprintf(f, "@echo %s\n", dest) -} - -func installProg(t *testing.T, dest, srcExe string) { - err := os.MkdirAll(filepath.Dir(dest), 0700) - if err != nil { - t.Fatal("os.MkdirAll failed: ", err) - } - if strings.ToLower(filepath.Ext(dest)) == ".bat" { - installBat(t, dest) - return - } - installExe(t, dest, srcExe) -} - -type lookPathTest struct { - rootDir string - PATH string - PATHEXT string - files []string - searchFor string - fails bool // test is expected to fail -} - -func (test lookPathTest) runProg(t *testing.T, env []string, args ...string) (string, error) { - cmd := Command(args[0], args[1:]...) - cmd.Env = env - cmd.Dir = test.rootDir - args[0] = filepath.Base(args[0]) - cmdText := fmt.Sprintf("%q command", strings.Join(args, " ")) - out, err := cmd.CombinedOutput() - if (err != nil) != test.fails { - if test.fails { - t.Fatalf("test=%+v: %s succeeded, but expected to fail", test, cmdText) - } - t.Fatalf("test=%+v: %s failed, but expected to succeed: %v - %v", test, cmdText, err, string(out)) - } - if err != nil { - return "", fmt.Errorf("test=%+v: %s failed: %v - %v", test, cmdText, err, string(out)) - } - // normalise program output - p := string(out) - // trim terminating \r and \n that batch file outputs - for len(p) > 0 && (p[len(p)-1] == '\n' || p[len(p)-1] == '\r') { - p = p[:len(p)-1] - } - if !filepath.IsAbs(p) { - return p, nil - } - if p[:len(test.rootDir)] != test.rootDir { - t.Fatalf("test=%+v: %s output is wrong: %q must have %q prefix", test, cmdText, p, test.rootDir) - } - return p[len(test.rootDir)+1:], nil -} - -func updateEnv(env []string, name, value string) []string { - for i, e := range env { - if strings.HasPrefix(strings.ToUpper(e), name+"=") { - env[i] = name + "=" + value - return env - } - } - return append(env, name+"="+value) -} - -func createEnv(dir, PATH, PATHEXT string) []string { - env := os.Environ() - env = updateEnv(env, "PATHEXT", PATHEXT) - // Add dir in front of every directory in the PATH. - dirs := splitList(PATH) - for i := range dirs { - dirs[i] = filepath.Join(dir, dirs[i]) - } - path := strings.Join(dirs, ";") - env = updateEnv(env, "PATH", path) - return env -} - -// createFiles copies srcPath file into multiply files. -// It uses dir as preifx for all destination files. -func createFiles(t *testing.T, dir string, files []string, srcPath string) { - for _, f := range files { - installProg(t, filepath.Join(dir, f), srcPath) - } -} - -func (test lookPathTest) run(t *testing.T, tmpdir, printpathExe string) { - test.rootDir = tmpdir - createFiles(t, test.rootDir, test.files, printpathExe) - env := createEnv(test.rootDir, test.PATH, test.PATHEXT) - // Run "cmd.exe /c test.searchFor" with new environment and - // work directory set. All candidates are copies of printpath.exe. - // These will output their program paths when run. - should, errCmd := test.runProg(t, env, "cmd", "/c", test.searchFor) - // Run the lookpath program with new environment and work directory set. - env = append(env, "GO_WANT_HELPER_PROCESS=1") - have, errLP := test.runProg(t, env, os.Args[0], "-test.run=TestHelperProcess", "--", "lookpath", test.searchFor) - // Compare results. - if errCmd == nil && errLP == nil { - // both succeeded - if should != have { - t.Fatalf("test=%+v failed: expected to find %q, but found %q", test, should, have) - } - return - } - if errCmd != nil && errLP != nil { - // both failed -> continue - return - } - if errCmd != nil { - t.Fatal(errCmd) - } - if errLP != nil { - t.Fatal(errLP) - } -} - -var lookPathTests = []lookPathTest{ - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`, `p2\a`}, - searchFor: `a`, - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1.dir;p2.dir`, - files: []string{`p1.dir\a`, `p2.dir\a.exe`}, - searchFor: `a`, - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`}, - searchFor: `a.exe`, - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\b.exe`}, - searchFor: `b`, - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\b`, `p2\a`}, - searchFor: `a`, - fails: true, // TODO(brainman): do not know why this fails - }, - // If the command name specifies a path, the shell searches - // the specified path for an executable file matching - // the command name. If a match is found, the external - // command (the executable file) executes. - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`}, - searchFor: `p2\a`, - }, - // If the command name specifies a path, the shell searches - // the specified path for an executable file matching the command - // name. ... If no match is found, the shell reports an error - // and command processing completes. - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\b.exe`, `p2\a.exe`}, - searchFor: `p2\b`, - fails: true, - }, - // If the command name does not specify a path, the shell - // searches the current directory for an executable file - // matching the command name. If a match is found, the external - // command (the executable file) executes. - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`a`, `p1\a.exe`, `p2\a.exe`}, - searchFor: `a`, - }, - // The shell now searches each directory specified by the - // PATH environment variable, in the order listed, for an - // executable file matching the command name. If a match - // is found, the external command (the executable file) executes. - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`}, - searchFor: `a`, - }, - // The shell now searches each directory specified by the - // PATH environment variable, in the order listed, for an - // executable file matching the command name. If no match - // is found, the shell reports an error and command processing - // completes. - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`}, - searchFor: `b`, - fails: true, - }, - // If the command name includes a file extension, the shell - // searches each directory for the exact file name specified - // by the command name. - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`}, - searchFor: `a.exe`, - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`}, - searchFor: `a.com`, - fails: true, // includes extension and not exact file name match - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1`, - files: []string{`p1\a.exe.exe`}, - searchFor: `a.exe`, - }, - { - PATHEXT: `.COM;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.exe`, `p2\a.exe`}, - searchFor: `a.exe`, - }, - // If the command name does not include a file extension, the shell - // adds the extensions listed in the PATHEXT environment variable, - // one by one, and searches the directory for that file name. Note - // that the shell tries all possible file extensions in a specific - // directory before moving on to search the next directory - // (if there is one). - { - PATHEXT: `.COM;.EXE`, - PATH: `p1;p2`, - files: []string{`p1\a.bat`, `p2\a.exe`}, - searchFor: `a`, - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.bat`, `p2\a.exe`}, - searchFor: `a`, - }, - { - PATHEXT: `.COM;.EXE;.BAT`, - PATH: `p1;p2`, - files: []string{`p1\a.bat`, `p1\a.exe`, `p2\a.bat`, `p2\a.exe`}, - searchFor: `a`, - }, - { - PATHEXT: `.COM`, - PATH: `p1;p2`, - files: []string{`p1\a.bat`, `p2\a.exe`}, - searchFor: `a`, - fails: true, // tried all extensions in PATHEXT, but none matches - }, -} - -func TestLookPath(t *testing.T) { - tmp, err := ioutil.TempDir("", "TestLookPath") - if err != nil { - t.Fatal("TempDir failed: ", err) - } - defer os.RemoveAll(tmp) - - printpathExe := buildPrintPathExe(t, tmp) - - // Run all tests. - for i, test := range lookPathTests { - dir := filepath.Join(tmp, "d"+strconv.Itoa(i)) - err := os.Mkdir(dir, 0700) - if err != nil { - t.Fatal("Mkdir failed: ", err) - } - test.run(t, dir, printpathExe) - } -} - -type commandTest struct { - PATH string - files []string - dir string - arg0 string - want string - fails bool // test is expected to fail -} - -func (test commandTest) isSuccess(rootDir, output string, err error) error { - if err != nil { - return fmt.Errorf("test=%+v: exec: %v %v", test, err, output) - } - path := output - if path[:len(rootDir)] != rootDir { - return fmt.Errorf("test=%+v: %q must have %q prefix", test, path, rootDir) - } - path = path[len(rootDir)+1:] - if path != test.want { - return fmt.Errorf("test=%+v: want %q, got %q", test, test.want, path) - } - return nil -} - -func (test commandTest) runOne(rootDir string, env []string, dir, arg0 string) error { - cmd := Command(os.Args[0], "-test.run=TestHelperProcess", "--", "exec", dir, arg0) - cmd.Dir = rootDir - cmd.Env = env - output, err := cmd.CombinedOutput() - err = test.isSuccess(rootDir, string(output), err) - if (err != nil) != test.fails { - if test.fails { - return fmt.Errorf("test=%+v: succeeded, but expected to fail", test) - } - return err - } - return nil -} - -func (test commandTest) run(t *testing.T, rootDir, printpathExe string) { - createFiles(t, rootDir, test.files, printpathExe) - PATHEXT := `.COM;.EXE;.BAT` - env := createEnv(rootDir, test.PATH, PATHEXT) - env = append(env, "GO_WANT_HELPER_PROCESS=1") - err := test.runOne(rootDir, env, test.dir, test.arg0) - if err != nil { - t.Error(err) - } -} - -var commandTests = []commandTest{ - // testing commands with no slash, like `a.exe` - { - // should find a.exe in current directory - files: []string{`a.exe`}, - arg0: `a.exe`, - want: `a.exe`, - }, - { - // like above, but add PATH in attempt to break the test - PATH: `p2;p`, - files: []string{`a.exe`, `p\a.exe`, `p2\a.exe`}, - arg0: `a.exe`, - want: `a.exe`, - }, - { - // like above, but use "a" instead of "a.exe" for command - PATH: `p2;p`, - files: []string{`a.exe`, `p\a.exe`, `p2\a.exe`}, - arg0: `a`, - want: `a.exe`, - }, - // testing commands with slash, like `.\a.exe` - { - // should find p\a.exe - files: []string{`p\a.exe`}, - arg0: `p\a.exe`, - want: `p\a.exe`, - }, - { - // like above, but adding `.` in front of executable should still be OK - files: []string{`p\a.exe`}, - arg0: `.\p\a.exe`, - want: `p\a.exe`, - }, - { - // like above, but with PATH added in attempt to break it - PATH: `p2`, - files: []string{`p\a.exe`, `p2\a.exe`}, - arg0: `p\a.exe`, - want: `p\a.exe`, - }, - { - // like above, but make sure .exe is tried even for commands with slash - PATH: `p2`, - files: []string{`p\a.exe`, `p2\a.exe`}, - arg0: `p\a`, - want: `p\a.exe`, - }, - // tests commands, like `a.exe`, with c.Dir set - { - // should not find a.exe in p, becasue LookPath(`a.exe`) will fail - files: []string{`p\a.exe`}, - dir: `p`, - arg0: `a.exe`, - want: `p\a.exe`, - fails: true, - }, - { - // LookPath(`a.exe`) will find `.\a.exe`, but prefixing that with - // dir `p\a.exe` will refer to not existant file - files: []string{`a.exe`, `p\not_important_file`}, - dir: `p`, - arg0: `a.exe`, - want: `a.exe`, - fails: true, - }, - { - // like above, but making test succeed by installing file - // in refered destination (so LookPath(`a.exe`) will still - // find `.\a.exe`, but we successfully execute `p\a.exe`) - files: []string{`a.exe`, `p\a.exe`}, - dir: `p`, - arg0: `a.exe`, - want: `p\a.exe`, - }, - { - // like above, but add PATH in attempt to break the test - PATH: `p2;p`, - files: []string{`a.exe`, `p\a.exe`, `p2\a.exe`}, - dir: `p`, - arg0: `a.exe`, - want: `p\a.exe`, - }, - { - // like above, but use "a" instead of "a.exe" for command - PATH: `p2;p`, - files: []string{`a.exe`, `p\a.exe`, `p2\a.exe`}, - dir: `p`, - arg0: `a`, - want: `p\a.exe`, - }, - { - // finds `a.exe` in the PATH regardless of dir set - // because LookPath returns full path in that case - PATH: `p2;p`, - files: []string{`p\a.exe`, `p2\a.exe`}, - dir: `p`, - arg0: `a.exe`, - want: `p2\a.exe`, - }, - // tests commands, like `.\a.exe`, with c.Dir set - { - // should use dir when command is path, like ".\a.exe" - files: []string{`p\a.exe`}, - dir: `p`, - arg0: `.\a.exe`, - want: `p\a.exe`, - }, - { - // like above, but with PATH added in attempt to break it - PATH: `p2`, - files: []string{`p\a.exe`, `p2\a.exe`}, - dir: `p`, - arg0: `.\a.exe`, - want: `p\a.exe`, - }, - { - // like above, but make sure .exe is tried even for commands with slash - PATH: `p2`, - files: []string{`p\a.exe`, `p2\a.exe`}, - dir: `p`, - arg0: `.\a`, - want: `p\a.exe`, - }, -} - -func TestCommand(t *testing.T) { - tmp, err := ioutil.TempDir("", "TestCommand") - if err != nil { - t.Fatal("TempDir failed: ", err) - } - defer os.RemoveAll(tmp) - - printpathExe := buildPrintPathExe(t, tmp) - - // Run all tests. - for i, test := range commandTests { - dir := filepath.Join(tmp, "d"+strconv.Itoa(i)) - err := os.Mkdir(dir, 0700) - if err != nil { - t.Fatal("Mkdir failed: ", err) - } - test.run(t, dir, printpathExe) - } -} - -// buildPrintPathExe creates a Go program that prints its own path. -// dir is a temp directory where executable will be created. -// The function returns full path to the created program. -func buildPrintPathExe(t *testing.T, dir string) string { - const name = "printpath" - srcname := name + ".go" - err := ioutil.WriteFile(filepath.Join(dir, srcname), []byte(printpathSrc), 0644) - if err != nil { - t.Fatalf("failed to create source: %v", err) - } - if err != nil { - t.Fatalf("failed to execute template: %v", err) - } - outname := name + ".exe" - cmd := Command("go", "build", "-o", outname, srcname) - cmd.Dir = dir - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("failed to build executable: %v - %v", err, string(out)) - } - return filepath.Join(dir, outname) -} - -const printpathSrc = ` -package main - -import ( - "os" - "syscall" - "unicode/utf16" - "unsafe" -) - -func getMyName() (string, error) { - var sysproc = syscall.MustLoadDLL("kernel32.dll").MustFindProc("GetModuleFileNameW") - b := make([]uint16, syscall.MAX_PATH) - r, _, err := sysproc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))) - n := uint32(r) - if n == 0 { - return "", err - } - return string(utf16.Decode(b[0:n])), nil -} - -func main() { - path, err := getMyName() - if err != nil { - os.Stderr.Write([]byte("getMyName failed: " + err.Error() + "\n")) - os.Exit(1) - } - os.Stdout.Write([]byte(path)) -} -` diff --git a/src/pkg/os/exec_plan9.go b/src/pkg/os/exec_plan9.go deleted file mode 100644 index 676be36ac..000000000 --- a/src/pkg/os/exec_plan9.go +++ /dev/null @@ -1,137 +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 - -import ( - "errors" - "runtime" - "syscall" - "time" -) - -// The only signal values guaranteed to be present on all systems -// are Interrupt (send the process an interrupt) and Kill (force -// the process to exit). -var ( - Interrupt Signal = syscall.Note("interrupt") - Kill Signal = syscall.Note("kill") -) - -func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { - sysattr := &syscall.ProcAttr{ - Dir: attr.Dir, - Env: attr.Env, - Sys: attr.Sys, - } - - for _, f := range attr.Files { - sysattr.Files = append(sysattr.Files, f.Fd()) - } - - pid, h, e := syscall.StartProcess(name, argv, sysattr) - if e != nil { - return nil, &PathError{"fork/exec", name, e} - } - - return newProcess(pid, h), nil -} - -func (p *Process) writeProcFile(file string, data string) error { - f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0) - if e != nil { - return e - } - defer f.Close() - _, e = f.Write([]byte(data)) - return e -} - -func (p *Process) signal(sig Signal) error { - if p.done() { - return errors.New("os: process already finished") - } - if e := p.writeProcFile("note", sig.String()); e != nil { - return NewSyscallError("signal", e) - } - return nil -} - -func (p *Process) kill() error { - return p.signal(Kill) -} - -func (p *Process) wait() (ps *ProcessState, err error) { - var waitmsg syscall.Waitmsg - - if p.Pid == -1 { - return nil, ErrInvalid - } - err = syscall.WaitProcess(p.Pid, &waitmsg) - if err != nil { - return nil, NewSyscallError("wait", err) - } - - p.setDone() - ps = &ProcessState{ - pid: waitmsg.Pid, - status: &waitmsg, - } - return ps, nil -} - -func (p *Process) release() error { - // NOOP for Plan 9. - p.Pid = -1 - // no need for a finalizer anymore - runtime.SetFinalizer(p, nil) - return nil -} - -func findProcess(pid int) (p *Process, err error) { - // NOOP for Plan 9. - return newProcess(pid, 0), nil -} - -// ProcessState stores information about a process, as reported by Wait. -type ProcessState struct { - pid int // The process's id. - status *syscall.Waitmsg // System-dependent status info. -} - -// Pid returns the process id of the exited process. -func (p *ProcessState) Pid() int { - return p.pid -} - -func (p *ProcessState) exited() bool { - return p.status.Exited() -} - -func (p *ProcessState) success() bool { - return p.status.ExitStatus() == 0 -} - -func (p *ProcessState) sys() interface{} { - return p.status -} - -func (p *ProcessState) sysUsage() interface{} { - return p.status -} - -func (p *ProcessState) userTime() time.Duration { - return time.Duration(p.status.Time[0]) * time.Millisecond -} - -func (p *ProcessState) systemTime() time.Duration { - return time.Duration(p.status.Time[1]) * time.Millisecond -} - -func (p *ProcessState) String() string { - if p == nil { - return "<nil>" - } - return "exit status: " + p.status.Msg -} diff --git a/src/pkg/os/exec_posix.go b/src/pkg/os/exec_posix.go deleted file mode 100644 index fb9d291e6..000000000 --- a/src/pkg/os/exec_posix.go +++ /dev/null @@ -1,134 +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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows - -package os - -import ( - "syscall" -) - -// The only signal values guaranteed to be present on all systems -// are Interrupt (send the process an interrupt) and Kill (force -// the process to exit). -var ( - Interrupt Signal = syscall.SIGINT - Kill Signal = syscall.SIGKILL -) - -func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { - // If there is no SysProcAttr (ie. no Chroot or changed - // UID/GID), double-check existence of the directory we want - // to chdir into. We can make the error clearer this way. - if attr != nil && attr.Sys == nil && attr.Dir != "" { - if _, err := Stat(attr.Dir); err != nil { - pe := err.(*PathError) - pe.Op = "chdir" - return nil, pe - } - } - - sysattr := &syscall.ProcAttr{ - Dir: attr.Dir, - Env: attr.Env, - Sys: attr.Sys, - } - if sysattr.Env == nil { - sysattr.Env = Environ() - } - for _, f := range attr.Files { - sysattr.Files = append(sysattr.Files, f.Fd()) - } - - pid, h, e := syscall.StartProcess(name, argv, sysattr) - if e != nil { - return nil, &PathError{"fork/exec", name, e} - } - return newProcess(pid, h), nil -} - -func (p *Process) kill() error { - return p.Signal(Kill) -} - -// ProcessState stores information about a process, as reported by Wait. -type ProcessState struct { - pid int // The process's id. - status syscall.WaitStatus // System-dependent status info. - rusage *syscall.Rusage -} - -// Pid returns the process id of the exited process. -func (p *ProcessState) Pid() int { - return p.pid -} - -func (p *ProcessState) exited() bool { - return p.status.Exited() -} - -func (p *ProcessState) success() bool { - return p.status.ExitStatus() == 0 -} - -func (p *ProcessState) sys() interface{} { - return p.status -} - -func (p *ProcessState) sysUsage() interface{} { - return p.rusage -} - -// Convert i to decimal string. -func itod(i int) string { - if i == 0 { - return "0" - } - - u := uint64(i) - if i < 0 { - u = -u - } - - // Assemble decimal in reverse order. - var b [32]byte - bp := len(b) - for ; u > 0; u /= 10 { - bp-- - b[bp] = byte(u%10) + '0' - } - - if i < 0 { - bp-- - b[bp] = '-' - } - - return string(b[bp:]) -} - -func (p *ProcessState) String() string { - if p == nil { - return "<nil>" - } - status := p.Sys().(syscall.WaitStatus) - res := "" - switch { - case status.Exited(): - res = "exit status " + itod(status.ExitStatus()) - case status.Signaled(): - res = "signal: " + status.Signal().String() - case status.Stopped(): - res = "stop signal: " + status.StopSignal().String() - if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 { - res += " (trap " + itod(status.TrapCause()) + ")" - } - case status.Continued(): - res = "continued" - } - if status.CoreDump() { - res += " (core dumped)" - } - return res -} diff --git a/src/pkg/os/exec_unix.go b/src/pkg/os/exec_unix.go deleted file mode 100644 index 1b1e3350b..000000000 --- a/src/pkg/os/exec_unix.go +++ /dev/null @@ -1,73 +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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris - -package os - -import ( - "errors" - "runtime" - "syscall" - "time" -) - -func (p *Process) wait() (ps *ProcessState, err error) { - if p.Pid == -1 { - return nil, syscall.EINVAL - } - var status syscall.WaitStatus - var rusage syscall.Rusage - pid1, e := syscall.Wait4(p.Pid, &status, 0, &rusage) - if e != nil { - return nil, NewSyscallError("wait", e) - } - if pid1 != 0 { - p.setDone() - } - ps = &ProcessState{ - pid: pid1, - status: status, - rusage: &rusage, - } - return ps, nil -} - -func (p *Process) signal(sig Signal) error { - if p.done() { - return errors.New("os: process already finished") - } - if p.Pid == -1 { - return errors.New("os: process already released") - } - s, ok := sig.(syscall.Signal) - if !ok { - return errors.New("os: unsupported signal type") - } - if e := syscall.Kill(p.Pid, s); e != nil { - return e - } - return nil -} - -func (p *Process) release() error { - // NOOP for unix. - p.Pid = -1 - // no need for a finalizer anymore - runtime.SetFinalizer(p, nil) - return nil -} - -func findProcess(pid int) (p *Process, err error) { - // NOOP for unix. - return newProcess(pid, 0), nil -} - -func (p *ProcessState) userTime() time.Duration { - return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond -} - -func (p *ProcessState) systemTime() time.Duration { - return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond -} diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go deleted file mode 100644 index c4f3d4f85..000000000 --- a/src/pkg/os/exec_windows.go +++ /dev/null @@ -1,115 +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 - -import ( - "errors" - "runtime" - "syscall" - "time" - "unsafe" -) - -func (p *Process) wait() (ps *ProcessState, err error) { - s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE) - switch s { - case syscall.WAIT_OBJECT_0: - break - case syscall.WAIT_FAILED: - return nil, NewSyscallError("WaitForSingleObject", e) - default: - return nil, errors.New("os: unexpected result from WaitForSingleObject") - } - var ec uint32 - e = syscall.GetExitCodeProcess(syscall.Handle(p.handle), &ec) - if e != nil { - return nil, NewSyscallError("GetExitCodeProcess", e) - } - var u syscall.Rusage - e = syscall.GetProcessTimes(syscall.Handle(p.handle), &u.CreationTime, &u.ExitTime, &u.KernelTime, &u.UserTime) - if e != nil { - return nil, NewSyscallError("GetProcessTimes", e) - } - p.setDone() - // NOTE(brainman): It seems that sometimes process is not dead - // when WaitForSingleObject returns. But we do not know any - // other way to wait for it. Sleeping for a while seems to do - // the trick sometimes. So we will sleep and smell the roses. - defer time.Sleep(5 * time.Millisecond) - defer p.Release() - return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil -} - -func terminateProcess(pid, exitcode int) error { - h, e := syscall.OpenProcess(syscall.PROCESS_TERMINATE, false, uint32(pid)) - if e != nil { - return NewSyscallError("OpenProcess", e) - } - defer syscall.CloseHandle(h) - e = syscall.TerminateProcess(h, uint32(exitcode)) - return NewSyscallError("TerminateProcess", e) -} - -func (p *Process) signal(sig Signal) error { - if p.done() { - return errors.New("os: process already finished") - } - if sig == Kill { - return terminateProcess(p.Pid, 1) - } - // TODO(rsc): Handle Interrupt too? - return syscall.Errno(syscall.EWINDOWS) -} - -func (p *Process) release() error { - if p.handle == uintptr(syscall.InvalidHandle) { - return syscall.EINVAL - } - e := syscall.CloseHandle(syscall.Handle(p.handle)) - if e != nil { - return NewSyscallError("CloseHandle", e) - } - p.handle = uintptr(syscall.InvalidHandle) - // no need for a finalizer anymore - runtime.SetFinalizer(p, nil) - return nil -} - -func findProcess(pid int) (p *Process, err error) { - const da = syscall.STANDARD_RIGHTS_READ | - syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE - h, e := syscall.OpenProcess(da, false, uint32(pid)) - if e != nil { - return nil, NewSyscallError("OpenProcess", e) - } - return newProcess(pid, uintptr(h)), nil -} - -func init() { - var argc int32 - cmd := syscall.GetCommandLine() - argv, e := syscall.CommandLineToArgv(cmd, &argc) - if e != nil { - return - } - defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv)))) - Args = make([]string, argc) - for i, v := range (*argv)[:argc] { - Args[i] = string(syscall.UTF16ToString((*v)[:])) - } -} - -func ftToDuration(ft *syscall.Filetime) time.Duration { - n := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime) // in 100-nanosecond intervals - return time.Duration(n*100) * time.Nanosecond -} - -func (p *ProcessState) userTime() time.Duration { - return ftToDuration(&p.rusage.UserTime) -} - -func (p *ProcessState) systemTime() time.Duration { - return ftToDuration(&p.rusage.KernelTime) -} diff --git a/src/pkg/os/export_test.go b/src/pkg/os/export_test.go deleted file mode 100644 index 9fa7936ae..000000000 --- a/src/pkg/os/export_test.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2011 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 - -// Export for testing. - -var Atime = atime -var LstatP = &lstat diff --git a/src/pkg/os/file.go b/src/pkg/os/file.go deleted file mode 100644 index b4a745801..000000000 --- a/src/pkg/os/file.go +++ /dev/null @@ -1,257 +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]) -// -package os - -import ( - "io" - "syscall" -) - -// Name returns the name of the file as presented to Open. -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. -var ( - Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin") - Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout") - Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr") -) - -// Flags to Open wrapping those of the underlying system. Not all flags -// may be implemented on a given system. -const ( - 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. - 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 // if possible, truncate file when opened. -) - -// Seek whence values. -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() -} - -// Read reads up to len(b) bytes from the File. -// It returns the number of bytes read and an error, if any. -// EOF is signaled by a zero count with err set to io.EOF. -func (f *File) Read(b []byte) (n int, err error) { - if f == nil { - return 0, ErrInvalid - } - n, e := f.read(b) - if n < 0 { - n = 0 - } - if n == 0 && len(b) > 0 && e == nil { - return 0, io.EOF - } - if e != nil { - err = &PathError{"read", f.name, e} - } - return n, err -} - -// 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 f == nil { - return 0, ErrInvalid - } - for len(b) > 0 { - m, e := f.pread(b, off) - if m == 0 && e == nil { - return n, io.EOF - } - if e != nil { - err = &PathError{"read", f.name, e} - break - } - n += m - b = b[m:] - off += int64(m) - } - return -} - -// 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 (f *File) Write(b []byte) (n int, err error) { - if f == nil { - return 0, ErrInvalid - } - n, e := f.write(b) - if n < 0 { - n = 0 - } - if n != len(b) { - err = io.ErrShortWrite - } - - epipecheck(f, e) - - if e != nil { - err = &PathError{"write", f.name, e} - } - return n, err -} - -// 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). -func (f *File) WriteAt(b []byte, off int64) (n int, err error) { - if f == nil { - return 0, ErrInvalid - } - for len(b) > 0 { - m, e := f.pwrite(b, off) - if e != nil { - err = &PathError{"write", f.name, e} - break - } - n += m - b = b[m:] - off += int64(m) - } - 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. -func (f *File) Seek(offset int64, whence int) (ret int64, err error) { - if f == nil { - return 0, ErrInvalid - } - r, e := f.seek(offset, whence) - if e == nil && f.dirinfo != nil && r != 0 { - e = syscall.EISDIR - } - if e != nil { - return 0, &PathError{"seek", f.name, 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) (ret int, err error) { - if f == nil { - return 0, ErrInvalid - } - return f.Write([]byte(s)) -} - -// Mkdir creates a new directory with the specified name and permission bits. -// If there is an error, it will be of type *PathError. -func Mkdir(name string, perm FileMode) error { - e := syscall.Mkdir(name, syscallMode(perm)) - if e != nil { - return &PathError{"mkdir", name, e} - } - return nil -} - -// 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 { - return &PathError{"chdir", dir, e} - } - return nil -} - -// Chdir changes the current working directory to the file, -// which must be a directory. -// If there is an error, it will be of type *PathError. -func (f *File) Chdir() error { - if f == nil { - return ErrInvalid - } - if e := syscall.Fchdir(f.fd); e != nil { - return &PathError{"chdir", f.name, e} - } - 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 *File, err error) { - return OpenFile(name, O_RDONLY, 0) -} - -// Create creates the named file 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. -// If there is an error, it will be of type *PathError. -func Create(name string) (file *File, err error) { - return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666) -} - -// lstat is overridden in tests. -var lstat = Lstat - -// Rename renames (moves) a file. OS-specific restrictions might apply. -func Rename(oldpath, newpath string) error { - return rename(oldpath, newpath) -} diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go deleted file mode 100644 index a804b8197..000000000 --- a/src/pkg/os/file_plan9.go +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright 2011 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 - -import ( - "runtime" - "syscall" - "time" -) - -// File represents an open file descriptor. -type File struct { - *file -} - -// file is the real representation of *File. -// The extra level of indirection ensures that no clients of os -// can overwrite this data, which could cause the finalizer -// to close the wrong file descriptor. -type file struct { - fd int - name string - dirinfo *dirInfo // nil unless directory being read -} - -// Fd returns the integer Unix file descriptor referencing the open file. -func (f *File) Fd() uintptr { - if f == nil { - return ^(uintptr(0)) - } - return uintptr(f.fd) -} - -// NewFile returns a new File with the given file descriptor and name. -func NewFile(fd uintptr, name string) *File { - fdi := int(fd) - if fdi < 0 { - return nil - } - f := &File{&file{fd: fdi, name: name}} - runtime.SetFinalizer(f.file, (*file).close) - return f -} - -// Auxiliary information if the File describes a directory -type dirInfo struct { - buf [syscall.STATMAX]byte // buffer for directory I/O - nbuf int // length of buf; return value from Read - bufp int // location of next record in buf. -} - -func epipecheck(file *File, e error) { -} - -// DevNull is the name of the operating system's ``null device.'' -// On Unix-like systems, it is "/dev/null"; on Windows, "NUL". -const DevNull = "/dev/null" - -// syscallMode returns the syscall-specific mode bits from Go's portable mode bits. -func syscallMode(i FileMode) (o uint32) { - o |= uint32(i.Perm()) - if i&ModeAppend != 0 { - o |= syscall.DMAPPEND - } - if i&ModeExclusive != 0 { - o |= syscall.DMEXCL - } - if i&ModeTemporary != 0 { - o |= syscall.DMTMP - } - return -} - -// 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, (0666 etc.) if applicable. 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 *File, err error) { - var ( - fd int - e error - create bool - excl bool - trunc bool - append bool - ) - - if flag&O_CREATE == O_CREATE { - flag = flag & ^O_CREATE - create = true - } - if flag&O_EXCL == O_EXCL { - excl = true - } - if flag&O_TRUNC == O_TRUNC { - trunc = true - } - // O_APPEND is emulated on Plan 9 - if flag&O_APPEND == O_APPEND { - flag = flag &^ O_APPEND - append = true - } - - if (create && trunc) || excl { - fd, e = syscall.Create(name, flag, syscallMode(perm)) - } else { - fd, e = syscall.Open(name, flag) - if e != nil && create { - var e1 error - fd, e1 = syscall.Create(name, flag, syscallMode(perm)) - if e1 == nil { - e = nil - } - } - } - - if e != nil { - return nil, &PathError{"open", name, e} - } - - if append { - if _, e = syscall.Seek(fd, 0, SEEK_END); e != nil { - return nil, &PathError{"seek", name, e} - } - } - - return NewFile(uintptr(fd), name), nil -} - -// Close closes the File, rendering it unusable for I/O. -// It returns an error, if any. -func (f *File) Close() error { - if f == nil { - return ErrInvalid - } - return f.file.close() -} - -func (file *file) close() error { - if file == nil || file.fd < 0 { - return ErrInvalid - } - var err error - syscall.ForkLock.RLock() - if e := syscall.Close(file.fd); e != nil { - err = &PathError{"close", file.name, e} - } - syscall.ForkLock.RUnlock() - file.fd = -1 // so it can't be closed again - - // no need for a finalizer anymore - runtime.SetFinalizer(file, nil) - return err -} - -// Stat returns the FileInfo structure describing file. -// If there is an error, it will be of type *PathError. -func (f *File) Stat() (fi FileInfo, err error) { - if f == nil { - return nil, ErrInvalid - } - d, err := dirstat(f) - if err != nil { - return nil, err - } - return fileInfoFromStat(d), nil -} - -// Truncate changes the size of the file. -// It does not change the I/O offset. -// If there is an error, it will be of type *PathError. -func (f *File) Truncate(size int64) error { - if f == nil { - return ErrInvalid - } - - var d syscall.Dir - d.Null() - d.Length = size - - var buf [syscall.STATFIXLEN]byte - n, err := d.Marshal(buf[:]) - if err != nil { - return &PathError{"truncate", f.name, err} - } - if err = syscall.Fwstat(f.fd, buf[:n]); err != nil { - return &PathError{"truncate", f.name, err} - } - return nil -} - -const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm) - -// 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 { - if f == nil { - return ErrInvalid - } - var d syscall.Dir - - odir, e := dirstat(f) - if e != nil { - return &PathError{"chmod", f.name, e} - } - d.Null() - d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask - - var buf [syscall.STATFIXLEN]byte - n, err := d.Marshal(buf[:]) - if err != nil { - return &PathError{"chmod", f.name, err} - } - if err = syscall.Fwstat(f.fd, buf[:n]); err != nil { - return &PathError{"chmod", f.name, err} - } - return nil -} - -// Sync commits the current contents of the file to stable storage. -// Typically, this means flushing the file system's in-memory copy -// of recently written data to disk. -func (f *File) Sync() (err error) { - if f == nil { - return ErrInvalid - } - var d syscall.Dir - d.Null() - - var buf [syscall.STATFIXLEN]byte - n, err := d.Marshal(buf[:]) - if err != nil { - return NewSyscallError("fsync", err) - } - if err = syscall.Fwstat(f.fd, buf[:n]); err != nil { - return NewSyscallError("fsync", err) - } - return nil -} - -// read reads up to len(b) bytes from the File. -// It returns the number of bytes read and an error, if any. -func (f *File) read(b []byte) (n int, err error) { - return syscall.Read(f.fd, b) -} - -// pread reads len(b) bytes from the File starting at byte offset off. -// It returns the number of bytes read and the error, if any. -// EOF is signaled by a zero count with err set to nil. -func (f *File) pread(b []byte, off int64) (n int, err error) { - return syscall.Pread(f.fd, b, off) -} - -// write writes len(b) bytes to the File. -// It returns the number of bytes written and an error, if any. -// Since Plan 9 preserves message boundaries, never allow -// a zero-byte write. -func (f *File) write(b []byte) (n int, err error) { - if len(b) == 0 { - return 0, nil - } - return syscall.Write(f.fd, b) -} - -// pwrite writes len(b) bytes to the File starting at byte offset off. -// It returns the number of bytes written and an error, if any. -// Since Plan 9 preserves message boundaries, never allow -// a zero-byte write. -func (f *File) pwrite(b []byte, off int64) (n int, err error) { - if len(b) == 0 { - return 0, nil - } - return syscall.Pwrite(f.fd, b, off) -} - -// 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. -func (f *File) seek(offset int64, whence int) (ret int64, err error) { - return syscall.Seek(f.fd, offset, whence) -} - -// Truncate changes the size of the named file. -// If the file is a symbolic link, it changes the size of the link's target. -// If there is an error, it will be of type *PathError. -func Truncate(name string, size int64) error { - var d syscall.Dir - - d.Null() - d.Length = size - - var buf [syscall.STATFIXLEN]byte - n, err := d.Marshal(buf[:]) - if err != nil { - return &PathError{"truncate", name, err} - } - if err = syscall.Wstat(name, buf[:n]); err != nil { - return &PathError{"truncate", name, err} - } - return nil -} - -// Remove removes the named file or directory. -// If there is an error, it will be of type *PathError. -func Remove(name string) error { - if e := syscall.Remove(name); e != nil { - return &PathError{"remove", name, e} - } - return nil -} - -// HasPrefix from the strings package. -func hasPrefix(s, prefix string) bool { - return len(s) >= len(prefix) && s[0:len(prefix)] == prefix -} - -// Variant of LastIndex from the strings package. -func lastIndex(s string, sep byte) int { - for i := len(s) - 1; i >= 0; i-- { - if s[i] == sep { - return i - } - } - return -1 -} - -func rename(oldname, newname string) error { - dirname := oldname[:lastIndex(oldname, '/')+1] - if hasPrefix(newname, dirname) { - newname = newname[len(dirname):] - } else { - return &LinkError{"rename", oldname, newname, ErrInvalid} - } - - // If newname still contains slashes after removing the oldname - // prefix, the rename is cross-directory and must be rejected. - // This case is caught by d.Marshal below. - - var d syscall.Dir - - d.Null() - d.Name = newname - - buf := make([]byte, syscall.STATFIXLEN+len(d.Name)) - n, err := d.Marshal(buf[:]) - if err != nil { - return &LinkError{"rename", oldname, newname, err} - } - if err = syscall.Wstat(oldname, buf[:n]); err != nil { - return &LinkError{"rename", oldname, newname, err} - } - return nil -} - -// 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. -func Chmod(name string, mode FileMode) error { - var d syscall.Dir - - odir, e := dirstat(name) - if e != nil { - return &PathError{"chmod", name, e} - } - d.Null() - d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask - - var buf [syscall.STATFIXLEN]byte - n, err := d.Marshal(buf[:]) - if err != nil { - return &PathError{"chmod", name, err} - } - if err = syscall.Wstat(name, buf[:n]); err != nil { - return &PathError{"chmod", name, err} - } - return nil -} - -// Chtimes changes the access and modification times of the named -// file, similar to the Unix utime() or utimes() functions. -// -// The underlying filesystem may truncate or round the values to a -// less precise time unit. -// If there is an error, it will be of type *PathError. -func Chtimes(name string, atime time.Time, mtime time.Time) error { - var d syscall.Dir - - d.Null() - d.Atime = uint32(atime.Unix()) - d.Mtime = uint32(mtime.Unix()) - - var buf [syscall.STATFIXLEN]byte - n, err := d.Marshal(buf[:]) - if err != nil { - return &PathError{"chtimes", name, err} - } - if err = syscall.Wstat(name, buf[:n]); err != nil { - return &PathError{"chtimes", name, err} - } - return nil -} - -// Pipe returns a connected pair of Files; reads from r return bytes -// written to w. It returns the files and an error, if any. -func Pipe() (r *File, w *File, err error) { - var p [2]int - - syscall.ForkLock.RLock() - if e := syscall.Pipe(p[0:]); e != nil { - syscall.ForkLock.RUnlock() - return nil, nil, NewSyscallError("pipe", e) - } - syscall.ForkLock.RUnlock() - - return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil -} - -// not supported on Plan 9 - -// Link creates newname as a hard link to the oldname file. -// If there is an error, it will be of type *LinkError. -func Link(oldname, newname string) error { - return &LinkError{"link", oldname, newname, syscall.EPLAN9} -} - -// Symlink creates newname as a symbolic link to oldname. -// If there is an error, it will be of type *LinkError. -func Symlink(oldname, newname string) error { - return &LinkError{"symlink", oldname, newname, syscall.EPLAN9} -} - -// Readlink returns the destination of the named symbolic link. -// If there is an error, it will be of type *PathError. -func Readlink(name string) (string, error) { - return "", &PathError{"readlink", name, syscall.EPLAN9} -} - -// Chown changes the numeric uid and gid of the named file. -// If the file is a symbolic link, it changes the uid and gid of the link's target. -// If there is an error, it will be of type *PathError. -func Chown(name string, uid, gid int) error { - return &PathError{"chown", name, syscall.EPLAN9} -} - -// Lchown changes the numeric uid and gid of the named file. -// If the file is a symbolic link, it changes the uid and gid of the link itself. -// If there is an error, it will be of type *PathError. -func Lchown(name string, uid, gid int) error { - return &PathError{"lchown", name, syscall.EPLAN9} -} - -// Chown changes the numeric uid and gid of the named file. -// If there is an error, it will be of type *PathError. -func (f *File) Chown(uid, gid int) error { - if f == nil { - return ErrInvalid - } - return &PathError{"chown", f.name, syscall.EPLAN9} -} - -// TempDir returns the default directory to use for temporary files. -func TempDir() string { - return "/tmp" -} diff --git a/src/pkg/os/file_posix.go b/src/pkg/os/file_posix.go deleted file mode 100644 index b3466b15c..000000000 --- a/src/pkg/os/file_posix.go +++ /dev/null @@ -1,169 +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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows - -package os - -import ( - "syscall" - "time" -) - -func sigpipe() // implemented in package runtime - -// Link creates newname as a hard link to the oldname file. -// If there is an error, it will be of type *LinkError. -func Link(oldname, newname string) error { - e := syscall.Link(oldname, newname) - if e != nil { - return &LinkError{"link", oldname, newname, e} - } - return nil -} - -// Symlink creates newname as a symbolic link to oldname. -// If there is an error, it will be of type *LinkError. -func Symlink(oldname, newname string) error { - e := syscall.Symlink(oldname, newname) - if e != nil { - return &LinkError{"symlink", oldname, newname, e} - } - return nil -} - -// Readlink returns the destination of the named symbolic link. -// If there is an error, it will be of type *PathError. -func Readlink(name string) (string, error) { - for len := 128; ; len *= 2 { - b := make([]byte, len) - n, e := syscall.Readlink(name, b) - if e != nil { - return "", &PathError{"readlink", name, e} - } - if n < len { - return string(b[0:n]), nil - } - } -} - -func rename(oldname, newname string) error { - e := syscall.Rename(oldname, newname) - if e != nil { - return &LinkError{"rename", oldname, newname, e} - } - return nil -} - -// syscallMode returns the syscall-specific mode bits from Go's portable mode bits. -func syscallMode(i FileMode) (o uint32) { - o |= uint32(i.Perm()) - if i&ModeSetuid != 0 { - o |= syscall.S_ISUID - } - if i&ModeSetgid != 0 { - o |= syscall.S_ISGID - } - if i&ModeSticky != 0 { - o |= syscall.S_ISVTX - } - // No mapping for Go's ModeTemporary (plan9 only). - return -} - -// 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. -func Chmod(name string, mode FileMode) error { - if e := syscall.Chmod(name, syscallMode(mode)); e != nil { - return &PathError{"chmod", name, e} - } - return nil -} - -// 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 { - if f == nil { - return ErrInvalid - } - if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil { - return &PathError{"chmod", f.name, e} - } - return nil -} - -// Chown changes the numeric uid and gid of the named file. -// If the file is a symbolic link, it changes the uid and gid of the link's target. -// If there is an error, it will be of type *PathError. -func Chown(name string, uid, gid int) error { - if e := syscall.Chown(name, uid, gid); e != nil { - return &PathError{"chown", name, e} - } - return nil -} - -// Lchown changes the numeric uid and gid of the named file. -// If the file is a symbolic link, it changes the uid and gid of the link itself. -// If there is an error, it will be of type *PathError. -func Lchown(name string, uid, gid int) error { - if e := syscall.Lchown(name, uid, gid); e != nil { - return &PathError{"lchown", name, e} - } - return nil -} - -// Chown changes the numeric uid and gid of the named file. -// If there is an error, it will be of type *PathError. -func (f *File) Chown(uid, gid int) error { - if f == nil { - return ErrInvalid - } - if e := syscall.Fchown(f.fd, uid, gid); e != nil { - return &PathError{"chown", f.name, e} - } - return nil -} - -// Truncate changes the size of the file. -// It does not change the I/O offset. -// If there is an error, it will be of type *PathError. -func (f *File) Truncate(size int64) error { - if f == nil { - return ErrInvalid - } - if e := syscall.Ftruncate(f.fd, size); e != nil { - return &PathError{"truncate", f.name, e} - } - return nil -} - -// Sync commits the current contents of the file to stable storage. -// Typically, this means flushing the file system's in-memory copy -// of recently written data to disk. -func (f *File) Sync() (err error) { - if f == nil { - return ErrInvalid - } - if e := syscall.Fsync(f.fd); e != nil { - return NewSyscallError("fsync", e) - } - return nil -} - -// Chtimes changes the access and modification times of the named -// file, similar to the Unix utime() or utimes() functions. -// -// The underlying filesystem may truncate or round the values to a -// less precise time unit. -// If there is an error, it will be of type *PathError. -func Chtimes(name string, atime time.Time, mtime time.Time) error { - var utimes [2]syscall.Timespec - utimes[0] = syscall.NsecToTimespec(atime.UnixNano()) - utimes[1] = syscall.NsecToTimespec(mtime.UnixNano()) - if e := syscall.UtimesNano(name, utimes[0:]); e != nil { - return &PathError{"chtimes", name, e} - } - return nil -} diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go deleted file mode 100644 index 76168339d..000000000 --- a/src/pkg/os/file_unix.go +++ /dev/null @@ -1,314 +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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris - -package os - -import ( - "runtime" - "sync/atomic" - "syscall" -) - -// File represents an open file descriptor. -type File struct { - *file -} - -// file is the real representation of *File. -// The extra level of indirection ensures that no clients of os -// can overwrite this data, which could cause the finalizer -// to close the wrong file descriptor. -type file struct { - fd int - name string - dirinfo *dirInfo // nil unless directory being read - nepipe int32 // number of consecutive EPIPE in Write -} - -// Fd returns the integer Unix file descriptor referencing the open file. -func (f *File) Fd() uintptr { - if f == nil { - return ^(uintptr(0)) - } - return uintptr(f.fd) -} - -// NewFile returns a new File with the given file descriptor and name. -func NewFile(fd uintptr, name string) *File { - fdi := int(fd) - if fdi < 0 { - return nil - } - f := &File{&file{fd: fdi, name: name}} - runtime.SetFinalizer(f.file, (*file).close) - return f -} - -// Auxiliary information if the File describes a directory -type dirInfo struct { - buf []byte // buffer for directory I/O - nbuf int // length of buf; return value from Getdirentries - bufp int // location of next record in buf. -} - -func epipecheck(file *File, e error) { - if e == syscall.EPIPE { - if atomic.AddInt32(&file.nepipe, 1) >= 10 { - sigpipe() - } - } else { - atomic.StoreInt32(&file.nepipe, 0) - } -} - -// DevNull is the name of the operating system's ``null device.'' -// On Unix-like systems, it is "/dev/null"; on Windows, "NUL". -const DevNull = "/dev/null" - -// 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, (0666 etc.) if applicable. 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 *File, err error) { - r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) - if e != nil { - return nil, &PathError{"open", name, e} - } - - // There's a race here with fork/exec, which we are - // content to live with. See ../syscall/exec_unix.go. - if !supportsCloseOnExec { - syscall.CloseOnExec(r) - } - - return NewFile(uintptr(r), name), nil -} - -// Close closes the File, rendering it unusable for I/O. -// It returns an error, if any. -func (f *File) Close() error { - if f == nil { - return ErrInvalid - } - return f.file.close() -} - -func (file *file) close() error { - if file == nil || file.fd < 0 { - return syscall.EINVAL - } - var err error - if e := syscall.Close(file.fd); e != nil { - err = &PathError{"close", file.name, e} - } - file.fd = -1 // so it can't be closed again - - // no need for a finalizer anymore - runtime.SetFinalizer(file, nil) - return err -} - -// Stat returns the FileInfo structure describing file. -// If there is an error, it will be of type *PathError. -func (f *File) Stat() (fi FileInfo, err error) { - if f == nil { - return nil, ErrInvalid - } - var stat syscall.Stat_t - err = syscall.Fstat(f.fd, &stat) - if err != nil { - return nil, &PathError{"stat", f.name, err} - } - return fileInfoFromStat(&stat, f.name), nil -} - -// Stat returns a FileInfo describing the named file. -// If there is an error, it will be of type *PathError. -func Stat(name string) (fi FileInfo, err error) { - var stat syscall.Stat_t - err = syscall.Stat(name, &stat) - if err != nil { - return nil, &PathError{"stat", name, err} - } - return fileInfoFromStat(&stat, name), nil -} - -// Lstat returns a FileInfo describing the named file. -// If the file is a symbolic link, the returned FileInfo -// describes the symbolic link. Lstat makes no attempt to follow the link. -// If there is an error, it will be of type *PathError. -func Lstat(name string) (fi FileInfo, err error) { - var stat syscall.Stat_t - err = syscall.Lstat(name, &stat) - if err != nil { - return nil, &PathError{"lstat", name, err} - } - return fileInfoFromStat(&stat, name), nil -} - -func (f *File) readdir(n int) (fi []FileInfo, err error) { - dirname := f.name - if dirname == "" { - dirname = "." - } - names, err := f.Readdirnames(n) - fi = make([]FileInfo, 0, len(names)) - for _, filename := range names { - fip, lerr := lstat(dirname + "/" + filename) - if IsNotExist(lerr) { - // File disappeared between readdir + stat. - // Just treat it as if it didn't exist. - continue - } - if lerr != nil { - return fi, lerr - } - fi = append(fi, fip) - } - return fi, err -} - -// Darwin and FreeBSD can't read or write 2GB+ at a time, -// even on 64-bit systems. See golang.org/issue/7812. -// Use 1GB instead of, say, 2GB-1, to keep subsequent -// reads aligned. -const ( - needsMaxRW = runtime.GOOS == "darwin" || runtime.GOOS == "freebsd" - maxRW = 1 << 30 -) - -// read reads up to len(b) bytes from the File. -// It returns the number of bytes read and an error, if any. -func (f *File) read(b []byte) (n int, err error) { - if needsMaxRW && len(b) > maxRW { - b = b[:maxRW] - } - return syscall.Read(f.fd, b) -} - -// pread reads len(b) bytes from the File starting at byte offset off. -// It returns the number of bytes read and the error, if any. -// EOF is signaled by a zero count with err set to nil. -func (f *File) pread(b []byte, off int64) (n int, err error) { - if needsMaxRW && len(b) > maxRW { - b = b[:maxRW] - } - return syscall.Pread(f.fd, b, off) -} - -// write writes len(b) bytes to the File. -// It returns the number of bytes written and an error, if any. -func (f *File) write(b []byte) (n int, err error) { - for { - bcap := b - if needsMaxRW && len(bcap) > maxRW { - bcap = bcap[:maxRW] - } - m, err := syscall.Write(f.fd, bcap) - n += m - - // If the syscall wrote some data but not all (short write) - // or it returned EINTR, then assume it stopped early for - // reasons that are uninteresting to the caller, and try again. - if 0 < m && m < len(bcap) || err == syscall.EINTR { - b = b[m:] - continue - } - - if needsMaxRW && len(bcap) != len(b) && err == nil { - b = b[m:] - continue - } - - return n, err - } -} - -// pwrite writes len(b) bytes to the File starting at byte offset off. -// It returns the number of bytes written and an error, if any. -func (f *File) pwrite(b []byte, off int64) (n int, err error) { - if needsMaxRW && len(b) > maxRW { - b = b[:maxRW] - } - return syscall.Pwrite(f.fd, b, off) -} - -// 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. -func (f *File) seek(offset int64, whence int) (ret int64, err error) { - return syscall.Seek(f.fd, offset, whence) -} - -// Truncate changes the size of the named file. -// If the file is a symbolic link, it changes the size of the link's target. -// If there is an error, it will be of type *PathError. -func Truncate(name string, size int64) error { - if e := syscall.Truncate(name, size); e != nil { - return &PathError{"truncate", name, e} - } - return nil -} - -// Remove removes the named file or directory. -// If there is an error, it will be of type *PathError. -func Remove(name string) error { - // System call interface forces us to know - // whether name is a file or directory. - // Try both: it is cheaper on average than - // doing a Stat plus the right one. - e := syscall.Unlink(name) - if e == nil { - return nil - } - e1 := syscall.Rmdir(name) - if e1 == nil { - return nil - } - - // Both failed: figure out which error to return. - // OS X and Linux differ on whether unlink(dir) - // returns EISDIR, so can't use that. However, - // both agree that rmdir(file) returns ENOTDIR, - // so we can use that to decide which error is real. - // Rmdir might also return ENOTDIR if given a bad - // file path, like /etc/passwd/foo, but in that case, - // both errors will be ENOTDIR, so it's okay to - // use the error from unlink. - if e1 != syscall.ENOTDIR { - e = e1 - } - return &PathError{"remove", name, e} -} - -// basename removes trailing slashes and the leading directory name from path name -func basename(name string) string { - i := len(name) - 1 - // Remove trailing slashes - for ; i > 0 && name[i] == '/'; i-- { - name = name[:i] - } - // Remove leading directory name - for i--; i >= 0; i-- { - if name[i] == '/' { - name = name[i+1:] - break - } - } - - return name -} - -// TempDir returns the default directory to use for temporary files. -func TempDir() string { - dir := Getenv("TMPDIR") - if dir == "" { - dir = "/tmp" - } - return dir -} diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go deleted file mode 100644 index efe8bc03f..000000000 --- a/src/pkg/os/file_windows.go +++ /dev/null @@ -1,495 +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 - -import ( - "io" - "runtime" - "sync" - "syscall" - "unicode/utf16" - "unicode/utf8" - "unsafe" -) - -// File represents an open file descriptor. -type File struct { - *file -} - -// file is the real representation of *File. -// The extra level of indirection ensures that no clients of os -// can overwrite this data, which could cause the finalizer -// to close the wrong file descriptor. -type file struct { - fd syscall.Handle - name string - dirinfo *dirInfo // nil unless directory being read - l sync.Mutex // used to implement windows pread/pwrite - - // only for console io - isConsole bool - lastbits []byte // first few bytes of the last incomplete rune in last write - readbuf []rune // input console buffer -} - -// Fd returns the Windows handle referencing the open file. -func (file *File) Fd() uintptr { - if file == nil { - return uintptr(syscall.InvalidHandle) - } - return uintptr(file.fd) -} - -// newFile returns a new File with the given file handle and name. -// Unlike NewFile, it does not check that h is syscall.InvalidHandle. -func newFile(h syscall.Handle, name string) *File { - f := &File{&file{fd: h, name: name}} - var m uint32 - if syscall.GetConsoleMode(f.fd, &m) == nil { - f.isConsole = true - } - runtime.SetFinalizer(f.file, (*file).close) - return f -} - -// NewFile returns a new File with the given file descriptor and name. -func NewFile(fd uintptr, name string) *File { - h := syscall.Handle(fd) - if h == syscall.InvalidHandle { - return nil - } - return newFile(h, name) -} - -// Auxiliary information if the File describes a directory -type dirInfo struct { - data syscall.Win32finddata - needdata bool - path string - isempty bool // set if FindFirstFile returns ERROR_FILE_NOT_FOUND -} - -func epipecheck(file *File, e error) { -} - -const DevNull = "NUL" - -func (f *file) isdir() bool { return f != nil && f.dirinfo != nil } - -func openFile(name string, flag int, perm FileMode) (file *File, err error) { - r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) - if e != nil { - return nil, e - } - return NewFile(uintptr(r), name), nil -} - -func openDir(name string) (file *File, err error) { - maskp, e := syscall.UTF16PtrFromString(name + `\*`) - if e != nil { - return nil, e - } - d := new(dirInfo) - r, e := syscall.FindFirstFile(maskp, &d.data) - if e != nil { - // FindFirstFile returns ERROR_FILE_NOT_FOUND when - // no matching files can be found. Then, if directory - // exists, we should proceed. - if e != syscall.ERROR_FILE_NOT_FOUND { - return nil, e - } - var fa syscall.Win32FileAttributeData - namep, e := syscall.UTF16PtrFromString(name) - if e != nil { - return nil, e - } - e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa))) - if e != nil { - return nil, e - } - if fa.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY == 0 { - return nil, e - } - d.isempty = true - } - d.path = name - if !isAbs(d.path) { - cwd, _ := Getwd() - d.path = cwd + `\` + d.path - } - f := newFile(r, name) - f.dirinfo = d - return f, nil -} - -// 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, (0666 etc.) if applicable. 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 *File, err error) { - if name == "" { - return nil, &PathError{"open", name, syscall.ENOENT} - } - r, errf := openFile(name, flag, perm) - if errf == nil { - return r, nil - } - r, errd := openDir(name) - if errd == nil { - if flag&O_WRONLY != 0 || flag&O_RDWR != 0 { - r.Close() - return nil, &PathError{"open", name, syscall.EISDIR} - } - return r, nil - } - return nil, &PathError{"open", name, errf} -} - -// Close closes the File, rendering it unusable for I/O. -// It returns an error, if any. -func (file *File) Close() error { - if file == nil { - return ErrInvalid - } - return file.file.close() -} - -func (file *file) close() error { - if file == nil { - return syscall.EINVAL - } - if file.isdir() && file.dirinfo.isempty { - // "special" empty directories - return nil - } - if file.fd == syscall.InvalidHandle { - return syscall.EINVAL - } - var e error - if file.isdir() { - e = syscall.FindClose(syscall.Handle(file.fd)) - } else { - e = syscall.CloseHandle(syscall.Handle(file.fd)) - } - var err error - if e != nil { - err = &PathError{"close", file.name, e} - } - file.fd = syscall.InvalidHandle // so it can't be closed again - - // no need for a finalizer anymore - runtime.SetFinalizer(file, nil) - return err -} - -func (file *File) readdir(n int) (fi []FileInfo, err error) { - if file == nil { - return nil, syscall.EINVAL - } - if !file.isdir() { - return nil, &PathError{"Readdir", file.name, syscall.ENOTDIR} - } - if !file.dirinfo.isempty && file.fd == syscall.InvalidHandle { - return nil, syscall.EINVAL - } - wantAll := n <= 0 - size := n - if wantAll { - n = -1 - size = 100 - } - fi = make([]FileInfo, 0, size) // Empty with room to grow. - d := &file.dirinfo.data - for n != 0 && !file.dirinfo.isempty { - if file.dirinfo.needdata { - e := syscall.FindNextFile(syscall.Handle(file.fd), d) - if e != nil { - if e == syscall.ERROR_NO_MORE_FILES { - break - } else { - err = &PathError{"FindNextFile", file.name, e} - if !wantAll { - fi = nil - } - return - } - } - } - file.dirinfo.needdata = true - name := string(syscall.UTF16ToString(d.FileName[0:])) - if name == "." || name == ".." { // Useless names - continue - } - f := &fileStat{ - name: name, - sys: syscall.Win32FileAttributeData{ - FileAttributes: d.FileAttributes, - CreationTime: d.CreationTime, - LastAccessTime: d.LastAccessTime, - LastWriteTime: d.LastWriteTime, - FileSizeHigh: d.FileSizeHigh, - FileSizeLow: d.FileSizeLow, - }, - path: file.dirinfo.path + `\` + name, - } - n-- - fi = append(fi, f) - } - if !wantAll && len(fi) == 0 { - return fi, io.EOF - } - return fi, nil -} - -// readConsole reads utf16 characters from console File, -// encodes them into utf8 and stores them in buffer b. -// It returns the number of utf8 bytes read and an error, if any. -func (f *File) readConsole(b []byte) (n int, err error) { - if len(b) == 0 { - return 0, nil - } - if len(f.readbuf) == 0 { - // syscall.ReadConsole seems to fail, if given large buffer. - // So limit the buffer to 16000 characters. - numBytes := len(b) - if numBytes > 16000 { - numBytes = 16000 - } - // get more input data from os - wchars := make([]uint16, numBytes) - var p *uint16 - if len(b) > 0 { - p = &wchars[0] - } - var nw uint32 - err := syscall.ReadConsole(f.fd, p, uint32(len(wchars)), &nw, nil) - if err != nil { - return 0, err - } - f.readbuf = utf16.Decode(wchars[:nw]) - } - for i, r := range f.readbuf { - if utf8.RuneLen(r) > len(b) { - f.readbuf = f.readbuf[i:] - return n, nil - } - nr := utf8.EncodeRune(b, r) - b = b[nr:] - n += nr - } - f.readbuf = nil - return n, nil -} - -// read reads up to len(b) bytes from the File. -// It returns the number of bytes read and an error, if any. -func (f *File) read(b []byte) (n int, err error) { - f.l.Lock() - defer f.l.Unlock() - if f.isConsole { - return f.readConsole(b) - } - return syscall.Read(f.fd, b) -} - -// pread reads len(b) bytes from the File starting at byte offset off. -// It returns the number of bytes read and the error, if any. -// EOF is signaled by a zero count with err set to 0. -func (f *File) pread(b []byte, off int64) (n int, err error) { - f.l.Lock() - defer f.l.Unlock() - curoffset, e := syscall.Seek(f.fd, 0, 1) - if e != nil { - return 0, e - } - defer syscall.Seek(f.fd, curoffset, 0) - o := syscall.Overlapped{ - OffsetHigh: uint32(off >> 32), - Offset: uint32(off), - } - var done uint32 - e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o) - if e != nil { - if e == syscall.ERROR_HANDLE_EOF { - // end of file - return 0, nil - } - return 0, e - } - return int(done), nil -} - -// writeConsole writes len(b) bytes to the console File. -// It returns the number of bytes written and an error, if any. -func (f *File) writeConsole(b []byte) (n int, err error) { - n = len(b) - runes := make([]rune, 0, 256) - if len(f.lastbits) > 0 { - b = append(f.lastbits, b...) - f.lastbits = nil - - } - for len(b) >= utf8.UTFMax || utf8.FullRune(b) { - r, l := utf8.DecodeRune(b) - runes = append(runes, r) - b = b[l:] - } - if len(b) > 0 { - f.lastbits = make([]byte, len(b)) - copy(f.lastbits, b) - } - // syscall.WriteConsole seems to fail, if given large buffer. - // So limit the buffer to 16000 characters. This number was - // discovered by experimenting with syscall.WriteConsole. - const maxWrite = 16000 - for len(runes) > 0 { - m := len(runes) - if m > maxWrite { - m = maxWrite - } - chunk := runes[:m] - runes = runes[m:] - uint16s := utf16.Encode(chunk) - for len(uint16s) > 0 { - var written uint32 - err = syscall.WriteConsole(f.fd, &uint16s[0], uint32(len(uint16s)), &written, nil) - if err != nil { - return 0, nil - } - uint16s = uint16s[written:] - } - } - return n, nil -} - -// write writes len(b) bytes to the File. -// It returns the number of bytes written and an error, if any. -func (f *File) write(b []byte) (n int, err error) { - f.l.Lock() - defer f.l.Unlock() - if f.isConsole { - return f.writeConsole(b) - } - return syscall.Write(f.fd, b) -} - -// pwrite writes len(b) bytes to the File starting at byte offset off. -// It returns the number of bytes written and an error, if any. -func (f *File) pwrite(b []byte, off int64) (n int, err error) { - f.l.Lock() - defer f.l.Unlock() - curoffset, e := syscall.Seek(f.fd, 0, 1) - if e != nil { - return 0, e - } - defer syscall.Seek(f.fd, curoffset, 0) - o := syscall.Overlapped{ - OffsetHigh: uint32(off >> 32), - Offset: uint32(off), - } - var done uint32 - e = syscall.WriteFile(syscall.Handle(f.fd), b, &done, &o) - if e != nil { - return 0, e - } - return int(done), nil -} - -// 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. -func (f *File) seek(offset int64, whence int) (ret int64, err error) { - f.l.Lock() - defer f.l.Unlock() - return syscall.Seek(f.fd, offset, whence) -} - -// Truncate changes the size of the named file. -// If the file is a symbolic link, it changes the size of the link's target. -func Truncate(name string, size int64) error { - f, e := OpenFile(name, O_WRONLY|O_CREATE, 0666) - if e != nil { - return e - } - defer f.Close() - e1 := f.Truncate(size) - if e1 != nil { - return e1 - } - return nil -} - -// Remove removes the named file or directory. -// If there is an error, it will be of type *PathError. -func Remove(name string) error { - p, e := syscall.UTF16PtrFromString(name) - if e != nil { - return &PathError{"remove", name, e} - } - - // Go file interface forces us to know whether - // name is a file or directory. Try both. - e = syscall.DeleteFile(p) - if e == nil { - return nil - } - e1 := syscall.RemoveDirectory(p) - if e1 == nil { - return nil - } - - // Both failed: figure out which error to return. - if e1 != e { - a, e2 := syscall.GetFileAttributes(p) - if e2 != nil { - e = e2 - } else { - if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - e = e1 - } - } - } - return &PathError{"remove", name, e} -} - -// Pipe returns a connected pair of Files; reads from r return bytes written to w. -// It returns the files and an error, if any. -func Pipe() (r *File, w *File, err error) { - var p [2]syscall.Handle - - // See ../syscall/exec.go for description of lock. - syscall.ForkLock.RLock() - e := syscall.Pipe(p[0:]) - if e != nil { - syscall.ForkLock.RUnlock() - return nil, nil, NewSyscallError("pipe", e) - } - syscall.CloseOnExec(p[0]) - syscall.CloseOnExec(p[1]) - syscall.ForkLock.RUnlock() - - return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil -} - -// TempDir returns the default directory to use for temporary files. -func TempDir() string { - const pathSep = '\\' - dirw := make([]uint16, syscall.MAX_PATH) - n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0]) - if n > uint32(len(dirw)) { - dirw = make([]uint16, n) - n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0]) - if n > uint32(len(dirw)) { - n = 0 - } - } - if n > 0 && dirw[n-1] == pathSep { - n-- - } - return string(utf16.Decode(dirw[0:n])) -} diff --git a/src/pkg/os/getwd.go b/src/pkg/os/getwd.go deleted file mode 100644 index a72edeaee..000000000 --- a/src/pkg/os/getwd.go +++ /dev/null @@ -1,119 +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 - -import ( - "sync" - "syscall" -) - -var getwdCache struct { - sync.Mutex - dir string -} - -// useSyscallwd determines whether to use the return value of -// syscall.Getwd based on its error. -var useSyscallwd = func(error) bool { return true } - -// Getwd returns a rooted path name corresponding to the -// current directory. If the current directory can be -// reached via multiple paths (due to symbolic links), -// Getwd may return any one of them. -func Getwd() (dir string, err error) { - // If the operating system provides a Getwd call, use it. - if syscall.ImplementsGetwd { - s, e := syscall.Getwd() - if useSyscallwd(e) { - return s, NewSyscallError("getwd", e) - } - } - - // Otherwise, we're trying to find our way back to ".". - dot, err := Stat(".") - if err != nil { - return "", err - } - - // Clumsy but widespread kludge: - // if $PWD is set and matches ".", use it. - dir = Getenv("PWD") - if len(dir) > 0 && dir[0] == '/' { - d, err := Stat(dir) - if err == nil && SameFile(dot, d) { - return dir, nil - } - } - - // Apply same kludge but to cached dir instead of $PWD. - getwdCache.Lock() - dir = getwdCache.dir - getwdCache.Unlock() - if len(dir) > 0 { - d, err := Stat(dir) - if err == nil && SameFile(dot, d) { - return dir, nil - } - } - - // Root is a special case because it has no parent - // and ends in a slash. - root, err := Stat("/") - if err != nil { - // Can't stat root - no hope. - return "", err - } - if SameFile(root, dot) { - return "/", nil - } - - // General algorithm: find name in parent - // and then find name of parent. Each iteration - // adds /name to the beginning of dir. - dir = "" - for parent := ".."; ; parent = "../" + parent { - if len(parent) >= 1024 { // Sanity check - return "", syscall.ENAMETOOLONG - } - fd, err := Open(parent) - if err != nil { - return "", err - } - - for { - names, err := fd.Readdirnames(100) - if err != nil { - fd.Close() - return "", err - } - for _, name := range names { - d, _ := Lstat(parent + "/" + name) - if SameFile(d, dot) { - dir = "/" + name + dir - goto Found - } - } - } - - Found: - pd, err := fd.Stat() - if err != nil { - return "", err - } - fd.Close() - if SameFile(pd, root) { - break - } - // Set up for next round. - dot = pd - } - - // Save answer as hint to avoid the expensive path next time. - getwdCache.Lock() - getwdCache.dir = dir - getwdCache.Unlock() - - return dir, nil -} diff --git a/src/pkg/os/getwd_darwin.go b/src/pkg/os/getwd_darwin.go deleted file mode 100644 index e51ffcd5e..000000000 --- a/src/pkg/os/getwd_darwin.go +++ /dev/null @@ -1,15 +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 - -import "syscall" - -func init() { - useSyscallwd = useSyscallwdDarwin -} - -func useSyscallwdDarwin(err error) bool { - return err != syscall.ENOTSUP -} diff --git a/src/pkg/os/os_test.go b/src/pkg/os/os_test.go deleted file mode 100644 index 16d5984e9..000000000 --- a/src/pkg/os/os_test.go +++ /dev/null @@ -1,1339 +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_test - -import ( - "bytes" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - . "os" - osexec "os/exec" - "path/filepath" - "reflect" - "runtime" - "sort" - "strings" - "syscall" - "testing" - "text/template" - "time" -) - -var dot = []string{ - "dir_unix.go", - "env.go", - "error.go", - "file.go", - "os_test.go", - "types.go", - "stat_darwin.go", - "stat_linux.go", -} - -type sysDir struct { - name string - files []string -} - -var sysdir = func() (sd *sysDir) { - switch runtime.GOOS { - case "windows": - sd = &sysDir{ - Getenv("SystemRoot") + "\\system32\\drivers\\etc", - []string{ - "networks", - "protocol", - "services", - }, - } - case "plan9": - sd = &sysDir{ - "/lib/ndb", - []string{ - "common", - "local", - }, - } - default: - sd = &sysDir{ - "/etc", - []string{ - "group", - "hosts", - "passwd", - }, - } - } - return -}() - -func size(name string, t *testing.T) int64 { - file, err := Open(name) - if err != nil { - t.Fatal("open failed:", err) - } - defer file.Close() - var buf [100]byte - len := 0 - for { - n, e := file.Read(buf[0:]) - len += n - if e == io.EOF { - break - } - if e != nil { - t.Fatal("read failed:", err) - } - } - return int64(len) -} - -func equal(name1, name2 string) (r bool) { - switch runtime.GOOS { - case "windows": - r = strings.ToLower(name1) == strings.ToLower(name2) - default: - r = name1 == name2 - } - return -} - -func newFile(testName string, t *testing.T) (f *File) { - // Use a local file system, not NFS. - // On Unix, override $TMPDIR in case the user - // has it set to an NFS-mounted directory. - dir := "" - if runtime.GOOS != "windows" { - dir = "/tmp" - } - f, err := ioutil.TempFile(dir, "_Go_"+testName) - if err != nil { - t.Fatalf("open %s: %s", testName, err) - } - return -} - -var sfdir = sysdir.name -var sfname = sysdir.files[0] - -func TestStat(t *testing.T) { - path := sfdir + "/" + sfname - dir, err := Stat(path) - if err != nil { - t.Fatal("stat failed:", err) - } - if !equal(sfname, dir.Name()) { - t.Error("name should be ", sfname, "; is", dir.Name()) - } - filesize := size(path, t) - if dir.Size() != filesize { - t.Error("size should be", filesize, "; is", dir.Size()) - } -} - -func TestFstat(t *testing.T) { - path := sfdir + "/" + sfname - file, err1 := Open(path) - if err1 != nil { - t.Fatal("open failed:", err1) - } - defer file.Close() - dir, err2 := file.Stat() - if err2 != nil { - t.Fatal("fstat failed:", err2) - } - if !equal(sfname, dir.Name()) { - t.Error("name should be ", sfname, "; is", dir.Name()) - } - filesize := size(path, t) - if dir.Size() != filesize { - t.Error("size should be", filesize, "; is", dir.Size()) - } -} - -func TestLstat(t *testing.T) { - path := sfdir + "/" + sfname - dir, err := Lstat(path) - if err != nil { - t.Fatal("lstat failed:", err) - } - if !equal(sfname, dir.Name()) { - t.Error("name should be ", sfname, "; is", dir.Name()) - } - filesize := size(path, t) - if dir.Size() != filesize { - t.Error("size should be", filesize, "; is", dir.Size()) - } -} - -// Read with length 0 should not return EOF. -func TestRead0(t *testing.T) { - path := sfdir + "/" + sfname - f, err := Open(path) - if err != nil { - t.Fatal("open failed:", err) - } - defer f.Close() - - b := make([]byte, 0) - n, err := f.Read(b) - if n != 0 || err != nil { - t.Errorf("Read(0) = %d, %v, want 0, nil", n, err) - } - b = make([]byte, 100) - n, err = f.Read(b) - if n <= 0 || err != nil { - t.Errorf("Read(100) = %d, %v, want >0, nil", n, err) - } -} - -func testReaddirnames(dir string, contents []string, t *testing.T) { - file, err := Open(dir) - if err != nil { - t.Fatalf("open %q failed: %v", dir, err) - } - defer file.Close() - s, err2 := file.Readdirnames(-1) - if err2 != nil { - t.Fatalf("readdirnames %q failed: %v", dir, err2) - } - for _, m := range contents { - found := false - for _, n := range s { - if n == "." || n == ".." { - t.Errorf("got %s in directory", n) - } - if equal(m, n) { - if found { - t.Error("present twice:", m) - } - found = true - } - } - if !found { - t.Error("could not find", m) - } - } -} - -func testReaddir(dir string, contents []string, t *testing.T) { - file, err := Open(dir) - if err != nil { - t.Fatalf("open %q failed: %v", dir, err) - } - defer file.Close() - s, err2 := file.Readdir(-1) - if err2 != nil { - t.Fatalf("readdir %q failed: %v", dir, err2) - } - for _, m := range contents { - found := false - for _, n := range s { - if equal(m, n.Name()) { - if found { - t.Error("present twice:", m) - } - found = true - } - } - if !found { - t.Error("could not find", m) - } - } -} - -func TestReaddirnames(t *testing.T) { - testReaddirnames(".", dot, t) - testReaddirnames(sysdir.name, sysdir.files, t) -} - -func TestReaddir(t *testing.T) { - testReaddir(".", dot, t) - testReaddir(sysdir.name, sysdir.files, t) -} - -// Read the directory one entry at a time. -func smallReaddirnames(file *File, length int, t *testing.T) []string { - names := make([]string, length) - count := 0 - for { - d, err := file.Readdirnames(1) - if err == io.EOF { - break - } - if err != nil { - t.Fatalf("readdirnames %q failed: %v", file.Name(), err) - } - if len(d) == 0 { - t.Fatalf("readdirnames %q returned empty slice and no error", file.Name()) - } - names[count] = d[0] - count++ - } - return names[0:count] -} - -// Check that reading a directory one entry at a time gives the same result -// as reading it all at once. -func TestReaddirnamesOneAtATime(t *testing.T) { - // big directory that doesn't change often. - dir := "/usr/bin" - switch runtime.GOOS { - case "windows": - dir = Getenv("SystemRoot") + "\\system32" - case "plan9": - dir = "/bin" - } - file, err := Open(dir) - if err != nil { - t.Fatalf("open %q failed: %v", dir, err) - } - defer file.Close() - all, err1 := file.Readdirnames(-1) - if err1 != nil { - t.Fatalf("readdirnames %q failed: %v", dir, err1) - } - file1, err2 := Open(dir) - if err2 != nil { - t.Fatalf("open %q failed: %v", dir, err2) - } - defer file1.Close() - small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up - if len(small) < len(all) { - t.Fatalf("len(small) is %d, less than %d", len(small), len(all)) - } - for i, n := range all { - if small[i] != n { - t.Errorf("small read %q mismatch: %v", small[i], n) - } - } -} - -func TestReaddirNValues(t *testing.T) { - if testing.Short() { - t.Skip("test.short; skipping") - } - dir, err := ioutil.TempDir("", "") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - defer RemoveAll(dir) - for i := 1; i <= 105; i++ { - f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i))) - if err != nil { - t.Fatalf("Create: %v", err) - } - f.Write([]byte(strings.Repeat("X", i))) - f.Close() - } - - var d *File - openDir := func() { - var err error - d, err = Open(dir) - if err != nil { - t.Fatalf("Open directory: %v", err) - } - } - - readDirExpect := func(n, want int, wantErr error) { - fi, err := d.Readdir(n) - if err != wantErr { - t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr) - } - if g, e := len(fi), want; g != e { - t.Errorf("Readdir of %d got %d files, want %d", n, g, e) - } - } - - readDirNamesExpect := func(n, want int, wantErr error) { - fi, err := d.Readdirnames(n) - if err != wantErr { - t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr) - } - if g, e := len(fi), want; g != e { - t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e) - } - } - - for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} { - // Test the slurp case - openDir() - fn(0, 105, nil) - fn(0, 0, nil) - d.Close() - - // Slurp with -1 instead - openDir() - fn(-1, 105, nil) - fn(-2, 0, nil) - fn(0, 0, nil) - d.Close() - - // Test the bounded case - openDir() - fn(1, 1, nil) - fn(2, 2, nil) - fn(105, 102, nil) // and tests buffer >100 case - fn(3, 0, io.EOF) - d.Close() - } -} - -func touch(t *testing.T, name string) { - f, err := Create(name) - if err != nil { - t.Fatal(err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } -} - -func TestReaddirStatFailures(t *testing.T) { - switch runtime.GOOS { - case "windows", "plan9": - // Windows and Plan 9 already do this correctly, - // but are structured with different syscalls such - // that they don't use Lstat, so the hook below for - // testing it wouldn't work. - t.Skipf("skipping test on %v", runtime.GOOS) - } - dir, err := ioutil.TempDir("", "") - if err != nil { - t.Fatalf("TempDir: %v", err) - } - defer RemoveAll(dir) - touch(t, filepath.Join(dir, "good1")) - touch(t, filepath.Join(dir, "x")) // will disappear or have an error - touch(t, filepath.Join(dir, "good2")) - defer func() { - *LstatP = Lstat - }() - var xerr error // error to return for x - *LstatP = func(path string) (FileInfo, error) { - if xerr != nil && strings.HasSuffix(path, "x") { - return nil, xerr - } - return Lstat(path) - } - readDir := func() ([]FileInfo, error) { - d, err := Open(dir) - if err != nil { - t.Fatal(err) - } - defer d.Close() - return d.Readdir(-1) - } - mustReadDir := func(testName string) []FileInfo { - fis, err := readDir() - if err != nil { - t.Fatalf("%s: Readdir: %v", testName, err) - } - return fis - } - names := func(fis []FileInfo) []string { - s := make([]string, len(fis)) - for i, fi := range fis { - s[i] = fi.Name() - } - sort.Strings(s) - return s - } - - if got, want := names(mustReadDir("inital readdir")), - []string{"good1", "good2", "x"}; !reflect.DeepEqual(got, want) { - t.Errorf("initial readdir got %q; want %q", got, want) - } - - xerr = ErrNotExist - if got, want := names(mustReadDir("with x disappearing")), - []string{"good1", "good2"}; !reflect.DeepEqual(got, want) { - t.Errorf("with x disappearing, got %q; want %q", got, want) - } - - xerr = errors.New("some real error") - if _, err := readDir(); err != xerr { - t.Errorf("with a non-ErrNotExist error, got error %v; want %v", err, xerr) - } -} - -func TestHardLink(t *testing.T) { - // Hardlinks are not supported under windows or Plan 9. - if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { - return - } - from, to := "hardlinktestfrom", "hardlinktestto" - Remove(from) // Just in case. - file, err := Create(to) - if err != nil { - t.Fatalf("open %q failed: %v", to, err) - } - defer Remove(to) - if err = file.Close(); err != nil { - t.Errorf("close %q failed: %v", to, err) - } - err = Link(to, from) - if err != nil { - t.Fatalf("link %q, %q failed: %v", to, from, err) - } - defer Remove(from) - tostat, err := Stat(to) - if err != nil { - t.Fatalf("stat %q failed: %v", to, err) - } - fromstat, err := Stat(from) - if err != nil { - t.Fatalf("stat %q failed: %v", from, err) - } - if !SameFile(tostat, fromstat) { - t.Errorf("link %q, %q did not create hard link", to, from) - } -} - -func TestSymlink(t *testing.T) { - switch runtime.GOOS { - case "windows", "plan9", "nacl": - t.Skipf("skipping on %s", runtime.GOOS) - } - from, to := "symlinktestfrom", "symlinktestto" - Remove(from) // Just in case. - file, err := Create(to) - if err != nil { - t.Fatalf("open %q failed: %v", to, err) - } - defer Remove(to) - if err = file.Close(); err != nil { - t.Errorf("close %q failed: %v", to, err) - } - err = Symlink(to, from) - if err != nil { - t.Fatalf("symlink %q, %q failed: %v", to, from, err) - } - defer Remove(from) - tostat, err := Lstat(to) - if err != nil { - t.Fatalf("stat %q failed: %v", to, err) - } - if tostat.Mode()&ModeSymlink != 0 { - t.Fatalf("stat %q claims to have found a symlink", to) - } - fromstat, err := Stat(from) - if err != nil { - t.Fatalf("stat %q failed: %v", from, err) - } - if !SameFile(tostat, fromstat) { - t.Errorf("symlink %q, %q did not create symlink", to, from) - } - fromstat, err = Lstat(from) - if err != nil { - t.Fatalf("lstat %q failed: %v", from, err) - } - if fromstat.Mode()&ModeSymlink == 0 { - t.Fatalf("symlink %q, %q did not create symlink", to, from) - } - fromstat, err = Stat(from) - if err != nil { - t.Fatalf("stat %q failed: %v", from, err) - } - if fromstat.Mode()&ModeSymlink != 0 { - t.Fatalf("stat %q did not follow symlink", from) - } - s, err := Readlink(from) - if err != nil { - t.Fatalf("readlink %q failed: %v", from, err) - } - if s != to { - t.Fatalf("after symlink %q != %q", s, to) - } - file, err = Open(from) - if err != nil { - t.Fatalf("open %q failed: %v", from, err) - } - file.Close() -} - -func TestLongSymlink(t *testing.T) { - switch runtime.GOOS { - case "windows", "plan9", "nacl": - t.Skipf("skipping on %s", runtime.GOOS) - } - s := "0123456789abcdef" - // Long, but not too long: a common limit is 255. - s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s - from := "longsymlinktestfrom" - Remove(from) // Just in case. - err := Symlink(s, from) - if err != nil { - t.Fatalf("symlink %q, %q failed: %v", s, from, err) - } - defer Remove(from) - r, err := Readlink(from) - if err != nil { - t.Fatalf("readlink %q failed: %v", from, err) - } - if r != s { - t.Fatalf("after symlink %q != %q", r, s) - } -} - -func TestRename(t *testing.T) { - from, to := "renamefrom", "renameto" - Remove(to) // Just in case. - file, err := Create(from) - if err != nil { - t.Fatalf("open %q failed: %v", to, err) - } - if err = file.Close(); err != nil { - t.Errorf("close %q failed: %v", to, err) - } - err = Rename(from, to) - if err != nil { - t.Fatalf("rename %q, %q failed: %v", to, from, err) - } - defer Remove(to) - _, err = Stat(to) - if err != nil { - t.Errorf("stat %q failed: %v", to, err) - } -} - -func exec(t *testing.T, dir, cmd string, args []string, expect string) { - r, w, err := Pipe() - if err != nil { - t.Fatalf("Pipe: %v", err) - } - defer r.Close() - attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}} - p, err := StartProcess(cmd, args, attr) - if err != nil { - t.Fatalf("StartProcess: %v", err) - } - w.Close() - - var b bytes.Buffer - io.Copy(&b, r) - output := b.String() - - fi1, _ := Stat(strings.TrimSpace(output)) - fi2, _ := Stat(expect) - if !SameFile(fi1, fi2) { - t.Errorf("exec %q returned %q wanted %q", - strings.Join(append([]string{cmd}, args...), " "), output, expect) - } - p.Wait() -} - -func TestStartProcess(t *testing.T) { - if runtime.GOOS == "nacl" { - t.Skip("skipping on nacl") - } - - var dir, cmd string - var args []string - if runtime.GOOS == "windows" { - cmd = Getenv("COMSPEC") - dir = Getenv("SystemRoot") - args = []string{"/c", "cd"} - } else { - cmd = "/bin/pwd" - dir = "/" - args = []string{} - } - cmddir, cmdbase := filepath.Split(cmd) - args = append([]string{cmdbase}, args...) - // Test absolute executable path. - exec(t, dir, cmd, args, dir) - // Test relative executable path. - exec(t, cmddir, cmdbase, args, cmddir) -} - -func checkMode(t *testing.T, path string, mode FileMode) { - dir, err := Stat(path) - if err != nil { - t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err) - } - if dir.Mode()&0777 != mode { - t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode) - } -} - -func TestChmod(t *testing.T) { - // Chmod is not supported under windows. - if runtime.GOOS == "windows" { - return - } - f := newFile("TestChmod", t) - defer Remove(f.Name()) - defer f.Close() - - if err := Chmod(f.Name(), 0456); err != nil { - t.Fatalf("chmod %s 0456: %s", f.Name(), err) - } - checkMode(t, f.Name(), 0456) - - if err := f.Chmod(0123); err != nil { - t.Fatalf("chmod %s 0123: %s", f.Name(), err) - } - checkMode(t, f.Name(), 0123) -} - -func checkSize(t *testing.T, f *File, size int64) { - dir, err := f.Stat() - if err != nil { - t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err) - } - if dir.Size() != size { - t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size) - } -} - -func TestFTruncate(t *testing.T) { - f := newFile("TestFTruncate", t) - defer Remove(f.Name()) - defer f.Close() - - checkSize(t, f, 0) - f.Write([]byte("hello, world\n")) - checkSize(t, f, 13) - f.Truncate(10) - checkSize(t, f, 10) - f.Truncate(1024) - checkSize(t, f, 1024) - f.Truncate(0) - checkSize(t, f, 0) - _, err := f.Write([]byte("surprise!")) - if err == nil { - checkSize(t, f, 13+9) // wrote at offset past where hello, world was. - } -} - -func TestTruncate(t *testing.T) { - f := newFile("TestTruncate", t) - defer Remove(f.Name()) - defer f.Close() - - checkSize(t, f, 0) - f.Write([]byte("hello, world\n")) - checkSize(t, f, 13) - Truncate(f.Name(), 10) - checkSize(t, f, 10) - Truncate(f.Name(), 1024) - checkSize(t, f, 1024) - Truncate(f.Name(), 0) - checkSize(t, f, 0) - _, err := f.Write([]byte("surprise!")) - if err == nil { - checkSize(t, f, 13+9) // wrote at offset past where hello, world was. - } -} - -// Use TempDir() to make sure we're on a local file system, -// so that timings are not distorted by latency and caching. -// On NFS, timings can be off due to caching of meta-data on -// NFS servers (Issue 848). -func TestChtimes(t *testing.T) { - f := newFile("TestChtimes", t) - defer Remove(f.Name()) - defer f.Close() - - f.Write([]byte("hello, world\n")) - f.Close() - - st, err := Stat(f.Name()) - if err != nil { - t.Fatalf("Stat %s: %s", f.Name(), err) - } - preStat := st - - // Move access and modification time back a second - at := Atime(preStat) - mt := preStat.ModTime() - err = Chtimes(f.Name(), at.Add(-time.Second), mt.Add(-time.Second)) - if err != nil { - t.Fatalf("Chtimes %s: %s", f.Name(), err) - } - - st, err = Stat(f.Name()) - if err != nil { - t.Fatalf("second Stat %s: %s", f.Name(), err) - } - postStat := st - - /* Plan 9, NaCl: - Mtime is the time of the last change of content. Similarly, atime is set whenever the - contents are accessed; also, it is set whenever mtime is set. - */ - pat := Atime(postStat) - pmt := postStat.ModTime() - if !pat.Before(at) && runtime.GOOS != "plan9" && runtime.GOOS != "nacl" { - t.Errorf("AccessTime didn't go backwards; was=%d, after=%d", at, pat) - } - - if !pmt.Before(mt) { - t.Errorf("ModTime didn't go backwards; was=%d, after=%d", mt, pmt) - } -} - -func TestChdirAndGetwd(t *testing.T) { - // TODO(brainman): file.Chdir() is not implemented on windows. - if runtime.GOOS == "windows" { - return - } - fd, err := Open(".") - if err != nil { - t.Fatalf("Open .: %s", err) - } - // These are chosen carefully not to be symlinks on a Mac - // (unlike, say, /var, /etc, and /tmp). - dirs := []string{"/", "/usr/bin"} - // /usr/bin does not usually exist on Plan 9. - if runtime.GOOS == "plan9" { - dirs = []string{"/", "/usr"} - } - for mode := 0; mode < 2; mode++ { - for _, d := range dirs { - if mode == 0 { - err = Chdir(d) - } else { - fd1, err := Open(d) - if err != nil { - t.Errorf("Open %s: %s", d, err) - continue - } - err = fd1.Chdir() - fd1.Close() - } - pwd, err1 := Getwd() - err2 := fd.Chdir() - if err2 != nil { - // We changed the current directory and cannot go back. - // Don't let the tests continue; they'll scribble - // all over some other directory. - fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2) - Exit(1) - } - if err != nil { - fd.Close() - t.Fatalf("Chdir %s: %s", d, err) - } - if err1 != nil { - fd.Close() - t.Fatalf("Getwd in %s: %s", d, err1) - } - if pwd != d { - fd.Close() - t.Fatalf("Getwd returned %q want %q", pwd, d) - } - } - } - fd.Close() -} - -func TestSeek(t *testing.T) { - f := newFile("TestSeek", t) - defer Remove(f.Name()) - defer f.Close() - - const data = "hello, world\n" - io.WriteString(f, data) - - type test struct { - in int64 - whence int - out int64 - } - var tests = []test{ - {0, 1, int64(len(data))}, - {0, 0, 0}, - {5, 0, 5}, - {0, 2, int64(len(data))}, - {0, 0, 0}, - {-1, 2, int64(len(data)) - 1}, - {1 << 33, 0, 1 << 33}, - {1 << 33, 2, 1<<33 + int64(len(data))}, - } - for i, tt := range tests { - off, err := f.Seek(tt.in, tt.whence) - if off != tt.out || err != nil { - if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 { - // Reiserfs rejects the big seeks. - // http://code.google.com/p/go/issues/detail?id=91 - break - } - t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out) - } - } -} - -type openErrorTest struct { - path string - mode int - error error -} - -var openErrorTests = []openErrorTest{ - { - sfdir + "/no-such-file", - O_RDONLY, - syscall.ENOENT, - }, - { - sfdir, - O_WRONLY, - syscall.EISDIR, - }, - { - sfdir + "/" + sfname + "/no-such-file", - O_WRONLY, - syscall.ENOTDIR, - }, -} - -func TestOpenError(t *testing.T) { - for _, tt := range openErrorTests { - f, err := OpenFile(tt.path, tt.mode, 0) - if err == nil { - t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode) - f.Close() - continue - } - perr, ok := err.(*PathError) - if !ok { - t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err) - } - if perr.Err != tt.error { - if runtime.GOOS == "plan9" { - syscallErrStr := perr.Err.Error() - expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1) - if !strings.HasSuffix(syscallErrStr, expectedErrStr) { - t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr) - } - continue - } - if runtime.GOOS == "dragonfly" { - // DragonFly incorrectly returns EACCES rather - // EISDIR when a directory is opened for write. - if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES { - continue - } - } - t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error()) - } - } -} - -func TestOpenNoName(t *testing.T) { - f, err := Open("") - if err == nil { - t.Fatal(`Open("") succeeded`) - f.Close() - } -} - -func run(t *testing.T, cmd []string) string { - // Run /bin/hostname and collect output. - r, w, err := Pipe() - if err != nil { - t.Fatal(err) - } - defer r.Close() - p, err := StartProcess("/bin/hostname", []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}}) - if err != nil { - t.Fatal(err) - } - w.Close() - - var b bytes.Buffer - io.Copy(&b, r) - _, err = p.Wait() - if err != nil { - t.Fatalf("run hostname Wait: %v", err) - } - err = p.Kill() - if err == nil { - t.Errorf("expected an error from Kill running 'hostname'") - } - output := b.String() - if n := len(output); n > 0 && output[n-1] == '\n' { - output = output[0 : n-1] - } - if output == "" { - t.Fatalf("%v produced no output", cmd) - } - - return output -} - -func TestHostname(t *testing.T) { - // There is no other way to fetch hostname on windows, but via winapi. - // On Plan 9 it is can be taken from #c/sysname as Hostname() does. - switch runtime.GOOS { - case "windows", "plan9", "nacl": - t.Skipf("skipping on %s", runtime.GOOS) - } - - // Check internal Hostname() against the output of /bin/hostname. - // Allow that the internal Hostname returns a Fully Qualified Domain Name - // and the /bin/hostname only returns the first component - hostname, err := Hostname() - if err != nil { - t.Fatalf("%v", err) - } - want := run(t, []string{"/bin/hostname"}) - if hostname != want { - i := strings.Index(hostname, ".") - if i < 0 || hostname[0:i] != want { - t.Errorf("Hostname() = %q, want %q", hostname, want) - } - } -} - -func TestReadAt(t *testing.T) { - f := newFile("TestReadAt", t) - defer Remove(f.Name()) - defer f.Close() - - const data = "hello, world\n" - io.WriteString(f, data) - - b := make([]byte, 5) - n, err := f.ReadAt(b, 7) - if err != nil || n != len(b) { - t.Fatalf("ReadAt 7: %d, %v", n, err) - } - if string(b) != "world" { - t.Fatalf("ReadAt 7: have %q want %q", string(b), "world") - } -} - -func TestWriteAt(t *testing.T) { - f := newFile("TestWriteAt", t) - defer Remove(f.Name()) - defer f.Close() - - const data = "hello, world\n" - io.WriteString(f, data) - - n, err := f.WriteAt([]byte("WORLD"), 7) - if err != nil || n != 5 { - t.Fatalf("WriteAt 7: %d, %v", n, err) - } - - b, err := ioutil.ReadFile(f.Name()) - if err != nil { - t.Fatalf("ReadFile %s: %v", f.Name(), err) - } - if string(b) != "hello, WORLD\n" { - t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n") - } -} - -func writeFile(t *testing.T, fname string, flag int, text string) string { - f, err := OpenFile(fname, flag, 0666) - if err != nil { - t.Fatalf("Open: %v", err) - } - n, err := io.WriteString(f, text) - if err != nil { - t.Fatalf("WriteString: %d, %v", n, err) - } - f.Close() - data, err := ioutil.ReadFile(fname) - if err != nil { - t.Fatalf("ReadFile: %v", err) - } - return string(data) -} - -func TestAppend(t *testing.T) { - const f = "append.txt" - defer Remove(f) - s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new") - if s != "new" { - t.Fatalf("writeFile: have %q want %q", s, "new") - } - s = writeFile(t, f, O_APPEND|O_RDWR, "|append") - if s != "new|append" { - t.Fatalf("writeFile: have %q want %q", s, "new|append") - } - s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append") - if s != "new|append|append" { - t.Fatalf("writeFile: have %q want %q", s, "new|append|append") - } - err := Remove(f) - if err != nil { - t.Fatalf("Remove: %v", err) - } - s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append") - if s != "new&append" { - t.Fatalf("writeFile: after append have %q want %q", s, "new&append") - } - s = writeFile(t, f, O_CREATE|O_RDWR, "old") - if s != "old&append" { - t.Fatalf("writeFile: after create have %q want %q", s, "old&append") - } - s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new") - if s != "new" { - t.Fatalf("writeFile: after truncate have %q want %q", s, "new") - } -} - -func TestStatDirWithTrailingSlash(t *testing.T) { - // Create new temporary directory and arrange to clean it up. - path, err := ioutil.TempDir("", "/_TestStatDirWithSlash_") - if err != nil { - t.Fatalf("TempDir: %s", err) - } - defer RemoveAll(path) - - // Stat of path should succeed. - _, err = Stat(path) - if err != nil { - t.Fatalf("stat %s failed: %s", path, err) - } - - // Stat of path+"/" should succeed too. - path += "/" - _, err = Stat(path) - if err != nil { - t.Fatalf("stat %s failed: %s", path, err) - } -} - -func TestNilProcessStateString(t *testing.T) { - var ps *ProcessState - s := ps.String() - if s != "<nil>" { - t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>") - } -} - -func TestSameFile(t *testing.T) { - fa, err := Create("a") - if err != nil { - t.Fatalf("Create(a): %v", err) - } - defer Remove(fa.Name()) - fa.Close() - fb, err := Create("b") - if err != nil { - t.Fatalf("Create(b): %v", err) - } - defer Remove(fb.Name()) - fb.Close() - - ia1, err := Stat("a") - if err != nil { - t.Fatalf("Stat(a): %v", err) - } - ia2, err := Stat("a") - if err != nil { - t.Fatalf("Stat(a): %v", err) - } - if !SameFile(ia1, ia2) { - t.Errorf("files should be same") - } - - ib, err := Stat("b") - if err != nil { - t.Fatalf("Stat(b): %v", err) - } - if SameFile(ia1, ib) { - t.Errorf("files should be different") - } -} - -func TestDevNullFile(t *testing.T) { - f, err := Open(DevNull) - if err != nil { - t.Fatalf("Open(%s): %v", DevNull, err) - } - defer f.Close() - fi, err := f.Stat() - if err != nil { - t.Fatalf("Stat(%s): %v", DevNull, err) - } - name := filepath.Base(DevNull) - if fi.Name() != name { - t.Fatalf("wrong file name have %v want %v", fi.Name(), name) - } - if fi.Size() != 0 { - t.Fatalf("wrong file size have %d want 0", fi.Size()) - } -} - -var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output") - -func TestLargeWriteToConsole(t *testing.T) { - if !*testLargeWrite { - t.Skip("skipping console-flooding test; enable with -large_write") - } - b := make([]byte, 32000) - for i := range b { - b[i] = '.' - } - b[len(b)-1] = '\n' - n, err := Stdout.Write(b) - if err != nil { - t.Fatalf("Write to os.Stdout failed: %v", err) - } - if n != len(b) { - t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n) - } - n, err = Stderr.Write(b) - if err != nil { - t.Fatalf("Write to os.Stderr failed: %v", err) - } - if n != len(b) { - t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n) - } -} - -func TestStatDirModeExec(t *testing.T) { - const mode = 0111 - - path, err := ioutil.TempDir("", "go-build") - if err != nil { - t.Fatalf("Failed to create temp directory: %v", err) - } - defer RemoveAll(path) - - if err := Chmod(path, 0777); err != nil { - t.Fatalf("Chmod %q 0777: %v", path, err) - } - - dir, err := Stat(path) - if err != nil { - t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err) - } - if dir.Mode()&mode != mode { - t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode) - } -} - -func TestReadAtEOF(t *testing.T) { - f := newFile("TestReadAtEOF", t) - defer Remove(f.Name()) - defer f.Close() - - _, err := f.ReadAt(make([]byte, 10), 0) - switch err { - case io.EOF: - // all good - case nil: - t.Fatalf("ReadAt succeeded") - default: - t.Fatalf("ReadAt failed: %s", err) - } -} - -func testKillProcess(t *testing.T, processKiller func(p *Process)) { - if runtime.GOOS == "nacl" { - t.Skip("skipping on nacl") - } - - dir, err := ioutil.TempDir("", "go-build") - if err != nil { - t.Fatalf("Failed to create temp directory: %v", err) - } - defer RemoveAll(dir) - - src := filepath.Join(dir, "main.go") - f, err := Create(src) - if err != nil { - t.Fatalf("Failed to create %v: %v", src, err) - } - st := template.Must(template.New("source").Parse(` -package main -import "time" -func main() { - time.Sleep(time.Second) -} -`)) - err = st.Execute(f, nil) - if err != nil { - f.Close() - t.Fatalf("Failed to execute template: %v", err) - } - f.Close() - - exe := filepath.Join(dir, "main.exe") - output, err := osexec.Command("go", "build", "-o", exe, src).CombinedOutput() - if err != nil { - t.Fatalf("Failed to build exe %v: %v %v", exe, err, string(output)) - } - - cmd := osexec.Command(exe) - err = cmd.Start() - if err != nil { - t.Fatalf("Failed to start test process: %v", err) - } - go func() { - time.Sleep(100 * time.Millisecond) - processKiller(cmd.Process) - }() - err = cmd.Wait() - if err == nil { - t.Errorf("Test process succeeded, but expected to fail") - } -} - -func TestKillStartProcess(t *testing.T) { - testKillProcess(t, func(p *Process) { - err := p.Kill() - if err != nil { - t.Fatalf("Failed to kill test process: %v", err) - } - }) -} - -func TestKillFindProcess(t *testing.T) { - testKillProcess(t, func(p *Process) { - p2, err := FindProcess(p.Pid) - if err != nil { - t.Fatalf("Failed to find test process: %v", err) - } - err = p2.Kill() - if err != nil { - t.Fatalf("Failed to kill test process: %v", err) - } - }) -} - -var nilFileMethodTests = []struct { - name string - f func(*File) error -}{ - {"Chdir", func(f *File) error { return f.Chdir() }}, - {"Close", func(f *File) error { return f.Close() }}, - {"Chmod", func(f *File) error { return f.Chmod(0) }}, - {"Chown", func(f *File) error { return f.Chown(0, 0) }}, - {"Read", func(f *File) error { _, err := f.Read(make([]byte, 0)); return err }}, - {"ReadAt", func(f *File) error { _, err := f.ReadAt(make([]byte, 0), 0); return err }}, - {"Readdir", func(f *File) error { _, err := f.Readdir(1); return err }}, - {"Readdirnames", func(f *File) error { _, err := f.Readdirnames(1); return err }}, - {"Seek", func(f *File) error { _, err := f.Seek(0, 0); return err }}, - {"Stat", func(f *File) error { _, err := f.Stat(); return err }}, - {"Sync", func(f *File) error { return f.Sync() }}, - {"Truncate", func(f *File) error { return f.Truncate(0) }}, - {"Write", func(f *File) error { _, err := f.Write(make([]byte, 0)); return err }}, - {"WriteAt", func(f *File) error { _, err := f.WriteAt(make([]byte, 0), 0); return err }}, - {"WriteString", func(f *File) error { _, err := f.WriteString(""); return err }}, -} - -// Test that all File methods give ErrInvalid if the receiver is nil. -func TestNilFileMethods(t *testing.T) { - for _, tt := range nilFileMethodTests { - var file *File - got := tt.f(file) - if got != ErrInvalid { - t.Errorf("%v should fail when f is nil; got %v", tt.name, got) - } - } -} diff --git a/src/pkg/os/os_unix_test.go b/src/pkg/os/os_unix_test.go deleted file mode 100644 index 21d40ccaf..000000000 --- a/src/pkg/os/os_unix_test.go +++ /dev/null @@ -1,76 +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. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package os_test - -import ( - . "os" - "runtime" - "syscall" - "testing" -) - -func checkUidGid(t *testing.T, path string, uid, gid int) { - dir, err := Stat(path) - if err != nil { - t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err) - } - sys := dir.Sys().(*syscall.Stat_t) - if int(sys.Uid) != uid { - t.Errorf("Stat %q: uid %d want %d", path, sys.Uid, uid) - } - if int(sys.Gid) != gid { - t.Errorf("Stat %q: gid %d want %d", path, sys.Gid, gid) - } -} - -func TestChown(t *testing.T) { - // Chown is not supported under windows os Plan 9. - // Plan9 provides a native ChownPlan9 version instead. - if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { - return - } - // Use TempDir() to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. On NFS, the Getgroups groups are - // basically useless. - f := newFile("TestChown", t) - defer Remove(f.Name()) - defer f.Close() - dir, err := f.Stat() - if err != nil { - t.Fatalf("stat %s: %s", f.Name(), err) - } - - // Can't change uid unless root, but can try - // changing the group id. First try our current group. - gid := Getgid() - t.Log("gid:", gid) - if err = Chown(f.Name(), -1, gid); err != nil { - t.Fatalf("chown %s -1 %d: %s", f.Name(), gid, err) - } - sys := dir.Sys().(*syscall.Stat_t) - checkUidGid(t, f.Name(), int(sys.Uid), gid) - - // Then try all the auxiliary groups. - groups, err := Getgroups() - if err != nil { - t.Fatalf("getgroups: %s", err) - } - t.Log("groups: ", groups) - for _, g := range groups { - if err = Chown(f.Name(), -1, g); err != nil { - t.Fatalf("chown %s -1 %d: %s", f.Name(), g, err) - } - checkUidGid(t, f.Name(), int(sys.Uid), g) - - // change back to gid to test fd.Chown - if err = f.Chown(-1, gid); err != nil { - t.Fatalf("fchown %s -1 %d: %s", f.Name(), gid, err) - } - checkUidGid(t, f.Name(), int(sys.Uid), gid) - } -} diff --git a/src/pkg/os/path.go b/src/pkg/os/path.go deleted file mode 100644 index 02a77ec80..000000000 --- a/src/pkg/os/path.go +++ /dev/null @@ -1,123 +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 - -import ( - "io" - "syscall" -) - -// MkdirAll creates a directory named path, -// along with any necessary parents, and returns nil, -// or else returns an error. -// The permission bits perm are used for all -// directories that MkdirAll creates. -// If path is already a directory, MkdirAll does nothing -// and returns nil. -func MkdirAll(path string, perm FileMode) error { - // If path exists, stop with success or error. - dir, err := Stat(path) - if err == nil { - if dir.IsDir() { - return nil - } - return &PathError{"mkdir", path, syscall.ENOTDIR} - } - - // Doesn't already exist; make sure parent does. - i := len(path) - for i > 0 && IsPathSeparator(path[i-1]) { // Skip trailing path separator. - i-- - } - - j := i - for j > 0 && !IsPathSeparator(path[j-1]) { // Scan backward over element. - j-- - } - - if j > 1 { - // Create parent - err = MkdirAll(path[0:j-1], perm) - if err != nil { - return err - } - } - - // Now parent exists, try to create. - err = Mkdir(path, perm) - if err != nil { - // Handle arguments like "foo/." by - // double-checking that directory doesn't exist. - dir, err1 := Lstat(path) - if err1 == nil && dir.IsDir() { - return nil - } - return err - } - return nil -} - -// RemoveAll removes path and any children it contains. -// It removes everything it can but returns the first error -// it encounters. If the path does not exist, RemoveAll -// returns nil (no error). -func RemoveAll(path string) error { - // Simple case: if Remove works, we're done. - err := Remove(path) - if err == nil { - return nil - } - - // Otherwise, is this a directory we need to recurse into? - dir, serr := Lstat(path) - if serr != nil { - if serr, ok := serr.(*PathError); ok && (IsNotExist(serr.Err) || serr.Err == syscall.ENOTDIR) { - return nil - } - return serr - } - if !dir.IsDir() { - // Not a directory; return the error from Remove. - return err - } - - // Directory. - fd, err := Open(path) - if err != nil { - return err - } - - // Remove contents & return first error. - err = nil - for { - names, err1 := fd.Readdirnames(100) - for _, name := range names { - err1 := RemoveAll(path + string(PathSeparator) + name) - if err == nil { - err = err1 - } - } - if err1 == io.EOF { - break - } - // If Readdirnames returned an error, use it. - if err == nil { - err = err1 - } - if len(names) == 0 { - break - } - } - - // Close directory, because windows won't remove opened directory. - fd.Close() - - // Remove directory. - err1 := Remove(path) - if err == nil { - err = err1 - } - return err -} diff --git a/src/pkg/os/path_plan9.go b/src/pkg/os/path_plan9.go deleted file mode 100644 index 64bad500a..000000000 --- a/src/pkg/os/path_plan9.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2011 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 - -const ( - PathSeparator = '/' // OS-specific path separator - PathListSeparator = '\000' // OS-specific path list separator -) - -// IsPathSeparator returns true if c is a directory separator character. -func IsPathSeparator(c uint8) bool { - return PathSeparator == c -} diff --git a/src/pkg/os/path_test.go b/src/pkg/os/path_test.go deleted file mode 100644 index 3af21cde9..000000000 --- a/src/pkg/os/path_test.go +++ /dev/null @@ -1,215 +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_test - -import ( - "io/ioutil" - . "os" - "path/filepath" - "runtime" - "syscall" - "testing" -) - -func TestMkdirAll(t *testing.T) { - tmpDir := TempDir() - path := tmpDir + "/_TestMkdirAll_/dir/./dir2" - err := MkdirAll(path, 0777) - if err != nil { - t.Fatalf("MkdirAll %q: %s", path, err) - } - defer RemoveAll(tmpDir + "/_TestMkdirAll_") - - // Already exists, should succeed. - err = MkdirAll(path, 0777) - if err != nil { - t.Fatalf("MkdirAll %q (second time): %s", path, err) - } - - // Make file. - fpath := path + "/file" - f, err := Create(fpath) - if err != nil { - t.Fatalf("create %q: %s", fpath, err) - } - defer f.Close() - - // Can't make directory named after file. - err = MkdirAll(fpath, 0777) - if err == nil { - t.Fatalf("MkdirAll %q: no error", fpath) - } - perr, ok := err.(*PathError) - if !ok { - t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err) - } - if filepath.Clean(perr.Path) != filepath.Clean(fpath) { - t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, filepath.Clean(perr.Path), filepath.Clean(fpath)) - } - - // Can't make subdirectory of file. - ffpath := fpath + "/subdir" - err = MkdirAll(ffpath, 0777) - if err == nil { - t.Fatalf("MkdirAll %q: no error", ffpath) - } - perr, ok = err.(*PathError) - if !ok { - t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err) - } - if filepath.Clean(perr.Path) != filepath.Clean(fpath) { - t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath)) - } - - if runtime.GOOS == "windows" { - path := tmpDir + `\_TestMkdirAll_\dir\.\dir2\` - err := MkdirAll(path, 0777) - if err != nil { - t.Fatalf("MkdirAll %q: %s", path, err) - } - } -} - -func TestRemoveAll(t *testing.T) { - tmpDir := TempDir() - // Work directory. - path := tmpDir + "/_TestRemoveAll_" - fpath := path + "/file" - dpath := path + "/dir" - - // Make directory with 1 file and remove. - if err := MkdirAll(path, 0777); err != nil { - t.Fatalf("MkdirAll %q: %s", path, err) - } - fd, err := Create(fpath) - if err != nil { - t.Fatalf("create %q: %s", fpath, err) - } - fd.Close() - if err = RemoveAll(path); err != nil { - t.Fatalf("RemoveAll %q (first): %s", path, err) - } - if _, err = Lstat(path); err == nil { - t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path) - } - - // Make directory with file and subdirectory and remove. - if err = MkdirAll(dpath, 0777); err != nil { - t.Fatalf("MkdirAll %q: %s", dpath, err) - } - fd, err = Create(fpath) - if err != nil { - t.Fatalf("create %q: %s", fpath, err) - } - fd.Close() - fd, err = Create(dpath + "/file") - if err != nil { - t.Fatalf("create %q: %s", fpath, err) - } - fd.Close() - if err = RemoveAll(path); err != nil { - t.Fatalf("RemoveAll %q (second): %s", path, err) - } - if _, err := Lstat(path); err == nil { - t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path) - } - - // Determine if we should run the following test. - testit := true - if runtime.GOOS == "windows" { - // Chmod is not supported under windows. - testit = false - } else { - // Test fails as root. - testit = Getuid() != 0 - } - if testit { - // Make directory with file and subdirectory and trigger error. - if err = MkdirAll(dpath, 0777); err != nil { - t.Fatalf("MkdirAll %q: %s", dpath, err) - } - - for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} { - fd, err = Create(s) - if err != nil { - t.Fatalf("create %q: %s", s, err) - } - fd.Close() - } - if err = Chmod(dpath, 0); err != nil { - t.Fatalf("Chmod %q 0: %s", dpath, err) - } - - // No error checking here: either RemoveAll - // will or won't be able to remove dpath; - // either way we want to see if it removes fpath - // and path/zzz. Reasons why RemoveAll might - // succeed in removing dpath as well include: - // * running as root - // * running on a file system without permissions (FAT) - RemoveAll(path) - Chmod(dpath, 0777) - - for _, s := range []string{fpath, path + "/zzz"} { - if _, err = Lstat(s); err == nil { - t.Fatalf("Lstat %q succeeded after partial RemoveAll", s) - } - } - } - if err = RemoveAll(path); err != nil { - t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err) - } - if _, err = Lstat(path); err == nil { - t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path) - } -} - -func TestMkdirAllWithSymlink(t *testing.T) { - switch runtime.GOOS { - case "nacl", "plan9", "windows": - t.Skipf("skipping on %s", runtime.GOOS) - } - - tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-") - if err != nil { - t.Fatal(err) - } - defer RemoveAll(tmpDir) - - dir := tmpDir + "/dir" - err = Mkdir(dir, 0755) - if err != nil { - t.Fatalf("Mkdir %s: %s", dir, err) - } - - link := tmpDir + "/link" - err = Symlink("dir", link) - if err != nil { - t.Fatalf("Symlink %s: %s", link, err) - } - - path := link + "/foo" - err = MkdirAll(path, 0755) - if err != nil { - t.Errorf("MkdirAll %q: %s", path, err) - } -} - -func TestMkdirAllAtSlash(t *testing.T) { - if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { - return - } - RemoveAll("/_go_os_test") - err := MkdirAll("/_go_os_test/dir", 0777) - if err != nil { - pathErr, ok := err.(*PathError) - // common for users not to be able to write to / - if ok && pathErr.Err == syscall.EACCES { - return - } - t.Fatalf(`MkdirAll "/_go_os_test/dir": %v`, err) - } - RemoveAll("/_go_os_test") -} diff --git a/src/pkg/os/path_unix.go b/src/pkg/os/path_unix.go deleted file mode 100644 index 0211107dd..000000000 --- a/src/pkg/os/path_unix.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2011 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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris - -package os - -const ( - PathSeparator = '/' // OS-specific path separator - PathListSeparator = ':' // OS-specific path list separator -) - -// IsPathSeparator returns true if c is a directory separator character. -func IsPathSeparator(c uint8) bool { - return PathSeparator == c -} diff --git a/src/pkg/os/path_windows.go b/src/pkg/os/path_windows.go deleted file mode 100644 index 61f2ca59f..000000000 --- a/src/pkg/os/path_windows.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2011 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 - -const ( - PathSeparator = '\\' // OS-specific path separator - PathListSeparator = ';' // OS-specific path list separator -) - -// IsPathSeparator returns true if c is a directory separator character. -func IsPathSeparator(c uint8) bool { - // NOTE: Windows accept / as path separator. - return c == '\\' || c == '/' -} diff --git a/src/pkg/os/pipe_bsd.go b/src/pkg/os/pipe_bsd.go deleted file mode 100644 index 3b81ed20f..000000000 --- a/src/pkg/os/pipe_bsd.go +++ /dev/null @@ -1,28 +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. - -// +build darwin dragonfly freebsd nacl netbsd openbsd solaris - -package os - -import "syscall" - -// Pipe returns a connected pair of Files; reads from r return bytes written to w. -// It returns the files and an error, if any. -func Pipe() (r *File, w *File, err error) { - var p [2]int - - // See ../syscall/exec.go for description of lock. - syscall.ForkLock.RLock() - e := syscall.Pipe(p[0:]) - if e != nil { - syscall.ForkLock.RUnlock() - return nil, nil, NewSyscallError("pipe", e) - } - syscall.CloseOnExec(p[0]) - syscall.CloseOnExec(p[1]) - syscall.ForkLock.RUnlock() - - return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil -} diff --git a/src/pkg/os/pipe_linux.go b/src/pkg/os/pipe_linux.go deleted file mode 100644 index 9bafad84f..000000000 --- a/src/pkg/os/pipe_linux.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 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 - -import "syscall" - -// Pipe returns a connected pair of Files; reads from r return bytes written to w. -// It returns the files and an error, if any. -func Pipe() (r *File, w *File, err error) { - var p [2]int - - e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC) - // pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it - // might not be implemented. - if e == syscall.ENOSYS { - // See ../syscall/exec.go for description of lock. - syscall.ForkLock.RLock() - e = syscall.Pipe(p[0:]) - if e != nil { - syscall.ForkLock.RUnlock() - return nil, nil, NewSyscallError("pipe", e) - } - syscall.CloseOnExec(p[0]) - syscall.CloseOnExec(p[1]) - syscall.ForkLock.RUnlock() - } else if e != nil { - return nil, nil, NewSyscallError("pipe2", e) - } - - return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil -} diff --git a/src/pkg/os/proc.go b/src/pkg/os/proc.go deleted file mode 100644 index 38c436ec5..000000000 --- a/src/pkg/os/proc.go +++ /dev/null @@ -1,36 +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. - -// Process etc. - -package os - -import "syscall" - -// Args hold the command-line arguments, starting with the program name. -var Args []string - -// Getuid returns the numeric user id of the caller. -func Getuid() int { return syscall.Getuid() } - -// Geteuid returns the numeric effective user id of the caller. -func Geteuid() int { return syscall.Geteuid() } - -// Getgid returns the numeric group id of the caller. -func Getgid() int { return syscall.Getgid() } - -// Getegid returns the numeric effective group id of the caller. -func Getegid() int { return syscall.Getegid() } - -// Getgroups returns a list of the numeric ids of groups that the caller belongs to. -func Getgroups() ([]int, error) { - gids, e := syscall.Getgroups() - return gids, NewSyscallError("getgroups", e) -} - -// Exit causes the current program to exit with the given status code. -// Conventionally, code zero indicates success, non-zero an error. -// The program terminates immediately; deferred functions are -// not run. -func Exit(code int) { syscall.Exit(code) } diff --git a/src/pkg/os/signal/example_test.go b/src/pkg/os/signal/example_test.go deleted file mode 100644 index 079ee5070..000000000 --- a/src/pkg/os/signal/example_test.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 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 signal_test - -import ( - "fmt" - "os" - "os/signal" -) - -func ExampleNotify() { - // Set up channel on which to send signal notifications. - // We must use a buffered channel or risk missing the signal - // if we're not ready to receive when the signal is sent. - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, os.Kill) - - // Block until a signal is received. - s := <-c - fmt.Println("Got signal:", s) -} diff --git a/src/pkg/os/signal/sig.s b/src/pkg/os/signal/sig.s deleted file mode 100644 index f860924aa..000000000 --- a/src/pkg/os/signal/sig.s +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 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. - -// Assembly to get into package runtime without using exported symbols. - -// +build amd64 amd64p32 arm 386 - -#include "../../../cmd/ld/textflag.h" - -#ifdef GOARCH_arm -#define JMP B -#endif - -TEXT ·signal_disable(SB),NOSPLIT,$0 - JMP runtime·signal_disable(SB) - -TEXT ·signal_enable(SB),NOSPLIT,$0 - JMP runtime·signal_enable(SB) - -TEXT ·signal_recv(SB),NOSPLIT,$0 - JMP runtime·signal_recv(SB) - diff --git a/src/pkg/os/signal/signal.go b/src/pkg/os/signal/signal.go deleted file mode 100644 index 300427549..000000000 --- a/src/pkg/os/signal/signal.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2012 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 signal implements access to incoming signals. -package signal - -// BUG(rsc): This package is not yet implemented on Plan 9. - -import ( - "os" - "sync" -) - -var handlers struct { - sync.Mutex - m map[chan<- os.Signal]*handler - ref [numSig]int64 -} - -type handler struct { - mask [(numSig + 31) / 32]uint32 -} - -func (h *handler) want(sig int) bool { - return (h.mask[sig/32]>>uint(sig&31))&1 != 0 -} - -func (h *handler) set(sig int) { - h.mask[sig/32] |= 1 << uint(sig&31) -} - -// Notify causes package signal to relay incoming signals to c. -// If no signals are listed, all incoming signals will be relayed to c. -// Otherwise, just the listed signals will. -// -// Package signal will not block sending to c: the caller must ensure -// that c has sufficient buffer space to keep up with the expected -// signal rate. For a channel used for notification of just one signal value, -// a buffer of size 1 is sufficient. -// -// It is allowed to call Notify multiple times with the same channel: -// each call expands the set of signals sent to that channel. -// The only way to remove signals from the set is to call Stop. -// -// It is allowed to call Notify multiple times with different channels -// and the same signals: each channel receives copies of incoming -// signals independently. -func Notify(c chan<- os.Signal, sig ...os.Signal) { - if c == nil { - panic("os/signal: Notify using nil channel") - } - - handlers.Lock() - defer handlers.Unlock() - - h := handlers.m[c] - if h == nil { - if handlers.m == nil { - handlers.m = make(map[chan<- os.Signal]*handler) - } - h = new(handler) - handlers.m[c] = h - } - - add := func(n int) { - if n < 0 { - return - } - if !h.want(n) { - h.set(n) - if handlers.ref[n] == 0 { - enableSignal(n) - } - handlers.ref[n]++ - } - } - - if len(sig) == 0 { - for n := 0; n < numSig; n++ { - add(n) - } - } else { - for _, s := range sig { - add(signum(s)) - } - } -} - -// Stop causes package signal to stop relaying incoming signals to c. -// It undoes the effect of all prior calls to Notify using c. -// When Stop returns, it is guaranteed that c will receive no more signals. -func Stop(c chan<- os.Signal) { - handlers.Lock() - defer handlers.Unlock() - - h := handlers.m[c] - if h == nil { - return - } - delete(handlers.m, c) - - for n := 0; n < numSig; n++ { - if h.want(n) { - handlers.ref[n]-- - if handlers.ref[n] == 0 { - disableSignal(n) - } - } - } -} - -func process(sig os.Signal) { - n := signum(sig) - if n < 0 { - return - } - - handlers.Lock() - defer handlers.Unlock() - - for c, h := range handlers.m { - if h.want(n) { - // send but do not block for it - select { - case c <- sig: - default: - } - } - } -} diff --git a/src/pkg/os/signal/signal_stub.go b/src/pkg/os/signal/signal_stub.go deleted file mode 100644 index d0a6935ff..000000000 --- a/src/pkg/os/signal/signal_stub.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2012 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. - -// +build plan9 - -package signal - -import "os" - -const numSig = 0 - -func signum(sig os.Signal) int { return -1 } - -func disableSignal(int) {} - -func enableSignal(int) {} diff --git a/src/pkg/os/signal/signal_test.go b/src/pkg/os/signal/signal_test.go deleted file mode 100644 index 076fe3f93..000000000 --- a/src/pkg/os/signal/signal_test.go +++ /dev/null @@ -1,208 +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. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris - -package signal - -import ( - "flag" - "io/ioutil" - "os" - "os/exec" - "runtime" - "strconv" - "syscall" - "testing" - "time" -) - -func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) { - select { - case s := <-c: - if s != sig { - t.Fatalf("signal was %v, want %v", s, sig) - } - case <-time.After(1 * time.Second): - t.Fatalf("timeout waiting for %v", sig) - } -} - -// Test that basic signal handling works. -func TestSignal(t *testing.T) { - // Ask for SIGHUP - c := make(chan os.Signal, 1) - Notify(c, syscall.SIGHUP) - defer Stop(c) - - // Send this process a SIGHUP - t.Logf("sighup...") - syscall.Kill(syscall.Getpid(), syscall.SIGHUP) - waitSig(t, c, syscall.SIGHUP) - - // Ask for everything we can get. - c1 := make(chan os.Signal, 1) - Notify(c1) - - // Send this process a SIGWINCH - t.Logf("sigwinch...") - syscall.Kill(syscall.Getpid(), syscall.SIGWINCH) - waitSig(t, c1, syscall.SIGWINCH) - - // Send two more SIGHUPs, to make sure that - // they get delivered on c1 and that not reading - // from c does not block everything. - t.Logf("sighup...") - syscall.Kill(syscall.Getpid(), syscall.SIGHUP) - waitSig(t, c1, syscall.SIGHUP) - t.Logf("sighup...") - syscall.Kill(syscall.Getpid(), syscall.SIGHUP) - waitSig(t, c1, syscall.SIGHUP) - - // The first SIGHUP should be waiting for us on c. - waitSig(t, c, syscall.SIGHUP) -} - -func TestStress(t *testing.T) { - dur := 3 * time.Second - if testing.Short() { - dur = 100 * time.Millisecond - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - done := make(chan bool) - finished := make(chan bool) - go func() { - sig := make(chan os.Signal, 1) - Notify(sig, syscall.SIGUSR1) - defer Stop(sig) - Loop: - for { - select { - case <-sig: - case <-done: - break Loop - } - } - finished <- true - }() - go func() { - Loop: - for { - select { - case <-done: - break Loop - default: - syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) - runtime.Gosched() - } - } - finished <- true - }() - time.Sleep(dur) - close(done) - <-finished - <-finished - // When run with 'go test -cpu=1,2,4' SIGUSR1 from this test can slip - // into subsequent TestSignal() causing failure. - // Sleep for a while to reduce the possibility of the failure. - time.Sleep(10 * time.Millisecond) -} - -var sendUncaughtSighup = flag.Int("send_uncaught_sighup", 0, "send uncaught SIGHUP during TestStop") - -// Test that Stop cancels the channel's registrations. -func TestStop(t *testing.T) { - sigs := []syscall.Signal{ - syscall.SIGWINCH, - syscall.SIGHUP, - } - - for _, sig := range sigs { - // Send the signal. - // If it's SIGWINCH, we should not see it. - // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do. - if sig != syscall.SIGHUP || *sendUncaughtSighup == 1 { - syscall.Kill(syscall.Getpid(), sig) - } - time.Sleep(10 * time.Millisecond) - - // Ask for signal - c := make(chan os.Signal, 1) - Notify(c, sig) - defer Stop(c) - - // Send this process that signal - syscall.Kill(syscall.Getpid(), sig) - waitSig(t, c, sig) - - Stop(c) - select { - case s := <-c: - t.Fatalf("unexpected signal %v", s) - case <-time.After(10 * time.Millisecond): - // nothing to read - good - } - - // Send the signal. - // If it's SIGWINCH, we should not see it. - // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do. - if sig != syscall.SIGHUP || *sendUncaughtSighup == 2 { - syscall.Kill(syscall.Getpid(), sig) - } - - select { - case s := <-c: - t.Fatalf("unexpected signal %v", s) - case <-time.After(10 * time.Millisecond): - // nothing to read - good - } - } -} - -// Test that when run under nohup, an uncaught SIGHUP does not kill the program, -// but a -func TestNohup(t *testing.T) { - // Ugly: ask for SIGHUP so that child will not have no-hup set - // even if test is running under nohup environment. - // We have no intention of reading from c. - c := make(chan os.Signal, 1) - Notify(c, syscall.SIGHUP) - - // When run without nohup, the test should crash on an uncaught SIGHUP. - // When run under nohup, the test should ignore uncaught SIGHUPs, - // because the runtime is not supposed to be listening for them. - // Either way, TestStop should still be able to catch them when it wants them - // and then when it stops wanting them, the original behavior should resume. - // - // send_uncaught_sighup=1 sends the SIGHUP before starting to listen for SIGHUPs. - // send_uncaught_sighup=2 sends the SIGHUP after no longer listening for SIGHUPs. - // - // Both should fail without nohup and succeed with nohup. - - for i := 1; i <= 2; i++ { - out, err := exec.Command(os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput() - if err == nil { - t.Fatalf("ran test with -send_uncaught_sighup=%d and it succeeded: expected failure.\nOutput:\n%s", i, out) - } - } - - Stop(c) - - // Again, this time with nohup, assuming we can find it. - _, err := os.Stat("/usr/bin/nohup") - if err != nil { - t.Skip("cannot find nohup; skipping second half of test") - } - - for i := 1; i <= 2; i++ { - os.Remove("nohup.out") - out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput() - - data, _ := ioutil.ReadFile("nohup.out") - os.Remove("nohup.out") - if err != nil { - t.Fatalf("ran test with -send_uncaught_sighup=%d under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", i, err, out, data) - } - } -} diff --git a/src/pkg/os/signal/signal_unix.go b/src/pkg/os/signal/signal_unix.go deleted file mode 100644 index 94b8ab3dd..000000000 --- a/src/pkg/os/signal/signal_unix.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2012 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. - -// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows - -package signal - -import ( - "os" - "syscall" -) - -// In assembly. -func signal_disable(uint32) -func signal_enable(uint32) -func signal_recv() uint32 - -func loop() { - for { - process(syscall.Signal(signal_recv())) - } -} - -func init() { - signal_enable(0) // first call - initialize - go loop() -} - -const ( - numSig = 65 // max across all systems -) - -func signum(sig os.Signal) int { - switch sig := sig.(type) { - case syscall.Signal: - i := int(sig) - if i < 0 || i >= numSig { - return -1 - } - return i - default: - return -1 - } -} - -func enableSignal(sig int) { - signal_enable(uint32(sig)) -} - -func disableSignal(sig int) { - signal_disable(uint32(sig)) -} diff --git a/src/pkg/os/signal/signal_windows_test.go b/src/pkg/os/signal/signal_windows_test.go deleted file mode 100644 index f3e6706b7..000000000 --- a/src/pkg/os/signal/signal_windows_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2012 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 signal - -import ( - "bytes" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "syscall" - "testing" - "time" -) - -func sendCtrlBreak(t *testing.T, pid int) { - d, e := syscall.LoadDLL("kernel32.dll") - if e != nil { - t.Fatalf("LoadDLL: %v\n", e) - } - p, e := d.FindProc("GenerateConsoleCtrlEvent") - if e != nil { - t.Fatalf("FindProc: %v\n", e) - } - r, _, e := p.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid)) - if r == 0 { - t.Fatalf("GenerateConsoleCtrlEvent: %v\n", e) - } -} - -func TestCtrlBreak(t *testing.T) { - // create source file - const source = ` -package main - -import ( - "log" - "os" - "os/signal" - "time" -) - - -func main() { - c := make(chan os.Signal, 10) - signal.Notify(c) - select { - case s := <-c: - if s != os.Interrupt { - log.Fatalf("Wrong signal received: got %q, want %q\n", s, os.Interrupt) - } - case <-time.After(3 * time.Second): - log.Fatalf("Timeout waiting for Ctrl+Break\n") - } -} -` - tmp, err := ioutil.TempDir("", "TestCtrlBreak") - if err != nil { - t.Fatal("TempDir failed: ", err) - } - defer os.RemoveAll(tmp) - - // write ctrlbreak.go - name := filepath.Join(tmp, "ctlbreak") - src := name + ".go" - f, err := os.Create(src) - if err != nil { - t.Fatalf("Failed to create %v: %v", src, err) - } - defer f.Close() - f.Write([]byte(source)) - - // compile it - exe := name + ".exe" - defer os.Remove(exe) - o, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput() - if err != nil { - t.Fatalf("Failed to compile: %v\n%v", err, string(o)) - } - - // run it - cmd := exec.Command(exe) - var b bytes.Buffer - cmd.Stdout = &b - cmd.Stderr = &b - cmd.SysProcAttr = &syscall.SysProcAttr{ - CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP, - } - err = cmd.Start() - if err != nil { - t.Fatalf("Start failed: %v", err) - } - go func() { - time.Sleep(1 * time.Second) - sendCtrlBreak(t, cmd.Process.Pid) - }() - err = cmd.Wait() - if err != nil { - t.Fatalf("Program exited with error: %v\n%v", err, string(b.Bytes())) - } -} diff --git a/src/pkg/os/stat_darwin.go b/src/pkg/os/stat_darwin.go deleted file mode 100644 index 0eea52201..000000000 --- a/src/pkg/os/stat_darwin.go +++ /dev/null @@ -1,61 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtimespec), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK, syscall.S_IFWHT: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec) -} diff --git a/src/pkg/os/stat_dragonfly.go b/src/pkg/os/stat_dragonfly.go deleted file mode 100644 index 605c1d9b6..000000000 --- a/src/pkg/os/stat_dragonfly.go +++ /dev/null @@ -1,61 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtim), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim) -} diff --git a/src/pkg/os/stat_freebsd.go b/src/pkg/os/stat_freebsd.go deleted file mode 100644 index 2ffb60fe2..000000000 --- a/src/pkg/os/stat_freebsd.go +++ /dev/null @@ -1,61 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtimespec), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec) -} diff --git a/src/pkg/os/stat_linux.go b/src/pkg/os/stat_linux.go deleted file mode 100644 index 605c1d9b6..000000000 --- a/src/pkg/os/stat_linux.go +++ /dev/null @@ -1,61 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtim), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim) -} diff --git a/src/pkg/os/stat_nacl.go b/src/pkg/os/stat_nacl.go deleted file mode 100644 index a503b59fa..000000000 --- a/src/pkg/os/stat_nacl.go +++ /dev/null @@ -1,62 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtime, st.MtimeNsec), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(sec, nsec int64) time.Time { - return time.Unix(sec, nsec) -} - -// For testing. -func atime(fi FileInfo) time.Time { - st := fi.Sys().(*syscall.Stat_t) - return timespecToTime(st.Atime, st.AtimeNsec) -} diff --git a/src/pkg/os/stat_netbsd.go b/src/pkg/os/stat_netbsd.go deleted file mode 100644 index 2ffb60fe2..000000000 --- a/src/pkg/os/stat_netbsd.go +++ /dev/null @@ -1,61 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtimespec), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atimespec) -} diff --git a/src/pkg/os/stat_openbsd.go b/src/pkg/os/stat_openbsd.go deleted file mode 100644 index 605c1d9b6..000000000 --- a/src/pkg/os/stat_openbsd.go +++ /dev/null @@ -1,61 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtim), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim) -} diff --git a/src/pkg/os/stat_plan9.go b/src/pkg/os/stat_plan9.go deleted file mode 100644 index 25c9a8c14..000000000 --- a/src/pkg/os/stat_plan9.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2011 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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - a := fs1.sys.(*syscall.Dir) - b := fs2.sys.(*syscall.Dir) - return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev -} - -func fileInfoFromStat(d *syscall.Dir) FileInfo { - fs := &fileStat{ - name: d.Name, - size: int64(d.Length), - modTime: time.Unix(int64(d.Mtime), 0), - sys: d, - } - fs.mode = FileMode(d.Mode & 0777) - if d.Mode&syscall.DMDIR != 0 { - fs.mode |= ModeDir - } - if d.Mode&syscall.DMAPPEND != 0 { - fs.mode |= ModeAppend - } - if d.Mode&syscall.DMEXCL != 0 { - fs.mode |= ModeExclusive - } - if d.Mode&syscall.DMTMP != 0 { - fs.mode |= ModeTemporary - } - return fs -} - -// arg is an open *File or a path string. -func dirstat(arg interface{}) (*syscall.Dir, error) { - var name string - - // This is big enough for most stat messages - // and rounded to a multiple of 128 bytes. - size := (syscall.STATFIXLEN + 16*4 + 128) &^ 128 - - for i := 0; i < 2; i++ { - buf := make([]byte, size) - - var n int - var err error - switch a := arg.(type) { - case *File: - name = a.name - n, err = syscall.Fstat(a.fd, buf) - case string: - name = a - n, err = syscall.Stat(a, buf) - default: - panic("phase error in dirstat") - } - if err != nil { - return nil, &PathError{"stat", name, err} - } - if n < syscall.STATFIXLEN { - return nil, &PathError{"stat", name, syscall.ErrShortStat} - } - - // Pull the real size out of the stat message. - size = int(uint16(buf[0]) | uint16(buf[1])<<8) - - // If the stat message is larger than our buffer we will - // go around the loop and allocate one that is big enough. - if size > n { - continue - } - - d, err := syscall.UnmarshalDir(buf[:n]) - if err != nil { - return nil, &PathError{"stat", name, err} - } - return d, nil - } - return nil, &PathError{"stat", name, syscall.ErrBadStat} -} - -// Stat returns a FileInfo describing the named file. -// If there is an error, it will be of type *PathError. -func Stat(name string) (fi FileInfo, err error) { - d, err := dirstat(name) - if err != nil { - return nil, err - } - return fileInfoFromStat(d), nil -} - -// Lstat returns a FileInfo describing the named file. -// If the file is a symbolic link, the returned FileInfo -// describes the symbolic link. Lstat makes no attempt to follow the link. -// If there is an error, it will be of type *PathError. -func Lstat(name string) (fi FileInfo, err error) { - return Stat(name) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return time.Unix(int64(fi.Sys().(*syscall.Dir).Atime), 0) -} diff --git a/src/pkg/os/stat_solaris.go b/src/pkg/os/stat_solaris.go deleted file mode 100644 index 605c1d9b6..000000000 --- a/src/pkg/os/stat_solaris.go +++ /dev/null @@ -1,61 +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 - -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtim), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK: - fs.mode |= ModeDevice - case syscall.S_IFCHR: - fs.mode |= ModeDevice | ModeCharDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - if st.Mode&syscall.S_ISVTX != 0 { - fs.mode |= ModeSticky - } - return fs -} - -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) -} - -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim) -} diff --git a/src/pkg/os/stat_windows.go b/src/pkg/os/stat_windows.go deleted file mode 100644 index 6dc386685..000000000 --- a/src/pkg/os/stat_windows.go +++ /dev/null @@ -1,160 +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 - -import ( - "syscall" - "unsafe" -) - -// Stat returns the FileInfo structure describing file. -// If there is an error, it will be of type *PathError. -func (file *File) Stat() (fi FileInfo, err error) { - if file == nil { - return nil, ErrInvalid - } - if file == nil || file.fd < 0 { - return nil, syscall.EINVAL - } - if file.isdir() { - // I don't know any better way to do that for directory - return Stat(file.name) - } - if file.name == DevNull { - return &devNullStat, nil - } - var d syscall.ByHandleFileInformation - e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d) - if e != nil { - return nil, &PathError{"GetFileInformationByHandle", file.name, e} - } - return &fileStat{ - name: basename(file.name), - sys: syscall.Win32FileAttributeData{ - FileAttributes: d.FileAttributes, - CreationTime: d.CreationTime, - LastAccessTime: d.LastAccessTime, - LastWriteTime: d.LastWriteTime, - FileSizeHigh: d.FileSizeHigh, - FileSizeLow: d.FileSizeLow, - }, - vol: d.VolumeSerialNumber, - idxhi: d.FileIndexHigh, - idxlo: d.FileIndexLow, - }, nil -} - -// Stat returns a FileInfo structure describing the named file. -// If there is an error, it will be of type *PathError. -func Stat(name string) (fi FileInfo, err error) { - if len(name) == 0 { - return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} - } - if name == DevNull { - return &devNullStat, nil - } - fs := &fileStat{name: basename(name)} - namep, e := syscall.UTF16PtrFromString(name) - if e != nil { - return nil, &PathError{"Stat", name, e} - } - e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys))) - if e != nil { - return nil, &PathError{"GetFileAttributesEx", name, e} - } - fs.path = name - if !isAbs(fs.path) { - cwd, _ := Getwd() - fs.path = cwd + `\` + fs.path - } - return fs, nil -} - -// Lstat returns the FileInfo structure describing the named file. -// If the file is a symbolic link, the returned FileInfo -// describes the symbolic link. Lstat makes no attempt to follow the link. -// If there is an error, it will be of type *PathError. -func Lstat(name string) (fi FileInfo, err error) { - // No links on Windows - return Stat(name) -} - -// basename removes trailing slashes and the leading -// directory name and drive letter from path name. -func basename(name string) string { - // Remove drive letter - if len(name) == 2 && name[1] == ':' { - name = "." - } else if len(name) > 2 && name[1] == ':' { - name = name[2:] - } - i := len(name) - 1 - // Remove trailing slashes - for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i-- { - name = name[:i] - } - // Remove leading directory name - for i--; i >= 0; i-- { - if name[i] == '/' || name[i] == '\\' { - name = name[i+1:] - break - } - } - return name -} - -func isSlash(c uint8) bool { - return c == '\\' || c == '/' -} - -func isAbs(path string) (b bool) { - v := volumeName(path) - if v == "" { - return false - } - path = path[len(v):] - if path == "" { - return false - } - return isSlash(path[0]) -} - -func volumeName(path string) (v string) { - if len(path) < 2 { - return "" - } - // with drive letter - c := path[0] - if path[1] == ':' && - ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' || - 'A' <= c && c <= 'Z') { - return path[:2] - } - // is it UNC - if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) && - !isSlash(path[2]) && path[2] != '.' { - // first, leading `\\` and next shouldn't be `\`. its server name. - for n := 3; n < l-1; n++ { - // second, next '\' shouldn't be repeated. - if isSlash(path[n]) { - n++ - // third, following something characters. its share name. - if !isSlash(path[n]) { - if path[n] == '.' { - break - } - for ; n < l; n++ { - if isSlash(path[n]) { - break - } - } - return path[:n] - } - break - } - } - } - return "" -} diff --git a/src/pkg/os/str.go b/src/pkg/os/str.go deleted file mode 100644 index e3606b61e..000000000 --- a/src/pkg/os/str.go +++ /dev/null @@ -1,22 +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. - -// +build plan9 - -package os - -func itoa(val int) string { // do it here rather than with fmt to avoid dependency - if val < 0 { - return "-" + itoa(-val) - } - var buf [32]byte // big enough for int64 - i := len(buf) - 1 - for val >= 10 { - buf[i] = byte(val%10 + '0') - i-- - val /= 10 - } - buf[i] = byte(val + '0') - return string(buf[i:]) -} diff --git a/src/pkg/os/sys_bsd.go b/src/pkg/os/sys_bsd.go deleted file mode 100644 index 8ad5e2183..000000000 --- a/src/pkg/os/sys_bsd.go +++ /dev/null @@ -1,20 +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. - -// +build darwin dragonfly freebsd nacl netbsd openbsd - -// os code shared between *BSD systems including OS X (Darwin) -// and FreeBSD. - -package os - -import "syscall" - -func hostname() (name string, err error) { - name, err = syscall.Sysctl("kern.hostname") - if err != nil { - return "", NewSyscallError("sysctl kern.hostname", err) - } - return name, nil -} diff --git a/src/pkg/os/sys_darwin.go b/src/pkg/os/sys_darwin.go deleted file mode 100644 index 7a8330abb..000000000 --- a/src/pkg/os/sys_darwin.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 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 - -import "syscall" - -// supportsCloseOnExec reports whether the platform supports the -// O_CLOEXEC flag. -var supportsCloseOnExec bool - -func init() { - // Seems like kern.osreldate is veiled on latest OS X. We use - // kern.osrelease instead. - osver, err := syscall.Sysctl("kern.osrelease") - if err != nil { - return - } - var i int - for i = range osver { - if osver[i] != '.' { - continue - } - } - // The O_CLOEXEC flag was introduced in OS X 10.7 (Darwin - // 11.0.0). See http://support.apple.com/kb/HT1633. - if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '1' { - supportsCloseOnExec = true - } -} diff --git a/src/pkg/os/sys_freebsd.go b/src/pkg/os/sys_freebsd.go deleted file mode 100644 index 273c2df1c..000000000 --- a/src/pkg/os/sys_freebsd.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 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 - -import "syscall" - -// supportsCloseOnExec reports whether the platform supports the -// O_CLOEXEC flag. -var supportsCloseOnExec bool - -func init() { - osrel, err := syscall.SysctlUint32("kern.osreldate") - if err != nil { - return - } - // The O_CLOEXEC flag was introduced in FreeBSD 8.3. - // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html. - if osrel >= 803000 { - supportsCloseOnExec = true - } -} diff --git a/src/pkg/os/sys_linux.go b/src/pkg/os/sys_linux.go deleted file mode 100644 index 76cdf5043..000000000 --- a/src/pkg/os/sys_linux.go +++ /dev/null @@ -1,26 +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. - -// Linux-specific - -package os - -func hostname() (name string, err error) { - f, err := Open("/proc/sys/kernel/hostname") - if err != nil { - return "", err - } - defer f.Close() - - var buf [512]byte // Enough for a DNS name. - n, err := f.Read(buf[0:]) - if err != nil { - return "", err - } - - if n > 0 && buf[n-1] == '\n' { - n-- - } - return string(buf[0:n]), nil -} diff --git a/src/pkg/os/sys_nacl.go b/src/pkg/os/sys_nacl.go deleted file mode 100644 index 07907c847..000000000 --- a/src/pkg/os/sys_nacl.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2014 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 - -// supportsCloseOnExec reports whether the platform supports the -// O_CLOEXEC flag. -const supportsCloseOnExec = false diff --git a/src/pkg/os/sys_plan9.go b/src/pkg/os/sys_plan9.go deleted file mode 100644 index 07a7905f4..000000000 --- a/src/pkg/os/sys_plan9.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2011 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. - -// Plan 9-specific - -package os - -func hostname() (name string, err error) { - f, err := Open("#c/sysname") - if err != nil { - return "", err - } - defer f.Close() - - var buf [128]byte - n, err := f.Read(buf[:len(buf)-1]) - - if err != nil { - return "", err - } - if n > 0 { - buf[n] = 0 - } - return string(buf[0:n]), nil -} diff --git a/src/pkg/os/sys_solaris.go b/src/pkg/os/sys_solaris.go deleted file mode 100644 index 917e8f2b0..000000000 --- a/src/pkg/os/sys_solaris.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2013 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 - -import "syscall" - -func hostname() (name string, err error) { - return syscall.Gethostname() -} diff --git a/src/pkg/os/sys_unix.go b/src/pkg/os/sys_unix.go deleted file mode 100644 index 39c20dc73..000000000 --- a/src/pkg/os/sys_unix.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2014 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. - -// +build dragonfly linux netbsd openbsd solaris - -package os - -// supportsCloseOnExec reports whether the platform supports the -// O_CLOEXEC flag. -const supportsCloseOnExec = true diff --git a/src/pkg/os/sys_windows.go b/src/pkg/os/sys_windows.go deleted file mode 100644 index 92617de5e..000000000 --- a/src/pkg/os/sys_windows.go +++ /dev/null @@ -1,15 +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 - -import "syscall" - -func hostname() (name string, err error) { - s, e := syscall.ComputerName() - if e != nil { - return "", NewSyscallError("ComputerName", e) - } - return s, nil -} diff --git a/src/pkg/os/types.go b/src/pkg/os/types.go deleted file mode 100644 index 473d431d4..000000000 --- a/src/pkg/os/types.go +++ /dev/null @@ -1,118 +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 - -import ( - "syscall" - "time" -) - -// Getpagesize returns the underlying system's memory page size. -func Getpagesize() int { return syscall.Getpagesize() } - -// A FileInfo describes a file and is returned by Stat and Lstat. -type FileInfo interface { - Name() string // base name of the file - Size() int64 // length in bytes for regular files; system-dependent for others - Mode() FileMode // file mode bits - ModTime() time.Time // modification time - IsDir() bool // abbreviation for Mode().IsDir() - Sys() interface{} // underlying data source (can return nil) -} - -// A FileMode represents a file's mode and permission bits. -// The bits have the same definition on all systems, so that -// information about files can be moved from one system -// to another portably. Not all bits apply to all systems. -// The only required bit is ModeDir for directories. -type FileMode uint32 - -// The defined file mode bits are the most significant bits of the FileMode. -// The nine least-significant bits are the standard Unix rwxrwxrwx permissions. -// The values of these bits should be considered part of the public API and -// may be used in wire protocols or disk representations: they must not be -// changed, although new bits might be added. -const ( - // The single letters are the abbreviations - // used by the String method's formatting. - ModeDir FileMode = 1 << (32 - 1 - iota) // d: is a directory - ModeAppend // a: append-only - ModeExclusive // l: exclusive use - ModeTemporary // T: temporary file (not backed up) - ModeSymlink // L: symbolic link - ModeDevice // D: device file - ModeNamedPipe // p: named pipe (FIFO) - ModeSocket // S: Unix domain socket - ModeSetuid // u: setuid - ModeSetgid // g: setgid - ModeCharDevice // c: Unix character device, when ModeDevice is set - ModeSticky // t: sticky - - // Mask for the type bits. For regular files, none will be set. - ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice - - ModePerm FileMode = 0777 // permission bits -) - -func (m FileMode) String() string { - const str = "dalTLDpSugct" - var buf [32]byte // Mode is uint32. - w := 0 - for i, c := range str { - if m&(1<<uint(32-1-i)) != 0 { - buf[w] = byte(c) - w++ - } - } - if w == 0 { - buf[w] = '-' - w++ - } - const rwx = "rwxrwxrwx" - for i, c := range rwx { - if m&(1<<uint(9-1-i)) != 0 { - buf[w] = byte(c) - } else { - buf[w] = '-' - } - w++ - } - return string(buf[:w]) -} - -// IsDir reports whether m describes a directory. -// That is, it tests for the ModeDir bit being set in m. -func (m FileMode) IsDir() bool { - return m&ModeDir != 0 -} - -// IsRegular reports whether m describes a regular file. -// That is, it tests that no mode type bits are set. -func (m FileMode) IsRegular() bool { - return m&ModeType == 0 -} - -// Perm returns the Unix permission bits in m. -func (m FileMode) Perm() FileMode { - return m & ModePerm -} - -func (fs *fileStat) Name() string { return fs.name } -func (fs *fileStat) IsDir() bool { return fs.Mode().IsDir() } - -// SameFile reports whether fi1 and fi2 describe the same file. -// For example, on Unix this means that the device and inode fields -// of the two underlying structures are identical; on other systems -// the decision may be based on the path names. -// SameFile only applies to results returned by this package's Stat. -// It returns false in other cases. -func SameFile(fi1, fi2 FileInfo) bool { - fs1, ok1 := fi1.(*fileStat) - fs2, ok2 := fi2.(*fileStat) - if !ok1 || !ok2 { - return false - } - return sameFile(fs1, fs2) -} diff --git a/src/pkg/os/types_notwin.go b/src/pkg/os/types_notwin.go deleted file mode 100644 index ea1a07393..000000000 --- a/src/pkg/os/types_notwin.go +++ /dev/null @@ -1,25 +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. - -// +build !windows - -package os - -import ( - "time" -) - -// A fileStat is the implementation of FileInfo returned by Stat and Lstat. -type fileStat struct { - name string - size int64 - mode FileMode - modTime time.Time - sys interface{} -} - -func (fs *fileStat) Size() int64 { return fs.size } -func (fs *fileStat) Mode() FileMode { return fs.mode } -func (fs *fileStat) ModTime() time.Time { return fs.modTime } -func (fs *fileStat) Sys() interface{} { return fs.sys } diff --git a/src/pkg/os/types_windows.go b/src/pkg/os/types_windows.go deleted file mode 100644 index 38901681e..000000000 --- a/src/pkg/os/types_windows.go +++ /dev/null @@ -1,104 +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 - -import ( - "sync" - "syscall" - "time" -) - -// A fileStat is the implementation of FileInfo returned by Stat and Lstat. -type fileStat struct { - name string - sys syscall.Win32FileAttributeData - - // used to implement SameFile - sync.Mutex - path string - vol uint32 - idxhi uint32 - idxlo uint32 -} - -func (fs *fileStat) Size() int64 { - return int64(fs.sys.FileSizeHigh)<<32 + int64(fs.sys.FileSizeLow) -} - -func (fs *fileStat) Mode() (m FileMode) { - if fs == &devNullStat { - return ModeDevice | ModeCharDevice | 0666 - } - if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - m |= ModeDir | 0111 - } - if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 { - m |= 0444 - } else { - m |= 0666 - } - return m -} - -func (fs *fileStat) ModTime() time.Time { - return time.Unix(0, fs.sys.LastWriteTime.Nanoseconds()) -} - -// Sys returns syscall.Win32FileAttributeData for file fs. -func (fs *fileStat) Sys() interface{} { return &fs.sys } - -func (fs *fileStat) loadFileId() error { - fs.Lock() - defer fs.Unlock() - if fs.path == "" { - // already done - return nil - } - pathp, err := syscall.UTF16PtrFromString(fs.path) - if err != nil { - return err - } - h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0) - if err != nil { - return err - } - defer syscall.CloseHandle(h) - var i syscall.ByHandleFileInformation - err = syscall.GetFileInformationByHandle(syscall.Handle(h), &i) - if err != nil { - return err - } - fs.path = "" - fs.vol = i.VolumeSerialNumber - fs.idxhi = i.FileIndexHigh - fs.idxlo = i.FileIndexLow - return nil -} - -// devNullStat is fileStat structure describing DevNull file ("NUL"). -var devNullStat = fileStat{ - name: DevNull, - // hopefully this will work for SameFile - vol: 0, - idxhi: 0, - idxlo: 0, -} - -func sameFile(fs1, fs2 *fileStat) bool { - e := fs1.loadFileId() - if e != nil { - return false - } - e = fs2.loadFileId() - if e != nil { - return false - } - return fs1.vol == fs2.vol && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo -} - -// For testing. -func atime(fi FileInfo) time.Time { - return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds()) -} diff --git a/src/pkg/os/user/lookup.go b/src/pkg/os/user/lookup.go deleted file mode 100644 index 09f00c7bd..000000000 --- a/src/pkg/os/user/lookup.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2011 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 user - -// Current returns the current user. -func Current() (*User, error) { - return current() -} - -// Lookup looks up a user by username. If the user cannot be found, the -// returned error is of type UnknownUserError. -func Lookup(username string) (*User, error) { - return lookup(username) -} - -// LookupId looks up a user by userid. If the user cannot be found, the -// returned error is of type UnknownUserIdError. -func LookupId(uid string) (*User, error) { - return lookupId(uid) -} diff --git a/src/pkg/os/user/lookup_plan9.go b/src/pkg/os/user/lookup_plan9.go deleted file mode 100644 index f7ef3482b..000000000 --- a/src/pkg/os/user/lookup_plan9.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 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 user - -import ( - "fmt" - "io/ioutil" - "os" - "syscall" -) - -// Partial os/user support on Plan 9. -// Supports Current(), but not Lookup()/LookupId(). -// The latter two would require parsing /adm/users. -const ( - userFile = "/dev/user" -) - -func current() (*User, error) { - ubytes, err := ioutil.ReadFile(userFile) - if err != nil { - return nil, fmt.Errorf("user: %s", err) - } - - uname := string(ubytes) - - u := &User{ - Uid: uname, - Gid: uname, - Username: uname, - Name: uname, - HomeDir: os.Getenv("home"), - } - - return u, nil -} - -func lookup(username string) (*User, error) { - return nil, syscall.EPLAN9 -} - -func lookupId(uid string) (*User, error) { - return nil, syscall.EPLAN9 -} diff --git a/src/pkg/os/user/lookup_stubs.go b/src/pkg/os/user/lookup_stubs.go deleted file mode 100644 index 86f0e6e64..000000000 --- a/src/pkg/os/user/lookup_stubs.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2011 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. - -// +build !cgo,!windows,!plan9 - -package user - -import ( - "fmt" - "runtime" -) - -func init() { - implemented = false -} - -func current() (*User, error) { - return nil, fmt.Errorf("user: Current not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -func lookup(username string) (*User, error) { - return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -func lookupId(uid string) (*User, error) { - return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} diff --git a/src/pkg/os/user/lookup_unix.go b/src/pkg/os/user/lookup_unix.go deleted file mode 100644 index f2baf05bb..000000000 --- a/src/pkg/os/user/lookup_unix.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2011 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. - -// +build darwin dragonfly freebsd linux netbsd openbsd solaris -// +build cgo - -package user - -import ( - "fmt" - "runtime" - "strconv" - "strings" - "syscall" - "unsafe" -) - -/* -#include <unistd.h> -#include <sys/types.h> -#include <pwd.h> -#include <stdlib.h> - -static int mygetpwuid_r(int uid, struct passwd *pwd, - char *buf, size_t buflen, struct passwd **result) { - return getpwuid_r(uid, pwd, buf, buflen, result); -} -*/ -import "C" - -func current() (*User, error) { - return lookupUnix(syscall.Getuid(), "", false) -} - -func lookup(username string) (*User, error) { - return lookupUnix(-1, username, true) -} - -func lookupId(uid string) (*User, error) { - i, e := strconv.Atoi(uid) - if e != nil { - return nil, e - } - return lookupUnix(i, "", false) -} - -func lookupUnix(uid int, username string, lookupByName bool) (*User, error) { - var pwd C.struct_passwd - var result *C.struct_passwd - - var bufSize C.long - if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" { - // DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX - // and just return -1. So just use the same - // size that Linux returns. - bufSize = 1024 - } else { - bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX) - if bufSize <= 0 || bufSize > 1<<20 { - return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize) - } - } - buf := C.malloc(C.size_t(bufSize)) - defer C.free(buf) - var rv C.int - if lookupByName { - nameC := C.CString(username) - defer C.free(unsafe.Pointer(nameC)) - rv = C.getpwnam_r(nameC, - &pwd, - (*C.char)(buf), - C.size_t(bufSize), - &result) - if rv != 0 { - return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.Errno(rv)) - } - if result == nil { - return nil, UnknownUserError(username) - } - } else { - // mygetpwuid_r is a wrapper around getpwuid_r to - // to avoid using uid_t because C.uid_t(uid) for - // unknown reasons doesn't work on linux. - rv = C.mygetpwuid_r(C.int(uid), - &pwd, - (*C.char)(buf), - C.size_t(bufSize), - &result) - if rv != 0 { - return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.Errno(rv)) - } - if result == nil { - return nil, UnknownUserIdError(uid) - } - } - u := &User{ - Uid: strconv.Itoa(int(pwd.pw_uid)), - Gid: strconv.Itoa(int(pwd.pw_gid)), - Username: C.GoString(pwd.pw_name), - Name: C.GoString(pwd.pw_gecos), - HomeDir: C.GoString(pwd.pw_dir), - } - // The pw_gecos field isn't quite standardized. Some docs - // say: "It is expected to be a comma separated list of - // personal data where the first item is the full name of the - // user." - if i := strings.Index(u.Name, ","); i >= 0 { - u.Name = u.Name[:i] - } - return u, nil -} diff --git a/src/pkg/os/user/lookup_windows.go b/src/pkg/os/user/lookup_windows.go deleted file mode 100644 index 99c325ff0..000000000 --- a/src/pkg/os/user/lookup_windows.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2012 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 user - -import ( - "fmt" - "syscall" - "unsafe" -) - -func isDomainJoined() (bool, error) { - var domain *uint16 - var status uint32 - err := syscall.NetGetJoinInformation(nil, &domain, &status) - if err != nil { - return false, err - } - syscall.NetApiBufferFree((*byte)(unsafe.Pointer(domain))) - return status == syscall.NetSetupDomainName, nil -} - -func lookupFullNameDomain(domainAndUser string) (string, error) { - return syscall.TranslateAccountName(domainAndUser, - syscall.NameSamCompatible, syscall.NameDisplay, 50) -} - -func lookupFullNameServer(servername, username string) (string, error) { - s, e := syscall.UTF16PtrFromString(servername) - if e != nil { - return "", e - } - u, e := syscall.UTF16PtrFromString(username) - if e != nil { - return "", e - } - var p *byte - e = syscall.NetUserGetInfo(s, u, 10, &p) - if e != nil { - return "", e - } - defer syscall.NetApiBufferFree(p) - i := (*syscall.UserInfo10)(unsafe.Pointer(p)) - if i.FullName == nil { - return "", nil - } - name := syscall.UTF16ToString((*[1024]uint16)(unsafe.Pointer(i.FullName))[:]) - return name, nil -} - -func lookupFullName(domain, username, domainAndUser string) (string, error) { - joined, err := isDomainJoined() - if err == nil && joined { - name, err := lookupFullNameDomain(domainAndUser) - if err == nil { - return name, nil - } - } - name, err := lookupFullNameServer(domain, username) - if err == nil { - return name, nil - } - // domain worked neigher as a domain nor as a server - // could be domain server unavailable - // pretend username is fullname - return username, nil -} - -func newUser(usid *syscall.SID, gid, dir string) (*User, error) { - username, domain, t, e := usid.LookupAccount("") - if e != nil { - return nil, e - } - if t != syscall.SidTypeUser { - return nil, fmt.Errorf("user: should be user account type, not %d", t) - } - domainAndUser := domain + `\` + username - uid, e := usid.String() - if e != nil { - return nil, e - } - name, e := lookupFullName(domain, username, domainAndUser) - if e != nil { - return nil, e - } - u := &User{ - Uid: uid, - Gid: gid, - Username: domainAndUser, - Name: name, - HomeDir: dir, - } - return u, nil -} - -func current() (*User, error) { - t, e := syscall.OpenCurrentProcessToken() - if e != nil { - return nil, e - } - defer t.Close() - u, e := t.GetTokenUser() - if e != nil { - return nil, e - } - pg, e := t.GetTokenPrimaryGroup() - if e != nil { - return nil, e - } - gid, e := pg.PrimaryGroup.String() - if e != nil { - return nil, e - } - dir, e := t.GetUserProfileDirectory() - if e != nil { - return nil, e - } - return newUser(u.User.Sid, gid, dir) -} - -// BUG(brainman): Lookup and LookupId functions do not set -// Gid and HomeDir fields in the User struct returned on windows. - -func newUserFromSid(usid *syscall.SID) (*User, error) { - // TODO(brainman): do not know where to get gid and dir fields - gid := "unknown" - dir := "Unknown directory" - return newUser(usid, gid, dir) -} - -func lookup(username string) (*User, error) { - sid, _, t, e := syscall.LookupSID("", username) - if e != nil { - return nil, e - } - if t != syscall.SidTypeUser { - return nil, fmt.Errorf("user: should be user account type, not %d", t) - } - return newUserFromSid(sid) -} - -func lookupId(uid string) (*User, error) { - sid, e := syscall.StringToSid(uid) - if e != nil { - return nil, e - } - return newUserFromSid(sid) -} diff --git a/src/pkg/os/user/user.go b/src/pkg/os/user/user.go deleted file mode 100644 index e8680fe54..000000000 --- a/src/pkg/os/user/user.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2011 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 user allows user account lookups by name or id. -package user - -import ( - "strconv" -) - -var implemented = true // set to false by lookup_stubs.go's init - -// User represents a user account. -// -// On posix systems Uid and Gid contain a decimal number -// representing uid and gid. On windows Uid and Gid -// contain security identifier (SID) in a string format. -// On Plan 9, Uid, Gid, Username, and Name will be the -// contents of /dev/user. -type User struct { - Uid string // user id - Gid string // primary group id - Username string - Name string - HomeDir string -} - -// UnknownUserIdError is returned by LookupId when -// a user cannot be found. -type UnknownUserIdError int - -func (e UnknownUserIdError) Error() string { - return "user: unknown userid " + strconv.Itoa(int(e)) -} - -// UnknownUserError is returned by Lookup when -// a user cannot be found. -type UnknownUserError string - -func (e UnknownUserError) Error() string { - return "user: unknown user " + string(e) -} diff --git a/src/pkg/os/user/user_test.go b/src/pkg/os/user/user_test.go deleted file mode 100644 index 9d9420e80..000000000 --- a/src/pkg/os/user/user_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2011 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 user - -import ( - "runtime" - "testing" -) - -func check(t *testing.T) { - if !implemented { - t.Skip("user: not implemented; skipping tests") - } -} - -func TestCurrent(t *testing.T) { - check(t) - - u, err := Current() - if err != nil { - t.Fatalf("Current: %v", err) - } - if u.HomeDir == "" { - t.Errorf("didn't get a HomeDir") - } - if u.Username == "" { - t.Errorf("didn't get a username") - } -} - -func compare(t *testing.T, want, got *User) { - if want.Uid != got.Uid { - t.Errorf("got Uid=%q; want %q", got.Uid, want.Uid) - } - if want.Username != got.Username { - t.Errorf("got Username=%q; want %q", got.Username, want.Username) - } - if want.Name != got.Name { - t.Errorf("got Name=%q; want %q", got.Name, want.Name) - } - // TODO(brainman): fix it once we know how. - if runtime.GOOS == "windows" { - t.Skip("skipping Gid and HomeDir comparisons") - } - if want.Gid != got.Gid { - t.Errorf("got Gid=%q; want %q", got.Gid, want.Gid) - } - if want.HomeDir != got.HomeDir { - t.Errorf("got HomeDir=%q; want %q", got.HomeDir, want.HomeDir) - } -} - -func TestLookup(t *testing.T) { - check(t) - - if runtime.GOOS == "plan9" { - t.Skipf("Lookup not implemented on %q", runtime.GOOS) - } - - want, err := Current() - if err != nil { - t.Fatalf("Current: %v", err) - } - got, err := Lookup(want.Username) - if err != nil { - t.Fatalf("Lookup: %v", err) - } - compare(t, want, got) -} - -func TestLookupId(t *testing.T) { - check(t) - - if runtime.GOOS == "plan9" { - t.Skipf("LookupId not implemented on %q", runtime.GOOS) - } - - want, err := Current() - if err != nil { - t.Fatalf("Current: %v", err) - } - got, err := LookupId(want.Uid) - if err != nil { - t.Fatalf("LookupId: %v", err) - } - compare(t, want, got) -} |