mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
os: do not assume syscall i/o funcs return n=0 on error
Fixes #9007. LGTM=iant, r R=r, iant CC=golang-codereviews https://golang.org/cl/160670043
This commit is contained in:
parent
bd1169dd21
commit
a62da2027b
6 changed files with 22 additions and 16 deletions
|
|
@ -36,7 +36,7 @@ func (f *File) readdirnames(n int) (names []string, err error) {
|
||||||
if d.bufp >= d.nbuf {
|
if d.bufp >= d.nbuf {
|
||||||
d.bufp = 0
|
d.bufp = 0
|
||||||
var errno error
|
var errno error
|
||||||
d.nbuf, errno = syscall.ReadDirent(f.fd, d.buf)
|
d.nbuf, errno = fixCount(syscall.ReadDirent(f.fd, d.buf))
|
||||||
if errno != nil {
|
if errno != nil {
|
||||||
return names, NewSyscallError("readdirent", errno)
|
return names, NewSyscallError("readdirent", errno)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -255,3 +255,12 @@ var lstat = Lstat
|
||||||
func Rename(oldpath, newpath string) error {
|
func Rename(oldpath, newpath string) error {
|
||||||
return rename(oldpath, newpath)
|
return rename(oldpath, newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Many functions in package syscall return a count of -1 instead of 0.
|
||||||
|
// Using fixCount(call()) instead of call() corrects the count.
|
||||||
|
func fixCount(n int, err error) (int, error) {
|
||||||
|
if n < 0 {
|
||||||
|
n = 0
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -244,14 +244,14 @@ func (f *File) Sync() (err error) {
|
||||||
// read reads up to len(b) bytes from the File.
|
// read reads up to len(b) bytes from the File.
|
||||||
// It returns the number of bytes read and an error, if any.
|
// It returns the number of bytes read and an error, if any.
|
||||||
func (f *File) read(b []byte) (n int, err error) {
|
func (f *File) read(b []byte) (n int, err error) {
|
||||||
return syscall.Read(f.fd, b)
|
return fixCount(syscall.Read(f.fd, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
// pread reads len(b) bytes from the File starting at byte offset off.
|
// 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.
|
// It returns the number of bytes read and the error, if any.
|
||||||
// EOF is signaled by a zero count with err set to nil.
|
// EOF is signaled by a zero count with err set to nil.
|
||||||
func (f *File) pread(b []byte, off int64) (n int, err error) {
|
func (f *File) pread(b []byte, off int64) (n int, err error) {
|
||||||
return syscall.Pread(f.fd, b, off)
|
return fixCount(syscall.Pread(f.fd, b, off))
|
||||||
}
|
}
|
||||||
|
|
||||||
// write writes len(b) bytes to the File.
|
// write writes len(b) bytes to the File.
|
||||||
|
|
@ -259,10 +259,7 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
|
||||||
// Since Plan 9 preserves message boundaries, never allow
|
// Since Plan 9 preserves message boundaries, never allow
|
||||||
// a zero-byte write.
|
// a zero-byte write.
|
||||||
func (f *File) write(b []byte) (n int, err error) {
|
func (f *File) write(b []byte) (n int, err error) {
|
||||||
if len(b) == 0 {
|
return fixCount(syscall.Write(f.fd, b))
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
return syscall.Write(f.fd, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pwrite writes len(b) bytes to the File starting at byte offset off.
|
// pwrite writes len(b) bytes to the File starting at byte offset off.
|
||||||
|
|
@ -273,7 +270,7 @@ func (f *File) pwrite(b []byte, off int64) (n int, err error) {
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
return syscall.Pwrite(f.fd, b, off)
|
return fixCount(syscall.Pwrite(f.fd, b, off))
|
||||||
}
|
}
|
||||||
|
|
||||||
// seek sets the offset for the next Read or Write on file to offset, interpreted
|
// seek sets the offset for the next Read or Write on file to offset, interpreted
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ func sigpipe() // implemented in package runtime
|
||||||
func Readlink(name string) (string, error) {
|
func Readlink(name string) (string, error) {
|
||||||
for len := 128; ; len *= 2 {
|
for len := 128; ; len *= 2 {
|
||||||
b := make([]byte, len)
|
b := make([]byte, len)
|
||||||
n, e := syscall.Readlink(name, b)
|
n, e := fixCount(syscall.Readlink(name, b))
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return "", &PathError{"readlink", name, e}
|
return "", &PathError{"readlink", name, e}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ func (f *File) read(b []byte) (n int, err error) {
|
||||||
if needsMaxRW && len(b) > maxRW {
|
if needsMaxRW && len(b) > maxRW {
|
||||||
b = b[:maxRW]
|
b = b[:maxRW]
|
||||||
}
|
}
|
||||||
return syscall.Read(f.fd, b)
|
return fixCount(syscall.Read(f.fd, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
// pread reads len(b) bytes from the File starting at byte offset off.
|
// pread reads len(b) bytes from the File starting at byte offset off.
|
||||||
|
|
@ -197,7 +197,7 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
|
||||||
if needsMaxRW && len(b) > maxRW {
|
if needsMaxRW && len(b) > maxRW {
|
||||||
b = b[:maxRW]
|
b = b[:maxRW]
|
||||||
}
|
}
|
||||||
return syscall.Pread(f.fd, b, off)
|
return fixCount(syscall.Pread(f.fd, b, off))
|
||||||
}
|
}
|
||||||
|
|
||||||
// write writes len(b) bytes to the File.
|
// write writes len(b) bytes to the File.
|
||||||
|
|
@ -208,7 +208,7 @@ func (f *File) write(b []byte) (n int, err error) {
|
||||||
if needsMaxRW && len(bcap) > maxRW {
|
if needsMaxRW && len(bcap) > maxRW {
|
||||||
bcap = bcap[:maxRW]
|
bcap = bcap[:maxRW]
|
||||||
}
|
}
|
||||||
m, err := syscall.Write(f.fd, bcap)
|
m, err := fixCount(syscall.Write(f.fd, bcap))
|
||||||
n += m
|
n += m
|
||||||
|
|
||||||
// If the syscall wrote some data but not all (short write)
|
// If the syscall wrote some data but not all (short write)
|
||||||
|
|
@ -234,7 +234,7 @@ func (f *File) pwrite(b []byte, off int64) (n int, err error) {
|
||||||
if needsMaxRW && len(b) > maxRW {
|
if needsMaxRW && len(b) > maxRW {
|
||||||
b = b[:maxRW]
|
b = b[:maxRW]
|
||||||
}
|
}
|
||||||
return syscall.Pwrite(f.fd, b, off)
|
return fixCount(syscall.Pwrite(f.fd, b, off))
|
||||||
}
|
}
|
||||||
|
|
||||||
// seek sets the offset for the next Read or Write on file to offset, interpreted
|
// seek sets the offset for the next Read or Write on file to offset, interpreted
|
||||||
|
|
@ -242,7 +242,7 @@ func (f *File) pwrite(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) {
|
||||||
return syscall.Seek(f.fd, offset, whence)
|
return fixCount(syscall.Seek(f.fd, offset, whence))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate changes the size of the named file.
|
// Truncate changes the size of the named file.
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@ func (f *File) read(b []byte) (n int, err error) {
|
||||||
if f.isConsole {
|
if f.isConsole {
|
||||||
return f.readConsole(b)
|
return f.readConsole(b)
|
||||||
}
|
}
|
||||||
return syscall.Read(f.fd, b)
|
return fixCount(syscall.Read(f.fd, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
// pread reads len(b) bytes from the File starting at byte offset off.
|
// pread reads len(b) bytes from the File starting at byte offset off.
|
||||||
|
|
@ -376,7 +376,7 @@ func (f *File) write(b []byte) (n int, err error) {
|
||||||
if f.isConsole {
|
if f.isConsole {
|
||||||
return f.writeConsole(b)
|
return f.writeConsole(b)
|
||||||
}
|
}
|
||||||
return syscall.Write(f.fd, b)
|
return fixCount(syscall.Write(f.fd, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
// pwrite writes len(b) bytes to the File starting at byte offset off.
|
// pwrite writes len(b) bytes to the File starting at byte offset off.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue