diff --git a/file_system.go b/file_system.go index d8fd3ac..5d50c71 100644 --- a/file_system.go +++ b/file_system.go @@ -258,6 +258,27 @@ func init() { // http://goo.gl/tvYyQt). type InodeAttributes struct { Size uint64 + + // The mode of the inode. This is exposed to the user in e.g. the result of + // fstat(2). + // + // The permissions bits of the mode are not necessarily respected by the FUSE + // kernel layer unless the file system is mounted with the + // 'default_permissions' option (cf. http://goo.gl/1LxOop). + // + // For example, in the case of mkdir: + // + // * (http://goo.gl/JkdxDI) sys_mkdirat calls inode_permission. + // + // * (...) inode_permission eventually calls do_inode_permission. + // + // * (http://goo.gl/aGCsmZ) calls i_op->permission, which is + // fuse_permission (cf. http://goo.gl/VZ9beH). + // + // * (http://goo.gl/5kqUKO) fuse_permission doesn't do anything at all for + // several code paths if FUSE_DEFAULT_PERMISSIONS is unset. In contrast, + // if that flag *is* set, then it calls generic_permission. + // Mode os.FileMode // Time information. See `man 2 stat` for full details. diff --git a/samples/memfs/fs.go b/samples/memfs/fs.go index 68489d4..b260cb4 100644 --- a/samples/memfs/fs.go +++ b/samples/memfs/fs.go @@ -61,7 +61,13 @@ type memFS struct { } // Create a file system that stores data and metadata in memory. +// +// The supplied UID/GID pair will own the root inode. This file system does no +// permissions checking, and should therefore be mounted with the +// default_permissions option. func NewMemFS( + uid uint32, + gid uint32, clock timeutil.Clock) fuse.FileSystem { // Set up the basic struct. fs := &memFS{ @@ -69,10 +75,11 @@ func NewMemFS( inodes: make([]*inode, fuse.RootInodeID+1), } - // Set up the root inode. Its ownership information will later be modified in - // Init. + // Set up the root inode. rootAttrs := fuse.InodeAttributes{ Mode: 0700 | os.ModeDir, + Uid: uid, + Gid: gid, } fs.inodes[fuse.RootInodeID] = newInode(clock, rootAttrs) @@ -196,17 +203,6 @@ func (fs *memFS) Init( req *fuse.InitRequest) (resp *fuse.InitResponse, err error) { resp = &fuse.InitResponse{} - fs.mu.RLock() - defer fs.mu.RUnlock() - - // Update the root inode's ownership information to match the credentials of - // the mounting process. - root := fs.getInodeForModifyingOrDie(fuse.RootInodeID) - defer root.mu.Unlock() - - root.attributes.Uid = req.Header.Uid - root.attributes.Gid = req.Header.Gid - return } diff --git a/samples/memfs/memfs_test.go b/samples/memfs/memfs_test.go index 73cdda8..e332107 100644 --- a/samples/memfs/memfs_test.go +++ b/samples/memfs/memfs_test.go @@ -27,6 +27,7 @@ import ( "testing" "time" + bazilfuse "bazil.org/fuse" "github.com/jacobsa/fuse" "github.com/jacobsa/fuse/fusetesting" "github.com/jacobsa/fuse/samples/memfs" @@ -111,8 +112,14 @@ func (t *MemFSTest) SetUp(ti *TestInfo) { } // Mount a file system. - fs := memfs.NewMemFS(&t.clock) - if t.mfs, err = fuse.Mount(mountPoint, fs); err != nil { + fs := memfs.NewMemFS(currentUid(), currentGid(), &t.clock) + + t.mfs, err = fuse.Mount( + mountPoint, + fs, + bazilfuse.DefaultPermissions()) + + if err != nil { panic("Mount: " + err.Error()) }