Commit d1b56cc4 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Filter O_APPEND from open flags.

As of Go 1.13, os.File doesn't allow WriteAt to O_APPEND. Since the
kernel translates writes to correct offsets, loopback does not have to
open the file as O_APPEND.

Fixes #325.

Change-Id: Ib1a7026b94b5604d415ac9fbb5850842dbeffc2a
parent 4b3866b7
......@@ -184,7 +184,7 @@ var _ = (NodeCreater)((*loopbackNode)(nil))
func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mode uint32, out *fuse.EntryOut) (inode *Inode, fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
p := filepath.Join(n.path(), name)
flags = flags &^ syscall.O_APPEND
fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode)
if err != nil {
return nil, nil, 0, ToErrno(err)
......@@ -259,6 +259,7 @@ func (n *loopbackNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
}
func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
flags = flags &^ syscall.O_APPEND
p := n.path()
f, err := syscall.Open(p, int(flags), 0)
if err != nil {
......
......@@ -119,6 +119,9 @@ func (fs *loopbackFileSystem) OpenDir(name string, context *fuse.Context) (strea
}
func (fs *loopbackFileSystem) Open(name string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) {
// filter out append. The kernel layer will translate the
// offsets for us appropriately.
flags = flags &^ syscall.O_APPEND
f, err := os.OpenFile(fs.GetPath(name), int(flags), 0)
if err != nil {
return nil, fuse.ToStatus(err)
......@@ -190,6 +193,7 @@ func (fs *loopbackFileSystem) Access(name string, mode uint32, context *fuse.Con
}
func (fs *loopbackFileSystem) Create(path string, flags uint32, mode uint32, context *fuse.Context) (fuseFile nodefs.File, code fuse.Status) {
flags = flags &^ syscall.O_APPEND
f, err := os.OpenFile(fs.GetPath(path), int(flags)|os.O_CREATE, os.FileMode(mode))
return nodefs.NewLoopbackFile(f), fuse.ToStatus(err)
}
......@@ -388,6 +388,7 @@ func TestPosix(t *testing.T) {
"RenameOverwriteDestExist",
"ReadDir",
"ReadDirPicksUpCreate",
"AppendWrite",
}
for _, k := range tests {
f := posixtest.All[k]
......
......@@ -20,6 +20,7 @@ import (
)
var All = map[string]func(*testing.T, string){
"AppendWrite": AppendWrite,
"SymlinkReadlink": SymlinkReadlink,
"FileBasic": FileBasic,
"TruncateFile": TruncateFile,
......@@ -393,3 +394,38 @@ func LinkUnlinkRename(t *testing.T, mnt string) {
t.Fatalf("Read got %q want %q", back, content)
}
}
// test open with O_APPEND
func AppendWrite(t *testing.T, mnt string) {
fd, err := syscall.Open(mnt+"/file", syscall.O_WRONLY|syscall.O_APPEND|syscall.O_CREAT, 0644)
if err != nil {
t.Fatalf("Open: %v", err)
}
defer func() {
if fd != 0 {
syscall.Close(fd)
}
}()
if _, err := syscall.Write(fd, []byte("hello")); err != nil {
t.Fatalf("Write 1: %v", err)
}
if _, err := syscall.Write(fd, []byte("world")); err != nil {
t.Fatalf("Write 2: %v", err)
}
if err := syscall.Close(fd); err != nil {
t.Fatalf("Open: %v", err)
}
fd = 0
want := []byte("helloworld")
got, err := ioutil.ReadFile(mnt + "/file")
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
if bytes.Compare(got, want) != 0 {
t.Errorf("got %q want %q", got, want)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment