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
ae5da07e
Commit
ae5da07e
authored
Jan 28, 2020
by
Michael Stapelberg
Committed by
GitHub
Jan 28, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove naked returns across the code base (#75)
fixes #73
parent
4898d792
Changes
39
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
678 additions
and
929 deletions
+678
-929
connection.go
connection.go
+30
-40
conversions.go
conversions.go
+48
-92
freelists.go
freelists.go
+6
-6
fsutil/fsutil.go
fsutil/fsutil.go
+6
-9
fusetesting/parallel.go
fusetesting/parallel.go
+41
-68
fusetesting/readdir.go
fusetesting/readdir.go
+4
-7
fusetesting/stat_darwin.go
fusetesting/stat_darwin.go
+4
-10
fusetesting/stat_linux.go
fusetesting/stat_linux.go
+4
-8
fuseutil/dirent.go
fuseutil/dirent.go
+2
-2
fuseutil/not_implemented_file_system.go
fuseutil/not_implemented_file_system.go
+56
-84
internal/buffer/in_message.go
internal/buffer/in_message.go
+15
-19
internal/buffer/out_message.go
internal/buffer/out_message.go
+7
-7
internal/buffer/out_message_test.go
internal/buffer/out_message_test.go
+7
-7
internal/freelist/freelist.go
internal/freelist/freelist.go
+4
-4
mount.go
mount.go
+10
-16
mount_config.go
mount_config.go
+2
-2
mount_darwin.go
mount_darwin.go
+13
-21
mount_test.go
mount_test.go
+2
-2
samples/cachingfs/caching_fs.go
samples/cachingfs/caching_fs.go
+19
-23
samples/cachingfs/caching_fs_test.go
samples/cachingfs/caching_fs_test.go
+3
-3
samples/dynamicfs/dynamic_fs.go
samples/dynamicfs/dynamic_fs.go
+32
-42
samples/errorfs/error_fs.go
samples/errorfs/error_fs.go
+35
-37
samples/flushfs/flush_fs.go
samples/flushfs/flush_fs.go
+40
-55
samples/flushfs/flush_fs_test.go
samples/flushfs/flush_fs_test.go
+20
-29
samples/forgetfs/forget_fs.go
samples/forgetfs/forget_fs.go
+22
-25
samples/hellofs/hello_fs.go
samples/hellofs/hello_fs.go
+27
-34
samples/in_process.go
samples/in_process.go
+13
-19
samples/interruptfs/interrupt_fs.go
samples/interruptfs/interrupt_fs.go
+19
-24
samples/memfs/inode.go
samples/memfs/inode.go
+29
-34
samples/memfs/memfs.go
samples/memfs/memfs.go
+78
-86
samples/memfs/posix_test.go
samples/memfs/posix_test.go
+1
-2
samples/mount_sample/mount.go
samples/mount_sample/mount.go
+13
-23
samples/statfs/statfs.go
samples/statfs/statfs.go
+16
-19
samples/statfs/statfs_darwin_test.go
samples/statfs/statfs_darwin_test.go
+2
-3
samples/statfs/statfs_test.go
samples/statfs/statfs_test.go
+7
-9
samples/subprocess.go
samples/subprocess.go
+29
-42
samples/unmount.go
samples/unmount.go
+4
-5
unmount_linux.go
unmount_linux.go
+4
-5
unmount_std.go
unmount_std.go
+4
-6
No files found.
connection.go
View file @
ae5da07e
...
...
@@ -95,8 +95,8 @@ func newConnection(
cfg
MountConfig
,
debugLogger
*
log
.
Logger
,
errorLogger
*
log
.
Logger
,
dev
*
os
.
File
)
(
c
*
Connection
,
err
error
)
{
c
=
&
Connection
{
dev
*
os
.
File
)
(
*
Connection
,
error
)
{
c
:
=
&
Connection
{
cfg
:
cfg
,
debugLogger
:
debugLogger
,
errorLogger
:
errorLogger
,
...
...
@@ -105,30 +105,26 @@ func newConnection(
}
// Initialize.
err
=
c
.
Init
()
if
err
!=
nil
{
if
err
:=
c
.
Init
();
err
!=
nil
{
c
.
close
()
err
=
fmt
.
Errorf
(
"Init: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"Init: %v"
,
err
)
}
return
return
c
,
nil
}
// Init performs the work necessary to cause the mount process to complete.
func
(
c
*
Connection
)
Init
()
(
err
error
)
{
func
(
c
*
Connection
)
Init
()
error
{
// Read the init op.
ctx
,
op
,
err
:=
c
.
ReadOp
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Reading init op: %v"
,
err
)
return
return
fmt
.
Errorf
(
"Reading init op: %v"
,
err
)
}
initOp
,
ok
:=
op
.
(
*
initOp
)
if
!
ok
{
c
.
Reply
(
ctx
,
syscall
.
EPROTO
)
err
=
fmt
.
Errorf
(
"Expected *initOp, got %T"
,
op
)
return
return
fmt
.
Errorf
(
"Expected *initOp, got %T"
,
op
)
}
// Make sure the protocol version spoken by the kernel is new enough.
...
...
@@ -139,8 +135,7 @@ func (c *Connection) Init() (err error) {
if
initOp
.
Kernel
.
LT
(
min
)
{
c
.
Reply
(
ctx
,
syscall
.
EPROTO
)
err
=
fmt
.
Errorf
(
"Version too old: %v"
,
initOp
.
Kernel
)
return
return
fmt
.
Errorf
(
"Version too old: %v"
,
initOp
.
Kernel
)
}
// Downgrade our protocol if necessary.
...
...
@@ -169,7 +164,7 @@ func (c *Connection) Init() (err error) {
}
c
.
Reply
(
ctx
,
nil
)
return
return
nil
}
// Log information for an operation with the given ID. calldepth is the depth
...
...
@@ -228,9 +223,9 @@ func (c *Connection) recordCancelFunc(
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
beginOp
(
opCode
uint32
,
fuseID
uint64
)
(
ctx
context
.
Context
)
{
fuseID
uint64
)
context
.
Context
{
// Start with the parent context.
ctx
=
c
.
cfg
.
OpContext
ctx
:
=
c
.
cfg
.
OpContext
// Set up a cancellation function.
//
...
...
@@ -246,7 +241,7 @@ func (c *Connection) beginOp(
c
.
recordCancelFunc
(
fuseID
,
cancel
)
}
return
return
ctx
}
// Clean up all state associated with an op to which the user has responded,
...
...
@@ -307,14 +302,14 @@ func (c *Connection) handleInterrupt(fuseID uint64) {
// Read the next message from the kernel. The message must later be destroyed
// using destroyInMessage.
func
(
c
*
Connection
)
readMessage
()
(
m
*
buffer
.
InMessage
,
err
error
)
{
func
(
c
*
Connection
)
readMessage
()
(
*
buffer
.
InMessage
,
error
)
{
// Allocate a message.
m
=
c
.
getInMessage
()
m
:
=
c
.
getInMessage
()
// Loop past transient errors.
for
{
// Attempt a reaed.
err
=
m
.
Init
(
c
.
dev
)
err
:
=
m
.
Init
(
c
.
dev
)
// Special cases:
//
...
...
@@ -336,28 +331,26 @@ func (c *Connection) readMessage() (m *buffer.InMessage, err error) {
if
err
!=
nil
{
c
.
putInMessage
(
m
)
m
=
nil
return
return
nil
,
err
}
return
return
m
,
nil
}
}
// Write the supplied message to the kernel.
func
(
c
*
Connection
)
writeMessage
(
msg
[]
byte
)
(
err
error
)
{
func
(
c
*
Connection
)
writeMessage
(
msg
[]
byte
)
error
{
// Avoid the retry loop in os.File.Write.
n
,
err
:=
syscall
.
Write
(
int
(
c
.
dev
.
Fd
()),
msg
)
if
err
!=
nil
{
return
return
err
}
if
n
!=
len
(
msg
)
{
err
=
fmt
.
Errorf
(
"Wrote %d bytes; expected %d"
,
n
,
len
(
msg
))
return
return
fmt
.
Errorf
(
"Wrote %d bytes; expected %d"
,
n
,
len
(
msg
))
}
return
return
nil
}
// ReadOp consumes the next op from the kernel process, returning the op and a
...
...
@@ -371,14 +364,13 @@ func (c *Connection) writeMessage(msg []byte) (err error) {
// /dev/fuse. It must not be called multiple times concurrently.
//
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
ReadOp
()
(
ctx
context
.
Context
,
op
interface
{},
err
error
)
{
func
(
c
*
Connection
)
ReadOp
()
(
_
context
.
Context
,
op
interface
{},
_
error
)
{
// Keep going until we find a request we know how to convert.
for
{
// Read the next message from the kernel.
var
inMsg
*
buffer
.
InMessage
inMsg
,
err
=
c
.
readMessage
()
inMsg
,
err
:=
c
.
readMessage
()
if
err
!=
nil
{
return
return
nil
,
nil
,
err
}
// Convert the message to an op.
...
...
@@ -386,8 +378,7 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
op
,
err
=
convertInMessage
(
inMsg
,
outMsg
,
c
.
protocol
)
if
err
!=
nil
{
c
.
putOutMessage
(
outMsg
)
err
=
fmt
.
Errorf
(
"convertInMessage: %v"
,
err
)
return
return
nil
,
nil
,
fmt
.
Errorf
(
"convertInMessage: %v"
,
err
)
}
// Choose an ID for this operation for the purposes of logging, and log it.
...
...
@@ -402,11 +393,11 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
}
// Set up a context that remembers information about this op.
ctx
=
c
.
beginOp
(
inMsg
.
Header
()
.
Opcode
,
inMsg
.
Header
()
.
Unique
)
ctx
:
=
c
.
beginOp
(
inMsg
.
Header
()
.
Opcode
,
inMsg
.
Header
()
.
Unique
)
ctx
=
context
.
WithValue
(
ctx
,
contextKey
,
opState
{
inMsg
,
outMsg
,
op
})
// Return the op to the user.
return
return
ctx
,
op
,
nil
}
}
...
...
@@ -499,10 +490,9 @@ func (c *Connection) Reply(ctx context.Context, opErr error) {
// Close the connection. Must not be called until operations that were read
// from the connection have been responded to.
func
(
c
*
Connection
)
close
()
(
err
error
)
{
func
(
c
*
Connection
)
close
()
error
{
// Posix doesn't say that close can be called concurrently with read or
// write, but luckily we exclude the possibility of a race by requiring the
// user to respond to all ops first.
err
=
c
.
dev
.
Close
()
return
return
c
.
dev
.
Close
()
}
conversions.go
View file @
ae5da07e
This diff is collapsed.
Click to expand it.
freelists.go
View file @
ae5da07e
...
...
@@ -25,16 +25,16 @@ import (
////////////////////////////////////////////////////////////////////////
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
getInMessage
()
(
x
*
buffer
.
InMessage
)
{
func
(
c
*
Connection
)
getInMessage
()
*
buffer
.
InMessage
{
c
.
mu
.
Lock
()
x
=
(
*
buffer
.
InMessage
)(
c
.
inMessages
.
Get
())
x
:
=
(
*
buffer
.
InMessage
)(
c
.
inMessages
.
Get
())
c
.
mu
.
Unlock
()
if
x
==
nil
{
x
=
new
(
buffer
.
InMessage
)
}
return
return
x
}
// LOCKS_EXCLUDED(c.mu)
...
...
@@ -49,9 +49,9 @@ func (c *Connection) putInMessage(x *buffer.InMessage) {
////////////////////////////////////////////////////////////////////////
// LOCKS_EXCLUDED(c.mu)
func
(
c
*
Connection
)
getOutMessage
()
(
x
*
buffer
.
OutMessage
)
{
func
(
c
*
Connection
)
getOutMessage
()
*
buffer
.
OutMessage
{
c
.
mu
.
Lock
()
x
=
(
*
buffer
.
OutMessage
)(
c
.
outMessages
.
Get
())
x
:
=
(
*
buffer
.
OutMessage
)(
c
.
outMessages
.
Get
())
c
.
mu
.
Unlock
()
if
x
==
nil
{
...
...
@@ -59,7 +59,7 @@ func (c *Connection) getOutMessage() (x *buffer.OutMessage) {
}
x
.
Reset
()
return
return
x
}
// LOCKS_EXCLUDED(c.mu)
...
...
fsutil/fsutil.go
View file @
ae5da07e
...
...
@@ -28,25 +28,22 @@ import (
// Warning: this is not production-quality code, and should only be used for
// testing purposes. In particular, there is a race between creating and
// unlinking by name.
func
AnonymousFile
(
dir
string
)
(
f
*
os
.
File
,
err
error
)
{
func
AnonymousFile
(
dir
string
)
(
*
os
.
File
,
error
)
{
// Choose a prefix based on the binary name.
prefix
:=
path
.
Base
(
os
.
Args
[
0
])
// Create the file.
f
,
err
=
ioutil
.
TempFile
(
dir
,
prefix
)
f
,
err
:
=
ioutil
.
TempFile
(
dir
,
prefix
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
}
// Unlink it.
err
=
os
.
Remove
(
f
.
Name
())
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Remove: %v"
,
err
)
return
if
err
:=
os
.
Remove
(
f
.
Name
());
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Remove: %v"
,
err
)
}
return
return
f
,
nil
}
// Call fdatasync on the supplied file.
...
...
fusetesting/parallel.go
View file @
ae5da07e
...
...
@@ -44,22 +44,18 @@ func RunCreateInParallelTest_NoTruncate(
// Set up a function that opens the file with O_CREATE and then appends a
// byte to it.
worker
:=
func
(
id
byte
)
(
err
error
)
{
worker
:=
func
(
id
byte
)
error
{
f
,
err
:=
os
.
OpenFile
(
filename
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_APPEND
,
0600
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
return
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
}
defer
f
.
Close
()
_
,
err
=
f
.
Write
([]
byte
{
id
})
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
return
if
_
,
err
:=
f
.
Write
([]
byte
{
id
});
err
!=
nil
{
return
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
}
return
return
nil
}
// Run several workers in parallel.
...
...
@@ -67,9 +63,8 @@ func RunCreateInParallelTest_NoTruncate(
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
err
=
worker
(
id
)
return
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
return
worker
(
id
)
})
}
...
...
@@ -121,21 +116,16 @@ func RunCreateInParallelTest_Truncate(
filename
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_APPEND
|
os
.
O_TRUNC
,
0600
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
return
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
}
defer
f
.
Close
()
_
,
err
=
f
.
Write
([]
byte
{
id
})
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
return
if
_
,
err
:=
f
.
Write
([]
byte
{
id
});
err
!=
nil
{
return
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
}
return
return
nil
}
// Run several workers in parallel.
...
...
@@ -143,9 +133,8 @@ func RunCreateInParallelTest_Truncate(
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
err
=
worker
(
id
)
return
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
return
worker
(
id
)
})
}
...
...
@@ -203,26 +192,22 @@ func RunCreateInParallelTest_Exclusive(
// If we failed to open due to the file already existing, just leave.
if
os
.
IsExist
(
err
)
{
err
=
nil
return
return
nil
}
// Propgate other errors.
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
return
return
fmt
.
Errorf
(
"Worker %d: Open: %v"
,
id
,
err
)
}
atomic
.
AddUint64
(
&
openCount
,
1
)
defer
f
.
Close
()
_
,
err
=
f
.
Write
([]
byte
{
id
})
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
return
if
_
,
err
:=
f
.
Write
([]
byte
{
id
});
err
!=
nil
{
return
fmt
.
Errorf
(
"Worker %d: Write: %v"
,
id
,
err
)
}
return
return
nil
}
// Run several workers in parallel.
...
...
@@ -230,9 +215,8 @@ func RunCreateInParallelTest_Exclusive(
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
err
=
worker
(
id
)
return
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
return
worker
(
id
)
})
}
...
...
@@ -269,19 +253,16 @@ func RunMkdirInParallelTest(
filename
:=
path
.
Join
(
dir
,
"foo"
)
// Set up a function that creates the directory, ignoring EEXIST errors.
worker
:=
func
(
id
byte
)
(
err
error
)
{
err
=
os
.
Mkdir
(
filename
,
0700
)
worker
:=
func
(
id
byte
)
error
{
err
:=
os
.
Mkdir
(
filename
,
0700
)
if
os
.
IsExist
(
err
)
{
err
=
nil
return
nil
}
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Mkdir: %v"
,
id
,
err
)
return
return
fmt
.
Errorf
(
"Worker %d: Mkdir: %v"
,
id
,
err
)
}
return
return
nil
}
// Run several workers in parallel.
...
...
@@ -289,9 +270,8 @@ func RunMkdirInParallelTest(
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
err
=
worker
(
id
)
return
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
return
worker
(
id
)
})
}
...
...
@@ -325,19 +305,17 @@ func RunSymlinkInParallelTest(
filename
:=
path
.
Join
(
dir
,
"foo"
)
// Set up a function that creates the symlink, ignoring EEXIST errors.
worker
:=
func
(
id
byte
)
(
err
error
)
{
err
=
os
.
Symlink
(
"blah"
,
filename
)
worker
:=
func
(
id
byte
)
error
{
err
:=
os
.
Symlink
(
"blah"
,
filename
)
if
os
.
IsExist
(
err
)
{
err
=
nil
return
nil
}
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Symlink: %v"
,
id
,
err
)
return
return
fmt
.
Errorf
(
"Worker %d: Symlink: %v"
,
id
,
err
)
}
return
return
nil
}
// Run several workers in parallel.
...
...
@@ -345,9 +323,8 @@ func RunSymlinkInParallelTest(
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
err
=
worker
(
id
)
return
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
return
worker
(
id
)
})
}
...
...
@@ -388,19 +365,16 @@ func RunHardlinkInParallelTest(
filename
:=
path
.
Join
(
dir
,
"foo"
)
// Set up a function that creates the symlink, ignoring EEXIST errors.
worker
:=
func
(
id
byte
)
(
err
error
)
{
err
=
os
.
Link
(
originalFile
,
filename
)
worker
:=
func
(
id
byte
)
error
{
err
:=
os
.
Link
(
originalFile
,
filename
)
if
os
.
IsExist
(
err
)
{
err
=
nil
return
nil
}
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Worker %d: Link: %v"
,
id
,
err
)
return
return
fmt
.
Errorf
(
"Worker %d: Link: %v"
,
id
,
err
)
}
return
return
nil
}
// Run several workers in parallel.
...
...
@@ -408,9 +382,8 @@ func RunHardlinkInParallelTest(
b
:=
syncutil
.
NewBundle
(
ctx
)
for
i
:=
0
;
i
<
numWorkers
;
i
++
{
id
:=
byte
(
i
)
b
.
Add
(
func
(
ctx
context
.
Context
)
(
err
error
)
{
err
=
worker
(
id
)
return
b
.
Add
(
func
(
ctx
context
.
Context
)
error
{
return
worker
(
id
)
})
}
...
...
fusetesting/readdir.go
View file @
ae5da07e
...
...
@@ -37,8 +37,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Open the directory.
f
,
err
:=
os
.
Open
(
dirname
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Open: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"Open: %v"
,
err
)
}
// Don't forget to close it later.
...
...
@@ -52,8 +51,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Read all of the names from the directory.
names
,
err
:=
f
.
Readdirnames
(
-
1
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Readdirnames: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"Readdirnames: %v"
,
err
)
}
// Stat each one.
...
...
@@ -62,8 +60,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
fi
,
err
=
os
.
Lstat
(
path
.
Join
(
dirname
,
name
))
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Lstat(%s): %v"
,
name
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"Lstat(%s): %v"
,
name
,
err
)
}
entries
=
append
(
entries
,
fi
)
...
...
@@ -72,5 +69,5 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Sort the entries by name.
sort
.
Sort
(
sortedEntries
(
entries
))
return
return
entries
,
nil
}
fusetesting/stat_darwin.go
View file @
ae5da07e
...
...
@@ -20,26 +20,20 @@ import (
)
func
extractMtime
(
sys
interface
{})
(
mtime
time
.
Time
,
ok
bool
)
{
mtime
=
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtimespec
.
Unix
())
ok
=
true
return
return
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtimespec
.
Unix
()),
true
}
func
extractBirthtime
(
sys
interface
{})
(
birthtime
time
.
Time
,
ok
bool
)
{
birthtime
=
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Birthtimespec
.
Unix
())
ok
=
true
return
return
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Birthtimespec
.
Unix
()),
true
}
func
extractNlink
(
sys
interface
{})
(
nlink
uint64
,
ok
bool
)
{
nlink
=
uint64
(
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
)
ok
=
true
return
return
uint64
(
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
),
true
}
func
getTimes
(
stat
*
syscall
.
Stat_t
)
(
atime
,
ctime
,
mtime
time
.
Time
)
{
atime
=
time
.
Unix
(
stat
.
Atimespec
.
Unix
())
ctime
=
time
.
Unix
(
stat
.
Ctimespec
.
Unix
())
mtime
=
time
.
Unix
(
stat
.
Mtimespec
.
Unix
())
return
return
atime
,
ctime
,
mtime
}
fusetesting/stat_linux.go
View file @
ae5da07e
...
...
@@ -20,24 +20,20 @@ import (
)
func
extractMtime
(
sys
interface
{})
(
mtime
time
.
Time
,
ok
bool
)
{
mtime
=
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtim
.
Unix
())
ok
=
true
return
return
time
.
Unix
(
sys
.
(
*
syscall
.
Stat_t
)
.
Mtim
.
Unix
()),
true
}
func
extractBirthtime
(
sys
interface
{})
(
birthtime
time
.
Time
,
ok
bool
)
{
return
return
time
.
Time
{},
false
}
func
extractNlink
(
sys
interface
{})
(
nlink
uint64
,
ok
bool
)
{
nlink
=
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
ok
=
true
return
return
sys
.
(
*
syscall
.
Stat_t
)
.
Nlink
,
true
}
func
getTimes
(
stat
*
syscall
.
Stat_t
)
(
atime
,
ctime
,
mtime
time
.
Time
)
{
atime
=
time
.
Unix
(
stat
.
Atim
.
Unix
())
ctime
=
time
.
Unix
(
stat
.
Ctim
.
Unix
())
mtime
=
time
.
Unix
(
stat
.
Mtim
.
Unix
())
return
return
atime
,
ctime
,
mtime
}
fuseutil/dirent.go
View file @
ae5da07e
...
...
@@ -79,7 +79,7 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
// Do we have enough room?
totalLen
:=
direntSize
+
len
(
d
.
Name
)
+
padLen
if
totalLen
>
len
(
buf
)
{
return
return
n
}
// Write the header.
...
...
@@ -101,5 +101,5 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
n
+=
copy
(
buf
[
n
:
],
padding
[
:
padLen
])
}
return
return
n
}
fuseutil/not_implemented_file_system.go
View file @
ae5da07e
...
...
@@ -32,198 +32,170 @@ var _ FileSystem = &NotImplementedFileSystem{}
func
(
fs
*
NotImplementedFileSystem
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
StatFSOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
LookUpInodeOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
SetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
SetInodeAttributesOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
SetInodeAttributesOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
ForgetInode
(
ctx
context
.
Context
,
op
*
fuseops
.
ForgetInodeOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
ForgetInodeOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
MkDir
(
ctx
context
.
Context
,
op
*
fuseops
.
MkDirOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
MkDirOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
MkNode
(
ctx
context
.
Context
,
op
*
fuseops
.
MkNodeOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
MkNodeOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
CreateFile
(
ctx
context
.
Context
,
op
*
fuseops
.
CreateFileOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
CreateFileOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
CreateSymlink
(
ctx
context
.
Context
,
op
*
fuseops
.
CreateSymlinkOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
CreateSymlinkOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
CreateLink
(
ctx
context
.
Context
,
op
*
fuseops
.
CreateLinkOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
CreateLinkOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
Rename
(
ctx
context
.
Context
,
op
*
fuseops
.
RenameOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
RenameOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
RmDir
(
ctx
context
.
Context
,
op
*
fuseops
.
RmDirOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
RmDirOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
Unlink
(
ctx
context
.
Context
,
op
*
fuseops
.
UnlinkOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
UnlinkOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
OpenDir
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
OpenDirOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
ReadDir
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
ReadDirOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
ReleaseDirHandle
(
ctx
context
.
Context
,
op
*
fuseops
.
ReleaseDirHandleOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
ReleaseDirHandleOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
OpenFileOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
ReadFile
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
ReadFileOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
WriteFile
(
ctx
context
.
Context
,
op
*
fuseops
.
WriteFileOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
WriteFileOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
SyncFile
(
ctx
context
.
Context
,
op
*
fuseops
.
SyncFileOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
SyncFileOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
FlushFile
(
ctx
context
.
Context
,
op
*
fuseops
.
FlushFileOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
FlushFileOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
ReleaseFileHandle
(
ctx
context
.
Context
,
op
*
fuseops
.
ReleaseFileHandleOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
ReleaseFileHandleOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
ReadSymlink
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadSymlinkOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
ReadSymlinkOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
RemoveXattr
(
ctx
context
.
Context
,
op
*
fuseops
.
RemoveXattrOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
RemoveXattrOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
GetXattr
(
ctx
context
.
Context
,
op
*
fuseops
.
GetXattrOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
GetXattrOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
ListXattr
(
ctx
context
.
Context
,
op
*
fuseops
.
ListXattrOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
ListXattrOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
SetXattr
(
ctx
context
.
Context
,
op
*
fuseops
.
SetXattrOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
SetXattrOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
Fallocate
(
ctx
context
.
Context
,
op
*
fuseops
.
FallocateOp
)
(
err
error
)
{
err
=
fuse
.
ENOSYS
return
op
*
fuseops
.
FallocateOp
)
error
{
return
fuse
.
ENOSYS
}
func
(
fs
*
NotImplementedFileSystem
)
Destroy
()
{
...
...
internal/buffer/in_message.go
View file @
ae5da07e
...
...
@@ -49,38 +49,34 @@ type InMessage struct {
// Initialize with the data read by a single call to r.Read. The first call to
// Consume will consume the bytes directly after the fusekernel.InHeader
// struct.
func
(
m
*
InMessage
)
Init
(
r
io
.
Reader
)
(
err
error
)
{
func
(
m
*
InMessage
)
Init
(
r
io
.
Reader
)
error
{
n
,
err
:=
r
.
Read
(
m
.
storage
[
:
])
if
err
!=
nil
{
return
return
err
}
// Make sure the message is long enough.
const
headerSize
=
unsafe
.
Sizeof
(
fusekernel
.
InHeader
{})
if
uintptr
(
n
)
<
headerSize
{
err
=
fmt
.
Errorf
(
"Unexpectedly read only %d bytes."
,
n
)
return
return
fmt
.
Errorf
(
"Unexpectedly read only %d bytes."
,
n
)
}
m
.
remaining
=
m
.
storage
[
headerSize
:
n
]
// Check the header's length.
if
int
(
m
.
Header
()
.
Len
)
!=
n
{
err
=
fmt
.
Errorf
(
return
fmt
.
Errorf
(
"Header says %d bytes, but we read %d"
,
m
.
Header
()
.
Len
,
n
)
return
}
return
return
nil
}
// Return a reference to the header read in the most recent call to Init.
func
(
m
*
InMessage
)
Header
()
(
h
*
fusekernel
.
InHeader
)
{
h
=
(
*
fusekernel
.
InHeader
)(
unsafe
.
Pointer
(
&
m
.
storage
[
0
]))
return
func
(
m
*
InMessage
)
Header
()
*
fusekernel
.
InHeader
{
return
(
*
fusekernel
.
InHeader
)(
unsafe
.
Pointer
(
&
m
.
storage
[
0
]))
}
// Return the number of bytes left to consume.
...
...
@@ -90,26 +86,26 @@ func (m *InMessage) Len() uintptr {
// Consume the next n bytes from the message, returning a nil pointer if there
// are fewer than n bytes available.
func
(
m
*
InMessage
)
Consume
(
n
uintptr
)
(
p
unsafe
.
Pointer
)
{
func
(
m
*
InMessage
)
Consume
(
n
uintptr
)
unsafe
.
Pointer
{
if
m
.
Len
()
==
0
||
n
>
m
.
Len
()
{
return
return
nil
}
p
=
unsafe
.
Pointer
(
&
m
.
remaining
[
0
])
p
:
=
unsafe
.
Pointer
(
&
m
.
remaining
[
0
])
m
.
remaining
=
m
.
remaining
[
n
:
]
return
return
p
}
// Equivalent to Consume, except returns a slice of bytes. The result will be
// nil if Consume would fail.
func
(
m
*
InMessage
)
ConsumeBytes
(
n
uintptr
)
(
b
[]
byte
)
{
func
(
m
*
InMessage
)
ConsumeBytes
(
n
uintptr
)
[]
byte
{
if
n
>
m
.
Len
()
{
return
return
nil
}
b
=
m
.
remaining
[
:
n
]
b
:
=
m
.
remaining
[
:
n
]
m
.
remaining
=
m
.
remaining
[
n
:
]
return
return
b
}
internal/buffer/out_message.go
View file @
ae5da07e
...
...
@@ -81,28 +81,28 @@ func (m *OutMessage) OutHeader() *fusekernel.OutHeader {
// Grow grows m's buffer by the given number of bytes, returning a pointer to
// the start of the new segment, which is guaranteed to be zeroed. If there is
// insufficient space, it returns nil.
func
(
m
*
OutMessage
)
Grow
(
n
int
)
(
p
unsafe
.
Pointer
)
{
p
=
m
.
GrowNoZero
(
n
)
func
(
m
*
OutMessage
)
Grow
(
n
int
)
unsafe
.
Pointer
{
p
:
=
m
.
GrowNoZero
(
n
)
if
p
!=
nil
{
memclr
(
p
,
uintptr
(
n
))
}
return
return
p
}
// GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use
// with caution!
func
(
m
*
OutMessage
)
GrowNoZero
(
n
int
)
(
p
unsafe
.
Pointer
)
{
func
(
m
*
OutMessage
)
GrowNoZero
(
n
int
)
unsafe
.
Pointer
{
// Will we overflow the buffer?
o
:=
m
.
payloadOffset
if
len
(
m
.
payload
)
-
o
<
n
{
return
return
nil
}
p
=
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
m
.
payload
))
+
uintptr
(
o
))
p
:
=
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
m
.
payload
))
+
uintptr
(
o
))
m
.
payloadOffset
=
o
+
n
return
return
p
}
// ShrinkTo shrinks m to the given size. It panics if the size is greater than
...
...
internal/buffer/out_message_test.go
View file @
ae5da07e
...
...
@@ -24,16 +24,16 @@ func toByteSlice(p unsafe.Pointer, n int) []byte {
}
// fillWithGarbage writes random data to [p, p+n).
func
fillWithGarbage
(
p
unsafe
.
Pointer
,
n
int
)
(
err
error
)
{
func
fillWithGarbage
(
p
unsafe
.
Pointer
,
n
int
)
error
{
b
:=
toByteSlice
(
p
,
n
)
_
,
err
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
return
_
,
err
:
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
return
err
}
func
randBytes
(
n
int
)
(
b
[]
byte
,
err
error
)
{
b
=
make
([]
byte
,
n
)
_
,
err
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
return
func
randBytes
(
n
int
)
(
[]
byte
,
error
)
{
b
:
=
make
([]
byte
,
n
)
_
,
err
:
=
io
.
ReadFull
(
rand
.
Reader
,
b
)
return
b
,
err
}
// findNonZero finds the offset of the first non-zero byte in [p, p+n). If
...
...
internal/freelist/freelist.go
View file @
ae5da07e
...
...
@@ -22,16 +22,16 @@ type Freelist struct {
}
// Get an element from the freelist, returning nil if empty.
func
(
fl
*
Freelist
)
Get
()
(
p
unsafe
.
Pointer
)
{
func
(
fl
*
Freelist
)
Get
()
unsafe
.
Pointer
{
l
:=
len
(
fl
.
list
)
if
l
==
0
{
return
return
nil
}
p
=
fl
.
list
[
l
-
1
]
p
:
=
fl
.
list
[
l
-
1
]
fl
.
list
=
fl
.
list
[
:
l
-
1
]
return
return
p
}
// Contribute an element back to the freelist.
...
...
mount.go
View file @
ae5da07e
...
...
@@ -35,25 +35,23 @@ type Server interface {
func
Mount
(
dir
string
,
server
Server
,
config
*
MountConfig
)
(
mfs
*
MountedFileSystem
,
err
error
)
{
config
*
MountConfig
)
(
*
MountedFileSystem
,
error
)
{
// Sanity check: make sure the mount point exists and is a directory. This
// saves us from some confusing errors later on OS X.
fi
,
err
:=
os
.
Stat
(
dir
)
switch
{
case
os
.
IsNotExist
(
err
)
:
return
return
nil
,
err
case
err
!=
nil
:
err
=
fmt
.
Errorf
(
"Statting mount point: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"Statting mount point: %v"
,
err
)
case
!
fi
.
IsDir
()
:
err
=
fmt
.
Errorf
(
"Mount point %s is not a directory"
,
dir
)
return
return
nil
,
fmt
.
Errorf
(
"Mount point %s is not a directory"
,
dir
)
}
// Initialize the struct.
mfs
=
&
MountedFileSystem
{
mfs
:
=
&
MountedFileSystem
{
dir
:
dir
,
joinStatusAvailable
:
make
(
chan
struct
{}),
}
...
...
@@ -62,8 +60,7 @@ func Mount(
ready
:=
make
(
chan
error
,
1
)
dev
,
err
:=
mount
(
dir
,
config
,
ready
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"mount: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"mount: %v"
,
err
)
}
// Choose a parent context for ops.
...
...
@@ -78,10 +75,8 @@ func Mount(
config
.
DebugLogger
,
config
.
ErrorLogger
,
dev
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"newConnection: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"newConnection: %v"
,
err
)
}
// Serve the connection in the background. When done, set the join status.
...
...
@@ -92,10 +87,9 @@ func Mount(
}()
// Wait for the mount process to complete.
if
err
=
<-
ready
;
err
!=
nil
{
err
=
fmt
.
Errorf
(
"mount (background): %v"
,
err
)
return
if
err
:=
<-
ready
;
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"mount (background): %v"
,
err
)
}
return
return
mfs
,
nil
}
mount_config.go
View file @
ae5da07e
...
...
@@ -213,14 +213,14 @@ func (c *MountConfig) toMap() (opts map[string]string) {
opts
[
k
]
=
v
}
return
return
opts
}
func
escapeOptionsKey
(
s
string
)
(
res
string
)
{
res
=
s
res
=
strings
.
Replace
(
res
,
`\`
,
`\\`
,
-
1
)
res
=
strings
.
Replace
(
res
,
`,`
,
`\,`
,
-
1
)
return
return
res
}
func
mapToOptionsString
(
opts
map
[
string
]
string
)
string
{
...
...
mount_darwin.go
View file @
ae5da07e
...
...
@@ -76,13 +76,11 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
if
os
.
IsNotExist
(
err
)
{
if
i
==
0
{
// Not even the first device was found. Fuse must not be loaded.
err
=
errNotLoaded
return
return
nil
,
errNotLoaded
}
// Otherwise we've run out of kernel-provided devices
err
=
errNoAvail
return
return
nil
,
errNoAvail
}
if
err2
,
ok
:=
err
.
(
*
os
.
PathError
);
ok
&&
err2
.
Err
==
syscall
.
EBUSY
{
...
...
@@ -90,7 +88,7 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
continue
}
return
return
dev
,
nil
}
}
...
...
@@ -100,7 +98,7 @@ func callMount(
dir
string
,
cfg
*
MountConfig
,
dev
*
os
.
File
,
ready
chan
<-
error
)
(
err
error
)
{
ready
chan
<-
error
)
error
{
// The mount helper doesn't understand any escaping.
for
k
,
v
:=
range
cfg
.
toMap
()
{
...
...
@@ -143,9 +141,8 @@ func callMount(
cmd
.
Stdout
=
&
buf
cmd
.
Stderr
=
&
buf
err
=
cmd
.
Start
()
if
err
!=
nil
{
return
if
err
:=
cmd
.
Start
();
err
!=
nil
{
return
err
}
// In the background, wait for the command to complete.
...
...
@@ -162,7 +159,7 @@ func callMount(
ready
<-
err
}()
return
return
nil
}
// Begin the process of mounting at the given directory, returning a connection
...
...
@@ -188,8 +185,7 @@ func mount(
if
err
==
errNotLoaded
{
err
=
loadOSXFUSE
(
loc
.
Load
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"loadOSXFUSE: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"loadOSXFUSE: %v"
,
err
)
}
dev
,
err
=
openOSXFUSEDev
(
loc
.
DevicePrefix
)
...
...
@@ -197,21 +193,17 @@ func mount(
// Propagate errors.
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"openOSXFUSEDev: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"openOSXFUSEDev: %v"
,
err
)
}
// Call the mount binary with the device.
err
=
callMount
(
loc
.
Mount
,
loc
.
DaemonVar
,
dir
,
cfg
,
dev
,
ready
)
if
err
!=
nil
{
if
err
:=
callMount
(
loc
.
Mount
,
loc
.
DaemonVar
,
dir
,
cfg
,
dev
,
ready
);
err
!=
nil
{
dev
.
Close
()
err
=
fmt
.
Errorf
(
"callMount: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"callMount: %v"
,
err
)
}
return
return
dev
,
nil
}
err
=
errOSXFUSENotFound
return
return
nil
,
errOSXFUSENotFound
}
mount_test.go
View file @
ae5da07e
...
...
@@ -26,8 +26,8 @@ type minimalFS struct {
func
(
fs
*
minimalFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
////////////////////////////////////////////////////////////////////////
...
...
samples/cachingfs/caching_fs.go
View file @
ae5da07e
...
...
@@ -82,7 +82,7 @@ type CachingFS interface {
//
func
NewCachingFS
(
lookupEntryTimeout
time
.
Duration
,
getattrTimeout
time
.
Duration
)
(
fs
CachingFS
,
err
error
)
{
getattrTimeout
time
.
Duration
)
(
CachingFS
,
error
)
{
roundUp
:=
func
(
n
fuseops
.
InodeID
)
fuseops
.
InodeID
{
return
numInodes
*
((
n
+
numInodes
-
1
)
/
numInodes
)
}
...
...
@@ -96,8 +96,7 @@ func NewCachingFS(
cfs
.
mu
=
syncutil
.
NewInvariantMutex
(
cfs
.
checkInvariants
)
fs
=
cfs
return
return
cfs
,
nil
}
const
(
...
...
@@ -262,14 +261,14 @@ func (fs *cachingFS) SetKeepCache(keep bool) {
func
(
fs
*
cachingFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
cachingFS
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -281,8 +280,7 @@ func (fs *cachingFS) LookUpInode(
case
"foo"
:
// Parent must be the root.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
id
=
fs
.
fooID
()
...
...
@@ -291,8 +289,7 @@ func (fs *cachingFS) LookUpInode(
case
"dir"
:
// Parent must be the root.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
id
=
fs
.
dirID
()
...
...
@@ -301,16 +298,14 @@ func (fs *cachingFS) LookUpInode(
case
"bar"
:
// Parent must be dir.
if
op
.
Parent
==
fuseops
.
RootInodeID
||
op
.
Parent
%
numInodes
!=
dirOffset
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
id
=
fs
.
barID
()
attrs
=
fs
.
barAttrs
()
default
:
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Fill in the response.
...
...
@@ -318,13 +313,13 @@ func (fs *cachingFS) LookUpInode(
op
.
Entry
.
Attributes
=
attrs
op
.
Entry
.
EntryExpiration
=
time
.
Now
()
.
Add
(
fs
.
lookupEntryTimeout
)
return
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
cachingFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -349,29 +344,30 @@ func (fs *cachingFS) GetInodeAttributes(
op
.
Attributes
=
attrs
op
.
AttributesExpiration
=
time
.
Now
()
.
Add
(
fs
.
getattrTimeout
)
return
return
nil
}
func
(
fs
*
cachingFS
)
OpenDir
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
return
op
*
fuseops
.
OpenDirOp
)
error
{
return
nil
}
func
(
fs
*
cachingFS
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
op
.
KeepPageCache
=
fs
.
keepPageCache
return
return
nil
}
func
(
fs
*
cachingFS
)
ReadFile
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
var
err
error
op
.
BytesRead
,
err
=
io
.
ReadFull
(
rand
.
Reader
,
op
.
Dst
)
return
return
err
}
samples/cachingfs/caching_fs_test.go
View file @
ae5da07e
...
...
@@ -83,7 +83,7 @@ func (t *cachingFSTest) statAll() (foo, dir, bar os.FileInfo) {
bar
,
err
=
os
.
Stat
(
path
.
Join
(
t
.
Dir
,
"dir/bar"
))
AssertEq
(
nil
,
err
)
return
return
foo
,
dir
,
bar
}
func
(
t
*
cachingFSTest
)
openFiles
()
(
foo
,
dir
,
bar
*
os
.
File
)
{
...
...
@@ -98,7 +98,7 @@ func (t *cachingFSTest) openFiles() (foo, dir, bar *os.File) {
bar
,
err
=
os
.
Open
(
path
.
Join
(
t
.
Dir
,
"dir/bar"
))
AssertEq
(
nil
,
err
)
return
return
foo
,
dir
,
bar
}
func
(
t
*
cachingFSTest
)
statFiles
(
...
...
@@ -114,7 +114,7 @@ func (t *cachingFSTest) statFiles(
bar
,
err
=
h
.
Stat
()
AssertEq
(
nil
,
err
)
return
return
foo
,
dir
,
bar
}
func
getInodeID
(
fi
os
.
FileInfo
)
uint64
{
...
...
samples/dynamicfs/dynamic_fs.go
View file @
ae5da07e
...
...
@@ -33,15 +33,14 @@ import (
// This implementation depends on direct IO in fuse. Without it, all read
// operations are suppressed because the kernel detects that they read beyond
// the end of the files.
func
NewDynamicFS
(
clock
timeutil
.
Clock
)
(
server
fuse
.
Server
,
err
error
)
{
func
NewDynamicFS
(
clock
timeutil
.
Clock
)
(
fuse
.
Server
,
error
)
{
createTime
:=
clock
.
Now
()
fs
:=
&
dynamicFS
{
clock
:
clock
,
createTime
:
createTime
,
fileHandles
:
make
(
map
[
fuseops
.
HandleID
]
string
),
}
server
=
fuseutil
.
NewFileSystemServer
(
fs
)
return
return
fuseutil
.
NewFileSystemServer
(
fs
),
nil
}
type
dynamicFS
struct
{
...
...
@@ -114,16 +113,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
func
findChildInode
(
name
string
,
children
[]
fuseutil
.
Dirent
)
(
inode
fuseops
.
InodeID
,
err
error
)
{
children
[]
fuseutil
.
Dirent
)
(
fuseops
.
InodeID
,
error
)
{
for
_
,
e
:=
range
children
{
if
e
.
Name
==
name
{
inode
=
e
.
Inode
return
return
e
.
Inode
,
nil
}
}
err
=
fuse
.
ENOENT
return
return
0
,
fuse
.
ENOENT
}
func
(
fs
*
dynamicFS
)
findUnusedHandle
()
fuseops
.
HandleID
{
...
...
@@ -138,69 +135,64 @@ func (fs *dynamicFS) findUnusedHandle() fuseops.HandleID {
func
(
fs
*
dynamicFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Copy over its attributes.
op
.
Attributes
=
info
.
attributes
return
return
nil
}
func
(
fs
*
dynamicFS
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// Find the info for the parent.
parentInfo
,
ok
:=
gInodeInfo
[
op
.
Parent
]
if
!
ok
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Find the child within the parent.
childInode
,
err
:=
findChildInode
(
op
.
Name
,
parentInfo
.
children
)
if
err
!=
nil
{
return
return
err
}
// Copy over information.
op
.
Entry
.
Child
=
childInode
op
.
Entry
.
Attributes
=
gInodeInfo
[
childInode
]
.
attributes
return
return
nil
}
func
(
fs
*
dynamicFS
)
OpenDir
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
// Allow opening directory.
return
return
nil
}
func
(
fs
*
dynamicFS
)
ReadDir
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
if
!
info
.
dir
{
err
=
fuse
.
EIO
return
return
fuse
.
EIO
}
entries
:=
info
.
children
// Grab the range of interest.
if
op
.
Offset
>
fuseops
.
DirOffset
(
len
(
entries
))
{
err
=
fuse
.
EIO
return
return
fuse
.
EIO
}
entries
=
entries
[
op
.
Offset
:
]
...
...
@@ -215,12 +207,12 @@ func (fs *dynamicFS) ReadDir(
op
.
BytesRead
+=
n
}
return
return
nil
}
func
(
fs
*
dynamicFS
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
var
contents
string
...
...
@@ -233,51 +225,49 @@ func (fs *dynamicFS) OpenFile(
case
weekdayInode
:
contents
=
fmt
.
Sprintf
(
"Today is %s."
,
fs
.
clock
.
Now
()
.
Weekday
())
default
:
err
=
fuse
.
EINVAL
return
return
fuse
.
EINVAL
}
handle
:=
fs
.
findUnusedHandle
()
fs
.
fileHandles
[
handle
]
=
contents
op
.
UseDirectIO
=
true
op
.
Handle
=
handle
return
return
nil
}
func
(
fs
*
dynamicFS
)
ReadFile
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
contents
,
ok
:=
fs
.
fileHandles
[
op
.
Handle
]
if
!
ok
{
log
.
Printf
(
"ReadFile: no open file handle: %d"
,
op
.
Handle
)
err
=
fuse
.
EIO
return
return
fuse
.
EIO
}
reader
:=
strings
.
NewReader
(
contents
)
var
err
error
op
.
BytesRead
,
err
=
reader
.
ReadAt
(
op
.
Dst
,
op
.
Offset
)
if
err
==
io
.
EOF
{
err
=
nil
return
nil
}
return
return
err
}
func
(
fs
*
dynamicFS
)
ReleaseFileHandle
(
ctx
context
.
Context
,
op
*
fuseops
.
ReleaseFileHandleOp
)
(
err
error
)
{
op
*
fuseops
.
ReleaseFileHandleOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
_
,
ok
:=
fs
.
fileHandles
[
op
.
Handle
]
if
!
ok
{
log
.
Printf
(
"ReleaseFileHandle: bad handle: %d"
,
op
.
Handle
)
err
=
fuse
.
EIO
return
return
fuse
.
EIO
}
delete
(
fs
.
fileHandles
,
op
.
Handle
)
return
return
nil
}
func
(
fs
*
dynamicFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
samples/errorfs/error_fs.go
View file @
ae5da07e
...
...
@@ -49,12 +49,10 @@ type FS interface {
SetError
(
t
reflect
.
Type
,
err
syscall
.
Errno
)
}
func
New
()
(
fs
FS
,
err
error
)
{
fs
=
&
errorFS
{
func
New
()
(
FS
,
error
)
{
return
&
errorFS
{
errors
:
make
(
map
[
reflect
.
Type
]
syscall
.
Errno
),
}
return
},
nil
}
type
errorFS
struct
{
...
...
@@ -95,9 +93,10 @@ func (fs *errorFS) transformError(op interface{}, err *error) bool {
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
// Figure out which inode the request is for.
...
...
@@ -111,100 +110,99 @@ func (fs *errorFS) GetInodeAttributes(
op
.
Attributes
=
fooAttrs
default
:
err
=
fmt
.
Errorf
(
"Unknown inode: %d"
,
op
.
Inode
)
return
return
fmt
.
Errorf
(
"Unknown inode: %d"
,
op
.
Inode
)
}
return
return
nil
}
func
(
fs
*
errorFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
// Is this a known inode?
if
!
(
op
.
Parent
==
fuseops
.
RootInodeID
&&
op
.
Name
==
"foo"
)
{
err
=
syscall
.
ENOENT
return
return
syscall
.
ENOENT
}
op
.
Entry
.
Child
=
fooInodeID
op
.
Entry
.
Attributes
=
fooAttrs
return
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
if
op
.
Inode
!=
fooInodeID
{
err
=
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
return
return
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
}
return
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
ReadFile
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
if
op
.
Inode
!=
fooInodeID
||
op
.
Offset
!=
0
{
err
=
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
return
return
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
}
op
.
BytesRead
=
copy
(
op
.
Dst
,
FooContents
)
return
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
OpenDir
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
if
op
.
Inode
!=
fuseops
.
RootInodeID
{
err
=
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
return
return
fmt
.
Errorf
(
"Unsupported inode ID: %d"
,
op
.
Inode
)
}
return
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
errorFS
)
ReadDir
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
var
err
error
if
fs
.
transformError
(
op
,
&
err
)
{
return
return
err
}
if
op
.
Inode
!=
fuseops
.
RootInodeID
||
op
.
Offset
!=
0
{
err
=
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
return
return
fmt
.
Errorf
(
"Unexpected request: %#v"
,
op
)
}
op
.
BytesRead
=
fuseutil
.
WriteDirent
(
...
...
@@ -216,5 +214,5 @@ func (fs *errorFS) ReadDir(
Type
:
fuseutil
.
DT_File
,
})
return
return
nil
}
samples/flushfs/flush_fs.go
View file @
ae5da07e
...
...
@@ -35,14 +35,13 @@ import (
// The directory cannot be modified.
func
NewFileSystem
(
reportFlush
func
(
string
)
error
,
reportFsync
func
(
string
)
error
)
(
server
fuse
.
Server
,
err
error
)
{
reportFsync
func
(
string
)
error
)
(
fuse
.
Server
,
error
)
{
fs
:=
&
flushFS
{
reportFlush
:
reportFlush
,
reportFsync
:
reportFsync
,
}
server
=
fuseutil
.
NewFileSystemServer
(
fs
)
return
return
fuseutil
.
NewFileSystemServer
(
fs
),
nil
}
const
(
...
...
@@ -90,25 +89,19 @@ func (fs *flushFS) barAttributes() fuseops.InodeAttributes {
}
// LOCKS_REQUIRED(fs.mu)
func
(
fs
*
flushFS
)
getAttributes
(
id
fuseops
.
InodeID
)
(
attrs
fuseops
.
InodeAttributes
,
err
error
)
{
func
(
fs
*
flushFS
)
getAttributes
(
id
fuseops
.
InodeID
)
(
fuseops
.
InodeAttributes
,
error
)
{
switch
id
{
case
fuseops
.
RootInodeID
:
attrs
=
fs
.
rootAttributes
()
return
return
fs
.
rootAttributes
(),
nil
case
fooID
:
attrs
=
fs
.
fooAttributes
()
return
return
fs
.
fooAttributes
(),
nil
case
barID
:
attrs
=
fs
.
barAttributes
()
return
return
fs
.
barAttributes
(),
nil
default
:
err
=
fuse
.
ENOENT
return
return
fuseops
.
InodeAttributes
{},
fuse
.
ENOENT
}
}
...
...
@@ -118,20 +111,19 @@ func (fs *flushFS) getAttributes(id fuseops.InodeID) (
func
(
fs
*
flushFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
func
(
fs
*
flushFS
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
// Sanity check.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Set up the entry.
...
...
@@ -149,70 +141,69 @@ func (fs *flushFS) LookUpInode(
}
default
:
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
return
return
nil
}
func
(
fs
*
flushFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
var
err
error
op
.
Attributes
,
err
=
fs
.
getAttributes
(
op
.
Inode
)
return
return
err
}
func
(
fs
*
flushFS
)
SetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
SetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
SetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
// Ignore any changes and simply return existing attributes.
var
err
error
op
.
Attributes
,
err
=
fs
.
getAttributes
(
op
.
Inode
)
return
return
err
}
func
(
fs
*
flushFS
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
// Sanity check.
if
op
.
Inode
!=
fooID
{
err
=
fuse
.
ENOSYS
return
return
fuse
.
ENOSYS
}
return
return
nil
}
func
(
fs
*
flushFS
)
ReadFile
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
// Ensure the offset is in range.
if
op
.
Offset
>
int64
(
len
(
fs
.
fooContents
))
{
return
return
nil
}
// Read what we can.
op
.
BytesRead
=
copy
(
op
.
Dst
,
fs
.
fooContents
[
op
.
Offset
:
])
return
return
nil
}
func
(
fs
*
flushFS
)
WriteFile
(
ctx
context
.
Context
,
op
*
fuseops
.
WriteFileOp
)
(
err
error
)
{
op
*
fuseops
.
WriteFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -231,32 +222,30 @@ func (fs *flushFS) WriteFile(
panic
(
fmt
.
Sprintf
(
"Unexpected short copy: %v"
,
n
))
}
return
return
nil
}
func
(
fs
*
flushFS
)
SyncFile
(
ctx
context
.
Context
,
op
*
fuseops
.
SyncFileOp
)
(
err
error
)
{
op
*
fuseops
.
SyncFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
err
=
fs
.
reportFsync
(
string
(
fs
.
fooContents
))
return
return
fs
.
reportFsync
(
string
(
fs
.
fooContents
))
}
func
(
fs
*
flushFS
)
FlushFile
(
ctx
context
.
Context
,
op
*
fuseops
.
FlushFileOp
)
(
err
error
)
{
op
*
fuseops
.
FlushFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
err
=
fs
.
reportFlush
(
string
(
fs
.
fooContents
))
return
return
fs
.
reportFlush
(
string
(
fs
.
fooContents
))
}
func
(
fs
*
flushFS
)
OpenDir
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -266,16 +255,15 @@ func (fs *flushFS) OpenDir(
case
barID
:
default
:
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
return
return
nil
}
func
(
fs
*
flushFS
)
ReadDir
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -303,21 +291,19 @@ func (fs *flushFS) ReadDir(
case
barID
:
default
:
err
=
fmt
.
Errorf
(
"Unexpected inode: %v"
,
op
.
Inode
)
return
return
fmt
.
Errorf
(
"Unexpected inode: %v"
,
op
.
Inode
)
}
// 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
return
nil
case
0
:
default
:
err
=
fmt
.
Errorf
(
"Unexpected offset: %v"
,
op
.
Offset
)
return
return
fmt
.
Errorf
(
"Unexpected offset: %v"
,
op
.
Offset
)
}
// Fill in the listing.
...
...
@@ -326,12 +312,11 @@ func (fs *flushFS) ReadDir(
// We don't support doing this in anything more than one shot.
if
n
==
0
{
err
=
fmt
.
Errorf
(
"Couldn't fit listing in %v bytes"
,
len
(
op
.
Dst
))
return
return
fmt
.
Errorf
(
"Couldn't fit listing in %v bytes"
,
len
(
op
.
Dst
))
}
op
.
BytesRead
+=
n
}
return
return
nil
}
samples/flushfs/flush_fs_test.go
View file @
ae5da07e
...
...
@@ -121,30 +121,24 @@ var isDarwin = runtime.GOOS == "darwin"
func
readReports
(
f
*
os
.
File
)
(
reports
[]
string
,
err
error
)
{
// Seek the file to the start.
_
,
err
=
f
.
Seek
(
0
,
0
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Seek: %v"
,
err
)
return
if
_
,
err
:=
f
.
Seek
(
0
,
0
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Seek: %v"
,
err
)
}
// We expect reports to end in a newline (including the final one).
reader
:=
bufio
.
NewReader
(
f
)
for
{
var
record
[]
byte
record
,
err
=
reader
.
ReadBytes
(
'\n'
)
record
,
err
:=
reader
.
ReadBytes
(
'\n'
)
if
err
==
io
.
EOF
{
if
len
(
record
)
!=
0
{
err
=
fmt
.
Errorf
(
"Unexpected record:
\n
%s"
,
hex
.
Dump
(
record
))
return
return
nil
,
fmt
.
Errorf
(
"Unexpected record:
\n
%s"
,
hex
.
Dump
(
record
))
}
err
=
nil
return
return
reports
,
nil
}
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"ReadBytes: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"ReadBytes: %v"
,
err
)
}
// Strip the newline.
...
...
@@ -153,41 +147,39 @@ func readReports(f *os.File) (reports []string, err error) {
}
// Return a copy of the current contents of t.flushes.
func
(
t
*
flushFSTest
)
getFlushes
()
(
p
[]
string
)
{
var
err
error
if
p
,
err
=
readReports
(
t
.
flushes
);
err
!=
nil
{
func
(
t
*
flushFSTest
)
getFlushes
()
[]
string
{
p
,
err
:=
readReports
(
t
.
flushes
)
if
err
!=
nil
{
panic
(
err
)
}
return
return
p
}
// Return a copy of the current contents of t.fsyncs.
func
(
t
*
flushFSTest
)
getFsyncs
()
(
p
[]
string
)
{
var
err
error
if
p
,
err
=
readReports
(
t
.
fsyncs
);
err
!=
nil
{
func
(
t
*
flushFSTest
)
getFsyncs
()
[]
string
{
p
,
err
:=
readReports
(
t
.
fsyncs
)
if
err
!=
nil
{
panic
(
err
)
}
return
return
p
}
// Like syscall.Dup2, but correctly annotates the syscall as blocking. See here
// for more info: https://github.com/golang/go/issues/10202
func
dup2
(
oldfd
int
,
newfd
int
)
(
err
error
)
{
func
dup2
(
oldfd
int
,
newfd
int
)
error
{
_
,
_
,
e1
:=
syscall
.
Syscall
(
syscall
.
SYS_DUP2
,
uintptr
(
oldfd
),
uintptr
(
newfd
),
0
)
if
e1
!=
0
{
err
=
e1
return
e1
}
return
return
nil
}
// Call msync(2) with the MS_SYNC flag on a slice previously returned by
// mmap(2).
func
msync
(
p
[]
byte
)
(
err
error
)
{
func
msync
(
p
[]
byte
)
error
{
_
,
_
,
errno
:=
unix
.
Syscall
(
unix
.
SYS_MSYNC
,
uintptr
(
unsafe
.
Pointer
(
&
p
[
0
])),
...
...
@@ -195,11 +187,10 @@ func msync(p []byte) (err error) {
unix
.
MS_SYNC
)
if
errno
!=
0
{
err
=
errno
return
return
errno
}
return
return
nil
}
////////////////////////////////////////////////////////////////////////
...
...
samples/forgetfs/forget_fs.go
View file @
ae5da07e
...
...
@@ -38,7 +38,7 @@ import (
// after we expect it to be dead. Its Check method may be used to check that
// there are no inodes with unexpected reference counts remaining, after
// unmounting.
func
NewFileSystem
()
(
fs
*
ForgetFS
)
{
func
NewFileSystem
()
*
ForgetFS
{
// Set up the actual file system.
impl
:=
&
fsImpl
{
inodes
:
map
[
fuseops
.
InodeID
]
*
inode
{
...
...
@@ -78,12 +78,10 @@ func NewFileSystem() (fs *ForgetFS) {
impl
.
mu
=
syncutil
.
NewInvariantMutex
(
impl
.
checkInvariants
)
// Set up a wrapper that exposes only certain methods.
fs
=
&
ForgetFS
{
return
&
ForgetFS
{
impl
:
impl
,
server
:
fuseutil
.
NewFileSystemServer
(
impl
),
}
return
}
////////////////////////////////////////////////////////////////////////
...
...
@@ -206,8 +204,8 @@ func (fs *fsImpl) Check() {
// Look up the inode and verify it hasn't been forgotten.
//
// LOCKS_REQUIRED(fs.mu)
func
(
fs
*
fsImpl
)
findInodeByID
(
id
fuseops
.
InodeID
)
(
in
*
inode
)
{
in
=
fs
.
inodes
[
id
]
func
(
fs
*
fsImpl
)
findInodeByID
(
id
fuseops
.
InodeID
)
*
inode
{
in
:
=
fs
.
inodes
[
id
]
if
in
==
nil
{
panic
(
fmt
.
Sprintf
(
"Unknown inode: %v"
,
id
))
}
...
...
@@ -216,7 +214,7 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
panic
(
fmt
.
Sprintf
(
"Forgotten inode: %v"
,
id
))
}
return
return
in
}
////////////////////////////////////////////////////////////////////////
...
...
@@ -225,13 +223,13 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
func
(
fs
*
fsImpl
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
func
(
fs
*
fsImpl
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -248,8 +246,7 @@ func (fs *fsImpl) LookUpInode(
childID
=
cannedID_Bar
default
:
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Look up the child.
...
...
@@ -262,12 +259,12 @@ func (fs *fsImpl) LookUpInode(
Attributes
:
child
.
attributes
,
}
return
return
nil
}
func
(
fs
*
fsImpl
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -277,12 +274,12 @@ func (fs *fsImpl) GetInodeAttributes(
// Return appropriate attributes.
op
.
Attributes
=
in
.
attributes
return
return
nil
}
func
(
fs
*
fsImpl
)
ForgetInode
(
ctx
context
.
Context
,
op
*
fuseops
.
ForgetInodeOp
)
(
err
error
)
{
op
*
fuseops
.
ForgetInodeOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -290,12 +287,12 @@ func (fs *fsImpl) ForgetInode(
in
:=
fs
.
findInodeByID
(
op
.
Inode
)
in
.
DecrementLookupCount
(
op
.
N
)
return
return
nil
}
func
(
fs
*
fsImpl
)
MkDir
(
ctx
context
.
Context
,
op
*
fuseops
.
MkDirOp
)
(
err
error
)
{
op
*
fuseops
.
MkDirOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -322,12 +319,12 @@ func (fs *fsImpl) MkDir(
Attributes
:
child
.
attributes
,
}
return
return
nil
}
func
(
fs
*
fsImpl
)
CreateFile
(
ctx
context
.
Context
,
op
*
fuseops
.
CreateFileOp
)
(
err
error
)
{
op
*
fuseops
.
CreateFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
...
...
@@ -354,31 +351,31 @@ func (fs *fsImpl) CreateFile(
Attributes
:
child
.
attributes
,
}
return
return
nil
}
func
(
fs
*
fsImpl
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
// Verify that the inode has not been forgotten.
_
=
fs
.
findInodeByID
(
op
.
Inode
)
return
return
nil
}
func
(
fs
*
fsImpl
)
OpenDir
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
// Verify that the inode has not been forgotten.
_
=
fs
.
findInodeByID
(
op
.
Inode
)
return
return
nil
}
func
(
fs
*
fsImpl
)
Destroy
()
{
...
...
samples/hellofs/hello_fs.go
View file @
ae5da07e
...
...
@@ -33,13 +33,12 @@ import (
// world
//
// Each file contains the string "Hello, world!".
func
NewHelloFS
(
clock
timeutil
.
Clock
)
(
server
fuse
.
Server
,
err
error
)
{
func
NewHelloFS
(
clock
timeutil
.
Clock
)
(
fuse
.
Server
,
error
)
{
fs
:=
&
helloFS
{
Clock
:
clock
,
}
server
=
fuseutil
.
NewFileSystemServer
(
fs
)
return
return
fuseutil
.
NewFileSystemServer
(
fs
),
nil
}
type
helloFS
struct
{
...
...
@@ -128,16 +127,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
func
findChildInode
(
name
string
,
children
[]
fuseutil
.
Dirent
)
(
inode
fuseops
.
InodeID
,
err
error
)
{
children
[]
fuseutil
.
Dirent
)
(
fuseops
.
InodeID
,
error
)
{
for
_
,
e
:=
range
children
{
if
e
.
Name
==
name
{
inode
=
e
.
Inode
return
return
e
.
Inode
,
nil
}
}
err
=
fuse
.
ENOENT
return
return
0
,
fuse
.
ENOENT
}
func
(
fs
*
helloFS
)
patchAttributes
(
...
...
@@ -150,24 +147,23 @@ func (fs *helloFS) patchAttributes(
func
(
fs
*
helloFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
func
(
fs
*
helloFS
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// Find the info for the parent.
parentInfo
,
ok
:=
gInodeInfo
[
op
.
Parent
]
if
!
ok
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Find the child within the parent.
childInode
,
err
:=
findChildInode
(
op
.
Name
,
parentInfo
.
children
)
if
err
!=
nil
{
return
return
err
}
// Copy over information.
...
...
@@ -177,17 +173,16 @@ func (fs *helloFS) LookUpInode(
// Patch attributes.
fs
.
patchAttributes
(
&
op
.
Entry
.
Attributes
)
return
return
nil
}
func
(
fs
*
helloFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Copy over its attributes.
...
...
@@ -196,37 +191,34 @@ func (fs *helloFS) GetInodeAttributes(
// Patch attributes.
fs
.
patchAttributes
(
&
op
.
Attributes
)
return
return
nil
}
func
(
fs
*
helloFS
)
OpenDir
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenDirOp
)
(
err
error
)
{
op
*
fuseops
.
OpenDirOp
)
error
{
// Allow opening any directory.
return
return
nil
}
func
(
fs
*
helloFS
)
ReadDir
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadDirOp
)
(
err
error
)
{
op
*
fuseops
.
ReadDirOp
)
error
{
// Find the info for this inode.
info
,
ok
:=
gInodeInfo
[
op
.
Inode
]
if
!
ok
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
if
!
info
.
dir
{
err
=
fuse
.
EIO
return
return
fuse
.
EIO
}
entries
:=
info
.
children
// Grab the range of interest.
if
op
.
Offset
>
fuseops
.
DirOffset
(
len
(
entries
))
{
err
=
fuse
.
EIO
return
return
fuse
.
EIO
}
entries
=
entries
[
op
.
Offset
:
]
...
...
@@ -241,28 +233,29 @@ func (fs *helloFS) ReadDir(
op
.
BytesRead
+=
n
}
return
return
nil
}
func
(
fs
*
helloFS
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
op
*
fuseops
.
OpenFileOp
)
error
{
// Allow opening any file.
return
return
nil
}
func
(
fs
*
helloFS
)
ReadFile
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
// Let io.ReaderAt deal with the semantics.
reader
:=
strings
.
NewReader
(
"Hello, world!"
)
var
err
error
op
.
BytesRead
,
err
=
reader
.
ReadAt
(
op
.
Dst
,
op
.
Offset
)
// Special case: FUSE doesn't expect us to return io.EOF.
if
err
==
io
.
EOF
{
err
=
nil
return
nil
}
return
return
err
}
samples/in_process.go
View file @
ae5da07e
...
...
@@ -75,7 +75,7 @@ func (t *SampleTest) SetUp(ti *ogletest.TestInfo) {
func
(
t
*
SampleTest
)
initialize
(
ctx
context
.
Context
,
server
fuse
.
Server
,
config
*
fuse
.
MountConfig
)
(
err
error
)
{
config
*
fuse
.
MountConfig
)
error
{
// Initialize the context used by the test.
t
.
Ctx
=
ctx
...
...
@@ -89,20 +89,19 @@ func (t *SampleTest) initialize(
t
.
Clock
.
SetTime
(
time
.
Date
(
2012
,
8
,
15
,
22
,
56
,
0
,
0
,
time
.
Local
))
// Set up a temporary directory.
var
err
error
t
.
Dir
,
err
=
ioutil
.
TempDir
(
""
,
"sample_test"
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
return
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
}
// Mount the file system.
t
.
mfs
,
err
=
fuse
.
Mount
(
t
.
Dir
,
server
,
config
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Mount: %v"
,
err
)
return
return
fmt
.
Errorf
(
"Mount: %v"
,
err
)
}
return
return
nil
}
// Unmount the file system and clean up. Panics on error.
...
...
@@ -126,28 +125,23 @@ func (t *SampleTest) destroy() (err error) {
// Was the file system mounted?
if
t
.
mfs
==
nil
{
return
return
nil
}
// Unmount the file system.
err
=
unmount
(
t
.
Dir
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"unmount: %v"
,
err
)
return
if
err
:=
unmount
(
t
.
Dir
);
err
!=
nil
{
return
fmt
.
Errorf
(
"unmount: %v"
,
err
)
}
// Unlink the mount point.
if
err
=
os
.
Remove
(
t
.
Dir
);
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Unlinking mount point: %v"
,
err
)
return
if
err
:=
os
.
Remove
(
t
.
Dir
);
err
!=
nil
{
return
fmt
.
Errorf
(
"Unlinking mount point: %v"
,
err
)
}
// Join the file system.
err
=
t
.
mfs
.
Join
(
t
.
Ctx
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"mfs.Join: %v"
,
err
)
return
if
err
:=
t
.
mfs
.
Join
(
t
.
Ctx
);
err
!=
nil
{
return
fmt
.
Errorf
(
"mfs.Join: %v"
,
err
)
}
return
return
nil
}
samples/interruptfs/interrupt_fs.go
View file @
ae5da07e
...
...
@@ -56,13 +56,11 @@ type InterruptFS struct {
flushReceived
chan
struct
{}
}
func
New
()
(
fs
*
InterruptFS
)
{
fs
=
&
InterruptFS
{
func
New
()
*
InterruptFS
{
return
&
InterruptFS
{
readReceived
:
make
(
chan
struct
{}),
flushReceived
:
make
(
chan
struct
{}),
}
return
}
////////////////////////////////////////////////////////////////////////
...
...
@@ -101,35 +99,33 @@ func (fs *InterruptFS) EnableFlushBlocking() {
func
(
fs
*
InterruptFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
op
*
fuseops
.
StatFSOp
)
error
{
return
nil
}
func
(
fs
*
InterruptFS
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// We support only one parent.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fmt
.
Errorf
(
"Unexpected parent: %v"
,
op
.
Parent
)
return
return
fmt
.
Errorf
(
"Unexpected parent: %v"
,
op
.
Parent
)
}
// We support only one name.
if
op
.
Name
!=
"foo"
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
// Fill in the response.
op
.
Entry
.
Child
=
fooID
op
.
Entry
.
Attributes
=
fooAttrs
return
return
nil
}
func
(
fs
*
InterruptFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
switch
op
.
Inode
{
case
fuseops
.
RootInodeID
:
op
.
Attributes
=
rootAttrs
...
...
@@ -138,22 +134,21 @@ func (fs *InterruptFS) GetInodeAttributes(
op
.
Attributes
=
fooAttrs
default
:
err
=
fmt
.
Errorf
(
"Unexpected inode ID: %v"
,
op
.
Inode
)
return
return
fmt
.
Errorf
(
"Unexpected inode ID: %v"
,
op
.
Inode
)
}
return
return
nil
}
func
(
fs
*
InterruptFS
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
return
op
*
fuseops
.
OpenFileOp
)
error
{
return
nil
}
func
(
fs
*
InterruptFS
)
ReadFile
(
ctx
context
.
Context
,
op
*
fuseops
.
ReadFileOp
)
(
err
error
)
{
op
*
fuseops
.
ReadFileOp
)
error
{
fs
.
mu
.
Lock
()
shouldBlock
:=
fs
.
blockForReads
...
...
@@ -173,15 +168,15 @@ func (fs *InterruptFS) ReadFile(
}
<-
done
err
=
ctx
.
Err
()
return
ctx
.
Err
()
}
return
return
nil
}
func
(
fs
*
InterruptFS
)
FlushFile
(
ctx
context
.
Context
,
op
*
fuseops
.
FlushFileOp
)
(
err
error
)
{
op
*
fuseops
.
FlushFileOp
)
error
{
fs
.
mu
.
Lock
()
shouldBlock
:=
fs
.
blockForFlushes
...
...
@@ -201,8 +196,8 @@ func (fs *InterruptFS) FlushFile(
}
<-
done
err
=
ctx
.
Err
()
return
ctx
.
Err
()
}
return
return
nil
}
samples/memfs/inode.go
View file @
ae5da07e
...
...
@@ -73,20 +73,17 @@ type inode struct {
// Create a new inode with the supplied attributes, which need not contain
// time-related information (the inode object will take care of that).
func
newInode
(
attrs
fuseops
.
InodeAttributes
)
(
in
*
inode
)
{
func
newInode
(
attrs
fuseops
.
InodeAttributes
)
*
inode
{
// Update time info.
now
:=
time
.
Now
()
attrs
.
Mtime
=
now
attrs
.
Crtime
=
now
// Create the object.
in
=
&
inode
{
return
&
inode
{
attrs
:
attrs
,
xattrs
:
make
(
map
[
string
][]
byte
),
}
return
}
func
(
in
*
inode
)
CheckInvariants
()
{
...
...
@@ -168,12 +165,11 @@ func (in *inode) findChild(name string) (i int, ok bool) {
var
e
fuseutil
.
Dirent
for
i
,
e
=
range
in
.
entries
{
if
e
.
Name
==
name
{
ok
=
true
return
return
i
,
true
}
}
return
return
0
,
false
}
////////////////////////////////////////////////////////////////////////
...
...
@@ -183,14 +179,15 @@ func (in *inode) findChild(name string) (i int, ok bool) {
// Return the number of children of the directory.
//
// REQUIRES: in.isDir()
func
(
in
*
inode
)
Len
()
(
n
int
)
{
func
(
in
*
inode
)
Len
()
int
{
var
n
int
for
_
,
e
:=
range
in
.
entries
{
if
e
.
Type
!=
fuseutil
.
DT_Unknown
{
n
++
}
}
return
return
n
}
// Find an entry for the given child name and return its inode ID.
...
...
@@ -206,7 +203,7 @@ func (in *inode) LookUpChild(name string) (
typ
=
in
.
entries
[
index
]
.
Type
}
return
return
id
,
typ
,
ok
}
// Add an entry for a child.
...
...
@@ -272,11 +269,12 @@ func (in *inode) RemoveChild(name string) {
// Serve a ReadDir request.
//
// REQUIRES: in.isDir()
func
(
in
*
inode
)
ReadDir
(
p
[]
byte
,
offset
int
)
(
n
int
)
{
func
(
in
*
inode
)
ReadDir
(
p
[]
byte
,
offset
int
)
int
{
if
!
in
.
isDir
()
{
panic
(
"ReadDir called on non-directory."
)
}
var
n
int
for
i
:=
offset
;
i
<
len
(
in
.
entries
);
i
++
{
e
:=
in
.
entries
[
i
]
...
...
@@ -293,36 +291,35 @@ func (in *inode) ReadDir(p []byte, offset int) (n int) {
n
+=
tmp
}
return
return
n
}
// Read from the file's contents. See documentation for ioutil.ReaderAt.
//
// REQUIRES: in.isFile()
func
(
in
*
inode
)
ReadAt
(
p
[]
byte
,
off
int64
)
(
n
int
,
err
error
)
{
func
(
in
*
inode
)
ReadAt
(
p
[]
byte
,
off
int64
)
(
int
,
error
)
{
if
!
in
.
isFile
()
{
panic
(
"ReadAt called on non-file."
)
}
// Ensure the offset is in range.
if
off
>
int64
(
len
(
in
.
contents
))
{
err
=
io
.
EOF
return
return
0
,
io
.
EOF
}
// Read what we can.
n
=
copy
(
p
,
in
.
contents
[
off
:
])
n
:
=
copy
(
p
,
in
.
contents
[
off
:
])
if
n
<
len
(
p
)
{
err
=
io
.
EOF
return
n
,
io
.
EOF
}
return
return
n
,
nil
}
// Write to the file's contents. See documentation for ioutil.WriterAt.
//
// REQUIRES: in.isFile()
func
(
in
*
inode
)
WriteAt
(
p
[]
byte
,
off
int64
)
(
n
int
,
err
error
)
{
func
(
in
*
inode
)
WriteAt
(
p
[]
byte
,
off
int64
)
(
int
,
error
)
{
if
!
in
.
isFile
()
{
panic
(
"WriteAt called on non-file."
)
}
...
...
@@ -339,14 +336,14 @@ func (in *inode) WriteAt(p []byte, off int64) (n int, err error) {
}
// Copy in the data.
n
=
copy
(
in
.
contents
[
off
:
],
p
)
n
:
=
copy
(
in
.
contents
[
off
:
],
p
)
// Sanity check.
if
n
!=
len
(
p
)
{
panic
(
fmt
.
Sprintf
(
"Unexpected short copy: %v"
,
n
))
}
return
return
n
,
nil
}
// Update attributes from non-nil parameters.
...
...
@@ -384,17 +381,15 @@ func (in *inode) SetAttributes(
}
}
func
(
in
*
inode
)
Fallocate
(
mode
uint32
,
offset
uint64
,
length
uint64
)
(
err
error
)
{
if
mode
==
0
{
func
(
in
*
inode
)
Fallocate
(
mode
uint32
,
offset
uint64
,
length
uint64
)
error
{
if
mode
!=
0
{
return
fuse
.
ENOSYS
}
newSize
:=
int
(
offset
+
length
)
if
newSize
>
len
(
in
.
contents
)
{
padding
:=
make
([]
byte
,
newSize
-
len
(
in
.
contents
))
in
.
contents
=
append
(
in
.
contents
,
padding
...
)
in
.
attrs
.
Size
=
offset
+
length
}
}
else
{
err
=
fuse
.
ENOSYS
}
return
return
nil
}
samples/memfs/memfs.go
View file @
ae5da07e
This diff is collapsed.
Click to expand it.
samples/memfs/posix_test.go
View file @
ae5da07e
...
...
@@ -39,8 +39,7 @@ func TestPosix(t *testing.T) { RunTests(t) }
func
getFileOffset
(
f
*
os
.
File
)
(
offset
int64
,
err
error
)
{
const
relativeToCurrent
=
1
offset
,
err
=
f
.
Seek
(
0
,
relativeToCurrent
)
return
return
f
.
Seek
(
0
,
relativeToCurrent
)
}
////////////////////////////////////////////////////////////////////////
...
...
samples/mount_sample/mount.go
View file @
ae5da07e
...
...
@@ -42,11 +42,10 @@ var fFsyncError = flag.Int("flushfs.fsync_error", 0, "")
var
fReadOnly
=
flag
.
Bool
(
"read_only"
,
false
,
"Mount in read-only mode."
)
var
fDebug
=
flag
.
Bool
(
"debug"
,
false
,
"Enable debug logging."
)
func
makeFlushFS
()
(
server
fuse
.
Server
,
err
error
)
{
func
makeFlushFS
()
(
fuse
.
Server
,
error
)
{
// Check the flags.
if
*
fFlushesFile
==
0
||
*
fFsyncsFile
==
0
{
err
=
fmt
.
Errorf
(
"You must set the flushfs flags."
)
return
return
nil
,
fmt
.
Errorf
(
"You must set the flushfs flags."
)
}
// Set up the files.
...
...
@@ -67,18 +66,15 @@ func makeFlushFS() (server fuse.Server, err error) {
// Report flushes and fsyncs by writing the contents followed by a newline.
report
:=
func
(
f
*
os
.
File
,
outErr
error
)
func
(
string
)
error
{
return
func
(
s
string
)
(
err
error
)
{
return
func
(
s
string
)
error
{
buf
:=
[]
byte
(
s
)
buf
=
append
(
buf
,
'\n'
)
_
,
err
=
f
.
Write
(
buf
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Write: %v"
,
err
)
return
if
_
,
err
:=
f
.
Write
(
buf
);
err
!=
nil
{
return
fmt
.
Errorf
(
"Write: %v"
,
err
)
}
err
=
outErr
return
return
outErr
}
}
...
...
@@ -86,31 +82,25 @@ func makeFlushFS() (server fuse.Server, err error) {
reportFsync
:=
report
(
fsyncs
,
fsyncErr
)
// Create the file system.
server
,
err
=
flushfs
.
NewFileSystem
(
reportFlush
,
reportFsync
)
return
return
flushfs
.
NewFileSystem
(
reportFlush
,
reportFsync
)
}
func
makeFS
()
(
server
fuse
.
Server
,
err
error
)
{
func
makeFS
()
(
fuse
.
Server
,
error
)
{
switch
*
fType
{
default
:
err
=
fmt
.
Errorf
(
"Unknown FS type: %v"
,
*
fType
)
return
nil
,
fmt
.
Errorf
(
"Unknown FS type: %v"
,
*
fType
)
case
"flushfs"
:
server
,
err
=
makeFlushFS
()
return
makeFlushFS
()
}
return
}
func
getReadyFile
()
(
f
*
os
.
File
,
err
error
)
{
func
getReadyFile
()
(
*
os
.
File
,
error
)
{
if
*
fReadyFile
==
0
{
err
=
errors
.
New
(
"You must set --ready_file."
)
return
return
nil
,
errors
.
New
(
"You must set --ready_file."
)
}
f
=
os
.
NewFile
(
uintptr
(
*
fReadyFile
),
"(ready file)"
)
return
return
os
.
NewFile
(
uintptr
(
*
fReadyFile
),
"(ready file)"
),
nil
}
func
main
()
{
...
...
samples/statfs/statfs.go
View file @
ae5da07e
...
...
@@ -47,15 +47,13 @@ type FS interface {
MostRecentWriteSize
()
int
}
func
New
()
(
fs
FS
)
{
fs
=
&
statFS
{
func
New
()
FS
{
return
&
statFS
{
cannedStatResponse
:
fuseops
.
InodeAttributes
{
Mode
:
0666
,
},
mostRecentWriteSize
:
-
1
,
}
return
}
const
childInodeID
=
fuseops
.
RootInodeID
+
1
...
...
@@ -118,32 +116,31 @@ func (fs *statFS) MostRecentWriteSize() int {
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
statFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
op
*
fuseops
.
StatFSOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
*
op
=
fs
.
cannedResponse
return
return
nil
}
func
(
fs
*
statFS
)
LookUpInode
(
ctx
context
.
Context
,
op
*
fuseops
.
LookUpInodeOp
)
(
err
error
)
{
op
*
fuseops
.
LookUpInodeOp
)
error
{
// Only the root has children.
if
op
.
Parent
!=
fuseops
.
RootInodeID
{
err
=
fuse
.
ENOENT
return
return
fuse
.
ENOENT
}
op
.
Entry
.
Child
=
childInodeID
op
.
Entry
.
Attributes
=
fs
.
fileAttrs
()
return
return
nil
}
func
(
fs
*
statFS
)
GetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
GetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
GetInodeAttributesOp
)
error
{
switch
op
.
Inode
{
case
fuseops
.
RootInodeID
:
op
.
Attributes
=
dirAttrs
()
...
...
@@ -152,32 +149,32 @@ func (fs *statFS) GetInodeAttributes(
op
.
Attributes
=
fs
.
fileAttrs
()
default
:
err
=
fuse
.
ENOENT
return
fuse
.
ENOENT
}
return
return
nil
}
func
(
fs
*
statFS
)
SetInodeAttributes
(
ctx
context
.
Context
,
op
*
fuseops
.
SetInodeAttributesOp
)
(
err
error
)
{
op
*
fuseops
.
SetInodeAttributesOp
)
error
{
// Ignore calls to truncate existing files when opening.
return
return
nil
}
func
(
fs
*
statFS
)
OpenFile
(
ctx
context
.
Context
,
op
*
fuseops
.
OpenFileOp
)
(
err
error
)
{
return
op
*
fuseops
.
OpenFileOp
)
error
{
return
nil
}
// LOCKS_EXCLUDED(fs.mu)
func
(
fs
*
statFS
)
WriteFile
(
ctx
context
.
Context
,
op
*
fuseops
.
WriteFileOp
)
(
err
error
)
{
op
*
fuseops
.
WriteFileOp
)
error
{
fs
.
mu
.
Lock
()
defer
fs
.
mu
.
Unlock
()
fs
.
mostRecentWriteSize
=
len
(
op
.
Data
)
return
return
nil
}
samples/statfs/statfs_darwin_test.go
View file @
ae5da07e
...
...
@@ -35,7 +35,7 @@ var gDfOutputRegexp = regexp.MustCompile(`^\S+\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s+
// Helpers
////////////////////////////////////////////////////////////////////////
func
convertName
(
in
[]
int8
)
(
s
string
)
{
func
convertName
(
in
[]
int8
)
string
{
var
tmp
[]
byte
for
_
,
v
:=
range
in
{
if
v
==
0
{
...
...
@@ -45,8 +45,7 @@ func convertName(in []int8) (s string) {
tmp
=
append
(
tmp
,
byte
(
v
))
}
s
=
string
(
tmp
)
return
return
string
(
tmp
)
}
////////////////////////////////////////////////////////////////////////
...
...
samples/statfs/statfs_test.go
View file @
ae5da07e
...
...
@@ -53,7 +53,7 @@ func df(dir string) (capacity, used, available uint64, err error) {
output
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
// Scrape it.
...
...
@@ -65,23 +65,22 @@ func df(dir string) (capacity, used, available uint64, err error) {
submatches
:=
gDfOutputRegexp
.
FindSubmatch
(
line
)
if
submatches
==
nil
{
err
=
fmt
.
Errorf
(
"Unable to parse line: %q"
,
line
)
return
return
0
,
0
,
0
,
fmt
.
Errorf
(
"Unable to parse line: %q"
,
line
)
}
capacity
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
1
]),
10
,
64
)
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
used
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
2
]),
10
,
64
)
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
available
,
err
=
strconv
.
ParseUint
(
string
(
submatches
[
3
]),
10
,
64
)
if
err
!=
nil
{
return
return
0
,
0
,
0
,
err
}
// Scale appropriately based on the BLOCKSIZE set above.
...
...
@@ -89,11 +88,10 @@ func df(dir string) (capacity, used, available uint64, err error) {
used
*=
1024
available
*=
1024
return
return
capacity
,
used
,
available
,
nil
}
err
=
fmt
.
Errorf
(
"Unable to parse df output:
\n
%s"
,
output
)
return
return
0
,
0
,
0
,
fmt
.
Errorf
(
"Unable to parse df output:
\n
%s"
,
output
)
}
////////////////////////////////////////////////////////////////////////
...
...
samples/subprocess.go
View file @
ae5da07e
...
...
@@ -80,23 +80,21 @@ var getToolContents_Err error
var
getToolContents_Once
sync
.
Once
// Implementation detail of getToolPath.
func
getToolContentsImpl
()
(
contents
[]
byte
,
err
error
)
{
func
getToolContentsImpl
()
(
[]
byte
,
error
)
{
// Fast path: has the user set the flag?
if
*
fToolPath
!=
""
{
contents
,
err
=
ioutil
.
ReadFile
(
*
fToolPath
)
contents
,
err
:
=
ioutil
.
ReadFile
(
*
fToolPath
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Reading mount_sample contents: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"Reading mount_sample contents: %v"
,
err
)
}
return
return
contents
,
err
}
// Create a temporary directory into which we will compile the tool.
tempDir
,
err
:=
ioutil
.
TempDir
(
""
,
"sample_test"
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
}
toolPath
:=
path
.
Join
(
tempDir
,
"mount_sample"
)
...
...
@@ -114,34 +112,30 @@ func getToolContentsImpl() (contents []byte, err error) {
output
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
return
nil
,
fmt
.
Errorf
(
"mount_sample exited with %v, output:
\n
%s"
,
err
,
string
(
output
))
return
}
// Slurp the tool contents.
contents
,
err
=
ioutil
.
ReadFile
(
toolPath
)
contents
,
err
:
=
ioutil
.
ReadFile
(
toolPath
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"ReadFile: %v"
,
err
)
return
return
nil
,
fmt
.
Errorf
(
"ReadFile: %v"
,
err
)
}
return
return
contents
,
nil
}
// Build the mount_sample tool if it has not yet been built for this process.
// Return its contents.
func
getToolContents
()
(
contents
[]
byte
,
err
error
)
{
func
getToolContents
()
(
[]
byte
,
error
)
{
// Get hold of the binary contents, if we haven't yet.
getToolContents_Once
.
Do
(
func
()
{
getToolContents_Contents
,
getToolContents_Err
=
getToolContentsImpl
()
})
contents
,
err
=
getToolContents_Contents
,
getToolContents_Err
return
return
getToolContents_Contents
,
getToolContents_Err
}
func
waitForMountSample
(
...
...
@@ -184,29 +178,27 @@ func waitForReady(readyReader *os.File, c chan<- struct{}) {
}
// Like SetUp, but doens't panic.
func
(
t
*
SubprocessTest
)
initialize
(
ctx
context
.
Context
)
(
err
error
)
{
func
(
t
*
SubprocessTest
)
initialize
(
ctx
context
.
Context
)
error
{
// Initialize the context.
t
.
Ctx
=
ctx
// Set up a temporary directory.
var
err
error
t
.
Dir
,
err
=
ioutil
.
TempDir
(
""
,
"sample_test"
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
return
return
fmt
.
Errorf
(
"TempDir: %v"
,
err
)
}
// Build/read the mount_sample tool.
toolContents
,
err
:=
getToolContents
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"getTooltoolContents: %v"
,
err
)
return
return
fmt
.
Errorf
(
"getTooltoolContents: %v"
,
err
)
}
// Create a temporary file to hold the contents of the tool.
toolFile
,
err
:=
ioutil
.
TempFile
(
""
,
"sample_test"
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
return
return
fmt
.
Errorf
(
"TempFile: %v"
,
err
)
}
defer
toolFile
.
Close
()
...
...
@@ -217,21 +209,18 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
// Write out the tool contents and make them executable.
if
_
,
err
=
toolFile
.
Write
(
toolContents
);
err
!=
nil
{
err
=
fmt
.
Errorf
(
"toolFile.Write: %v"
,
err
)
return
return
fmt
.
Errorf
(
"toolFile.Write: %v"
,
err
)
}
if
err
=
toolFile
.
Chmod
(
0500
);
err
!=
nil
{
err
=
fmt
.
Errorf
(
"toolFile.Chmod: %v"
,
err
)
return
return
fmt
.
Errorf
(
"toolFile.Chmod: %v"
,
err
)
}
// Close the tool file to prevent "text file busy" errors below.
err
=
toolFile
.
Close
()
toolFile
=
nil
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"toolFile.Close: %v"
,
err
)
return
return
fmt
.
Errorf
(
"toolFile.Close: %v"
,
err
)
}
// Set up basic args for the subprocess.
...
...
@@ -247,8 +236,7 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
// Set up a pipe for the "ready" status.
readyReader
,
readyWriter
,
err
:=
os
.
Pipe
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Pipe: %v"
,
err
)
return
return
fmt
.
Errorf
(
"Pipe: %v"
,
err
)
}
defer
readyReader
.
Close
()
...
...
@@ -280,9 +268,8 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
}
// Start the command.
if
err
=
mountCmd
.
Start
();
err
!=
nil
{
err
=
fmt
.
Errorf
(
"mountCmd.Start: %v"
,
err
)
return
if
err
:=
mountCmd
.
Start
();
err
!=
nil
{
return
fmt
.
Errorf
(
"mountCmd.Start: %v"
,
err
)
}
// Launch a goroutine that waits for it and returns its status.
...
...
@@ -296,14 +283,14 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
select
{
case
<-
readyChan
:
case
err
=
<-
mountSampleErr
:
return
case
err
:
=
<-
mountSampleErr
:
return
err
}
// TearDown is no responsible for joining.
t
.
mountSampleErr
=
mountSampleErr
return
return
nil
}
// Unmount the file system and clean up. Panics on error.
...
...
@@ -329,7 +316,7 @@ func (t *SubprocessTest) destroy() (err error) {
// If we didn't try to mount the file system, there's nothing further to do.
if
t
.
mountSampleErr
==
nil
{
return
return
nil
}
// In the background, initiate an unmount.
...
...
@@ -358,9 +345,9 @@ func (t *SubprocessTest) destroy() (err error) {
}()
// Wait for the subprocess.
if
err
=
<-
t
.
mountSampleErr
;
err
!=
nil
{
return
if
err
:
=
<-
t
.
mountSampleErr
;
err
!=
nil
{
return
err
}
return
return
nil
}
samples/unmount.go
View file @
ae5da07e
...
...
@@ -27,12 +27,12 @@ import (
// "resource busy" errors, which happen from time to time on OS X (due to weird
// requests from the Finder) and when tests don't or can't synchronize all
// events.
func
unmount
(
dir
string
)
(
err
error
)
{
func
unmount
(
dir
string
)
error
{
delay
:=
10
*
time
.
Millisecond
for
{
err
=
fuse
.
Unmount
(
dir
)
err
:
=
fuse
.
Unmount
(
dir
)
if
err
==
nil
{
return
return
err
}
if
strings
.
Contains
(
err
.
Error
(),
"resource busy"
)
{
...
...
@@ -42,7 +42,6 @@ func unmount(dir string) (err error) {
continue
}
err
=
fmt
.
Errorf
(
"Unmount: %v"
,
err
)
return
return
fmt
.
Errorf
(
"Unmount: %v"
,
err
)
}
}
unmount_linux.go
View file @
ae5da07e
...
...
@@ -6,18 +6,17 @@ import (
"os/exec"
)
func
unmount
(
dir
string
)
(
err
error
)
{
func
unmount
(
dir
string
)
error
{
// Call fusermount.
cmd
:=
exec
.
Command
(
"fusermount"
,
"-u"
,
dir
)
output
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
if
len
(
output
)
>
0
{
output
=
bytes
.
TrimRight
(
output
,
"
\n
"
)
err
=
fmt
.
Errorf
(
"%v: %s"
,
err
,
output
)
return
fmt
.
Errorf
(
"%v: %s"
,
err
,
output
)
}
return
return
err
}
return
return
nil
}
unmount_std.go
View file @
ae5da07e
...
...
@@ -7,12 +7,10 @@ import (
"syscall"
)
func
unmount
(
dir
string
)
(
err
error
)
{
err
=
syscall
.
Unmount
(
dir
,
0
)
if
err
!=
nil
{
err
=
&
os
.
PathError
{
Op
:
"unmount"
,
Path
:
dir
,
Err
:
err
}
return
func
unmount
(
dir
string
)
error
{
if
err
:=
syscall
.
Unmount
(
dir
,
0
);
err
!=
nil
{
return
&
os
.
PathError
{
Op
:
"unmount"
,
Path
:
dir
,
Err
:
err
}
}
return
return
nil
}
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