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 (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ncw/rclone/fs"
|
"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")
|
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{
|
fh = &RWFileHandle{
|
||||||
o: f.o,
|
o: f.o,
|
||||||
file: f,
|
file: f,
|
||||||
|
@ -69,6 +75,8 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cacheFileOpenFlags := fh.flags
|
||||||
|
|
||||||
// if not truncating the file, need to read it first
|
// if not truncating the file, need to read it first
|
||||||
if fh.flags&os.O_TRUNC == 0 && !truncate {
|
if fh.flags&os.O_TRUNC == 0 && !truncate {
|
||||||
// Fetch the file if it hasn't changed
|
// Fetch the file if it hasn't changed
|
||||||
|
@ -92,12 +100,30 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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.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))
|
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "cache open file failed")
|
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 -
|
// FIXME measure whether we actually did any writes or not -
|
||||||
// no writes means no transfer?
|
// no writes means no transfer?
|
||||||
if rdwrMode == os.O_RDONLY {
|
if rdwrMode == os.O_RDONLY && fh.flags&os.O_TRUNC == 0 {
|
||||||
fs.Debugf(fh.remote, "read only so not transferring")
|
fs.Debugf(fh.remote, "read only and not truncating so not transferring")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,30 +328,35 @@ func (fh *RWFileHandle) Stat() (os.FileInfo, error) {
|
||||||
return fh.file, nil
|
return fh.file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read bytes from the file
|
// readFn is a general purpose read function - pass in a closure to do
|
||||||
func (fh *RWFileHandle) Read(b []byte) (n int, err error) {
|
// the actual read
|
||||||
|
func (fh *RWFileHandle) readFn(read func() (int, error)) (n int, err error) {
|
||||||
fh.mu.Lock()
|
fh.mu.Lock()
|
||||||
defer fh.mu.Unlock()
|
defer fh.mu.Unlock()
|
||||||
if fh.closed {
|
if fh.closed {
|
||||||
return 0, ECLOSED
|
return 0, ECLOSED
|
||||||
}
|
}
|
||||||
|
if fh.flags&accessModeMask == os.O_WRONLY {
|
||||||
|
return 0, EBADF
|
||||||
|
}
|
||||||
if err = fh.openPending(false); err != nil {
|
if err = fh.openPending(false); err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
return fh.File.Read(b)
|
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
|
// ReadAt bytes from the file at off
|
||||||
func (fh *RWFileHandle) ReadAt(b []byte, off int64) (n int, err error) {
|
func (fh *RWFileHandle) ReadAt(b []byte, off int64) (n int, err error) {
|
||||||
fh.mu.Lock()
|
return fh.readFn(func() (int, error) {
|
||||||
defer fh.mu.Unlock()
|
return fh.File.ReadAt(b, off)
|
||||||
if fh.closed {
|
})
|
||||||
return 0, ECLOSED
|
|
||||||
}
|
|
||||||
if err = fh.openPending(false); err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return fh.File.ReadAt(b, off)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek to new file position
|
// Seek to new file position
|
||||||
|
@ -350,6 +381,9 @@ func (fh *RWFileHandle) writeFn(write func() error) (err error) {
|
||||||
if fh.closed {
|
if fh.closed {
|
||||||
return ECLOSED
|
return ECLOSED
|
||||||
}
|
}
|
||||||
|
if fh.flags&accessModeMask == os.O_RDONLY {
|
||||||
|
return EBADF
|
||||||
|
}
|
||||||
if err = fh.openPending(false); err != nil {
|
if err = fh.openPending(false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -421,5 +455,8 @@ func (fh *RWFileHandle) Sync() error {
|
||||||
if !fh.opened {
|
if !fh.opened {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if fh.flags&accessModeMask == os.O_RDONLY {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fh.File.Sync()
|
return fh.File.Sync()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package vfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -286,6 +287,10 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 7, n)
|
assert.Equal(t, 7, n)
|
||||||
|
|
||||||
|
// Sync
|
||||||
|
err = fh.Sync()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Stat
|
// Stat
|
||||||
var fi os.FileInfo
|
var fi os.FileInfo
|
||||||
fi, err = fh.Stat()
|
fi, err = fh.Stat()
|
||||||
|
@ -434,3 +439,87 @@ func TestRWFileHandleReleaseWrite(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, fh.closed)
|
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