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)) ...@@ -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) { 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) p := filepath.Join(n.path(), name)
flags = flags &^ syscall.O_APPEND
fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode) fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode)
if err != nil { if err != nil {
return nil, nil, 0, ToErrno(err) return nil, nil, 0, ToErrno(err)
...@@ -259,6 +259,7 @@ func (n *loopbackNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) { ...@@ -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) { func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
flags = flags &^ syscall.O_APPEND
p := n.path() p := n.path()
f, err := syscall.Open(p, int(flags), 0) f, err := syscall.Open(p, int(flags), 0)
if err != nil { if err != nil {
......
...@@ -119,6 +119,9 @@ func (fs *loopbackFileSystem) OpenDir(name string, context *fuse.Context) (strea ...@@ -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) { 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) f, err := os.OpenFile(fs.GetPath(name), int(flags), 0)
if err != nil { if err != nil {
return nil, fuse.ToStatus(err) return nil, fuse.ToStatus(err)
...@@ -190,6 +193,7 @@ func (fs *loopbackFileSystem) Access(name string, mode uint32, context *fuse.Con ...@@ -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) { 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)) f, err := os.OpenFile(fs.GetPath(path), int(flags)|os.O_CREATE, os.FileMode(mode))
return nodefs.NewLoopbackFile(f), fuse.ToStatus(err) return nodefs.NewLoopbackFile(f), fuse.ToStatus(err)
} }
...@@ -388,6 +388,7 @@ func TestPosix(t *testing.T) { ...@@ -388,6 +388,7 @@ func TestPosix(t *testing.T) {
"RenameOverwriteDestExist", "RenameOverwriteDestExist",
"ReadDir", "ReadDir",
"ReadDirPicksUpCreate", "ReadDirPicksUpCreate",
"AppendWrite",
} }
for _, k := range tests { for _, k := range tests {
f := posixtest.All[k] f := posixtest.All[k]
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
) )
var All = map[string]func(*testing.T, string){ var All = map[string]func(*testing.T, string){
"AppendWrite": AppendWrite,
"SymlinkReadlink": SymlinkReadlink, "SymlinkReadlink": SymlinkReadlink,
"FileBasic": FileBasic, "FileBasic": FileBasic,
"TruncateFile": TruncateFile, "TruncateFile": TruncateFile,
...@@ -393,3 +394,38 @@ func LinkUnlinkRename(t *testing.T, mnt string) { ...@@ -393,3 +394,38 @@ func LinkUnlinkRename(t *testing.T, mnt string) {
t.Fatalf("Read got %q want %q", back, content) 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