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) { ...@@ -106,6 +106,9 @@ func Hostname() (name string, err error) {
// directory, Readdir returns the FileInfo read until that point // directory, Readdir returns the FileInfo read until that point
// and a non-nil error. // and a non-nil error.
func (f *File) Readdir(n int) (fi []FileInfo, err error) { func (f *File) Readdir(n int) (fi []FileInfo, err error) {
if f == nil {
return nil, ErrInvalid
}
return f.readdir(n) return f.readdir(n)
} }
...@@ -122,5 +125,8 @@ func (f *File) Readdir(n int) (fi []FileInfo, err error) { ...@@ -122,5 +125,8 @@ func (f *File) Readdir(n int) (fi []FileInfo, err error) {
// directory, Readdirnames returns the names read until that point and // directory, Readdirnames returns the names read until that point and
// a non-nil error. // a non-nil error.
func (f *File) Readdirnames(n int) (names []string, err error) { func (f *File) Readdirnames(n int) (names []string, err error) {
if f == nil {
return nil, ErrInvalid
}
return f.readdirnames(n) return f.readdirnames(n)
} }
...@@ -174,6 +174,9 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) { ...@@ -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. // relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any. // It returns the new offset and an error, if any.
func (f *File) Seek(offset int64, whence int) (ret int64, err error) { func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
if f == nil {
return 0, ErrInvalid
}
r, e := f.seek(offset, whence) r, e := f.seek(offset, whence)
if e == nil && f.dirinfo != nil && r != 0 { if e == nil && f.dirinfo != nil && r != 0 {
e = syscall.EISDIR e = syscall.EISDIR
...@@ -216,6 +219,9 @@ func Chdir(dir string) error { ...@@ -216,6 +219,9 @@ func Chdir(dir string) error {
// which must be a directory. // which must be a directory.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Chdir() error { func (f *File) Chdir() error {
if f == nil {
return ErrInvalid
}
if e := syscall.Fchdir(f.fd); e != nil { if e := syscall.Fchdir(f.fd); e != nil {
return &PathError{"chdir", f.name, e} return &PathError{"chdir", f.name, e}
} }
......
...@@ -133,6 +133,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { ...@@ -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. // Close closes the File, rendering it unusable for I/O.
// It returns an error, if any. // It returns an error, if any.
func (f *File) Close() error { func (f *File) Close() error {
if f == nil {
return ErrInvalid
}
return f.file.close() return f.file.close()
} }
...@@ -156,6 +159,9 @@ func (file *file) close() error { ...@@ -156,6 +159,9 @@ func (file *file) close() error {
// Stat returns the FileInfo structure describing file. // Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Stat() (fi FileInfo, err error) { func (f *File) Stat() (fi FileInfo, err error) {
if f == nil {
return nil, ErrInvalid
}
d, err := dirstat(f) d, err := dirstat(f)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -167,8 +173,11 @@ func (f *File) Stat() (fi FileInfo, err error) { ...@@ -167,8 +173,11 @@ func (f *File) Stat() (fi FileInfo, err error) {
// It does not change the I/O offset. // It does not change the I/O offset.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Truncate(size int64) error { func (f *File) Truncate(size int64) error {
var d syscall.Dir if f == nil {
return ErrInvalid
}
var d syscall.Dir
d.Null() d.Null()
d.Length = size d.Length = size
...@@ -188,6 +197,9 @@ const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | Mod ...@@ -188,6 +197,9 @@ const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | Mod
// Chmod changes the mode of the file to mode. // Chmod changes the mode of the file to mode.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Chmod(mode FileMode) error { func (f *File) Chmod(mode FileMode) error {
if f == nil {
return ErrInvalid
}
var d syscall.Dir var d syscall.Dir
odir, e := dirstat(f) odir, e := dirstat(f)
...@@ -419,6 +431,9 @@ func Lchown(name string, uid, gid int) error { ...@@ -419,6 +431,9 @@ func Lchown(name string, uid, gid int) error {
// Chown changes the numeric uid and gid of the named file. // Chown changes the numeric uid and gid of the named file.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error { func (f *File) Chown(uid, gid int) error {
if f == nil {
return ErrInvalid
}
return &PathError{"chown", f.name, syscall.EPLAN9} return &PathError{"chown", f.name, syscall.EPLAN9}
} }
......
...@@ -86,6 +86,9 @@ func Chmod(name string, mode FileMode) error { ...@@ -86,6 +86,9 @@ func Chmod(name string, mode FileMode) error {
// Chmod changes the mode of the file to mode. // Chmod changes the mode of the file to mode.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Chmod(mode FileMode) error { func (f *File) Chmod(mode FileMode) error {
if f == nil {
return ErrInvalid
}
if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil { if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil {
return &PathError{"chmod", f.name, e} return &PathError{"chmod", f.name, e}
} }
...@@ -115,6 +118,9 @@ func Lchown(name string, uid, gid int) error { ...@@ -115,6 +118,9 @@ func Lchown(name string, uid, gid int) error {
// Chown changes the numeric uid and gid of the named file. // Chown changes the numeric uid and gid of the named file.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error { func (f *File) Chown(uid, gid int) error {
if f == nil {
return ErrInvalid
}
if e := syscall.Fchown(f.fd, uid, gid); e != nil { if e := syscall.Fchown(f.fd, uid, gid); e != nil {
return &PathError{"chown", f.name, e} return &PathError{"chown", f.name, e}
} }
...@@ -125,6 +131,9 @@ func (f *File) Chown(uid, gid int) error { ...@@ -125,6 +131,9 @@ func (f *File) Chown(uid, gid int) error {
// It does not change the I/O offset. // It does not change the I/O offset.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Truncate(size int64) error { func (f *File) Truncate(size int64) error {
if f == nil {
return ErrInvalid
}
if e := syscall.Ftruncate(f.fd, size); e != nil { if e := syscall.Ftruncate(f.fd, size); e != nil {
return &PathError{"truncate", f.name, e} return &PathError{"truncate", f.name, e}
} }
......
...@@ -96,6 +96,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { ...@@ -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. // Close closes the File, rendering it unusable for I/O.
// It returns an error, if any. // It returns an error, if any.
func (f *File) Close() error { func (f *File) Close() error {
if f == nil {
return ErrInvalid
}
return f.file.close() return f.file.close()
} }
...@@ -117,6 +120,9 @@ func (file *file) close() error { ...@@ -117,6 +120,9 @@ func (file *file) close() error {
// Stat returns the FileInfo structure describing file. // Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (f *File) Stat() (fi FileInfo, err error) { func (f *File) Stat() (fi FileInfo, err error) {
if f == nil {
return nil, ErrInvalid
}
var stat syscall.Stat_t var stat syscall.Stat_t
err = syscall.Fstat(f.fd, &stat) err = syscall.Fstat(f.fd, &stat)
if err != nil { if err != nil {
......
...@@ -153,6 +153,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { ...@@ -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. // Close closes the File, rendering it unusable for I/O.
// It returns an error, if any. // It returns an error, if any.
func (file *File) Close() error { func (file *File) Close() error {
if f == nil {
return ErrInvalid
}
return file.file.close() return file.file.close()
} }
......
...@@ -12,6 +12,9 @@ import ( ...@@ -12,6 +12,9 @@ import (
// Stat returns the FileInfo structure describing file. // Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError. // If there is an error, it will be of type *PathError.
func (file *File) Stat() (fi FileInfo, err error) { func (file *File) Stat() (fi FileInfo, err error) {
if file == nil {
return nil, ErrInvalid
}
if file == nil || file.fd < 0 { if file == nil || file.fd < 0 {
return nil, syscall.EINVAL 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