diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 15:47:21 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 15:47:21 +0000 |
commit | adb0401dac41c81571722312d4586b2693f95aa6 (patch) | |
tree | ea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/os/file_plan9.go | |
parent | 5548ca3540bccbc908a45942896d635ea5f1c23f (diff) | |
download | gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.gz |
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/os/file_plan9.go')
-rw-r--r-- | libgo/go/os/file_plan9.go | 108 |
1 files changed, 83 insertions, 25 deletions
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go index 7b473f80221..1e94fb715b9 100644 --- a/libgo/go/os/file_plan9.go +++ b/libgo/go/os/file_plan9.go @@ -9,6 +9,31 @@ import ( "syscall" ) +// File represents an open 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 (file *File) Fd() int { + if file == nil { + return -1 + } + return file.fd +} + +// NewFile returns a new File with the given file descriptor and name. +func NewFile(fd int, name string) *File { + if fd < 0 { + return nil + } + f := &File{fd: fd, name: name} + runtime.SetFinalizer(f, (*File).Close) + return f +} + // Auxiliary information if the File describes a directory type dirInfo struct { buf [syscall.STATMAX]byte // buffer for directory I/O @@ -19,7 +44,6 @@ type dirInfo struct { func epipecheck(file *File, e syscall.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" @@ -30,14 +54,43 @@ const DevNull = "/dev/null" // methods on the returned File can be used for I/O. // It returns the File and an Error, if any. func OpenFile(name string, flag int, perm uint32) (file *File, err Error) { - var fd int - var e syscall.Error + var ( + fd int + e syscall.Error + create bool + excl bool + trunc bool + append bool + ) - syscall.ForkLock.RLock() if flag&O_CREATE == O_CREATE { - fd, e = syscall.Create(name, flag & ^O_CREATE, perm) + 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 + } + + syscall.ForkLock.RLock() + if (create && trunc) || excl { + fd, e = syscall.Create(name, flag, perm) } else { fd, e = syscall.Open(name, flag) + if e != nil && create { + var e1 syscall.Error + fd, e1 = syscall.Create(name, flag, perm) + if e1 == nil { + e = nil + } + } } syscall.ForkLock.RUnlock() @@ -45,6 +98,12 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err Error) { 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(fd, name), nil } @@ -69,8 +128,12 @@ func (file *File) Close() Error { // Stat returns the FileInfo structure describing file. // It returns the FileInfo and an error, if any. -func (file *File) Stat() (fi *FileInfo, err Error) { - return dirstat(file) +func (f *File) Stat() (fi *FileInfo, err Error) { + d, err := dirstat(f) + if iserror(err) { + return nil, err + } + return fileInfoFromStat(new(FileInfo), d), err } // Truncate changes the size of the file. @@ -90,10 +153,15 @@ func (f *File) Truncate(size int64) Error { // Chmod changes the mode of the file to mode. func (f *File) Chmod(mode uint32) Error { var d Dir - d.Null() + var mask = ^uint32(0777) - d.Mode = mode & 0777 + d.Null() + odir, e := dirstat(f) + if iserror(e) { + return &PathError{"chmod", f.name, e} + } + d.Mode = (odir.Mode & mask) | (mode &^ mask) if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) { return &PathError{"chmod", f.name, e} } @@ -188,26 +256,17 @@ func Rename(oldname, newname string) Error { // Chmod changes the mode of the named file to mode. func Chmod(name string, mode uint32) Error { var d Dir - d.Null() - - d.Mode = mode & 0777 + var mask = ^uint32(0777) - if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) { + d.Null() + odir, e := dirstat(name) + if iserror(e) { return &PathError{"chmod", name, e} } - return nil -} - -// ChownPlan9 changes the uid and gid strings of the named file. -func ChownPlan9(name, uid, gid string) Error { - var d Dir - d.Null() - - d.Uid = uid - d.Gid = gid + d.Mode = (odir.Mode & mask) | (mode &^ mask) if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) { - return &PathError{"chown_plan9", name, e} + return &PathError{"chmod", name, e} } return nil } @@ -244,7 +303,6 @@ func Pipe() (r *File, w *File, err Error) { return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil } - // not supported on Plan 9 // Link creates a hard link. |