mirror of
https://github.com/rclone/rclone.git
synced 2024-11-25 09:41:44 +08:00
vfs: make sure all 96 combinations of flags for Open work
This commit is contained in:
parent
d1b19f975d
commit
0978957a2e
228
vfs/make_open_tests.go
Normal file
228
vfs/make_open_tests.go
Normal file
|
@ -0,0 +1,228 @@
|
|||
// This makes the open test suite
|
||||
//
|
||||
// Run with go run make_open_tests.go | gofmt > open_test.go
|
||||
//
|
||||
//+build none
|
||||
|
||||
// FIXME include read too?
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Interprets err into a vfs error
|
||||
func whichError(err error) string {
|
||||
switch err {
|
||||
case nil:
|
||||
return "nil"
|
||||
case io.EOF:
|
||||
return "io.EOF"
|
||||
}
|
||||
s := err.Error()
|
||||
switch {
|
||||
case strings.Contains(s, "no such file or directory"):
|
||||
return "ENOENT"
|
||||
case strings.Contains(s, "bad file descriptor"):
|
||||
return "EBADF"
|
||||
case strings.Contains(s, "file exists"):
|
||||
return "EEXIST"
|
||||
}
|
||||
log.Fatalf("Unknown error: %v", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// test Opening, reading and writing the file handle with the flags given
|
||||
func test(fileName string, flags int, mode string) {
|
||||
// first try with file not existing
|
||||
_, err := os.Stat(fileName)
|
||||
if !os.IsNotExist(err) {
|
||||
log.Fatalf("File must not exist")
|
||||
}
|
||||
f, openNonExistentErr := os.OpenFile(fileName, flags, 0666)
|
||||
|
||||
var readNonExistentErr error
|
||||
var writeNonExistentErr error
|
||||
if openNonExistentErr == nil {
|
||||
// read some bytes
|
||||
buf := []byte{0, 0}
|
||||
_, readNonExistentErr = f.Read(buf)
|
||||
|
||||
// write some bytes
|
||||
_, writeNonExistentErr = f.Write([]byte("hello"))
|
||||
|
||||
// close
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to close: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// write the file
|
||||
f, err = os.Create(fileName)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create: %v", err)
|
||||
}
|
||||
n, err := f.Write([]byte("hello"))
|
||||
if n != 5 || err != nil {
|
||||
log.Fatalf("failed to write n=%d: %v", n, err)
|
||||
}
|
||||
// close
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to close: %v", err)
|
||||
}
|
||||
|
||||
// then open file and try with file existing
|
||||
|
||||
f, openExistingErr := os.OpenFile(fileName, flags, 0666)
|
||||
var readExistingErr error
|
||||
var writeExistingErr error
|
||||
if openExistingErr == nil {
|
||||
// read some bytes
|
||||
buf := []byte{0, 0}
|
||||
_, readExistingErr = f.Read(buf)
|
||||
|
||||
// write some bytes
|
||||
n, writeExistingErr = f.Write([]byte("HEL"))
|
||||
|
||||
// close
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to close: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// read the file
|
||||
f, err = os.Open(fileName)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open: %v", err)
|
||||
}
|
||||
var buf = make([]byte, 64)
|
||||
n, err = f.Read(buf)
|
||||
if err != nil && err != io.EOF {
|
||||
log.Fatalf("failed to read n=%d: %v", n, err)
|
||||
}
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to close: %v", err)
|
||||
}
|
||||
contents := string(buf[:n])
|
||||
|
||||
// remove file
|
||||
err = os.Remove(fileName)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to remove: %v", err)
|
||||
}
|
||||
|
||||
// output the struct
|
||||
fmt.Printf(`{
|
||||
flags: %s,
|
||||
what: %q,
|
||||
openNonExistentErr: %s,
|
||||
readNonExistentErr: %s,
|
||||
writeNonExistentErr: %s,
|
||||
openExistingErr: %s,
|
||||
readExistingErr: %s,
|
||||
writeExistingErr: %s,
|
||||
contents: %q,
|
||||
},`,
|
||||
mode,
|
||||
mode,
|
||||
whichError(openNonExistentErr),
|
||||
whichError(readNonExistentErr),
|
||||
whichError(writeNonExistentErr),
|
||||
whichError(openExistingErr),
|
||||
whichError(readExistingErr),
|
||||
whichError(writeExistingErr),
|
||||
contents)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Printf(`// data generated by go run make_open_tests.go | gofmt > open_test.go
|
||||
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"io"
|
||||
)
|
||||
|
||||
// openTest describes a test of OpenFile
|
||||
type openTest struct{
|
||||
flags int
|
||||
what string
|
||||
openNonExistentErr error
|
||||
readNonExistentErr error
|
||||
writeNonExistentErr error
|
||||
openExistingErr error
|
||||
readExistingErr error
|
||||
writeExistingErr error
|
||||
contents string
|
||||
}
|
||||
|
||||
// openTests is a suite of tests for OpenFile with all possible
|
||||
// combination of flags. This obeys Unix semantics even on Windows.
|
||||
var openTests = []openTest{
|
||||
`)
|
||||
f, err := ioutil.TempFile("", "open-test")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fileName := f.Name()
|
||||
_ = f.Close()
|
||||
err = os.Remove(fileName)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to remove: %v", err)
|
||||
}
|
||||
for _, rwMode := range []int{os.O_RDONLY, os.O_WRONLY, os.O_RDWR} {
|
||||
flags0 := rwMode
|
||||
parts0 := []string{"os.O_RDONLY", "os.O_WRONLY", "os.O_RDWR"}[rwMode : rwMode+1]
|
||||
for _, appendMode := range []int{0, os.O_APPEND} {
|
||||
flags1 := flags0 | appendMode
|
||||
parts1 := parts0
|
||||
if appendMode != 0 {
|
||||
parts1 = append(parts1, "os.O_APPEND")
|
||||
}
|
||||
for _, createMode := range []int{0, os.O_CREATE} {
|
||||
flags2 := flags1 | createMode
|
||||
parts2 := parts1
|
||||
if createMode != 0 {
|
||||
parts2 = append(parts2, "os.O_CREATE")
|
||||
}
|
||||
for _, exclMode := range []int{0, os.O_EXCL} {
|
||||
flags3 := flags2 | exclMode
|
||||
parts3 := parts2
|
||||
if exclMode != 0 {
|
||||
parts3 = append(parts2, "os.O_EXCL")
|
||||
}
|
||||
for _, syncMode := range []int{0, os.O_SYNC} {
|
||||
flags4 := flags3 | syncMode
|
||||
parts4 := parts3
|
||||
if syncMode != 0 {
|
||||
parts4 = append(parts4, "os.O_SYNC")
|
||||
}
|
||||
for _, truncMode := range []int{0, os.O_TRUNC} {
|
||||
flags5 := flags4 | truncMode
|
||||
parts5 := parts4
|
||||
if truncMode != 0 {
|
||||
parts5 = append(parts5, "os.O_TRUNC")
|
||||
}
|
||||
textMode := strings.Join(parts5, "|")
|
||||
flags := flags5
|
||||
|
||||
test(fileName, flags, textMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n}\n")
|
||||
}
|
987
vfs/open_test.go
Normal file
987
vfs/open_test.go
Normal file
|
@ -0,0 +1,987 @@
|
|||
// data generated by go run make_open_tests.go | gofmt > open_test.go
|
||||
|
||||
package vfs
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// openTest describes a test of OpenFile
|
||||
type openTest struct {
|
||||
flags int
|
||||
what string
|
||||
openNonExistentErr error
|
||||
readNonExistentErr error
|
||||
writeNonExistentErr error
|
||||
openExistingErr error
|
||||
readExistingErr error
|
||||
writeExistingErr error
|
||||
contents string
|
||||
}
|
||||
|
||||
// openTests is a suite of tests for OpenFile with all possible
|
||||
// combination of flags. This obeys Unix semantics even on Windows.
|
||||
var openTests = []openTest{
|
||||
{
|
||||
flags: os.O_RDONLY,
|
||||
what: "os.O_RDONLY",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_TRUNC,
|
||||
what: "os.O_RDONLY|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_SYNC,
|
||||
what: "os.O_RDONLY|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDONLY|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_EXCL,
|
||||
what: "os.O_RDONLY|os.O_EXCL",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_RDONLY|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_RDONLY|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_CREATE,
|
||||
what: "os.O_RDONLY|os.O_CREATE",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_CREATE | os.O_TRUNC,
|
||||
what: "os.O_RDONLY|os.O_CREATE|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_CREATE | os.O_SYNC,
|
||||
what: "os.O_RDONLY|os.O_CREATE|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL,
|
||||
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_CREATE | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_RDONLY|os.O_CREATE|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_APPEND,
|
||||
what: "os.O_RDONLY|os.O_APPEND",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_APPEND | os.O_TRUNC,
|
||||
what: "os.O_RDONLY|os.O_APPEND|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_APPEND | os.O_SYNC,
|
||||
what: "os.O_RDONLY|os.O_APPEND|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_APPEND | os.O_EXCL,
|
||||
what: "os.O_RDONLY|os.O_APPEND|os.O_EXCL",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE,
|
||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: EBADF,
|
||||
contents: "",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_RDONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
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",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: EBADF,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY,
|
||||
what: "os.O_WRONLY",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HELlo",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HELlo",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_EXCL,
|
||||
what: "os.O_WRONLY|os.O_EXCL",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HELlo",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HELlo",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE,
|
||||
what: "os.O_WRONLY|os.O_CREATE",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HELlo",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_CREATE|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_CREATE|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HELlo",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE | os.O_EXCL,
|
||||
what: "os.O_WRONLY|os.O_CREATE|os.O_EXCL",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_CREATE|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND,
|
||||
what: "os.O_WRONLY|os.O_APPEND",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_EXCL,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_EXCL",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: EBADF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: EBADF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR,
|
||||
what: "os.O_RDWR",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "heHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "heHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_EXCL,
|
||||
what: "os.O_RDWR|os.O_EXCL",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "heHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "heHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE,
|
||||
what: "os.O_RDWR|os.O_CREATE",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "heHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_CREATE|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_CREATE|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "heHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE | os.O_EXCL,
|
||||
what: "os.O_RDWR|os.O_CREATE|os.O_EXCL",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND,
|
||||
what: "os.O_RDWR|os.O_APPEND",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_EXCL,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_EXCL",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: ENOENT,
|
||||
readNonExistentErr: nil,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "helloHEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: nil,
|
||||
readExistingErr: io.EOF,
|
||||
writeExistingErr: nil,
|
||||
contents: "HEL",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_EXCL,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_EXCL",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_SYNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
}, {
|
||||
flags: os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_EXCL | os.O_SYNC | os.O_TRUNC,
|
||||
what: "os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_EXCL|os.O_SYNC|os.O_TRUNC",
|
||||
openNonExistentErr: nil,
|
||||
readNonExistentErr: io.EOF,
|
||||
writeNonExistentErr: nil,
|
||||
openExistingErr: EEXIST,
|
||||
readExistingErr: nil,
|
||||
writeExistingErr: nil,
|
||||
contents: "hello",
|
||||
},
|
||||
}
|
|
@ -3,6 +3,7 @@ package vfs
|
|||
import (
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/ncw/rclone/fs"
|
||||
|
@ -44,6 +45,11 @@ func newRWFileHandle(d *Dir, f *File, remote string, flags int) (fh *RWFileHandl
|
|||
return nil, errors.Wrap(err, "open RW handle failed to make cache directory")
|
||||
}
|
||||
|
||||
// if O_CREATE and O_EXCL are set and if path already exists, then return EEXIST
|
||||
if flags&(os.O_CREATE|os.O_EXCL) == os.O_CREATE|os.O_EXCL && f.exists() {
|
||||
return nil, EEXIST
|
||||
}
|
||||
|
||||
fh = &RWFileHandle{
|
||||
o: f.o,
|
||||
file: f,
|
||||
|
@ -69,6 +75,8 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
cacheFileOpenFlags := fh.flags
|
||||
|
||||
// if not truncating the file, need to read it first
|
||||
if fh.flags&os.O_TRUNC == 0 && !truncate {
|
||||
// Fetch the file if it hasn't changed
|
||||
|
@ -92,12 +100,30 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// Set the size to 0 since we are truncating
|
||||
// Set the size to 0 since we are truncating and flag we need to write it back
|
||||
fh.file.setSize(0)
|
||||
fh.writeCalled = true
|
||||
if fh.flags&os.O_CREATE != 0 && fh.file.exists() {
|
||||
// create and empty file if it exists on the source
|
||||
cacheFileOpenFlags |= os.O_CREATE
|
||||
}
|
||||
// Windows doesn't seem to deal well with O_TRUNC and
|
||||
// certain access modes so so truncate the file if it
|
||||
// exists in these cases.
|
||||
if runtime.GOOS == "windows" && (fh.flags&accessModeMask == os.O_RDONLY || fh.flags|os.O_APPEND != 0) {
|
||||
cacheFileOpenFlags &^= os.O_TRUNC
|
||||
_, err = os.Stat(fh.osPath)
|
||||
if err == nil {
|
||||
err = os.Truncate(fh.osPath, 0)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cache open failed to truncate")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs.Debugf(fh.remote, "Opening cached copy with flags=%s", decodeOpenFlags(fh.flags))
|
||||
fd, err := os.OpenFile(fh.osPath, fh.flags|os.O_CREATE, 0600)
|
||||
fd, err := os.OpenFile(fh.osPath, cacheFileOpenFlags, 0600)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cache open file failed")
|
||||
}
|
||||
|
@ -180,8 +206,8 @@ func (fh *RWFileHandle) close() (err error) {
|
|||
|
||||
// FIXME measure whether we actually did any writes or not -
|
||||
// no writes means no transfer?
|
||||
if rdwrMode == os.O_RDONLY {
|
||||
fs.Debugf(fh.remote, "read only so not transferring")
|
||||
if rdwrMode == os.O_RDONLY && fh.flags&os.O_TRUNC == 0 {
|
||||
fs.Debugf(fh.remote, "read only and not truncating so not transferring")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -302,30 +328,35 @@ func (fh *RWFileHandle) Stat() (os.FileInfo, error) {
|
|||
return fh.file, nil
|
||||
}
|
||||
|
||||
// Read bytes from the file
|
||||
func (fh *RWFileHandle) Read(b []byte) (n int, err error) {
|
||||
// readFn is a general purpose read function - pass in a closure to do
|
||||
// the actual read
|
||||
func (fh *RWFileHandle) readFn(read func() (int, error)) (n int, err error) {
|
||||
fh.mu.Lock()
|
||||
defer fh.mu.Unlock()
|
||||
if fh.closed {
|
||||
return 0, ECLOSED
|
||||
}
|
||||
if fh.flags&accessModeMask == os.O_WRONLY {
|
||||
return 0, EBADF
|
||||
}
|
||||
if err = fh.openPending(false); err != nil {
|
||||
return n, err
|
||||
}
|
||||
return read()
|
||||
}
|
||||
|
||||
// Read bytes from the file
|
||||
func (fh *RWFileHandle) Read(b []byte) (n int, err error) {
|
||||
return fh.readFn(func() (int, error) {
|
||||
return fh.File.Read(b)
|
||||
})
|
||||
}
|
||||
|
||||
// ReadAt bytes from the file at off
|
||||
func (fh *RWFileHandle) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
fh.mu.Lock()
|
||||
defer fh.mu.Unlock()
|
||||
if fh.closed {
|
||||
return 0, ECLOSED
|
||||
}
|
||||
if err = fh.openPending(false); err != nil {
|
||||
return n, err
|
||||
}
|
||||
return fh.readFn(func() (int, error) {
|
||||
return fh.File.ReadAt(b, off)
|
||||
})
|
||||
}
|
||||
|
||||
// Seek to new file position
|
||||
|
@ -350,6 +381,9 @@ func (fh *RWFileHandle) writeFn(write func() error) (err error) {
|
|||
if fh.closed {
|
||||
return ECLOSED
|
||||
}
|
||||
if fh.flags&accessModeMask == os.O_RDONLY {
|
||||
return EBADF
|
||||
}
|
||||
if err = fh.openPending(false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -421,5 +455,8 @@ func (fh *RWFileHandle) Sync() error {
|
|||
if !fh.opened {
|
||||
return nil
|
||||
}
|
||||
if fh.flags&accessModeMask == os.O_RDONLY {
|
||||
return nil
|
||||
}
|
||||
return fh.File.Sync()
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package vfs
|
|||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
|
@ -286,6 +287,10 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, 7, n)
|
||||
|
||||
// Sync
|
||||
err = fh.Sync()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Stat
|
||||
var fi os.FileInfo
|
||||
fi, err = fh.Stat()
|
||||
|
@ -434,3 +439,87 @@ func TestRWFileHandleReleaseWrite(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.True(t, fh.closed)
|
||||
}
|
||||
|
||||
func testRWFileHandleOpenTest(t *testing.T, vfs *VFS, test *openTest) {
|
||||
fileName := "open-test-file"
|
||||
|
||||
// first try with file not existing
|
||||
_, err := vfs.Stat(fileName)
|
||||
require.True(t, os.IsNotExist(err), test.what)
|
||||
|
||||
f, openNonExistentErr := vfs.OpenFile(fileName, test.flags, 0666)
|
||||
|
||||
var readNonExistentErr error
|
||||
var writeNonExistentErr error
|
||||
if openNonExistentErr == nil {
|
||||
// read some bytes
|
||||
buf := []byte{0, 0}
|
||||
_, readNonExistentErr = f.Read(buf)
|
||||
|
||||
// write some bytes
|
||||
_, writeNonExistentErr = f.Write([]byte("hello"))
|
||||
|
||||
// close
|
||||
err = f.Close()
|
||||
require.NoError(t, err, test.what)
|
||||
}
|
||||
|
||||
// write the file
|
||||
f, err = vfs.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0777)
|
||||
require.NoError(t, err, test.what)
|
||||
_, err = f.Write([]byte("hello"))
|
||||
require.NoError(t, err, test.what)
|
||||
err = f.Close()
|
||||
require.NoError(t, err, test.what)
|
||||
|
||||
// then open file and try with file existing
|
||||
|
||||
f, openExistingErr := vfs.OpenFile(fileName, test.flags, 0666)
|
||||
var readExistingErr error
|
||||
var writeExistingErr error
|
||||
if openExistingErr == nil {
|
||||
// read some bytes
|
||||
buf := []byte{0, 0}
|
||||
_, readExistingErr = f.Read(buf)
|
||||
|
||||
// write some bytes
|
||||
_, writeExistingErr = f.Write([]byte("HEL"))
|
||||
|
||||
// close
|
||||
err = f.Close()
|
||||
require.NoError(t, err, test.what)
|
||||
}
|
||||
|
||||
// read the file
|
||||
f, err = vfs.OpenFile(fileName, os.O_RDONLY, 0)
|
||||
require.NoError(t, err, test.what)
|
||||
buf, err := ioutil.ReadAll(f)
|
||||
require.NoError(t, err, test.what)
|
||||
err = f.Close()
|
||||
require.NoError(t, err, test.what)
|
||||
contents := string(buf)
|
||||
|
||||
// remove file
|
||||
node, err := vfs.Stat(fileName)
|
||||
require.NoError(t, err, test.what)
|
||||
err = node.Remove()
|
||||
require.NoError(t, err, test.what)
|
||||
|
||||
// check
|
||||
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.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.contents, contents, test.what)
|
||||
}
|
||||
|
||||
func TestRWFileHandleOpenTests(t *testing.T) {
|
||||
r := fstest.NewRun(t)
|
||||
defer r.Finalise()
|
||||
|
||||
vfs := New(r.Fremote, nil)
|
||||
vfs.Opt.CacheMode = CacheModeFull
|
||||
for _, test := range openTests {
|
||||
testRWFileHandleOpenTest(t, vfs, &test)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user