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 {
// OnAdd is an alternative way to specify the OnAdd
// functionality of the root node.
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
}
func (b *rawBridge) setEntryOutTimeout(out *fuse.EntryOut) {
b.setAttr(&out.Attr)
if b.options.AttrTimeout != nil && out.AttrTimeout() == 0 {
out.SetAttrTimeout(*b.options.AttrTimeout)
}
......@@ -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) {
if b.options.AttrTimeout != nil && out.Timeout() == 0 {
out.SetTimeout(*b.options.AttrTimeout)
......@@ -222,11 +232,10 @@ func (b *rawBridge) Lookup(cancel <-chan struct{}, header *fuse.InHeader, name s
return errnoToStatus(errno)
}
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
out.Mode = child.nodeAttr.Mode | (out.Mode & 07777)
return fuse.OK
}
......@@ -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)
}
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
return fuse.OK
......@@ -312,9 +322,9 @@ func (b *rawBridge) Mknod(cancel <-chan struct{}, input *fuse.MknodIn, name stri
return errnoToStatus(errno)
}
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
child.setEntryOut(out)
return fuse.OK
}
......@@ -349,8 +359,8 @@ func (b *rawBridge) Create(cancel <-chan struct{}, input *fuse.CreateIn, name st
out.AttrValid = temp.AttrValid
out.AttrValidNsec = temp.AttrValidNsec
b.setEntryOutTimeout(&out.EntryOut)
child.setEntryOut(&out.EntryOut)
b.setEntryOutTimeout(&out.EntryOut)
return fuse.OK
}
......@@ -399,9 +409,10 @@ func (b *rawBridge) getattr(ctx context.Context, n *Inode, f FileHandle, out *fu
}
if errno == 0 {
b.setAttrTimeout(out)
out.Ino = n.nodeAttr.Ino
out.Mode = (out.Attr.Mode & 07777) | n.nodeAttr.Mode
b.setAttr(&out.Attr)
b.setAttrTimeout(out)
}
return errno
}
......@@ -454,9 +465,9 @@ func (b *rawBridge) Link(cancel <-chan struct{}, input *fuse.LinkIn, name string
return errnoToStatus(errno)
}
child.setEntryOut(out)
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
child.setEntryOut(out)
return fuse.OK
}
return fuse.ENOTSUP
......@@ -472,8 +483,8 @@ func (b *rawBridge) Symlink(cancel <-chan struct{}, header *fuse.InHeader, targe
}
b.addNewChild(parent, name, child, nil, 0, out)
b.setEntryOutTimeout(out)
child.setEntryOut(out)
b.setEntryOutTimeout(out)
return fuse.OK
}
return fuse.ENOTSUP
......@@ -860,6 +871,7 @@ func (b *rawBridge) ReadDirPlus(cancel <-chan struct{}, input *fuse.ReadIn, out
}
} else {
b.addNewChild(n, e.Name, child, nil, 0, entryOut)
child.setEntryOut(entryOut)
b.setEntryOutTimeout(entryOut)
if (e.Mode &^ 07777) != (child.nodeAttr.Mode &^ 07777) {
// should go back and change the
......
......@@ -5,8 +5,12 @@
package nodefs
import (
"context"
"path/filepath"
"syscall"
"testing"
"github.com/hanwen/go-fuse/fuse"
)
func TestReadonlyCreate(t *testing.T) {
......@@ -20,3 +24,31 @@ func TestReadonlyCreate(t *testing.T) {
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