diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-12-12 23:13:29 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-12-12 23:13:29 +0000 |
commit | a42a906c420d7bb196cb8541e0ab65264a0b04b0 (patch) | |
tree | 8c441679e35147b1e9bec048f733fc394fb0c161 /libgo/go/os | |
parent | bc77608b97abcc4bb3171f08a71e34ae342e9f8d (diff) | |
download | gcc-a42a906c420d7bb196cb8541e0ab65264a0b04b0.zip gcc-a42a906c420d7bb196cb8541e0ab65264a0b04b0.tar.gz gcc-a42a906c420d7bb196cb8541e0ab65264a0b04b0.tar.bz2 |
libgo: Update to current master library sources.
From-SVN: r194460
Diffstat (limited to 'libgo/go/os')
-rw-r--r-- | libgo/go/os/dir_plan9.go | 259 | ||||
-rw-r--r-- | libgo/go/os/file_plan9.go | 92 | ||||
-rw-r--r-- | libgo/go/os/os_test.go | 22 | ||||
-rw-r--r-- | libgo/go/os/stat_plan9.go | 36 | ||||
-rw-r--r-- | libgo/go/os/user/lookup.go | 22 | ||||
-rw-r--r-- | libgo/go/os/user/lookup_stubs.go | 6 | ||||
-rw-r--r-- | libgo/go/os/user/lookup_unix.go | 19 | ||||
-rw-r--r-- | libgo/go/os/user/lookup_windows.go | 9 |
8 files changed, 169 insertions, 296 deletions
diff --git a/libgo/go/os/dir_plan9.go b/libgo/go/os/dir_plan9.go index 060c0b2..8195c02 100644 --- a/libgo/go/os/dir_plan9.go +++ b/libgo/go/os/dir_plan9.go @@ -5,15 +5,11 @@ package os import ( - "errors" "io" "syscall" ) -var errShortStat = errors.New("short stat message") -var errBadStat = errors.New("bad stat message format") - -func (file *File) readdir(n int) (fi []FileInfo, err error) { +func (file *File) readdir(n int) ([]FileInfo, error) { // If this file has no dirinfo, create one. if file.dirinfo == nil { file.dirinfo = new(dirInfo) @@ -24,44 +20,47 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) { size = 100 n = -1 } - result := make([]FileInfo, 0, size) // Empty with room to grow. + fi := make([]FileInfo, 0, size) // Empty with room to grow. for n != 0 { - // Refill the buffer if necessary + // Refill the buffer if necessary. if d.bufp >= d.nbuf { - d.bufp = 0 - var e error - d.nbuf, e = file.Read(d.buf[:]) - if e != nil && e != io.EOF { - return result, &PathError{"readdir", file.name, e} - } - if e == io.EOF { - break + 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 d.nbuf < syscall.STATFIXLEN { - return result, &PathError{"readdir", file.name, errShortStat} + if nb < syscall.STATFIXLEN { + return fi, &PathError{"readdir", file.name, syscall.ErrShortStat} } } - // Get a record from buffer - m, _ := gbit16(d.buf[d.bufp:]) - m += 2 + // 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 result, &PathError{"readdir", file.name, errShortStat} + return fi, &PathError{"readdir", file.name, syscall.ErrShortStat} } - dir, e := unmarshalDir(d.buf[d.bufp : d.bufp+int(m)]) - if e != nil { - return result, &PathError{"readdir", file.name, e} + + dir, err := syscall.UnmarshalDir(b[:m]) + if err != nil { + return fi, &PathError{"readdir", file.name, err} } - result = append(result, fileInfoFromStat(dir)) + fi = append(fi, fileInfoFromStat(dir)) - d.bufp += int(m) + d.bufp += m n-- } - if n >= 0 && len(result) == 0 { - return result, io.EOF + if n >= 0 && len(fi) == 0 { + return fi, io.EOF } - return result, nil + return fi, nil } func (file *File) readdirnames(n int) (names []string, err error) { @@ -72,205 +71,3 @@ func (file *File) readdirnames(n int) (names []string, err error) { } return } - -type dir struct { - // system-modified data - Type uint16 // server type - Dev uint32 // server subtype - // file data - Qid qid // unique id from server - Mode uint32 // permissions - Atime uint32 // last read time - Mtime uint32 // last write time - Length uint64 // file length - Name string // last element of path - Uid string // owner name - Gid string // group name - Muid string // last modifier name -} - -type qid struct { - Path uint64 // the file server's unique identification for the file - Vers uint32 // version number for given Path - Type uint8 // the type of the file (syscall.QTDIR for example) -} - -var nullDir = dir{ - ^uint16(0), - ^uint32(0), - qid{^uint64(0), ^uint32(0), ^uint8(0)}, - ^uint32(0), - ^uint32(0), - ^uint32(0), - ^uint64(0), - "", - "", - "", - "", -} - -// Null assigns members of d with special "don't care" values indicating -// they should not be written by syscall.Wstat. -func (d *dir) Null() { - *d = nullDir -} - -// pdir appends a 9P Stat message based on the contents of Dir d to a byte slice b. -func pdir(b []byte, d *dir) []byte { - n := len(b) - b = pbit16(b, 0) // length, filled in later - b = pbit16(b, d.Type) - b = pbit32(b, d.Dev) - b = pqid(b, d.Qid) - b = pbit32(b, d.Mode) - b = pbit32(b, d.Atime) - b = pbit32(b, d.Mtime) - b = pbit64(b, d.Length) - b = pstring(b, d.Name) - b = pstring(b, d.Uid) - b = pstring(b, d.Gid) - b = pstring(b, d.Muid) - pbit16(b[0:n], uint16(len(b)-(n+2))) - return b -} - -// unmarshalDir reads a 9P Stat message from a 9P protocol message stored in b, -// returning the corresponding dir struct. -func unmarshalDir(b []byte) (d *dir, err error) { - n := uint16(0) - n, b = gbit16(b) - - if int(n) != len(b) { - return nil, errBadStat - } - - d = new(dir) - d.Type, b = gbit16(b) - d.Dev, b = gbit32(b) - d.Qid, b = gqid(b) - d.Mode, b = gbit32(b) - d.Atime, b = gbit32(b) - d.Mtime, b = gbit32(b) - d.Length, b = gbit64(b) - d.Name, b = gstring(b) - d.Uid, b = gstring(b) - d.Gid, b = gstring(b) - d.Muid, b = gstring(b) - - if len(b) != 0 { - return nil, errBadStat - } - - return d, nil -} - -// gqid reads the qid part of a 9P Stat message from a 9P protocol message stored in b, -// returning the corresponding qid struct and the remaining slice of b. -func gqid(b []byte) (qid, []byte) { - var q qid - q.Path, b = gbit64(b) - q.Vers, b = gbit32(b) - q.Type, b = gbit8(b) - return q, b -} - -// pqid appends a qid struct q to a 9P message b. -func pqid(b []byte, q qid) []byte { - b = pbit64(b, q.Path) - b = pbit32(b, q.Vers) - b = pbit8(b, q.Type) - return b -} - -// gbit8 reads a byte-sized numeric value from a 9P protocol message stored in b, -// returning the value and the remaining slice of b. -func gbit8(b []byte) (uint8, []byte) { - return uint8(b[0]), b[1:] -} - -// gbit16 reads a 16-bit numeric value from a 9P protocol message stored in b, -// returning the value and the remaining slice of b. -func gbit16(b []byte) (uint16, []byte) { - return uint16(b[0]) | uint16(b[1])<<8, b[2:] -} - -// gbit32 reads a 32-bit numeric value from a 9P protocol message stored in b, -// returning the value and the remaining slice of b. -func gbit32(b []byte) (uint32, []byte) { - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:] -} - -// gbit64 reads a 64-bit numeric value from a 9P protocol message stored in b, -// returning the value and the remaining slice of b. -func gbit64(b []byte) (uint64, []byte) { - lo, b := gbit32(b) - hi, b := gbit32(b) - return uint64(hi)<<32 | uint64(lo), b -} - -// gstring reads a string from a 9P protocol message stored in b, -// returning the value as a Go string and the remaining slice of b. -func gstring(b []byte) (string, []byte) { - n, b := gbit16(b) - return string(b[0:n]), b[n:] -} - -// pbit8 appends a byte-sized numeric value x to a 9P message b. -func pbit8(b []byte, x uint8) []byte { - n := len(b) - if n+1 > cap(b) { - nb := make([]byte, n, 100+2*cap(b)) - copy(nb, b) - b = nb - } - b = b[0 : n+1] - b[n] = x - return b -} - -// pbit16 appends a 16-bit numeric value x to a 9P message b. -func pbit16(b []byte, x uint16) []byte { - n := len(b) - if n+2 > cap(b) { - nb := make([]byte, n, 100+2*cap(b)) - copy(nb, b) - b = nb - } - b = b[0 : n+2] - b[n] = byte(x) - b[n+1] = byte(x >> 8) - return b -} - -// pbit32 appends a 32-bit numeric value x to a 9P message b. -func pbit32(b []byte, x uint32) []byte { - n := len(b) - if n+4 > cap(b) { - nb := make([]byte, n, 100+2*cap(b)) - copy(nb, b) - b = nb - } - b = b[0 : n+4] - b[n] = byte(x) - b[n+1] = byte(x >> 8) - b[n+2] = byte(x >> 16) - b[n+3] = byte(x >> 24) - return b -} - -// pbit64 appends a 64-bit numeric value x to a 9P message b. -func pbit64(b []byte, x uint64) []byte { - b = pbit32(b, uint32(x)) - b = pbit32(b, uint32(x>>32)) - return b -} - -// pstring appends a Go string s to a 9P message b. -func pstring(b []byte, s string) []byte { - if len(s) >= 1<<16 { - panic(errors.New("string too long")) - } - b = pbit16(b, uint16(len(s))) - b = append(b, s...) - return b -} diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go index db366a0..fb2f234 100644 --- a/libgo/go/os/file_plan9.go +++ b/libgo/go/os/file_plan9.go @@ -169,13 +169,18 @@ func (f *File) Stat() (fi FileInfo, err error) { // 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 { - var d dir - d.Null() + var d syscall.Dir - d.Length = uint64(size) + d.Null() + d.Length = size - if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil { - return &PathError{"truncate", f.name, e} + 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 } @@ -185,7 +190,7 @@ const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | Mod // 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 { - var d dir + var d syscall.Dir odir, e := dirstat(f) if e != nil { @@ -193,8 +198,14 @@ func (f *File) Chmod(mode FileMode) error { } d.Null() d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask - if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil { - return &PathError{"chmod", f.name, e} + + 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 } @@ -206,12 +217,16 @@ func (f *File) Sync() (err error) { if f == nil { return ErrInvalid } - - var d dir + var d syscall.Dir d.Null() - if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil { - return NewSyscallError("fsync", e) + 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 } @@ -253,13 +268,18 @@ func (f *File) seek(offset int64, whence int) (ret int64, err error) { // 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 dir - d.Null() + var d syscall.Dir - d.Length = uint64(size) + d.Null() + d.Length = size - if e := syscall.Wstat(name, pdir(nil, &d)); e != nil { - return &PathError{"truncate", name, e} + 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 } @@ -275,13 +295,18 @@ func Remove(name string) error { // Rename renames a file. func Rename(oldname, newname string) error { - var d dir - d.Null() + var d syscall.Dir + d.Null() d.Name = newname - if e := syscall.Wstat(oldname, pdir(nil, &d)); e != nil { - return &PathError{"rename", oldname, e} + var buf [syscall.STATFIXLEN]byte + n, err := d.Marshal(buf[:]) + if err != nil { + return &PathError{"rename", oldname, err} + } + if err = syscall.Wstat(oldname, buf[:n]); err != nil { + return &PathError{"rename", oldname, err} } return nil } @@ -290,7 +315,7 @@ func Rename(oldname, newname string) error { // 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 dir + var d syscall.Dir odir, e := dirstat(name) if e != nil { @@ -298,8 +323,14 @@ func Chmod(name string, mode FileMode) error { } d.Null() d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask - if e := syscall.Wstat(name, pdir(nil, &d)); e != nil { - return &PathError{"chmod", name, e} + + 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 } @@ -311,14 +342,19 @@ func Chmod(name string, mode FileMode) error { // 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 dir - d.Null() + var d syscall.Dir + d.Null() d.Atime = uint32(atime.Unix()) d.Mtime = uint32(mtime.Unix()) - if e := syscall.Wstat(name, pdir(nil, &d)); e != nil { - return &PathError{"chtimes", name, e} + 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 } diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go index 671c301..9f0bbdc 100644 --- a/libgo/go/os/os_test.go +++ b/libgo/go/os/os_test.go @@ -1093,3 +1093,25 @@ func TestLargeWriteToConsole(t *testing.T) { 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) + } +} diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go index b3dd188..6822cc0 100644 --- a/libgo/go/os/stat_plan9.go +++ b/libgo/go/os/stat_plan9.go @@ -10,12 +10,12 @@ import ( ) func sameFile(sys1, sys2 interface{}) bool { - a := sys1.(*dir) - b := sys2.(*dir) + a := sys1.(*syscall.Dir) + b := sys2.(*syscall.Dir) return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev } -func fileInfoFromStat(d *dir) FileInfo { +func fileInfoFromStat(d *syscall.Dir) FileInfo { fs := &fileStat{ name: d.Name, size: int64(d.Length), @@ -39,7 +39,7 @@ func fileInfoFromStat(d *dir) FileInfo { } // arg is an open *File or a path string. -func dirstat(arg interface{}) (d *dir, err error) { +func dirstat(arg interface{}) (*syscall.Dir, error) { var name string // This is big enough for most stat messages @@ -50,36 +50,40 @@ func dirstat(arg interface{}) (d *dir, err error) { 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(name, buf) + 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, errShortStat} + return nil, &PathError{"stat", name, syscall.ErrShortStat} } // Pull the real size out of the stat message. - s, _ := gbit16(buf) - size = int(s) + 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 { - d, err = unmarshalDir(buf[:n]) - if err != nil { - return nil, &PathError{"stat", name, err} - } - return + 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, errBadStat} + return nil, &PathError{"stat", name, syscall.ErrBadStat} } // Stat returns a FileInfo describing the named file. @@ -102,5 +106,5 @@ func Lstat(name string) (fi FileInfo, err error) { // For testing. func atime(fi FileInfo) time.Time { - return time.Unix(int64(fi.Sys().(*dir).Atime), 0) + return time.Unix(int64(fi.Sys().(*syscall.Dir).Atime), 0) } diff --git a/libgo/go/os/user/lookup.go b/libgo/go/os/user/lookup.go new file mode 100644 index 0000000..09f00c7 --- /dev/null +++ b/libgo/go/os/user/lookup.go @@ -0,0 +1,22 @@ +// 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/libgo/go/os/user/lookup_stubs.go b/libgo/go/os/user/lookup_stubs.go index 415f869..ad06907 100644 --- a/libgo/go/os/user/lookup_stubs.go +++ b/libgo/go/os/user/lookup_stubs.go @@ -15,14 +15,14 @@ func init() { implemented = false } -func Current() (*User, error) { +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) { +func lookup(username string) (*User, error) { return nil, fmt.Errorf("user: Lookup not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } -func LookupId(string) (*User, error) { +func lookupId(uid string) (*User, error) { return nil, fmt.Errorf("user: LookupId not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } diff --git a/libgo/go/os/user/lookup_unix.go b/libgo/go/os/user/lookup_unix.go index e0baae2..7e67495 100644 --- a/libgo/go/os/user/lookup_unix.go +++ b/libgo/go/os/user/lookup_unix.go @@ -44,28 +44,23 @@ func bytePtrToString(p *byte) string { return string(a[:i]) } -// Current returns the current user. -func Current() (*User, error) { - return lookup(syscall.Getuid(), "", false) +func current() (*User, error) { + return lookupUnix(syscall.Getuid(), "", false) } -// 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(-1, username, true) +func lookup(username string) (*User, error) { + return lookupUnix(-1, username, true) } -// 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) { +func lookupId(uid string) (*User, error) { i, e := strconv.Atoi(uid) if e != nil { return nil, e } - return lookup(i, "", false) + return lookupUnix(i, "", false) } -func lookup(uid int, username string, lookupByName bool) (*User, error) { +func lookupUnix(uid int, username string, lookupByName bool) (*User, error) { var pwd syscall.Passwd var result *syscall.Passwd diff --git a/libgo/go/os/user/lookup_windows.go b/libgo/go/os/user/lookup_windows.go index 3626a4e..a0a8a4e 100644 --- a/libgo/go/os/user/lookup_windows.go +++ b/libgo/go/os/user/lookup_windows.go @@ -68,8 +68,7 @@ func newUser(usid *syscall.SID, gid, dir string) (*User, error) { return u, nil } -// Current returns the current user. -func Current() (*User, error) { +func current() (*User, error) { t, e := syscall.OpenCurrentProcessToken() if e != nil { return nil, e @@ -103,8 +102,7 @@ func newUserFromSid(usid *syscall.SID) (*User, error) { return newUser(usid, gid, dir) } -// Lookup looks up a user by username. -func Lookup(username string) (*User, error) { +func lookup(username string) (*User, error) { sid, _, t, e := syscall.LookupSID("", username) if e != nil { return nil, e @@ -115,8 +113,7 @@ func Lookup(username string) (*User, error) { return newUserFromSid(sid) } -// LookupId looks up a user by userid. -func LookupId(uid string) (*User, error) { +func lookupId(uid string) (*User, error) { sid, e := syscall.StringToSid(uid) if e != nil { return nil, e |