mirror of
https://github.com/rclone/rclone.git
synced 2024-11-22 16:07:57 +08:00
vfs: Make OpenFile and friends return EINVAL if O_RDONLY and O_TRUNC
Before this change Open("name", os.O_RDONLY|os.O_TRUNC) would have truncated the file. This is what Linux does, but is counterintuitive. POSIX states this is undefined, so return an error in this case instead. This preserves the invariant O_RDONLY => file is not changed.
This commit is contained in:
parent
3282fd26af
commit
54deb01f00
|
@ -540,6 +540,8 @@ func translateError(err error) (errc int) {
|
||||||
return -fuse.EROFS
|
return -fuse.EROFS
|
||||||
case vfs.ENOSYS:
|
case vfs.ENOSYS:
|
||||||
return -fuse.ENOSYS
|
return -fuse.ENOSYS
|
||||||
|
case vfs.EINVAL:
|
||||||
|
return -fuse.EINVAL
|
||||||
}
|
}
|
||||||
fs.Errorf(nil, "IO error: %v", err)
|
fs.Errorf(nil, "IO error: %v", err)
|
||||||
return -fuse.EIO
|
return -fuse.EIO
|
||||||
|
|
|
@ -91,6 +91,8 @@ func translateError(err error) error {
|
||||||
return fuse.Errno(syscall.EROFS)
|
return fuse.Errno(syscall.EROFS)
|
||||||
case vfs.ENOSYS:
|
case vfs.ENOSYS:
|
||||||
return fuse.ENOSYS
|
return fuse.ENOSYS
|
||||||
|
case vfs.EINVAL:
|
||||||
|
return fuse.Errno(syscall.EINVAL)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ var (
|
||||||
ENOENT = os.ErrNotExist
|
ENOENT = os.ErrNotExist
|
||||||
EEXIST = os.ErrExist
|
EEXIST = os.ErrExist
|
||||||
EPERM = os.ErrPermission
|
EPERM = os.ErrPermission
|
||||||
|
EINVAL = os.ErrInvalid
|
||||||
// ECLOSED see errors_{old,new}.go
|
// ECLOSED see errors_{old,new}.go
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
12
vfs/file.go
12
vfs/file.go
|
@ -292,7 +292,6 @@ func (f *File) openRead() (fh *ReadFileHandle, err error) {
|
||||||
|
|
||||||
fh, err = newReadFileHandle(f, o)
|
fh, err = newReadFileHandle(f, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "open for read")
|
|
||||||
fs.Errorf(f, "File.openRead failed: %v", err)
|
fs.Errorf(f, "File.openRead failed: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -308,7 +307,6 @@ func (f *File) openWrite(flags int) (fh *WriteFileHandle, err error) {
|
||||||
|
|
||||||
fh, err = newWriteFileHandle(f.d, f, f.Path(), flags)
|
fh, err = newWriteFileHandle(f.d, f, f.Path(), flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "open for write")
|
|
||||||
fs.Errorf(f, "File.openWrite failed: %v", err)
|
fs.Errorf(f, "File.openWrite failed: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -327,7 +325,6 @@ func (f *File) openRW(flags int) (fh *RWFileHandle, err error) {
|
||||||
|
|
||||||
fh, err = newRWFileHandle(f.d, f, f.Path(), flags)
|
fh, err = newRWFileHandle(f.d, f, f.Path(), flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "open for read write")
|
|
||||||
fs.Errorf(f, "File.openRW failed: %v", err)
|
fs.Errorf(f, "File.openRW failed: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -400,9 +397,16 @@ func (f *File) Open(flags int) (fd Handle, err error) {
|
||||||
var (
|
var (
|
||||||
write bool // if set need write support
|
write bool // if set need write support
|
||||||
read bool // if set need read support
|
read bool // if set need read support
|
||||||
rdwrMode = flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)
|
rdwrMode = flags & accessModeMask
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// http://pubs.opengroup.org/onlinepubs/7908799/xsh/open.html
|
||||||
|
// The result of using O_TRUNC with O_RDONLY is undefined.
|
||||||
|
// Linux seems to truncate the file, but we prefer to return EINVAL
|
||||||
|
if rdwrMode == os.O_RDONLY && flags&os.O_TRUNC != 0 {
|
||||||
|
return nil, EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
// Figure out the read/write intents
|
// Figure out the read/write intents
|
||||||
switch {
|
switch {
|
||||||
case rdwrMode == os.O_RDONLY:
|
case rdwrMode == os.O_RDONLY:
|
||||||
|
|
168
vfs/open_test.go
168
vfs/open_test.go
|
@ -36,13 +36,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_SYNC,
|
flags: os.O_RDONLY | os.O_SYNC,
|
||||||
what: "os.O_RDONLY|os.O_SYNC",
|
what: "os.O_RDONLY|os.O_SYNC",
|
||||||
|
@ -56,13 +56,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_EXCL,
|
flags: os.O_RDONLY | os.O_EXCL,
|
||||||
what: "os.O_RDONLY|os.O_EXCL",
|
what: "os.O_RDONLY|os.O_EXCL",
|
||||||
|
@ -76,13 +76,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_EXCL | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_EXCL | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_EXCL|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_EXCL|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_EXCL | os.O_SYNC,
|
flags: os.O_RDONLY | os.O_EXCL | os.O_SYNC,
|
||||||
what: "os.O_RDONLY|os.O_EXCL|os.O_SYNC",
|
what: "os.O_RDONLY|os.O_EXCL|os.O_SYNC",
|
||||||
|
@ -96,13 +96,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_CREATE,
|
flags: os.O_RDONLY | os.O_CREATE,
|
||||||
what: "os.O_RDONLY|os.O_CREATE",
|
what: "os.O_RDONLY|os.O_CREATE",
|
||||||
|
@ -116,13 +116,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_CREATE | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_CREATE | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_CREATE|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_CREATE|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_CREATE | os.O_SYNC,
|
flags: os.O_RDONLY | os.O_CREATE | os.O_SYNC,
|
||||||
what: "os.O_RDONLY|os.O_CREATE|os.O_SYNC",
|
what: "os.O_RDONLY|os.O_CREATE|os.O_SYNC",
|
||||||
|
@ -136,13 +136,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL,
|
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL,
|
||||||
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL",
|
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL",
|
||||||
|
@ -156,10 +156,10 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: EEXIST,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: nil,
|
readExistingErr: nil,
|
||||||
writeExistingErr: nil,
|
writeExistingErr: nil,
|
||||||
contents: "hello",
|
contents: "hello",
|
||||||
|
@ -176,10 +176,10 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: EEXIST,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: nil,
|
readExistingErr: nil,
|
||||||
writeExistingErr: nil,
|
writeExistingErr: nil,
|
||||||
contents: "hello",
|
contents: "hello",
|
||||||
|
@ -196,13 +196,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_SYNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_SYNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_SYNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_SYNC",
|
||||||
|
@ -216,13 +216,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL",
|
||||||
|
@ -236,13 +236,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL | os.O_SYNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL | os.O_SYNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL|os.O_SYNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL|os.O_SYNC",
|
||||||
|
@ -256,13 +256,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: ENOENT,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: nil,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: nil,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE",
|
||||||
|
@ -276,13 +276,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_SYNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_SYNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC",
|
||||||
|
@ -296,13 +296,13 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: nil,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: io.EOF,
|
readExistingErr: nil,
|
||||||
writeExistingErr: EBADF,
|
writeExistingErr: nil,
|
||||||
contents: "",
|
contents: "hello",
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL",
|
||||||
|
@ -316,10 +316,10 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: EEXIST,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: nil,
|
readExistingErr: nil,
|
||||||
writeExistingErr: nil,
|
writeExistingErr: nil,
|
||||||
contents: "hello",
|
contents: "hello",
|
||||||
|
@ -336,10 +336,10 @@ var openTests = []openTest{
|
||||||
}, {
|
}, {
|
||||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||||
openNonExistentErr: nil,
|
openNonExistentErr: EINVAL,
|
||||||
readNonExistentErr: io.EOF,
|
readNonExistentErr: nil,
|
||||||
writeNonExistentErr: EBADF,
|
writeNonExistentErr: nil,
|
||||||
openExistingErr: EEXIST,
|
openExistingErr: EINVAL,
|
||||||
readExistingErr: nil,
|
readExistingErr: nil,
|
||||||
writeExistingErr: nil,
|
writeExistingErr: nil,
|
||||||
contents: "hello",
|
contents: "hello",
|
||||||
|
|
|
@ -523,8 +523,10 @@ func testRWFileHandleOpenTest(t *testing.T, vfs *VFS, test *openTest) {
|
||||||
require.NoError(t, err, test.what)
|
require.NoError(t, err, test.what)
|
||||||
|
|
||||||
// check
|
// check
|
||||||
|
assert.Equal(t, test.openNonExistentErr, openNonExistentErr, "openNonExistentErr: %s: want=%v, got=%v", test.what, test.openNonExistentErr, openNonExistentErr)
|
||||||
assert.Equal(t, test.readNonExistentErr, readNonExistentErr, "readNonExistentErr: %s: want=%v, got=%v", test.what, test.readNonExistentErr, readNonExistentErr)
|
assert.Equal(t, test.readNonExistentErr, readNonExistentErr, "readNonExistentErr: %s: want=%v, got=%v", test.what, test.readNonExistentErr, readNonExistentErr)
|
||||||
assert.Equal(t, test.writeNonExistentErr, writeNonExistentErr, "writeNonExistentErr: %s: want=%v, got=%v", test.what, test.writeNonExistentErr, writeNonExistentErr)
|
assert.Equal(t, test.writeNonExistentErr, writeNonExistentErr, "writeNonExistentErr: %s: want=%v, got=%v", test.what, test.writeNonExistentErr, writeNonExistentErr)
|
||||||
|
assert.Equal(t, test.openExistingErr, openExistingErr, "openExistingErr: %s: want=%v, got=%v", test.what, test.openExistingErr, openExistingErr)
|
||||||
assert.Equal(t, test.readExistingErr, readExistingErr, "readExistingErr: %s: want=%v, got=%v", test.what, test.readExistingErr, readExistingErr)
|
assert.Equal(t, test.readExistingErr, readExistingErr, "readExistingErr: %s: want=%v, got=%v", test.what, test.readExistingErr, readExistingErr)
|
||||||
assert.Equal(t, test.writeExistingErr, writeExistingErr, "writeExistingErr: %s: want=%v, got=%v", test.what, test.writeExistingErr, writeExistingErr)
|
assert.Equal(t, test.writeExistingErr, writeExistingErr, "writeExistingErr: %s: want=%v, got=%v", test.what, test.writeExistingErr, writeExistingErr)
|
||||||
assert.Equal(t, test.contents, contents, test.what)
|
assert.Equal(t, test.contents, contents, test.what)
|
||||||
|
|
|
@ -393,6 +393,14 @@ func decodeOpenFlags(flags int) string {
|
||||||
// OpenFile a file according to the flags and perm provided
|
// OpenFile a file according to the flags and perm provided
|
||||||
func (vfs *VFS) OpenFile(name string, flags int, perm os.FileMode) (fd Handle, err error) {
|
func (vfs *VFS) OpenFile(name string, flags int, perm os.FileMode) (fd Handle, err error) {
|
||||||
defer log.Trace(name, "flags=%s, perm=%v", decodeOpenFlags(flags), perm)("fd=%v, err=%v", &fd, &err)
|
defer log.Trace(name, "flags=%s, perm=%v", decodeOpenFlags(flags), perm)("fd=%v, err=%v", &fd, &err)
|
||||||
|
|
||||||
|
// http://pubs.opengroup.org/onlinepubs/7908799/xsh/open.html
|
||||||
|
// The result of using O_TRUNC with O_RDONLY is undefined.
|
||||||
|
// Linux seems to truncate the file, but we prefer to return EINVAL
|
||||||
|
if flags&accessModeMask == os.O_RDONLY && flags&os.O_TRUNC != 0 {
|
||||||
|
return nil, EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
node, err := vfs.Stat(name)
|
node, err := vfs.Stat(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != ENOENT || flags&os.O_CREATE == 0 {
|
if err != ENOENT || flags&os.O_CREATE == 0 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user