Commit 3377c503 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

nodefs: add Options.DefaultPermissions

parent eac61bbc
...@@ -454,4 +454,8 @@ type Options struct { ...@@ -454,4 +454,8 @@ type Options struct {
// OnAdd is an alternative way to specify the OnAdd // OnAdd is an alternative way to specify the OnAdd
// functionality of the root node. // functionality of the root node.
OnAdd func(ctx context.Context) OnAdd func(ctx context.Context)
// DefaultPermissions sets all file permissions to 755 (dirs)
// or 644 (other files.)
DefaultPermissions bool
} }
...@@ -134,6 +134,7 @@ func (b *rawBridge) addNewChild(parent *Inode, name string, child *Inode, file F ...@@ -134,6 +134,7 @@ func (b *rawBridge) addNewChild(parent *Inode, name string, child *Inode, file F
} }
func (b *rawBridge) setEntryOutTimeout(out *fuse.EntryOut) { func (b *rawBridge) setEntryOutTimeout(out *fuse.EntryOut) {
b.setAttr(&out.Attr)
if b.options.AttrTimeout != nil && out.AttrTimeout() == 0 { if b.options.AttrTimeout != nil && out.AttrTimeout() == 0 {
out.SetAttrTimeout(*b.options.AttrTimeout) out.SetAttrTimeout(*b.options.AttrTimeout)
} }
...@@ -142,6 +143,15 @@ func (b *rawBridge) setEntryOutTimeout(out *fuse.EntryOut) { ...@@ -142,6 +143,15 @@ func (b *rawBridge) setEntryOutTimeout(out *fuse.EntryOut) {
} }
} }
func (b *rawBridge) setAttr(out *fuse.Attr) {
if b.options.DefaultPermissions && out.Mode&07777 == 0 {
out.Mode |= 0644
if out.Mode&syscall.S_IFDIR != 0 {
out.Mode |= 0111
}
}
}
func (b *rawBridge) setAttrTimeout(out *fuse.AttrOut) { func (b *rawBridge) setAttrTimeout(out *fuse.AttrOut) {
if b.options.AttrTimeout != nil && out.Timeout() == 0 { if b.options.AttrTimeout != nil && out.Timeout() == 0 {
out.SetTimeout(*b.options.AttrTimeout) out.SetTimeout(*b.options.AttrTimeout)
...@@ -222,11 +232,10 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s ...@@ -222,11 +232,10 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s
return errnoToStatus(errno) return errnoToStatus(errno)
} }
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out) b.setEntryOutTimeout(out)
out.Mode = child.nodeAttr.Mode | (out.Mode & 07777)
return fuse.OK return fuse.OK
} }
...@@ -294,6 +303,7 @@ func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name stri ...@@ -294,6 +303,7 @@ func (b *rawBridge) Mkdir(cancel <-chan struct{}, input *fuse.MkdirIn, name stri
log.Panicf("Mkdir: mode must be S_IFDIR (%o), got %o", fuse.S_IFDIR, out.Attr.Mode) log.Panicf("Mkdir: mode must be S_IFDIR (%o), got %o", fuse.S_IFDIR, out.Attr.Mode)
} }
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out) b.setEntryOutTimeout(out)
return fuse.OK return fuse.OK
...@@ -312,9 +322,9 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri ...@@ -312,9 +322,9 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
return errnoToStatus(errno) return errnoToStatus(errno)
} }
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out) b.setEntryOutTimeout(out)
child.setEntryOut(out)
return fuse.OK return fuse.OK
} }
...@@ -349,8 +359,8 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st ...@@ -349,8 +359,8 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
out.AttrValid = temp.AttrValid out.AttrValid = temp.AttrValid
out.AttrValidNsec = temp.AttrValidNsec out.AttrValidNsec = temp.AttrValidNsec
b.setEntryOutTimeout(&out.EntryOut)
child.setEntryOut(&out.EntryOut) child.setEntryOut(&out.EntryOut)
b.setEntryOutTimeout(&out.EntryOut)
return fuse.OK return fuse.OK
} }
...@@ -399,9 +409,10 @@ func (b *rawBridge) getattr(ctx context.Context, n *Inode, f FileHandle, out *fu ...@@ -399,9 +409,10 @@ func (b *rawBridge) getattr(ctx context.Context, n *Inode, f FileHandle, out *fu
} }
if errno == 0 { if errno == 0 {
b.setAttrTimeout(out)
out.Ino = n.nodeAttr.Ino out.Ino = n.nodeAttr.Ino
out.Mode = (out.Attr.Mode & 07777) | n.nodeAttr.Mode out.Mode = (out.Attr.Mode & 07777) | n.nodeAttr.Mode
b.setAttr(&out.Attr)
b.setAttrTimeout(out)
} }
return errno return errno
} }
...@@ -454,9 +465,9 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string ...@@ -454,9 +465,9 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string
return errnoToStatus(errno) return errnoToStatus(errno)
} }
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out) b.setEntryOutTimeout(out)
child.setEntryOut(out)
return fuse.OK return fuse.OK
} }
return fuse.ENOTSUP return fuse.ENOTSUP
...@@ -472,8 +483,8 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe ...@@ -472,8 +483,8 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe
} }
b.addNewChild(parent, name, child, nil, 0, out) b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
child.setEntryOut(out) child.setEntryOut(out)
b.setEntryOutTimeout(out)
return fuse.OK return fuse.OK
} }
return fuse.ENOTSUP return fuse.ENOTSUP
...@@ -860,6 +871,7 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out ...@@ -860,6 +871,7 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
} }
} else { } else {
b.addNewChild(n, e.Name, child, nil, 0, entryOut) b.addNewChild(n, e.Name, child, nil, 0, entryOut)
child.setEntryOut(entryOut)
b.setEntryOutTimeout(entryOut) b.setEntryOutTimeout(entryOut)
if (e.Mode &^ 07777) != (child.nodeAttr.Mode &^ 07777) { if (e.Mode &^ 07777) != (child.nodeAttr.Mode &^ 07777) {
// should go back and change the // should go back and change the
......
...@@ -5,8 +5,12 @@ ...@@ -5,8 +5,12 @@
package nodefs package nodefs
import ( import (
"context"
"path/filepath"
"syscall" "syscall"
"testing" "testing"
"github.com/hanwen/go-fuse/fuse"
) )
func TestReadonlyCreate(t *testing.T) { func TestReadonlyCreate(t *testing.T) {
...@@ -20,3 +24,31 @@ func TestReadonlyCreate(t *testing.T) { ...@@ -20,3 +24,31 @@ func TestReadonlyCreate(t *testing.T) {
t.Fatalf("got err %v, want %v", err, want) t.Fatalf("got err %v, want %v", err, want)
} }
} }
func TestDefaultPermissions(t *testing.T) {
root := &Inode{}
mntDir, clean := testMount(t, root, &Options{
DefaultPermissions: true,
OnAdd: func(ctx context.Context) {
dir := root.NewPersistentInode(ctx, &Inode{}, NodeAttr{Mode: syscall.S_IFDIR})
file := root.NewPersistentInode(ctx, &Inode{}, NodeAttr{Mode: syscall.S_IFREG})
root.AddChild("dir", dir, false)
root.AddChild("file", file, false)
},
})
defer clean()
for k, v := range map[string]uint32{
"dir": fuse.S_IFDIR | 0755,
"file": fuse.S_IFREG | 0644,
} {
var st syscall.Stat_t
if err := syscall.Lstat(filepath.Join(mntDir, k), &st); err != nil {
t.Error("Lstat", err)
} else if st.Mode != v {
t.Errorf("got %o want %o", st.Mode, v)
}
}
}
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