diff options
| author | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
| commit | d90e7cbac65c5792ce312ee82fbe03a5dfc98c6f (patch) | |
| tree | 7032a11d0cac2ae4d3e90f7a189b575b5a50f848 /src/lib/os | |
| parent | bf5c0c957c3c3ea9add6cfd51b90c463cb4814b5 (diff) | |
| download | go-d90e7cbac65c5792ce312ee82fbe03a5dfc98c6f.tar.xz | |
mv src/lib to src/pkg
tests: all.bash passes, gobuild still works, godoc still works.
R=rsc
OCL=30096
CL=30102
Diffstat (limited to 'src/lib/os')
| -rw-r--r-- | src/lib/os/Makefile | 91 | ||||
| -rw-r--r-- | src/lib/os/dir_darwin_386.go | 76 | ||||
| -rw-r--r-- | src/lib/os/dir_darwin_amd64.go | 76 | ||||
| -rw-r--r-- | src/lib/os/dir_linux_386.go | 83 | ||||
| -rw-r--r-- | src/lib/os/dir_linux_amd64.go | 79 | ||||
| -rw-r--r-- | src/lib/os/env.go | 80 | ||||
| -rw-r--r-- | src/lib/os/error.go | 83 | ||||
| -rw-r--r-- | src/lib/os/exec.go | 101 | ||||
| -rw-r--r-- | src/lib/os/file.go | 383 | ||||
| -rw-r--r-- | src/lib/os/getwd.go | 94 | ||||
| -rw-r--r-- | src/lib/os/os_test.go | 549 | ||||
| -rw-r--r-- | src/lib/os/path.go | 121 | ||||
| -rw-r--r-- | src/lib/os/path_test.go | 152 | ||||
| -rw-r--r-- | src/lib/os/proc.go | 50 | ||||
| -rw-r--r-- | src/lib/os/proc_linux.go | 20 | ||||
| -rw-r--r-- | src/lib/os/stat_darwin_386.go | 41 | ||||
| -rw-r--r-- | src/lib/os/stat_darwin_amd64.go | 41 | ||||
| -rw-r--r-- | src/lib/os/stat_linux_386.go | 47 | ||||
| -rw-r--r-- | src/lib/os/stat_linux_amd64.go | 41 | ||||
| -rw-r--r-- | src/lib/os/time.go | 24 | ||||
| -rw-r--r-- | src/lib/os/types.go | 75 |
21 files changed, 0 insertions, 2307 deletions
diff --git a/src/lib/os/Makefile b/src/lib/os/Makefile deleted file mode 100644 index c5f790f15d..0000000000 --- a/src/lib/os/Makefile +++ /dev/null @@ -1,91 +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. - -# DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m dir_${GOOS}_${GOARCH}.go env.go error.go file.go path.go stat_${GOOS}_${GOARCH}.go time.go types.go exec.go proc.go getwd.go >Makefile - -D= - -include $(GOROOT)/src/Make.$(GOARCH) -AR=gopack - -default: packages - -clean: - rm -rf *.[$(OS)] *.a [$(OS)].out _obj - -test: packages - gotest - -coverage: packages - gotest - 6cov -g `pwd` | grep -v '_test\.go:' - -%.$O: %.go - $(GC) -I_obj $*.go - -%.$O: %.c - $(CC) $*.c - -%.$O: %.s - $(AS) $*.s - -O1=\ - error.$O\ - types.$O\ - -O2=\ - proc.$O\ - stat_$(GOOS)_$(GOARCH).$O\ - time.$O\ - -O3=\ - env.$O\ - file.$O\ - -O4=\ - dir_$(GOOS)_$(GOARCH).$O\ - exec.$O\ - getwd.$O\ - path.$O\ - - -phases: a1 a2 a3 a4 -_obj$D/os.a: phases - -a1: $(O1) - $(AR) grc _obj$D/os.a error.$O types.$O - rm -f $(O1) - -a2: $(O2) - $(AR) grc _obj$D/os.a proc.$O stat_$(GOOS)_$(GOARCH).$O time.$O - rm -f $(O2) - -a3: $(O3) - $(AR) grc _obj$D/os.a env.$O file.$O - rm -f $(O3) - -a4: $(O4) - $(AR) grc _obj$D/os.a dir_$(GOOS)_$(GOARCH).$O exec.$O getwd.$O path.$O - rm -f $(O4) - - -newpkg: clean - mkdir -p _obj$D - $(AR) grc _obj$D/os.a - -$(O1): newpkg -$(O2): a1 -$(O3): a2 -$(O4): a3 -$(O5): a4 - -nuke: clean - rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/os.a - -packages: _obj$D/os.a - -install: packages - test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D - cp _obj$D/os.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/os.a diff --git a/src/lib/os/dir_darwin_386.go b/src/lib/os/dir_darwin_386.go deleted file mode 100644 index 2803ecee27..0000000000 --- a/src/lib/os/dir_darwin_386.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. - -package os - -import ( - "os"; - "syscall"; - "unsafe"; -) - -const ( - blockSize = 4096 // TODO(r): use statfs -) - -// Negative count means read until EOF. -func readdirnames(file *File, count int) (names []string, err Error) { - // If this file has no dirinfo, create one. - if file.dirinfo == nil { - file.dirinfo = new(dirInfo); - // The buffer must be at least a block long. - // TODO(r): use fstatfs to find fs block size. - file.dirinfo.buf = make([]byte, blockSize); - } - d := file.dirinfo; - size := count; - if size < 0 { - size = 100 - } - names = make([]string, 0, size); // Empty with room to grow. - for count != 0 { - // Refill the buffer if necessary - if d.bufp >= d.nbuf { - var errno int; - d.bufp = 0; - // Final argument is (basep *uintptr) and the syscall doesn't take nil. - d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr)); - if errno != 0 { - d.nbuf = 0; - return names, ErrnoToError(errno) - } - if d.nbuf == 0 { - break // EOF - } - } - // Drain the buffer - for count != 0 && d.bufp < d.nbuf { - dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); - if dirent.Reclen == 0 { - d.bufp = d.nbuf; - break - } - d.bufp += int(dirent.Reclen); - if dirent.Ino == 0 { // File absent in directory. - continue - } - bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); - var name = string(bytes[0:dirent.Namlen]); - if name == "." || name == ".." { // Useless names - continue - } - count--; - if len(names) == cap(names) { - nnames := make([]string, len(names), 2*len(names)); - for i := 0; i < len(names); i++ { - nnames[i] = names[i] - } - names = nnames; - } - names = names[0:len(names)+1]; - names[len(names)-1] = name; - } - } - return names, nil -} diff --git a/src/lib/os/dir_darwin_amd64.go b/src/lib/os/dir_darwin_amd64.go deleted file mode 100644 index 2803ecee27..0000000000 --- a/src/lib/os/dir_darwin_amd64.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. - -package os - -import ( - "os"; - "syscall"; - "unsafe"; -) - -const ( - blockSize = 4096 // TODO(r): use statfs -) - -// Negative count means read until EOF. -func readdirnames(file *File, count int) (names []string, err Error) { - // If this file has no dirinfo, create one. - if file.dirinfo == nil { - file.dirinfo = new(dirInfo); - // The buffer must be at least a block long. - // TODO(r): use fstatfs to find fs block size. - file.dirinfo.buf = make([]byte, blockSize); - } - d := file.dirinfo; - size := count; - if size < 0 { - size = 100 - } - names = make([]string, 0, size); // Empty with room to grow. - for count != 0 { - // Refill the buffer if necessary - if d.bufp >= d.nbuf { - var errno int; - d.bufp = 0; - // Final argument is (basep *uintptr) and the syscall doesn't take nil. - d.nbuf, errno = syscall.Getdirentries(file.fd, d.buf, new(uintptr)); - if errno != 0 { - d.nbuf = 0; - return names, ErrnoToError(errno) - } - if d.nbuf == 0 { - break // EOF - } - } - // Drain the buffer - for count != 0 && d.bufp < d.nbuf { - dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); - if dirent.Reclen == 0 { - d.bufp = d.nbuf; - break - } - d.bufp += int(dirent.Reclen); - if dirent.Ino == 0 { // File absent in directory. - continue - } - bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); - var name = string(bytes[0:dirent.Namlen]); - if name == "." || name == ".." { // Useless names - continue - } - count--; - if len(names) == cap(names) { - nnames := make([]string, len(names), 2*len(names)); - for i := 0; i < len(names); i++ { - nnames[i] = names[i] - } - names = nnames; - } - names = names[0:len(names)+1]; - names[len(names)-1] = name; - } - } - return names, nil -} diff --git a/src/lib/os/dir_linux_386.go b/src/lib/os/dir_linux_386.go deleted file mode 100644 index c4594a52df..0000000000 --- a/src/lib/os/dir_linux_386.go +++ /dev/null @@ -1,83 +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. - -// TODO(rsc): Once the porting dust settles, consider -// whether this file should be dir_linux.go (and similarly -// dir_darwin.go) instead of having one copy per architecture. - -package os - -import ( - "os"; - "syscall"; - "unsafe"; -) - -const ( - blockSize = 4096 // TODO(r): use statfs -) - -func clen(n []byte) int { - for i := 0; i < len(n); i++ { - if n[i] == 0 { - return i - } - } - return len(n) -} - -// Negative count means read until EOF. -func readdirnames(file *File, count int) (names []string, err Error) { - // If this file has no dirinfo, create one. - if file.dirinfo == nil { - file.dirinfo = new(dirInfo); - // The buffer must be at least a block long. - // TODO(r): use fstatfs to find fs block size. - file.dirinfo.buf = make([]byte, blockSize); - } - d := file.dirinfo; - size := count; - if size < 0 { - size = 100 - } - names = make([]string, 0, size); // Empty with room to grow. - for count != 0 { - // Refill the buffer if necessary - if d.bufp >= d.nbuf { - var errno int; - d.nbuf, errno = syscall.Getdents(file.fd, d.buf); - if d.nbuf < 0 { - return names, ErrnoToError(errno) - } - if d.nbuf == 0 { - break // EOF - } - d.bufp = 0; - } - // Drain the buffer - for count != 0 && d.bufp < d.nbuf { - dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); - d.bufp += int(dirent.Reclen); - if dirent.Ino == 0 { // File absent in directory. - continue - } - bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); - var name = string(bytes[0:clen(bytes)]); - if name == "." || name == ".." { // Useless names - continue - } - count--; - if len(names) == cap(names) { - nnames := make([]string, len(names), 2*len(names)); - for i := 0; i < len(names); i++ { - nnames[i] = names[i] - } - names = nnames; - } - names = names[0:len(names)+1]; - names[len(names)-1] = name; - } - } - return names, nil; -} diff --git a/src/lib/os/dir_linux_amd64.go b/src/lib/os/dir_linux_amd64.go deleted file mode 100644 index 05b3d4c65d..0000000000 --- a/src/lib/os/dir_linux_amd64.go +++ /dev/null @@ -1,79 +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 ( - "os"; - "syscall"; - "unsafe"; -) - -const ( - blockSize = 4096 // TODO(r): use statfs -) - -func clen(n []byte) int { - for i := 0; i < len(n); i++ { - if n[i] == 0 { - return i - } - } - return len(n) -} - -// Negative count means read until EOF. -func readdirnames(file *File, count int) (names []string, err Error) { - // If this file has no dirinfo, create one. - if file.dirinfo == nil { - file.dirinfo = new(dirInfo); - // The buffer must be at least a block long. - // TODO(r): use fstatfs to find fs block size. - file.dirinfo.buf = make([]byte, blockSize); - } - d := file.dirinfo; - size := count; - if size < 0 { - size = 100 - } - names = make([]string, 0, size); // Empty with room to grow. - for count != 0 { - // Refill the buffer if necessary - if d.bufp >= d.nbuf { - var errno int; - d.nbuf, errno = syscall.Getdents(file.fd, d.buf); - if d.nbuf < 0 { - return names, ErrnoToError(errno) - } - if d.nbuf == 0 { - break // EOF - } - d.bufp = 0; - } - // Drain the buffer - for count != 0 && d.bufp < d.nbuf { - dirent := (*syscall.Dirent)(unsafe.Pointer(&d.buf[d.bufp])); - d.bufp += int(dirent.Reclen); - if dirent.Ino == 0 { // File absent in directory. - continue - } - bytes := (*[len(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])); - var name = string(bytes[0:clen(bytes)]); - if name == "." || name == ".." { // Useless names - continue - } - count--; - if len(names) == cap(names) { - nnames := make([]string, len(names), 2*len(names)); - for i := 0; i < len(names); i++ { - nnames[i] = names[i] - } - names = nnames; - } - names = names[0:len(names)+1]; - names[len(names)-1] = name; - } - } - return names, nil; -} diff --git a/src/lib/os/env.go b/src/lib/os/env.go deleted file mode 100644 index 7487504130..0000000000 --- a/src/lib/os/env.go +++ /dev/null @@ -1,80 +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. - -// Environment variables. - -package os - -import ( - "once"; - "os"; -) - -// ENOENV is the Error indicating that an environment variable does not exist. -var ENOENV = NewError("no such environment variable"); - -var env map[string] string; - - -func copyenv() { - env = make(map[string] string); - for i, s := range os.Envs { - for j := 0; j < len(s); j++ { - if s[j] == '=' { - env[s[0:j]] = s[j+1:len(s)]; - break; - } - } - } -} - -// Getenv retrieves the value of the environment variable named by the key. -// It returns the value and an error, if any. -func Getenv(key string) (value string, err Error) { - once.Do(copyenv); - - if len(key) == 0 { - return "", EINVAL; - } - v, ok := env[key]; - if !ok { - return "", ENOENV; - } - return v, nil; -} - -// Setenv sets the value of the environment variable named by the key. -// It returns an Error, if any. -func Setenv(key, value string) Error { - once.Do(copyenv); - - if len(key) == 0 { - return EINVAL; - } - env[key] = value; - return nil; -} - -// Clearenv deletes all environment variables. -func Clearenv() { - once.Do(copyenv); // prevent copyenv in Getenv/Setenv - env = make(map[string] string); -} - -// Environ returns an array of strings representing the environment, -// in the form "key=value". -func Environ() []string { - once.Do(copyenv); - a := make([]string, len(env)); - i := 0; - for k, v := range(env) { - // check i < len(a) for safety, - // in case env is changing underfoot. - if i < len(a) { - a[i] = k + "=" + v; - i++; - } - } - return a[0:i]; -} diff --git a/src/lib/os/error.go b/src/lib/os/error.go deleted file mode 100644 index 718499b212..0000000000 --- a/src/lib/os/error.go +++ /dev/null @@ -1,83 +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 "syscall" - -// An Error can represent any printable error condition. -type Error interface { - String() string -} - -// A helper type that can be embedded or wrapped to simplify satisfying -// Error. -type ErrorString string -func (e ErrorString) String() string { - return string(e) -} - -// NewError converts s to an ErrorString, which satisfies the Error interface. -func NewError(s string) Error { - return ErrorString(s) -} - -// Errno is the Unix error number. Names such as EINVAL are simple -// wrappers to convert the error number into an Error. -type Errno int64 -func (e Errno) String() string { - return syscall.Errstr(int(e)) -} - -// ErrnoToError converts errno to an Error (underneath, an Errno). -// It returns nil for the "no error" errno. -func ErrnoToError(errno int) Error { - if errno == 0 { - return nil - } - return Errno(errno) -} - -// Commonly known Unix errors. -var ( - EPERM Error = Errno(syscall.EPERM); - ENOENT Error = Errno(syscall.ENOENT); - ESRCH Error = Errno(syscall.ESRCH); - EINTR Error = Errno(syscall.EINTR); - EIO Error = Errno(syscall.EIO); - ENXIO Error = Errno(syscall.ENXIO); - E2BIG Error = Errno(syscall.E2BIG); - ENOEXEC Error = Errno(syscall.ENOEXEC); - EBADF Error = Errno(syscall.EBADF); - ECHILD Error = Errno(syscall.ECHILD); - EDEADLK Error = Errno(syscall.EDEADLK); - ENOMEM Error = Errno(syscall.ENOMEM); - EACCES Error = Errno(syscall.EACCES); - EFAULT Error = Errno(syscall.EFAULT); - ENOTBLK Error = Errno(syscall.ENOTBLK); - EBUSY Error = Errno(syscall.EBUSY); - EEXIST Error = Errno(syscall.EEXIST); - EXDEV Error = Errno(syscall.EXDEV); - ENODEV Error = Errno(syscall.ENODEV); - ENOTDIR Error = Errno(syscall.ENOTDIR); - EISDIR Error = Errno(syscall.EISDIR); - EINVAL Error = Errno(syscall.EINVAL); - ENFILE Error = Errno(syscall.ENFILE); - EMFILE Error = Errno(syscall.EMFILE); - ENOTTY Error = Errno(syscall.ENOTTY); - ETXTBSY Error = Errno(syscall.ETXTBSY); - EFBIG Error = Errno(syscall.EFBIG); - ENOSPC Error = Errno(syscall.ENOSPC); - ESPIPE Error = Errno(syscall.ESPIPE); - EROFS Error = Errno(syscall.EROFS); - EMLINK Error = Errno(syscall.EMLINK); - EPIPE Error = Errno(syscall.EPIPE); - EAGAIN Error = Errno(syscall.EAGAIN); - EDOM Error = Errno(syscall.EDOM); - ERANGE Error = Errno(syscall.ERANGE); - EADDRINUSE Error = Errno(syscall.EADDRINUSE); - ECONNREFUSED Error = Errno(syscall.ECONNREFUSED); - ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG); -) - diff --git a/src/lib/os/exec.go b/src/lib/os/exec.go deleted file mode 100644 index d283c72670..0000000000 --- a/src/lib/os/exec.go +++ /dev/null @@ -1,101 +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 ( - "os"; - "syscall"; -) - -// ForkExec forks the current process and invokes Exec with the file, arguments, -// and environment specified by argv0, argv, and envv. It returns the process -// id of the forked process and an Error, if any. The fd array specifies the -// file descriptors to be set up in the new process: fd[0] will be Unix file -// descriptor 0 (standard input), fd[1] descriptor 1, and so on. A nil entry -// will cause the child to have no open file descriptor with that index. -// If dir is not empty, the child chdirs into the directory before execing the program. -func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) - (pid int, err Error) -{ - // Create array of integer (system) fds. - intfd := make([]int, len(fd)); - for i, f := range(fd) { - if f == nil { - intfd[i] = -1; - } else { - intfd[i] = f.Fd(); - } - } - - p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd); - return int(p), ErrnoToError(e); -} - -// Exec replaces the current process with an execution of the program -// named by argv0, with arguments argv and environment envv. -// If successful, Exec never returns. If it fails, it returns an Error. -// ForkExec is almost always a better way to execute a program. -func Exec(argv0 string, argv []string, envv []string) Error { - if envv == nil { - envv = Environ(); - } - e := syscall.Exec(argv0, argv, envv); - return ErrnoToError(e); -} - -// TODO(rsc): Should os implement its own syscall.WaitStatus -// wrapper with the methods, or is exposing the underlying one enough? -// -// TODO(rsc): Certainly need to have os.Rusage struct, -// since syscall one might have different field types across -// different OS. - -// Waitmsg stores the information about an exited process as reported by Wait. -type Waitmsg struct { - Pid int; // The process's id. - syscall.WaitStatus; // System-dependent status info. - Rusage *syscall.Rusage; // System-dependent resource usage info. -} - -// Options for Wait. -const ( - WNOHANG = syscall.WNOHANG; // Don't wait if no process has exited. - WSTOPPED = syscall.WSTOPPED; // If set, status of stopped subprocesses is also reported. - WUNTRACED = WSTOPPED; - WRUSAGE = 1<<30; // Record resource usage. -) - -// Wait waits for process pid to exit or stop, and then returns a -// Waitmsg describing its status and an Error, if any. The options -// (WNOHANG etc.) affect the behavior of the Wait call. -func Wait(pid int, options int) (w *Waitmsg, err Error) { - var status syscall.WaitStatus; - var rusage *syscall.Rusage; - if options & WRUSAGE != 0 { - rusage = new(syscall.Rusage); - options ^= WRUSAGE; - } - pid1, e := syscall.Wait4(pid, &status, options, rusage); - if e != 0 { - return nil, ErrnoToError(e); - } - w = new(Waitmsg); - w.Pid = pid; - w.WaitStatus = status; - w.Rusage = rusage; - return w, nil; -} - -// Getpid returns the process id of the caller. -func Getpid() int { - p, r2, e := syscall.Syscall(syscall.SYS_GETPID, 0, 0, 0); - return int(p) -} - -// Getppid returns the process id of the caller's parent. -func Getppid() int { - p, r2, e := syscall.Syscall(syscall.SYS_GETPPID, 0, 0, 0); - return int(p) -} diff --git a/src/lib/os/file.go b/src/lib/os/file.go deleted file mode 100644 index 1562b1b0e4..0000000000 --- a/src/lib/os/file.go +++ /dev/null @@ -1,383 +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. - -// The os package provides a platform-independent interface to operating -// system functionality. The design is Unix-like. -package os - -import ( - "os"; - "syscall"; -) - -// 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. -} - -// File represents an open file descriptor. -type File struct { - fd int; - name string; - dirinfo *dirInfo; // nil unless directory being read - nepipe int; // number of consecutive EPIPE in Write -} - -// Fd returns the integer Unix file descriptor referencing the open file. -func (file *File) Fd() int { - return file.fd -} - -// Name returns the name of the file as presented to Open. -func (file *File) Name() string { - return file.name -} - -// NewFile returns a new File with the given file descriptor and name. -func NewFile(file int, name string) *File { - if file < 0 { - return nil - } - return &File{file, name, nil, 0} -} - -// Stdin, Stdout, and Stderr are open Files pointing to the standard input, -// standard output, and standard error file descriptors. -var ( - Stdin = NewFile(0, "/dev/stdin"); - Stdout = NewFile(1, "/dev/stdout"); - Stderr = NewFile(2, "/dev/stderr"); -) - -// Flags to Open wrapping those of the underlying system. Not all flags -// may be implemented on a given system. -const ( - O_RDONLY = syscall.O_RDONLY; // open the file read-only. - O_WRONLY = syscall.O_WRONLY; // open the file write-only. - O_RDWR = syscall.O_RDWR; // open the file read-write. - O_APPEND = syscall.O_APPEND; // open the file append-only. - O_ASYNC = syscall.O_ASYNC; // generate a signal when I/O is available. - O_CREAT = syscall.O_CREAT; // create a new file if none exists. - O_NOCTTY = syscall.O_NOCTTY; // do not make file the controlling tty. - O_NONBLOCK = syscall.O_NONBLOCK; // open in non-blocking mode. - O_NDELAY = O_NONBLOCK; // synonym for O_NONBLOCK - O_SYNC = syscall.O_SYNC; // open for synchronous I/O. - O_TRUNC = syscall.O_TRUNC; // if possible, truncate file when opened. -) - -// Open 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. -// It returns the File and an Error, if any. -func Open(name string, flag int, perm int) (file *File, err Error) { - r, e := syscall.Open(name, flag | syscall.O_CLOEXEC, perm); - if e != 0 { - return nil, ErrnoToError(e); - } - - // There's a race here with fork/exec, which we are - // content to live with. See ../syscall/exec.go - if syscall.O_CLOEXEC == 0 { // O_CLOEXEC not supported - syscall.CloseOnExec(r); - } - - return NewFile(r, name), ErrnoToError(e) -} - -// 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 EINVAL - } - err := ErrnoToError(syscall.Close(file.fd)); - file.fd = -1; // so it can't be closed again - return err; -} - -// 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 a nil Error. -// TODO(r): Add Pread, Pwrite (maybe ReadAt, WriteAt). -func (file *File) Read(b []byte) (ret int, err Error) { - if file == nil { - return 0, EINVAL - } - n, e := syscall.Read(file.fd, b); - if n < 0 { - n = 0; - } - return n, ErrnoToError(e); -} - -// Write writes len(b) bytes to the File. -// It returns the number of bytes written and an Error, if any. -// If the byte count differs from len(b), it usually implies an error occurred. -func (file *File) Write(b []byte) (ret int, err Error) { - if file == nil { - return 0, EINVAL - } - n, e := syscall.Write(file.fd, b); - if n < 0 { - n = 0 - } - if e == syscall.EPIPE { - file.nepipe++; - if file.nepipe >= 10 { - os.Exit(syscall.EPIPE); - } - } else { - file.nepipe = 0; - } - return n, ErrnoToError(e) -} - -// 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 (file *File) Seek(offset int64, whence int) (ret int64, err Error) { - r, e := syscall.Seek(file.fd, offset, whence); - if e != 0 { - return -1, ErrnoToError(e) - } - if file.dirinfo != nil && r != 0 { - return -1, ErrnoToError(syscall.EISDIR) - } - return r, nil -} - -// WriteString is like Write, but writes the contents of string s rather than -// an array of bytes. -func (file *File) WriteString(s string) (ret int, err Error) { - if file == nil { - return 0, EINVAL - } - b := syscall.StringByteSlice(s); - b = b[0:len(b)-1]; - r, e := syscall.Write(file.fd, b); - if r < 0 { - r = 0 - } - return int(r), ErrnoToError(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]int; - - // See ../syscall/exec.go for description of lock. - syscall.ForkLock.RLock(); - e := syscall.Pipe(&p); - if e != 0 { - syscall.ForkLock.RUnlock(); - return nil, nil, ErrnoToError(e) - } - syscall.CloseOnExec(p[0]); - syscall.CloseOnExec(p[1]); - syscall.ForkLock.RUnlock(); - - return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil -} - -// Mkdir creates a new directory with the specified name and permission bits. -// It returns an error, if any. -func Mkdir(name string, perm int) Error { - return ErrnoToError(syscall.Mkdir(name, perm)); -} - -// Stat returns a Dir structure describing the named file and an error, if any. -// If name names a valid symbolic link, the returned Dir describes -// the file pointed at by the link and has dir.FollowedSymlink set to true. -// If name names an invalid symbolic link, the returned Dir describes -// the link itself and has dir.FollowedSymlink set to false. -func Stat(name string) (dir *Dir, err Error) { - var lstat, stat syscall.Stat_t; - e := syscall.Lstat(name, &lstat); - if e != 0 { - return nil, ErrnoToError(e); - } - statp := &lstat; - if lstat.Mode & syscall.S_IFMT == syscall.S_IFLNK { - e := syscall.Stat(name, &stat); - if e == 0 { - statp = &stat; - } - } - return dirFromStat(name, new(Dir), &lstat, statp), nil -} - -// Stat returns the Dir structure describing file. -// It returns the Dir and an error, if any. -func (file *File) Stat() (dir *Dir, err Error) { - var stat syscall.Stat_t; - e := syscall.Fstat(file.fd, &stat); - if e != 0 { - return nil, ErrnoToError(e) - } - return dirFromStat(file.name, new(Dir), &stat, &stat), nil -} - -// Lstat returns the Dir structure describing the named file and an error, if any. -// If the file is a symbolic link, the returned Dir describes the -// symbolic link. Lstat makes no attempt to follow the link. -func Lstat(name string) (dir *Dir, err Error) { - var stat syscall.Stat_t; - e := syscall.Lstat(name, &stat); - if e != 0 { - return nil, ErrnoToError(e) - } - return dirFromStat(name, new(Dir), &stat, &stat), nil -} - -// Readdirnames has a non-portable implemenation so its code is separated into an -// operating-system-dependent file. -func readdirnames(file *File, count int) (names []string, err Error) - -// Readdirnames reads the contents of the directory associated with file and -// returns an array of up to count names, in directory order. Subsequent -// calls on the same file will yield further names. -// A negative count means to read until EOF. -// Readdirnames returns the array and an Error, if any. -func (file *File) Readdirnames(count int) (names []string, err Error) { - return readdirnames(file, count); -} - -// Readdir reads the contents of the directory associated with file and -// returns an array of up to count Dir structures, as would be returned -// by Stat, in directory order. Subsequent calls on the same file will yield further Dirs. -// A negative count means to read until EOF. -// Readdir returns the array and an Error, if any. -func (file *File) Readdir(count int) (dirs []Dir, err Error) { - dirname := file.name; - if dirname == "" { - dirname = "."; - } - dirname += "/"; - names, err1 := file.Readdirnames(count); - if err1 != nil { - return nil, err1 - } - dirs = make([]Dir, len(names)); - for i, filename := range names { - dirp, err := Stat(dirname + filename); - if dirp == nil || err != nil { - dirs[i].Name = filename // rest is already zeroed out - } else { - dirs[i] = *dirp - } - } - return -} - -// Chdir changes the current working directory to the named directory. -func Chdir(dir string) Error { - return ErrnoToError(syscall.Chdir(dir)); -} - -// Chdir changes the current working directory to the file, -// which must be a directory. -func (f *File) Chdir() Error { - return ErrnoToError(syscall.Fchdir(f.fd)); -} - -// Remove removes the named file or directory. -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 == 0 { - return nil; - } - e1 := syscall.Rmdir(name); - if e1 == 0 { - 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 ErrnoToError(e); -} - -// Link creates a hard link. -func Link(oldname, newname string) Error { - return ErrnoToError(syscall.Link(oldname, newname)); -} - -// Symlink creates a symbolic link. -func Symlink(oldname, newname string) Error { - return ErrnoToError(syscall.Symlink(oldname, newname)); -} - -// Readlink reads the contents of a symbolic link: the destination of -// the link. It returns the contents and an Error, if any. -func Readlink(name string) (string, Error) { - for len := 128; ; len *= 2 { - b := make([]byte, len); - n, e := syscall.Readlink(name, b); - if e != 0 { - return "", ErrnoToError(e); - } - if n < len { - return string(b[0:n]), nil; - } - } - // Silence 6g. - return "", nil; -} - -// Chmod changes the mode of the named file to mode. -// If the file is a symbolic link, it changes the uid and gid of the link's target. -func Chmod(name string, mode int) Error { - return ErrnoToError(syscall.Chmod(name, mode)); -} - -// Chmod changes the mode of the file to mode. -func (f *File) Chmod(mode int) Error { - return ErrnoToError(syscall.Fchmod(f.fd, mode)); -} - -// 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. -func Chown(name string, uid, gid int) Error { - return ErrnoToError(syscall.Chown(name, uid, gid)); -} - -// 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. -func Lchown(name string, uid, gid int) Error { - return ErrnoToError(syscall.Lchown(name, uid, gid)); -} - -// Chown changes the numeric uid and gid of the named file. -func (f *File) Chown(uid, gid int) Error { - return ErrnoToError(syscall.Fchown(f.fd, uid, gid)); -} - -// 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 { - return ErrnoToError(syscall.Truncate(name, size)); -} - -// Truncate changes the size of the file. -// It does not change the I/O offset. -func (f *File) Truncate(size int64) Error { - return ErrnoToError(syscall.Ftruncate(f.fd, size)); -} - diff --git a/src/lib/os/getwd.go b/src/lib/os/getwd.go deleted file mode 100644 index 2d7b754b51..0000000000 --- a/src/lib/os/getwd.go +++ /dev/null @@ -1,94 +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 ( - "os"; - "syscall" -) - -// 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() (string, Error) { - // If the operating system provides a Getwd call, use it. - if syscall.ImplementsGetwd { - s, e := syscall.Getwd(); - return s, ErrnoToError(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. - pwd, _ := Getenv("PWD"); - if len(pwd) > 0 && pwd[0] == '/' { - d, err := Stat(pwd); - if err == nil && d.Dev == dot.Dev && d.Ino == dot.Ino { - return pwd, 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 root.Dev == dot.Dev && root.Ino == dot.Ino { - return "/", nil - } - - // General algorithm: find name in parent - // and then find name of parent. Each iteration - // adds /name to the beginning of pwd. - elem := make([]string, 0, 16); - pwd = ""; - for parent := "..";; parent = "../" + parent { - if len(parent) >= 1024 { // Sanity check - return "", ENAMETOOLONG; - } - fd, err := Open(parent, O_RDONLY, 0); - if err != nil { - return "", err; - } - - for { - names, err := fd.Readdirnames(100); - if err != nil { - fd.Close(); - return "", err; - } - for i, name := range names { - d, err := Lstat(parent + "/" + name); - if d.Dev == dot.Dev && d.Ino == dot.Ino { - pwd = "/" + name + pwd; - goto Found; - } - } - } - fd.Close(); - return "", ENOENT; - - Found: - pd, err := fd.Stat(); - if err != nil { - return "", err; - } - fd.Close(); - if pd.Dev == root.Dev && pd.Ino == root.Ino { - break; - } - // Set up for next round. - dot = pd; - } - return pwd, nil -} diff --git a/src/lib/os/os_test.go b/src/lib/os/os_test.go deleted file mode 100644 index 9f3e833f39..0000000000 --- a/src/lib/os/os_test.go +++ /dev/null @@ -1,549 +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 ( - "fmt"; - "io"; - "os"; - "testing"; -) - -var dot = []string{ - "dir_darwin_amd64.go", - "dir_linux_amd64.go", - "env.go", - "error.go", - "file.go", - "os_test.go", - "time.go", - "types.go", - "stat_darwin_amd64.go", - "stat_linux_amd64.go" -} - -var etc = []string{ - "group", - "hosts", - "passwd", -} - -func size(name string, t *testing.T) uint64 { - file, err := Open(name, O_RDONLY, 0); - defer file.Close(); - if err != nil { - t.Fatal("open failed:", err); - } - var buf [100]byte; - len := 0; - for { - n, e := file.Read(&buf); - if n < 0 || e != nil { - t.Fatal("read failed:", err); - } - if n == 0 { - break - } - len += n; - } - return uint64(len) -} - -func TestStat(t *testing.T) { - dir, err := Stat("/etc/passwd"); - if err != nil { - t.Fatal("stat failed:", err); - } - if dir.Name != "passwd" { - t.Error("name should be passwd; is", dir.Name); - } - filesize := size("/etc/passwd", t); - if dir.Size != filesize { - t.Error("size should be ", filesize, "; is", dir.Size); - } -} - -func TestFstat(t *testing.T) { - file, err1 := Open("/etc/passwd", O_RDONLY, 0); - defer file.Close(); - if err1 != nil { - t.Fatal("open failed:", err1); - } - dir, err2 := file.Stat(); - if err2 != nil { - t.Fatal("fstat failed:", err2); - } - if dir.Name != "passwd" { - t.Error("name should be passwd; is", dir.Name); - } - filesize := size("/etc/passwd", t); - if dir.Size != filesize { - t.Error("size should be ", filesize, "; is", dir.Size); - } -} - -func TestLstat(t *testing.T) { - dir, err := Lstat("/etc/passwd"); - if err != nil { - t.Fatal("lstat failed:", err); - } - if dir.Name != "passwd" { - t.Error("name should be passwd; is", dir.Name); - } - filesize := size("/etc/passwd", t); - if dir.Size != filesize { - t.Error("size should be ", filesize, "; is", dir.Size); - } -} - -func testReaddirnames(dir string, contents []string, t *testing.T) { - file, err := Open(dir, O_RDONLY, 0); - defer file.Close(); - if err != nil { - t.Fatalf("open %q failed: %v", dir, err); - } - s, err2 := file.Readdirnames(-1); - if err2 != nil { - t.Fatalf("readdirnames %q failed: %v", err2); - } - for i, m := range contents { - found := false; - for j, n := range s { - if n == "." || n == ".." { - t.Errorf("got %s in directory", n); - } - if 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, O_RDONLY, 0); - defer file.Close(); - if err != nil { - t.Fatalf("open %q failed: %v", dir, err); - } - s, err2 := file.Readdir(-1); - if err2 != nil { - t.Fatalf("readdir %q failed: %v", dir, err2); - } - for i, m := range contents { - found := false; - for j, n := range s { - if 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("/etc", etc, t); -} - -func TestReaddir(t *testing.T) { - testReaddir(".", dot, t); - testReaddir("/etc", etc, 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 != nil { - t.Fatalf("readdir %q failed: %v", file.Name(), err); - } - if len(d) == 0 { - break - } - 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) { - dir := "/usr/bin"; // big directory that doesn't change often. - file, err := Open(dir, O_RDONLY, 0); - defer file.Close(); - if err != nil { - t.Fatalf("open %q failed: %v", dir, err); - } - all, err1 := file.Readdirnames(-1); - if err1 != nil { - t.Fatalf("readdirnames %q failed: %v", dir, err1); - } - file1, err2 := Open(dir, O_RDONLY, 0); - if err2 != nil { - t.Fatalf("open %q failed: %v", dir, err2); - } - small := smallReaddirnames(file1, len(all)+100, t); // +100 in case we screw up - for i, n := range all { - if small[i] != n { - t.Errorf("small read %q %q mismatch: %v", small[i], n); - } - } -} - -func TestHardLink(t *testing.T) { - from, to := "hardlinktestfrom", "hardlinktestto"; - Remove(from); // Just in case. - file, err := Open(to, O_CREAT | O_WRONLY, 0666); - 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 tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino { - t.Errorf("link %q, %q did not create hard link", to, from); - } -} - -func TestSymLink(t *testing.T) { - from, to := "symlinktestfrom", "symlinktestto"; - Remove(from); // Just in case. - file, err := Open(to, O_CREAT | O_WRONLY, 0666); - 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 := Stat(to); - if err != nil { - t.Fatalf("stat %q failed: %v", to, err); - } - if tostat.FollowedSymlink { - t.Fatalf("stat %q claims to have followed a symlink", to); - } - fromstat, err := Stat(from); - if err != nil { - t.Fatalf("stat %q failed: %v", from, err); - } - if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino { - 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.IsSymlink() { - 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.FollowedSymlink { - t.Fatalf("stat %q did not follow symlink"); - } - 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, O_RDONLY, 0); - if err != nil { - t.Fatalf("open %q failed: %v", from, err); - } - file.Close(); -} - -func TestLongSymlink(t *testing.T) { - s := "0123456789abcdef"; - s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s; - from := "longsymlinktestfrom"; - 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 TestForkExec(t *testing.T) { - r, w, err := Pipe(); - if err != nil { - t.Fatalf("Pipe: %v", err); - } - pid, err := ForkExec("/bin/pwd", []string{"pwd"}, nil, "/", []*File{nil, w, Stderr}); - if err != nil { - t.Fatalf("ForkExec: %v", err); - } - w.Close(); - - var b io.ByteBuffer; - io.Copy(r, &b); - output := string(b.Data()); - expect := "/\n"; - if output != expect { - t.Errorf("exec /bin/pwd returned %q wanted %q", output, expect); - } - Wait(pid, 0); -} - -func checkMode(t *testing.T, path string, mode uint32) { - 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, 0777); - } -} - -func TestChmod(t *testing.T) { - MkdirAll("_obj", 0777); - const Path = "_obj/_TestChmod_"; - fd, err := Open(Path, O_WRONLY | O_CREAT, 0666); - if err != nil { - t.Fatalf("create %s: %s", Path, err); - } - - if err = Chmod(Path, 0456); err != nil { - t.Fatalf("chmod %s 0456: %s", Path, err); - } - checkMode(t, Path, 0456); - - if err = fd.Chmod(0123); err != nil { - t.Fatalf("fchmod %s 0123: %s", Path, err); - } - checkMode(t, Path, 0123); - - fd.Close(); - Remove(Path); -} - -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 %#o/%#o): %s", path, uid, gid, err); - } - if dir.Uid != uint32(uid) { - t.Errorf("Stat %q: uid %#o want %#o", path, dir.Uid, uid); - } - if dir.Gid != uint32(gid) { - t.Errorf("Stat %q: gid %#o want %#o", path, dir.Gid, uid); - } -} - -func TestChown(t *testing.T) { - // Use /tmp, not _obj, to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. If _obj is on NFS, the Getgroups groups are - // basically useless. - - const Path = "/tmp/_TestChown_"; - fd, err := Open(Path, O_WRONLY | O_CREAT, 0666); - if err != nil { - t.Fatalf("create %s: %s", Path, err); - } - dir, err := fd.Stat(); - if err != nil { - t.Fatalf("fstat %s: %s", Path, err); - } - defer fd.Close(); - defer Remove(Path); - - // Can't change uid unless root, but can try - // changing the group id. First try our current group. - gid := Getgid(); - if err = Chown(Path, -1, gid); err != nil { - t.Fatalf("chown %s -1 %d: %s", Path, gid, err); - } - checkUidGid(t, Path, int(dir.Uid), gid); - - // Then try all the auxiliary groups. - groups, err := Getgroups(); - if err != nil { - t.Fatalf("getgroups: %s", err); - } - for i, g := range groups { - if err = Chown(Path, -1, g); err != nil { - t.Fatalf("chown %s -1 %d: %s", Path, g, err); - } - checkUidGid(t, Path, int(dir.Uid), g); - - // change back to gid to test fd.Chown - if err = fd.Chown(-1, gid); err != nil { - t.Fatalf("fchown %s -1 %d: %s", Path, gid, err); - } - checkUidGid(t, Path, int(dir.Uid), gid); - } -} - -func checkSize(t *testing.T, path string, size uint64) { - dir, err := Stat(path); - if err != nil { - t.Fatalf("Stat %q (looking for size %d): %s", path, size, err); - } - if dir.Size != size { - t.Errorf("Stat %q: size %d want %d", path, dir.Size, size); - } -} - -func TestTruncate(t *testing.T) { - MkdirAll("_obj", 0777); - const Path = "_obj/_TestTruncate_"; - fd, err := Open(Path, O_WRONLY | O_CREAT, 0666); - if err != nil { - t.Fatalf("create %s: %s", Path, err); - } - - checkSize(t, Path, 0); - fd.Write(io.StringBytes("hello, world\n")); - checkSize(t, Path, 13); - fd.Truncate(10); - checkSize(t, Path, 10); - fd.Truncate(1024); - checkSize(t, Path, 1024); - fd.Truncate(0); - checkSize(t, Path, 0); - fd.Write(io.StringBytes("surprise!")); - checkSize(t, Path, 13 + 9); // wrote at offset past where hello, world was. - fd.Close(); - Remove(Path); -} - -func TestChdirAndGetwd(t *testing.T) { - fd, err := Open(".", O_RDONLY, 0); - 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{ "/bin", "/", "/usr/local/bin" }; - for mode := 0; mode < 2; mode++ { - for i, d := range dirs { - if mode == 0 { - err = Chdir(d); - } else { - fd1, err := Open(d, O_RDONLY, 0); - 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 TestTime(t *testing.T) { - // Just want to check that Time() is getting something. - // A common failure mode on Darwin is to get 0, 0, - // because it returns the time in registers instead of - // filling in the structure passed to the system call. - // TODO(rsc): Too bad the compiler doesn't know that - // 365.24*86400 is an integer. - sec, nsec, err := Time(); - if sec < (2009-1970)*36524*864 { - t.Errorf("Time() = %d, %d, %s; not plausible", sec, nsec, err); - } -} - -func TestSeek(t *testing.T) { - f, err := Open("_obj/seektest", O_CREAT|O_RDWR|O_TRUNC, 0666); - if err != nil { - t.Fatalf("open _obj/seektest: %s", err); - } - - const data = "hello, world\n"; - io.WriteString(f, data); - - type test struct { - in int64; - whence int; - out int64; - } - var tests = []test { - test{ 0, 1, int64(len(data)) }, - test{ 0, 0, 0 }, - test{ 5, 0, 5 }, - test{ 0, 2, int64(len(data)) }, - test{ 0, 0, 0 }, - test{ -1, 2, int64(len(data)) - 1 }, - test{ 1<<40, 0, 1<<40 }, - test{ 1<<40, 2, 1<<40 + int64(len(data)) } - }; - for i, tt := range tests { - off, err := f.Seek(tt.in, tt.whence); - if off != tt.out || err != nil { - t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out); - } - } - f.Close(); -} diff --git a/src/lib/os/path.go b/src/lib/os/path.go deleted file mode 100644 index 0b86b8f8bd..0000000000 --- a/src/lib/os/path.go +++ /dev/null @@ -1,121 +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 "os" - -// PathError reports an error and the file path where it occurred. -type PathError struct { - Path string; - Error Error; -} - -func (p *PathError) String() string { - return p.Path + ": " + p.Error.String(); -} - -// 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 int) Error { - // If path exists, stop with success or error. - dir, err := os.Lstat(path); - if err == nil { - if dir.IsDirectory() { - return nil; - } - return &PathError{path, ENOTDIR}; - } - - // Doesn't already exist; make sure parent does. - i := len(path); - for i > 0 && path[i-1] == '/' { // Skip trailing slashes. - i--; - } - - j := i; - for j > 0 && path[j-1] != '/' { // Scan backward over element. - j--; - } - - if j > 0 { - // 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 := os.Lstat(path); - if err1 == nil && dir.IsDirectory() { - return nil; - } - return &PathError{path, err}; - } - return nil; -} - -// RemoveAll removes path and any children it contains. -// It removes everything it can but returns the first error -// it encounters. -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, err1 := os.Lstat(path); - if err1 != nil { - return &PathError{path, err1}; - } - if !dir.IsDirectory() { - // Not a directory; return the error from Remove. - return &PathError{path, err}; - } - - // Directory. - fd, err := Open(path, os.O_RDONLY, 0); - if err != nil { - return &PathError{path, err}; - } - defer fd.Close(); - - // Remove contents & return first error. - err = nil; - for { - names, err1 := fd.Readdirnames(100); - for i, name := range names { - err1 := RemoveAll(path + "/" + name); - if err1 != nil && err == nil { - err = err1; - } - } - // If Readdirnames returned an error, use it. - if err1 != nil && err == nil { - err = &PathError{path, err1}; - } - if len(names) == 0 { - break; - } - } - - // Remove directory. - err1 = Remove(path); - if err1 != nil && err == nil { - err = &PathError{path, err1}; - } - return err; -} diff --git a/src/lib/os/path_test.go b/src/lib/os/path_test.go deleted file mode 100644 index bb6148920e..0000000000 --- a/src/lib/os/path_test.go +++ /dev/null @@ -1,152 +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 ( - "os"; - "testing"; -) - -func TestMkdirAll(t *testing.T) { - // Create new dir, in _obj so it will get - // cleaned up by make if not by us. - path := "_obj/_TestMkdirAll_/dir/./dir2"; - err := MkdirAll(path, 0777); - if err != nil { - t.Fatalf("MkdirAll %q: %s", path, err); - } - - // 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"; - fd, err := os.Open(fpath, os.O_WRONLY | os.O_CREAT, 0666); - if err != nil { - t.Fatalf("create %q: %s", fpath, err); - } - - // Can't make directory named after file. - err = MkdirAll(fpath, 0777); - if err == nil { - t.Fatalf("MkdirAll %q: no error"); - } - perr, ok := err.(*PathError); - if !ok { - t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err); - } - if perr.Path != fpath { - t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, perr.Path, fpath); - } - - // Can't make subdirectory of file. - ffpath := fpath + "/subdir"; - err = MkdirAll(ffpath, 0777); - if err == nil { - t.Fatalf("MkdirAll %q: no error"); - } - perr, ok = err.(*PathError); - if !ok { - t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err); - } - if perr.Path != fpath { - t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath); - } - - RemoveAll("_obj/_TestMkdirAll_"); -} - -func TestRemoveAll(t *testing.T) { - // Work directory. - path := "_obj/_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 := os.Open(fpath, os.O_WRONLY | os.O_CREAT, 0666); - 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 dir, err := os.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 = os.Open(fpath, os.O_WRONLY | os.O_CREAT, 0666); - if err != nil { - t.Fatalf("create %q: %s", fpath, err); - } - fd.Close(); - fd, err = os.Open(dpath+"/file", os.O_WRONLY | os.O_CREAT, 0666); - 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 dir, err := os.Lstat(path); err == nil { - t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path); - } - - // Make directory with file and subdirectory and trigger error. - if err = MkdirAll(dpath, 0777); err != nil { - t.Fatalf("MkdirAll %q: %s", dpath, err); - } - - // TODO(rsc): toss tmp once bug152 is fixed - tmp := []string{fpath, dpath+"/file1", path+"/zzz"}; - for i, s := range tmp { - fd, err = os.Open(s, os.O_WRONLY | os.O_CREAT, 0666); - if err != nil { - t.Fatalf("create %q: %s", s, err); - } - fd.Close(); - } - if err = os.Chmod(dpath, 0); err != nil { - t.Fatalf("Chmod %q 0: %s", dpath, err); - } - if err = RemoveAll(path); err == nil { - dir, err := Lstat(path); - if err == nil { - t.Errorf("Can lstat %q after supposed RemoveAll", path); - } - t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err); - } - perr, ok := err.(*PathError); - if !ok { - t.Fatalf("RemoveAll %q returned %T not *PathError", path, err); - } - if perr.Path != dpath { - t.Fatalf("RemoveAll %q failed at %q not %q", path, perr.Path, dpath); - } - if err = os.Chmod(dpath, 0777); err != nil { - t.Fatalf("Chmod %q 0777: %s", dpath, err); - } - for i, s := range []string{fpath, path+"/zzz"} { - if dir, err := os.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 dir, err := os.Lstat(path); err == nil { - t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path); - } -} diff --git a/src/lib/os/proc.go b/src/lib/os/proc.go deleted file mode 100644 index d2fd6493eb..0000000000 --- a/src/lib/os/proc.go +++ /dev/null @@ -1,50 +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"; - "os"; - "unsafe"; -) - -var Args []string; // provided by runtime -var Envs []string; // provided by runtime - - -// 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, os.Error) { - gids, errno := syscall.Getgroups(); - return gids, ErrnoToError(errno); -} - -// Exit causes the current program to exit with the given status code. -// Conventionally, code zero indicates success, non-zero an error. -func Exit(code int) { - syscall.Exit(code); -} - diff --git a/src/lib/os/proc_linux.go b/src/lib/os/proc_linux.go deleted file mode 100644 index a802284f37..0000000000 --- a/src/lib/os/proc_linux.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. - -package os - -import ( - "os"; - "syscall"; -) - -var Args []string; // provided by runtime -var Envs []string; // provided by runtime - -// Exit causes the current program to exit with the given status code. -// Conventionally, code zero indicates success, non-zero an error. -func Exit(code int) { - syscall.Syscall(syscall.SYS_EXIT_GROUP, int64(code), 0, 0) -} - diff --git a/src/lib/os/stat_darwin_386.go b/src/lib/os/stat_darwin_386.go deleted file mode 100644 index a6d7b78d15..0000000000 --- a/src/lib/os/stat_darwin_386.go +++ /dev/null @@ -1,41 +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. - -// 386, Darwin - -package os - -import syscall "syscall" -import os "os" - -func isSymlink(stat *syscall.Stat_t) bool { - return stat.Mode & syscall.S_IFMT == syscall.S_IFLNK -} - -func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { - dir.Dev = uint64(stat.Dev); - dir.Ino = stat.Ino; - dir.Nlink = uint64(stat.Nlink); - dir.Mode = uint32(stat.Mode); - dir.Uid = stat.Uid; - dir.Gid = stat.Gid; - dir.Rdev = uint64(stat.Rdev); - dir.Size = uint64(stat.Size); - dir.Blksize = uint64(stat.Blksize); - dir.Blocks = uint64(stat.Blocks); - dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec)); - dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec)); - dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec)); - for i := len(name) - 1; i >= 0; i-- { - if name[i] == '/' { - name = name[i+1:len(name)]; - break; - } - } - dir.Name = name; - if isSymlink(lstat) && !isSymlink(stat) { - dir.FollowedSymlink = true; - } - return dir; -} diff --git a/src/lib/os/stat_darwin_amd64.go b/src/lib/os/stat_darwin_amd64.go deleted file mode 100644 index 1771ca160b..0000000000 --- a/src/lib/os/stat_darwin_amd64.go +++ /dev/null @@ -1,41 +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. - -// AMD64, Darwin - -package os - -import syscall "syscall" -import os "os" - -func isSymlink(stat *syscall.Stat_t) bool { - return stat.Mode & syscall.S_IFMT == syscall.S_IFLNK -} - -func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { - dir.Dev = uint64(stat.Dev); - dir.Ino = stat.Ino; - dir.Nlink = uint64(stat.Nlink); - dir.Mode = uint32(stat.Mode); - dir.Uid = stat.Uid; - dir.Gid = stat.Gid; - dir.Rdev = uint64(stat.Rdev); - dir.Size = uint64(stat.Size); - dir.Blksize = uint64(stat.Blksize); - dir.Blocks = uint64(stat.Blocks); - dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atimespec)); - dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtimespec)); - dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctimespec)); - for i := len(name) - 1; i >= 0; i-- { - if name[i] == '/' { - name = name[i+1:len(name)]; - break; - } - } - dir.Name = name; - if isSymlink(lstat) && !isSymlink(stat) { - dir.FollowedSymlink = true; - } - return dir; -} diff --git a/src/lib/os/stat_linux_386.go b/src/lib/os/stat_linux_386.go deleted file mode 100644 index 13ee942c97..0000000000 --- a/src/lib/os/stat_linux_386.go +++ /dev/null @@ -1,47 +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. - -// TODO(rsc): Once the porting dust settles, consider -// whether this file should be stat_linux.go (and similarly -// stat_darwin.go) instead of having one copy per architecture. - -// 386, Linux - -package os - -import ( - "os"; - "syscall"; -) - -func isSymlink(stat *syscall.Stat_t) bool { - return stat.Mode & syscall.S_IFMT == syscall.S_IFLNK -} - -func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { - dir.Dev = stat.Dev; - dir.Ino = uint64(stat.Ino); - dir.Nlink = uint64(stat.Nlink); - dir.Mode = stat.Mode; - dir.Uid = stat.Uid; - dir.Gid = stat.Gid; - dir.Rdev = stat.Rdev; - dir.Size = uint64(stat.Size); - dir.Blksize = uint64(stat.Blksize); - dir.Blocks = uint64(stat.Blocks); - dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim)); - dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim)); - dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim)); - for i := len(name) - 1; i >= 0; i-- { - if name[i] == '/' { - name = name[i+1:len(name)]; - break; - } - } - dir.Name = name; - if isSymlink(lstat) && !isSymlink(stat) { - dir.FollowedSymlink = true; - } - return dir; -} diff --git a/src/lib/os/stat_linux_amd64.go b/src/lib/os/stat_linux_amd64.go deleted file mode 100644 index 9b30181784..0000000000 --- a/src/lib/os/stat_linux_amd64.go +++ /dev/null @@ -1,41 +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. - -// AMD64, Linux - -package os - -import syscall "syscall" -import os "os" - -func isSymlink(stat *syscall.Stat_t) bool { - return stat.Mode & syscall.S_IFMT == syscall.S_IFLNK -} - -func dirFromStat(name string, dir *Dir, lstat, stat *syscall.Stat_t) *Dir { - dir.Dev = stat.Dev; - dir.Ino = stat.Ino; - dir.Nlink = stat.Nlink; - dir.Mode = stat.Mode; - dir.Uid = stat.Uid; - dir.Gid = stat.Gid; - dir.Rdev = stat.Rdev; - dir.Size = uint64(stat.Size); - dir.Blksize = uint64(stat.Blksize); - dir.Blocks = uint64(stat.Blocks); - dir.Atime_ns = uint64(syscall.TimespecToNsec(stat.Atim)); - dir.Mtime_ns = uint64(syscall.TimespecToNsec(stat.Mtim)); - dir.Ctime_ns = uint64(syscall.TimespecToNsec(stat.Ctim)); - for i := len(name) - 1; i >= 0; i-- { - if name[i] == '/' { - name = name[i+1:len(name)]; - break; - } - } - dir.Name = name; - if isSymlink(lstat) && !isSymlink(stat) { - dir.FollowedSymlink = true; - } - return dir; -} diff --git a/src/lib/os/time.go b/src/lib/os/time.go deleted file mode 100644 index 3eee243cc5..0000000000 --- a/src/lib/os/time.go +++ /dev/null @@ -1,24 +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 ( - "os"; - "syscall" -) - - -// Time returns the current time, in whole seconds and -// fractional nanoseconds, plus an Error if any. The current -// time is thus 1e9*sec+nsec, in nanoseconds. The zero of -// time is the Unix epoch. -func Time() (sec int64, nsec int64, err Error) { - var tv syscall.Timeval; - if errno := syscall.Gettimeofday(&tv); errno != 0 { - return 0, 0, ErrnoToError(errno) - } - return int64(tv.Sec), int64(tv.Usec)*1000, err; -} - diff --git a/src/lib/os/types.go b/src/lib/os/types.go deleted file mode 100644 index b5db866606..0000000000 --- a/src/lib/os/types.go +++ /dev/null @@ -1,75 +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" - -// An operating-system independent representation of Unix data structures. -// OS-specific routines in this directory convert the OS-local versions to these. - -// Getpagesize returns the underlying system's memory page size. -func Getpagesize() int{ - return syscall.Getpagesize() -} - -// A Dir describes a file and is returned by Stat, Fstat, and Lstat -type Dir struct { - Dev uint64; // device number of file system holding file. - Ino uint64; // inode number. - Nlink uint64; // number of hard links. - Mode uint32; // permission and mode bits. - Uid uint32; // user id of owner. - Gid uint32; // group id of owner. - Rdev uint64; // device type for special file. - Size uint64; // length in bytes. - Blksize uint64; // size of blocks, in bytes. - Blocks uint64; // number of blocks allocated for file. - Atime_ns uint64; // access time; nanoseconds since epoch. - Mtime_ns uint64; // modified time; nanoseconds since epoch. - Ctime_ns uint64; // status change time; nanoseconds since epoch. - Name string; // name of file as presented to Open. - FollowedSymlink bool; // followed a symlink to get this information -} - -// IsFifo reports whether the Dir describes a FIFO file. -func (dir *Dir) IsFifo() bool { - return (dir.Mode & syscall.S_IFMT) == syscall.S_IFIFO -} - -// IsChar reports whether the Dir describes a character special file. -func (dir *Dir) IsChar() bool { - return (dir.Mode & syscall.S_IFMT) == syscall.S_IFCHR -} - -// IsDirectory reports whether the Dir describes a directory. -func (dir *Dir) IsDirectory() bool { - return (dir.Mode & syscall.S_IFMT) == syscall.S_IFDIR -} - -// IsBlock reports whether the Dir describes a block special file. -func (dir *Dir) IsBlock() bool { - return (dir.Mode & syscall.S_IFMT) == syscall.S_IFBLK -} - -// IsRegular reports whether the Dir describes a regular file. -func (dir *Dir) IsRegular() bool { - return (dir.Mode & syscall.S_IFMT) == syscall.S_IFREG -} - -// IsSymlink reports whether the Dir describes a symbolic link. -func (dir *Dir) IsSymlink() bool { - return (dir.Mode & syscall.S_IFMT) == syscall.S_IFLNK -} - -// IsSocket reports whether the Dir describes a socket. -func (dir *Dir) IsSocket() bool { - return (dir.Mode & syscall.S_IFMT) == syscall.S_IFSOCK -} - -// Permission returns the file permission bits. -func (dir *Dir) Permission() int { - return int(dir.Mode & 0777) -} - |
