summaryrefslogtreecommitdiff
path: root/src/pkg/os/file_plan9.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/os/file_plan9.go')
-rw-r--r--src/pkg/os/file_plan9.go69
1 files changed, 59 insertions, 10 deletions
diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go
index 7b473f802..b0c42d14d 100644
--- a/src/pkg/os/file_plan9.go
+++ b/src/pkg/os/file_plan9.go
@@ -30,14 +30,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 +74,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 +104,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 +129,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,10 +232,15 @@ 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()
+ var mask = ^uint32(0777)
- d.Mode = mode & 0777
+ d.Null()
+ odir, e := dirstat(name)
+ if iserror(e) {
+ return &PathError{"chmod", name, e}
+ }
+ d.Mode = (odir.Mode & mask) | (mode &^ mask)
if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
return &PathError{"chmod", name, e}
}