Commit 513c37b3 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Add Owner to MountOptions to override returned uid/gid.

parent 31adaab5
...@@ -90,6 +90,10 @@ type FileSystemOptions struct { ...@@ -90,6 +90,10 @@ type FileSystemOptions struct {
EntryTimeout float64 EntryTimeout float64
AttrTimeout float64 AttrTimeout float64
NegativeTimeout float64 NegativeTimeout float64
// If set, replace all uids with given UID. NewFileSystemOptions() will set
// this to the daemon's uid/gid.
*Owner
} }
type MountOptions struct { type MountOptions struct {
...@@ -102,7 +106,7 @@ type DefaultFileSystem struct{} ...@@ -102,7 +106,7 @@ type DefaultFileSystem struct{}
// DefaultFile returns ENOSYS for every operation. // DefaultFile returns ENOSYS for every operation.
type DefaultFile struct{} type DefaultFile struct{}
// RawFileSystem is an interface closer to the FUSE wire protocol. // RawFileSystem is an interface closer to the FUSE wire protocol.
// //
// Unless you really know what you are doing, you should not implement // Unless you really know what you are doing, you should not implement
// this, but rather the FileSystem interface; the details of getting // this, but rather the FileSystem interface; the details of getting
......
package fuse
import (
"os"
"testing"
)
type ownerFs struct {
DefaultFileSystem
}
const _RANDOM_OWNER = 31415265
func (me *ownerFs) GetAttr(name string) (*os.FileInfo, Status) {
if name == "" {
return &os.FileInfo{
Mode: S_IFDIR | 0755,
}, OK
}
return &os.FileInfo{
Mode: S_IFREG | 0644,
Uid: _RANDOM_OWNER,
Gid: _RANDOM_OWNER,
}, OK
}
func setupOwnerTest(opts *FileSystemOptions) (workdir string, cleanup func()) {
wd := MakeTempDir()
fs := &ownerFs{}
state, _, err := MountFileSystem(wd, fs, opts)
CheckSuccess(err)
go state.Loop(false)
return wd, func() {
state.Unmount()
os.RemoveAll(wd)
}
}
func TestOwnerDefault(t *testing.T) {
wd, cleanup := setupOwnerTest(NewFileSystemOptions())
defer cleanup()
fi, err := os.Lstat(wd + "/foo")
CheckSuccess(err)
if fi.Uid != os.Getuid() || fi.Gid != os.Getgid() {
t.Fatal("Should use current uid for mount", fi.Uid, fi.Gid)
}
}
func TestOwnerRoot(t *testing.T) {
wd, cleanup := setupOwnerTest(&FileSystemOptions{})
defer cleanup()
fi, err := os.Lstat(wd + "/foo")
CheckSuccess(err)
if fi.Uid != _RANDOM_OWNER || fi.Gid != _RANDOM_OWNER {
t.Fatal("Should use FS owner uid", fi.Uid, fi.Gid)
}
}
func TestOwnerOverride(t *testing.T) {
wd, cleanup := setupOwnerTest(&FileSystemOptions{Owner: &Owner{42, 43}})
defer cleanup()
fi, err := os.Lstat(wd + "/foo")
CheckSuccess(err)
if fi.Uid != 42 || fi.Gid != 43 {
t.Fatal("Should use current uid for mount", fi.Uid, fi.Gid)
}
}
...@@ -44,7 +44,6 @@ func (me *FileSystemDebug) Add(name string, callback getter) { ...@@ -44,7 +44,6 @@ func (me *FileSystemDebug) Add(name string, callback getter) {
} }
func (me *FileSystemDebug) Open(path string, flags uint32) (fuseFile File, status Status) { func (me *FileSystemDebug) Open(path string, flags uint32) (fuseFile File, status Status) {
content := me.getContent(path) content := me.getContent(path)
if content != nil { if content != nil {
return NewReadOnlyFile(content), OK return NewReadOnlyFile(content), OK
......
...@@ -21,6 +21,7 @@ package fuse ...@@ -21,6 +21,7 @@ package fuse
import ( import (
"fmt" "fmt"
"log" "log"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
...@@ -53,6 +54,13 @@ func newMount(fs FileSystem) *mountData { ...@@ -53,6 +54,13 @@ func newMount(fs FileSystem) *mountData {
return &mountData{fs: fs} return &mountData{fs: fs}
} }
func (me *mountData) setOwner(attr *Attr) {
if me.options.Owner != nil {
attr.Owner = *me.options.Owner
}
}
// Tests should set to true. // Tests should set to true.
var paranoia = false var paranoia = false
...@@ -165,11 +173,19 @@ func (me *inode) setParent(newParent *inode) { ...@@ -165,11 +173,19 @@ func (me *inode) setParent(newParent *inode) {
} }
} }
func CurrentOwner() *Owner {
return &Owner{
Uid: uint32(os.Getuid()),
Gid: uint32(os.Getgid()),
}
}
func NewFileSystemOptions() *FileSystemOptions { func NewFileSystemOptions() *FileSystemOptions {
return &FileSystemOptions{ return &FileSystemOptions{
NegativeTimeout: 0.0, NegativeTimeout: 0.0,
AttrTimeout: 1.0, AttrTimeout: 1.0,
EntryTimeout: 1.0, EntryTimeout: 1.0,
Owner: CurrentOwner(),
} }
} }
......
...@@ -72,9 +72,11 @@ func (me *FileSystemConnector) internalLookupWithNode(parent *inode, name string ...@@ -72,9 +72,11 @@ func (me *FileSystemConnector) internalLookupWithNode(parent *inode, name string
SplitNs(mount.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec) SplitNs(mount.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
CopyFileInfo(fi, &out.Attr) CopyFileInfo(fi, &out.Attr)
out.Attr.Ino = data.NodeId out.Attr.Ino = data.NodeId
mount.setOwner(&out.Attr)
return out, OK, data return out, OK, data
} }
func (me *FileSystemConnector) Forget(h *InHeader, input *ForgetIn) { func (me *FileSystemConnector) Forget(h *InHeader, input *ForgetIn) {
me.forgetUpdate(h.NodeId, int(input.Nlookup)) me.forgetUpdate(h.NodeId, int(input.Nlookup))
} }
...@@ -110,8 +112,8 @@ func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out ...@@ -110,8 +112,8 @@ func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out
out = &AttrOut{} out = &AttrOut{}
CopyFileInfo(fi, &out.Attr) CopyFileInfo(fi, &out.Attr)
out.Attr.Ino = header.NodeId out.Attr.Ino = header.NodeId
mount.setOwner(&out.Attr)
SplitNs(mount.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec) SplitNs(mount.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
return out, OK return out, OK
} }
......
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