Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jacobsa-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
jacobsa-fuse
Commits
54cb69c5
Commit
54cb69c5
authored
May 18, 2015
by
Aaron Jacobs
Browse files
Options
Browse Files
Download
Plain Diff
Added support for mounting a file system in read-only mode.
For GoogleCloudPlatform/gcsfuse#48.
parents
cb273d01
abdc5138
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
195 additions
and
8 deletions
+195
-8
mounted_file_system.go
mounted_file_system.go
+10
-0
samples/flushfs/flush_fs.go
samples/flushfs/flush_fs.go
+69
-2
samples/flushfs/flush_fs_test.go
samples/flushfs/flush_fs_test.go
+109
-5
samples/mount_sample/mount.go
samples/mount_sample/mount.go
+7
-1
No files found.
mounted_file_system.go
View file @
54cb69c5
...
...
@@ -65,6 +65,11 @@ type MountConfig struct {
// should inherit. If nil, context.Background() will be used.
OpContext
context
.
Context
// Mount the file system in read-only mode. File modes will appear as normal,
// but opening a file for writing and metadata operations like chmod,
// chtimes, etc. will fail.
ReadOnly
bool
// OS X only.
//
// Normally on OS X we mount with the novncache option
...
...
@@ -89,6 +94,11 @@ func (c *MountConfig) bazilfuseOptions() (opts []bazilfuse.MountOption) {
// InodeAttributes.Mode.
opts
=
append
(
opts
,
bazilfuse
.
SetOption
(
"default_permissions"
,
""
))
// Read only?
if
c
.
ReadOnly
{
opts
=
append
(
opts
,
bazilfuse
.
ReadOnly
())
}
// OS X: set novncache when appropriate.
if
isDarwin
&&
!
c
.
EnableVnodeCaching
{
opts
=
append
(
opts
,
bazilfuse
.
SetOption
(
"novncache"
,
""
))
...
...
samples/flushfs/flush_fs.go
View file @
54cb69c5
...
...
@@ -259,8 +259,75 @@ func (fs *flushFS) OpenDir(
defer
fs
.
mu
.
Unlock
()
// Sanity check.
if
op
.
Inode
!=
barID
{
err
=
fuse
.
ENOSYS
switch
op
.
Inode
{
case
fuseops
.
RootInodeID
:
case
barID
:
default
:
err
=
fuse
.
ENOENT
return
}
return
}
func
(
fs
*
flushFS
)
ReadDir
(
op
*
fuseops
.
ReadDirOp
)
{
var
err
error
defer
fuseutil
.
RespondToOp
(
op
,
&
err
)
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
// Create the appropriate listing.
var
dirents
[]
fuseutil
.
Dirent
switch
op
.
Inode
{
case
fuseops
.
RootInodeID
:
dirents
=
[]
fuseutil
.
Dirent
{
fuseutil
.
Dirent
{
Offset
:
1
,
Inode
:
fooID
,
Name
:
"foo"
,
Type
:
fuseutil
.
DT_File
,
},
fuseutil
.
Dirent
{
Offset
:
2
,
Inode
:
barID
,
Name
:
"bar"
,
Type
:
fuseutil
.
DT_Directory
,
},
}
case
barID
:
default
:
err
=
fmt
.
Errorf
(
"Unexpected inode: %v"
,
op
.
Inode
)
return
}
// If the offset is for the end of the listing, we're done. Otherwise we
// expect it to be for the start.
switch
op
.
Offset
{
case
fuseops
.
DirOffset
(
len
(
dirents
))
:
return
case
0
:
default
:
err
=
fmt
.
Errorf
(
"Unexpected offset: %v"
,
op
.
Offset
)
return
}
// Fill in the listing.
for
_
,
de
:=
range
dirents
{
op
.
Data
=
fuseutil
.
AppendDirent
(
op
.
Data
,
de
)
}
// We don't support doing this in anything more than one shot.
if
len
(
op
.
Data
)
>
op
.
Size
{
err
=
fmt
.
Errorf
(
"Couldn't fit listing in %v bytes"
,
op
.
Size
)
return
}
...
...
samples/flushfs/flush_fs_test.go
View file @
54cb69c5
...
...
@@ -19,17 +19,20 @@ import (
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"runtime"
"syscall"
"testing"
"time"
"unsafe"
"golang.org/x/sys/unix"
"github.com/jacobsa/bazilfuse"
"github.com/jacobsa/fuse/fsutil"
"github.com/jacobsa/fuse/fusetesting"
"github.com/jacobsa/fuse/samples"
.
"github.com/jacobsa/oglematchers"
.
"github.com/jacobsa/ogletest"
...
...
@@ -56,7 +59,8 @@ type flushFSTest struct {
func
(
t
*
flushFSTest
)
setUp
(
ti
*
TestInfo
,
flushErr
bazilfuse
.
Errno
,
fsyncErr
bazilfuse
.
Errno
)
{
fsyncErr
bazilfuse
.
Errno
,
readOnly
bool
)
{
var
err
error
// Set up files to receive flush and fsync reports.
...
...
@@ -76,6 +80,10 @@ func (t *flushFSTest) setUp(
fmt
.
Sprintf
(
"%d"
,
int
(
fsyncErr
)),
}
if
readOnly
{
t
.
MountFlags
=
append
(
t
.
MountFlags
,
"--read_only"
)
}
t
.
MountFiles
=
map
[
string
]
*
os
.
File
{
"flushfs.flushes_file"
:
t
.
flushes
,
"flushfs.fsyncs_file"
:
t
.
fsyncs
,
...
...
@@ -207,7 +215,7 @@ func init() { RegisterTestSuite(&NoErrorsTest{}) }
func
(
t
*
NoErrorsTest
)
SetUp
(
ti
*
TestInfo
)
{
const
noErr
=
0
t
.
flushFSTest
.
setUp
(
ti
,
noErr
,
noErr
)
t
.
flushFSTest
.
setUp
(
ti
,
noErr
,
noErr
,
false
)
}
func
(
t
*
NoErrorsTest
)
Close_ReadWrite
()
{
...
...
@@ -802,7 +810,7 @@ func init() { RegisterTestSuite(&FlushErrorTest{}) }
func
(
t
*
FlushErrorTest
)
SetUp
(
ti
*
TestInfo
)
{
const
noErr
=
0
t
.
flushFSTest
.
setUp
(
ti
,
bazilfuse
.
ENOENT
,
noErr
)
t
.
flushFSTest
.
setUp
(
ti
,
bazilfuse
.
ENOENT
,
noErr
,
false
)
}
func
(
t
*
FlushErrorTest
)
Close
()
{
...
...
@@ -871,7 +879,7 @@ func (t *FlushErrorTest) Dup2() {
}
////////////////////////////////////////////////////////////////////////
// Fsync
error
// Fsync error
////////////////////////////////////////////////////////////////////////
type
FsyncErrorTest
struct
{
...
...
@@ -882,7 +890,7 @@ func init() { RegisterTestSuite(&FsyncErrorTest{}) }
func
(
t
*
FsyncErrorTest
)
SetUp
(
ti
*
TestInfo
)
{
const
noErr
=
0
t
.
flushFSTest
.
setUp
(
ti
,
noErr
,
bazilfuse
.
ENOENT
)
t
.
flushFSTest
.
setUp
(
ti
,
noErr
,
bazilfuse
.
ENOENT
,
false
)
}
func
(
t
*
FsyncErrorTest
)
Fsync
()
{
...
...
@@ -943,3 +951,99 @@ func (t *FsyncErrorTest) Msync() {
err
=
syscall
.
Munmap
(
data
)
AssertEq
(
nil
,
err
)
}
////////////////////////////////////////////////////////////////////////
// Read-only mount
////////////////////////////////////////////////////////////////////////
type
ReadOnlyTest
struct
{
flushFSTest
}
func
init
()
{
RegisterTestSuite
(
&
ReadOnlyTest
{})
}
func
(
t
*
ReadOnlyTest
)
SetUp
(
ti
*
TestInfo
)
{
const
noErr
=
0
t
.
flushFSTest
.
setUp
(
ti
,
noErr
,
noErr
,
true
)
}
func
(
t
*
ReadOnlyTest
)
ReadRoot
()
{
var
fi
os
.
FileInfo
// Read.
entries
,
err
:=
fusetesting
.
ReadDirPicky
(
t
.
Dir
)
AssertEq
(
nil
,
err
)
AssertEq
(
2
,
len
(
entries
))
// bar
fi
=
entries
[
0
]
ExpectEq
(
"bar"
,
fi
.
Name
())
ExpectEq
(
os
.
FileMode
(
0777
)
|
os
.
ModeDir
,
fi
.
Mode
())
// foo
fi
=
entries
[
1
]
ExpectEq
(
"foo"
,
fi
.
Name
())
ExpectEq
(
os
.
FileMode
(
0777
),
fi
.
Mode
())
}
func
(
t
*
ReadOnlyTest
)
StatFiles
()
{
var
fi
os
.
FileInfo
var
err
error
// bar
fi
,
err
=
os
.
Stat
(
path
.
Join
(
t
.
Dir
,
"bar"
))
AssertEq
(
nil
,
err
)
ExpectEq
(
"bar"
,
fi
.
Name
())
ExpectEq
(
os
.
FileMode
(
0777
)
|
os
.
ModeDir
,
fi
.
Mode
())
// foo
fi
,
err
=
os
.
Stat
(
path
.
Join
(
t
.
Dir
,
"foo"
))
AssertEq
(
nil
,
err
)
ExpectEq
(
"foo"
,
fi
.
Name
())
ExpectEq
(
os
.
FileMode
(
0777
),
fi
.
Mode
())
}
func
(
t
*
ReadOnlyTest
)
ReadFile
()
{
_
,
err
:=
ioutil
.
ReadFile
(
path
.
Join
(
t
.
Dir
,
"foo"
))
ExpectEq
(
nil
,
err
)
}
func
(
t
*
ReadOnlyTest
)
ReadDir
()
{
_
,
err
:=
fusetesting
.
ReadDirPicky
(
path
.
Join
(
t
.
Dir
,
"bar"
))
ExpectEq
(
nil
,
err
)
}
func
(
t
*
ReadOnlyTest
)
CreateFile
()
{
err
:=
ioutil
.
WriteFile
(
path
.
Join
(
t
.
Dir
,
"blah"
),
[]
byte
{},
0400
)
ExpectThat
(
err
,
Error
(
HasSubstr
(
"read-only"
)))
}
func
(
t
*
ReadOnlyTest
)
Mkdir
()
{
err
:=
os
.
Mkdir
(
path
.
Join
(
t
.
Dir
,
"blah"
),
0700
)
ExpectThat
(
err
,
Error
(
HasSubstr
(
"read-only"
)))
}
func
(
t
*
ReadOnlyTest
)
OpenForWrite
()
{
modes
:=
[]
int
{
os
.
O_WRONLY
,
os
.
O_RDWR
,
}
for
_
,
mode
:=
range
modes
{
f
,
err
:=
os
.
OpenFile
(
path
.
Join
(
t
.
Dir
,
"foo"
),
mode
,
0700
)
f
.
Close
()
ExpectThat
(
err
,
Error
(
HasSubstr
(
"read-only"
)),
"mode: %v"
,
mode
)
}
}
func
(
t
*
ReadOnlyTest
)
Chtimes
()
{
err
:=
os
.
Chtimes
(
path
.
Join
(
t
.
Dir
,
"foo"
),
time
.
Now
(),
time
.
Now
())
ExpectThat
(
err
,
Error
(
MatchesRegexp
(
"read-only|not permitted"
)))
}
func
(
t
*
ReadOnlyTest
)
Chmod
()
{
err
:=
os
.
Chmod
(
path
.
Join
(
t
.
Dir
,
"foo"
),
0700
)
ExpectThat
(
err
,
Error
(
HasSubstr
(
"read-only"
)))
}
samples/mount_sample/mount.go
View file @
54cb69c5
...
...
@@ -39,6 +39,8 @@ var fFsyncsFile = flag.Uint64("flushfs.fsyncs_file", 0, "")
var
fFlushError
=
flag
.
Int
(
"flushfs.flush_error"
,
0
,
""
)
var
fFsyncError
=
flag
.
Int
(
"flushfs.fsync_error"
,
0
,
""
)
var
fReadOnly
=
flag
.
Bool
(
"read_only"
,
false
,
"Mount in read-only mode."
)
func
makeFlushFS
()
(
server
fuse
.
Server
,
err
error
)
{
// Check the flags.
if
*
fFlushesFile
==
0
||
*
fFsyncsFile
==
0
{
...
...
@@ -134,7 +136,11 @@ func main() {
log
.
Fatalf
(
"You must set --mount_point."
)
}
mfs
,
err
:=
fuse
.
Mount
(
*
fMountPoint
,
server
,
&
fuse
.
MountConfig
{})
cfg
:=
&
fuse
.
MountConfig
{
ReadOnly
:
*
fReadOnly
,
}
mfs
,
err
:=
fuse
.
Mount
(
*
fMountPoint
,
server
,
cfg
)
if
err
!=
nil
{
log
.
Fatalf
(
"Mount: %v"
,
err
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment