diff options
Diffstat (limited to 'src/pkg/os/file_plan9.go')
-rw-r--r-- | src/pkg/os/file_plan9.go | 148 |
1 files changed, 89 insertions, 59 deletions
diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go index 1e94fb715..7d136eb36 100644 --- a/src/pkg/os/file_plan9.go +++ b/src/pkg/os/file_plan9.go @@ -7,10 +7,19 @@ package os import ( "runtime" "syscall" + "time" ) // File represents an open file descriptor. type File struct { + *file +} + +// file is the real representation of *File. +// The extra level of indirection ensures that no clients of os +// can overwrite this data, which could cause the finalizer +// to close the wrong file descriptor. +type file struct { fd int name string dirinfo *dirInfo // nil unless directory being read @@ -29,8 +38,8 @@ func NewFile(fd int, name string) *File { if fd < 0 { return nil } - f := &File{fd: fd, name: name} - runtime.SetFinalizer(f, (*File).Close) + f := &File{&file{fd: fd, name: name}} + runtime.SetFinalizer(f.file, (*file).close) return f } @@ -41,22 +50,37 @@ type dirInfo struct { bufp int // location of next record in buf. } -func epipecheck(file *File, e syscall.Error) { +func epipecheck(file *File, e error) { } // DevNull is the name of the operating system's ``null device.'' // On Unix-like systems, it is "/dev/null"; on Windows, "NUL". const DevNull = "/dev/null" +// syscallMode returns the syscall-specific mode bits from Go's portable mode bits. +func syscallMode(i FileMode) (o uint32) { + o |= uint32(i.Perm()) + if i&ModeAppend != 0 { + o |= syscall.DMAPPEND + } + if i&ModeExclusive != 0 { + o |= syscall.DMEXCL + } + if i&ModeTemporary != 0 { + o |= syscall.DMTMP + } + return +} + // OpenFile is the generalized open call; most users will use Open // or Create instead. It opens the named file with specified flag // (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, // methods on the returned File can be used for I/O. -// It returns the File and an Error, if any. -func OpenFile(name string, flag int, perm uint32) (file *File, err Error) { +// It returns the File and an error, if any. +func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { var ( fd int - e syscall.Error + e error create bool excl bool trunc bool @@ -81,12 +105,12 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err Error) { syscall.ForkLock.RLock() if (create && trunc) || excl { - fd, e = syscall.Create(name, flag, perm) + fd, e = syscall.Create(name, flag, syscallMode(perm)) } else { fd, e = syscall.Open(name, flag) if e != nil && create { - var e1 syscall.Error - fd, e1 = syscall.Create(name, flag, perm) + var e1 error + fd, e1 = syscall.Create(name, flag, syscallMode(perm)) if e1 == nil { e = nil } @@ -108,12 +132,16 @@ func OpenFile(name string, flag int, perm uint32) (file *File, err Error) { } // Close closes the File, rendering it unusable for I/O. -// It returns an Error, if any. -func (file *File) Close() Error { +// It returns an error, if any. +func (file *File) Close() error { + return file.file.close() +} + +func (file *file) close() error { if file == nil || file.fd < 0 { return Ebadfd } - var err Error + var err error syscall.ForkLock.RLock() if e := syscall.Close(file.fd); e != nil { err = &PathError{"close", file.name, e} @@ -128,41 +156,41 @@ func (file *File) Close() Error { // Stat returns the FileInfo structure describing file. // It returns the FileInfo and an error, if any. -func (f *File) Stat() (fi *FileInfo, err Error) { +func (f *File) Stat() (FileInfo, error) { d, err := dirstat(f) - if iserror(err) { + if err != nil { return nil, err } - return fileInfoFromStat(new(FileInfo), d), err + return fileInfoFromStat(d), nil } // Truncate changes the size of the file. // It does not change the I/O offset. -func (f *File) Truncate(size int64) Error { +func (f *File) Truncate(size int64) error { var d Dir d.Null() d.Length = uint64(size) - if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) { + if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil { return &PathError{"truncate", f.name, e} } return nil } +const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | ModePerm) + // Chmod changes the mode of the file to mode. -func (f *File) Chmod(mode uint32) Error { +func (f *File) Chmod(mode FileMode) error { var d Dir - var mask = ^uint32(0777) - d.Null() odir, e := dirstat(f) - if iserror(e) { + if e != nil { return &PathError{"chmod", f.name, e} } - - d.Mode = (odir.Mode & mask) | (mode &^ mask) - if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) { + 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} } return nil @@ -171,7 +199,7 @@ func (f *File) Chmod(mode uint32) Error { // Sync commits the current contents of the file to stable storage. // Typically, this means flushing the file system's in-memory copy // of recently written data to disk. -func (f *File) Sync() (err Error) { +func (f *File) Sync() (err error) { if f == nil { return EINVAL } @@ -179,7 +207,7 @@ func (f *File) Sync() (err Error) { var d Dir d.Null() - if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) { + if e := syscall.Fwstat(f.fd, pdir(nil, &d)); e != nil { return NewSyscallError("fsync", e) } return nil @@ -187,26 +215,26 @@ func (f *File) Sync() (err Error) { // read reads up to len(b) bytes from the File. // It returns the number of bytes read and an error, if any. -func (f *File) read(b []byte) (n int, err syscall.Error) { +func (f *File) read(b []byte) (n int, err error) { return syscall.Read(f.fd, b) } // pread reads len(b) bytes from the File starting at byte offset off. // It returns the number of bytes read and the error, if any. // EOF is signaled by a zero count with err set to nil. -func (f *File) pread(b []byte, off int64) (n int, err syscall.Error) { +func (f *File) pread(b []byte, off int64) (n int, err error) { return syscall.Pread(f.fd, b, off) } // write writes len(b) bytes to the File. // It returns the number of bytes written and an error, if any. -func (f *File) write(b []byte) (n int, err syscall.Error) { +func (f *File) write(b []byte) (n int, err error) { return syscall.Write(f.fd, b) } // pwrite writes len(b) bytes to the File starting at byte offset off. // It returns the number of bytes written and an error, if any. -func (f *File) pwrite(b []byte, off int64) (n int, err syscall.Error) { +func (f *File) pwrite(b []byte, off int64) (n int, err error) { return syscall.Pwrite(f.fd, b, off) } @@ -214,58 +242,56 @@ func (f *File) pwrite(b []byte, off int64) (n int, err syscall.Error) { // according to whence: 0 means relative to the origin of the file, 1 means // relative to the current offset, and 2 means relative to the end. // It returns the new offset and an error, if any. -func (f *File) seek(offset int64, whence int) (ret int64, err syscall.Error) { +func (f *File) seek(offset int64, whence int) (ret int64, err error) { return syscall.Seek(f.fd, offset, whence) } // Truncate changes the size of the named file. // If the file is a symbolic link, it changes the size of the link's target. -func Truncate(name string, size int64) Error { +func Truncate(name string, size int64) error { var d Dir d.Null() d.Length = uint64(size) - if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) { + if e := syscall.Wstat(name, pdir(nil, &d)); e != nil { return &PathError{"truncate", name, e} } return nil } // Remove removes the named file or directory. -func Remove(name string) Error { - if e := syscall.Remove(name); iserror(e) { +func Remove(name string) error { + if e := syscall.Remove(name); e != nil { return &PathError{"remove", name, e} } return nil } // Rename renames a file. -func Rename(oldname, newname string) Error { +func Rename(oldname, newname string) error { var d Dir d.Null() d.Name = newname - if e := syscall.Wstat(oldname, pdir(nil, &d)); iserror(e) { + if e := syscall.Wstat(oldname, pdir(nil, &d)); e != nil { return &PathError{"rename", oldname, e} } return nil } // Chmod changes the mode of the named file to mode. -func Chmod(name string, mode uint32) Error { +func Chmod(name string, mode FileMode) error { var d Dir - var mask = ^uint32(0777) - d.Null() odir, e := dirstat(name) - if iserror(e) { + if e != nil { return &PathError{"chmod", name, e} } - - d.Mode = (odir.Mode & mask) | (mode &^ mask) - if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) { + 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} } return nil @@ -274,27 +300,26 @@ func Chmod(name string, mode uint32) Error { // Chtimes changes the access and modification times of the named // file, similar to the Unix utime() or utimes() functions. // -// The argument times are in nanoseconds, although the underlying -// filesystem may truncate or round the values to a more -// coarse time unit. -func Chtimes(name string, atimeNs int64, mtimeNs int64) Error { +// The underlying filesystem may truncate or round the values to a +// less precise time unit. +func Chtimes(name string, atime time.Time, mtime time.Time) error { var d Dir d.Null() - d.Atime = uint32(atimeNs / 1e9) - d.Mtime = uint32(mtimeNs / 1e9) + d.Atime = uint32(atime.Unix()) + d.Mtime = uint32(mtime.Unix()) - if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) { + if e := syscall.Wstat(name, pdir(nil, &d)); e != nil { return &PathError{"chtimes", name, e} } return nil } -func Pipe() (r *File, w *File, err Error) { +func Pipe() (r *File, w *File, err error) { var p [2]int syscall.ForkLock.RLock() - if e := syscall.Pipe(p[0:]); iserror(e) { + if e := syscall.Pipe(p[0:]); e != nil { syscall.ForkLock.RUnlock() return nil, nil, NewSyscallError("pipe", e) } @@ -306,26 +331,31 @@ func Pipe() (r *File, w *File, err Error) { // not supported on Plan 9 // Link creates a hard link. -func Link(oldname, newname string) Error { +func Link(oldname, newname string) error { return EPLAN9 } -func Symlink(oldname, newname string) Error { +func Symlink(oldname, newname string) error { return EPLAN9 } -func Readlink(name string) (string, Error) { +func Readlink(name string) (string, error) { return "", EPLAN9 } -func Chown(name string, uid, gid int) Error { +func Chown(name string, uid, gid int) error { return EPLAN9 } -func Lchown(name string, uid, gid int) Error { +func Lchown(name string, uid, gid int) error { return EPLAN9 } -func (f *File) Chown(uid, gid int) Error { +func (f *File) Chown(uid, gid int) error { return EPLAN9 } + +// TempDir returns the default directory to use for temporary files. +func TempDir() string { + return "/tmp" +} |