Commit 4cb086b8 authored by Rob Pike's avatar Rob Pike

os: be consistent about File methods with nil receivers

Some crashed, some didn't. Make a nil receiver always
return ErrInvalid rather than crash.
Fixes #5824.
The program in the bug listing is silent now, at least on my Mac.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/13108044
parent a3695fb2
......@@ -106,6 +106,9 @@ func Hostname() (name string, err error) {
// directory, Readdir returns the FileInfo read until that point
// and a non-nil error.
func (f *File) Readdir(n int) (fi []FileInfo, err error) {
if f == nil {
return nil, ErrInvalid
}
return f.readdir(n)
}
......@@ -122,5 +125,8 @@ func (f *File) Readdir(n int) (fi []FileInfo, err error) {
// directory, Readdirnames returns the names read until that point and
// a non-nil error.
func (f *File) Readdirnames(n int) (names []string, err error) {
if f == nil {
return nil, ErrInvalid
}
return f.readdirnames(n)
}
......@@ -174,6 +174,9 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
// 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 error) {
if f == nil {
return 0, ErrInvalid
}
r, e := f.seek(offset, whence)
if e == nil && f.dirinfo != nil && r != 0 {
e = syscall.EISDIR
......@@ -216,6 +219,9 @@ func Chdir(dir string) error {
// which must be a directory.
// If there is an error, it will be of type *PathError.
func (f *File) Chdir() error {
if f == nil {
return ErrInvalid
}
if e := syscall.Fchdir(f.fd); e != nil {
return &PathError{"chdir", f.name, e}
}
......
......@@ -133,6 +133,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (f *File) Close() error {
if f == nil {
return ErrInvalid
}
return f.file.close()
}
......@@ -156,6 +159,9 @@ func (file *file) close() error {
// Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError.
func (f *File) Stat() (fi FileInfo, err error) {
if f == nil {
return nil, ErrInvalid
}
d, err := dirstat(f)
if err != nil {
return nil, err
......@@ -167,8 +173,11 @@ 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 syscall.Dir
if f == nil {
return ErrInvalid
}
var d syscall.Dir
d.Null()
d.Length = size
......@@ -188,6 +197,9 @@ 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 {
if f == nil {
return ErrInvalid
}
var d syscall.Dir
odir, e := dirstat(f)
......@@ -419,6 +431,9 @@ func Lchown(name string, uid, gid int) error {
// Chown changes the numeric uid and gid of the named file.
// If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error {
if f == nil {
return ErrInvalid
}
return &PathError{"chown", f.name, syscall.EPLAN9}
}
......
......@@ -86,6 +86,9 @@ func Chmod(name string, mode FileMode) error {
// 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 {
if f == nil {
return ErrInvalid
}
if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil {
return &PathError{"chmod", f.name, e}
}
......@@ -115,6 +118,9 @@ func Lchown(name string, uid, gid int) error {
// Chown changes the numeric uid and gid of the named file.
// If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error {
if f == nil {
return ErrInvalid
}
if e := syscall.Fchown(f.fd, uid, gid); e != nil {
return &PathError{"chown", f.name, e}
}
......@@ -125,6 +131,9 @@ func (f *File) Chown(uid, gid int) 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 {
if f == nil {
return ErrInvalid
}
if e := syscall.Ftruncate(f.fd, size); e != nil {
return &PathError{"truncate", f.name, e}
}
......
......@@ -96,6 +96,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (f *File) Close() error {
if f == nil {
return ErrInvalid
}
return f.file.close()
}
......@@ -117,6 +120,9 @@ func (file *file) close() error {
// Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError.
func (f *File) Stat() (fi FileInfo, err error) {
if f == nil {
return nil, ErrInvalid
}
var stat syscall.Stat_t
err = syscall.Fstat(f.fd, &stat)
if err != nil {
......
......@@ -153,6 +153,9 @@ func OpenFile(name string, flag int, perm FileMode) (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 {
if f == nil {
return ErrInvalid
}
return file.file.close()
}
......
......@@ -12,6 +12,9 @@ import (
// Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError.
func (file *File) Stat() (fi FileInfo, err error) {
if file == nil {
return nil, ErrInvalid
}
if file == nil || file.fd < 0 {
return nil, syscall.EINVAL
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment