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
652a72aa
Commit
652a72aa
authored
Feb 29, 2016
by
Aaron Jacobs
Browse files
Options
Browse Files
Download
Plain Diff
Return better errors from Mount, instead of dumping them to stderr.
For googlecloudplatform/gcsfuse#161.
parents
608feace
2c0c70f4
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
150 additions
and
53 deletions
+150
-53
mount_linux.go
mount_linux.go
+8
-53
mount_test.go
mount_test.go
+142
-0
No files found.
mount_linux.go
View file @
652a72aa
package
fuse
package
fuse
import
(
import
(
"b
ufio
"
"b
ytes
"
"fmt"
"fmt"
"io"
"log"
"net"
"net"
"os"
"os"
"os/exec"
"os/exec"
"sync"
"syscall"
"syscall"
)
)
func
lineLogger
(
wg
*
sync
.
WaitGroup
,
prefix
string
,
r
io
.
ReadCloser
)
{
defer
wg
.
Done
()
scanner
:=
bufio
.
NewScanner
(
r
)
for
scanner
.
Scan
()
{
switch
line
:=
scanner
.
Text
();
line
{
case
`fusermount: failed to open /etc/fuse.conf: Permission denied`
:
// Silence this particular message, it occurs way too
// commonly and isn't very relevant to whether the mount
// succeeds or not.
continue
default
:
log
.
Printf
(
"%s: %s"
,
prefix
,
line
)
}
}
if
err
:=
scanner
.
Err
();
err
!=
nil
{
log
.
Printf
(
"%s, error reading: %v"
,
prefix
,
err
)
}
}
// Begin the process of mounting at the given directory, returning a connection
// Begin the process of mounting at the given directory, returning a connection
// to the kernel. Mounting continues in the background, and is complete when an
// to the kernel. Mounting continues in the background, and is complete when an
// error is written to the supplied channel. The file system may need to
// error is written to the supplied channel. The file system may need to
...
@@ -57,7 +34,9 @@ func mount(
...
@@ -57,7 +34,9 @@ func mount(
readFile
:=
os
.
NewFile
(
uintptr
(
fds
[
1
]),
"fusermount-parent-reads"
)
readFile
:=
os
.
NewFile
(
uintptr
(
fds
[
1
]),
"fusermount-parent-reads"
)
defer
readFile
.
Close
()
defer
readFile
.
Close
()
// Start fusermount, passing it pipes for stdout and stderr.
// Start fusermount, passing it a buffer in which to write stderr.
var
stderr
bytes
.
Buffer
cmd
:=
exec
.
Command
(
cmd
:=
exec
.
Command
(
"fusermount"
,
"fusermount"
,
"-o"
,
cfg
.
toOptionsString
(),
"-o"
,
cfg
.
toOptionsString
(),
...
@@ -67,36 +46,12 @@ func mount(
...
@@ -67,36 +46,12 @@ func mount(
cmd
.
Env
=
append
(
os
.
Environ
(),
"_FUSE_COMMFD=3"
)
cmd
.
Env
=
append
(
os
.
Environ
(),
"_FUSE_COMMFD=3"
)
cmd
.
ExtraFiles
=
[]
*
os
.
File
{
writeFile
}
cmd
.
ExtraFiles
=
[]
*
os
.
File
{
writeFile
}
cmd
.
Stderr
=
&
stderr
stdout
,
err
:=
cmd
.
StdoutPipe
()
// Run the command.
if
err
!=
nil
{
err
=
cmd
.
Run
()
err
=
fmt
.
Errorf
(
"StdoutPipe: %v"
,
err
)
return
}
stderr
,
err
:=
cmd
.
StderrPipe
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"StderrPipe: %v"
,
err
)
return
}
err
=
cmd
.
Start
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Starting fusermount: %v"
,
err
)
return
}
// Log fusermount output until it closes stdout and stderr.
var
wg
sync
.
WaitGroup
wg
.
Add
(
2
)
go
lineLogger
(
&
wg
,
"mount helper output"
,
stdout
)
go
lineLogger
(
&
wg
,
"mount helper error"
,
stderr
)
wg
.
Wait
()
// Wait for the command.
err
=
cmd
.
Wait
()
if
err
!=
nil
{
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"
fusermount: %v"
,
err
)
err
=
fmt
.
Errorf
(
"
running fusermount: %v
\n\n
stderr:
\n
%s"
,
err
,
stderr
.
Bytes
()
)
return
return
}
}
...
...
mount_test.go
0 → 100644
View file @
652a72aa
package
fuse_test
import
(
"io/ioutil"
"os"
"path"
"runtime"
"strings"
"testing"
"golang.org/x/net/context"
"github.com/jacobsa/fuse"
"github.com/jacobsa/fuse/fuseops"
"github.com/jacobsa/fuse/fuseutil"
)
////////////////////////////////////////////////////////////////////////
// minimalFS
////////////////////////////////////////////////////////////////////////
// A minimal fuseutil.FileSystem that can successfully mount but do nothing
// else.
type
minimalFS
struct
{
fuseutil
.
NotImplementedFileSystem
}
func
(
fs
*
minimalFS
)
StatFS
(
ctx
context
.
Context
,
op
*
fuseops
.
StatFSOp
)
(
err
error
)
{
return
}
////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////
func
TestSuccessfulMount
(
t
*
testing
.
T
)
{
ctx
:=
context
.
Background
()
// Set up a temporary directory.
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"mount_test"
)
if
err
!=
nil
{
t
.
Fatal
(
"ioutil.TempDir: %v"
,
err
)
}
defer
os
.
RemoveAll
(
dir
)
// Mount.
fs
:=
&
minimalFS
{}
mfs
,
err
:=
fuse
.
Mount
(
dir
,
fuseutil
.
NewFileSystemServer
(
fs
),
&
fuse
.
MountConfig
{})
if
err
!=
nil
{
t
.
Fatalf
(
"fuse.Mount: %v"
,
err
)
}
defer
func
()
{
if
err
:=
mfs
.
Join
(
ctx
);
err
!=
nil
{
t
.
Errorf
(
"Joining: %v"
,
err
)
}
}()
defer
fuse
.
Unmount
(
mfs
.
Dir
())
}
func
TestNonEmptyMountPoint
(
t
*
testing
.
T
)
{
ctx
:=
context
.
Background
()
// osxfuse appears to be happy to mount over a non-empty mount point.
//
// We leave this test in for Linux, because it tickles the behavior of
// fusermount writing to stderr and exiting with an error code. We want to
// make sure that a descriptive error makes it back to the user.
if
runtime
.
GOOS
==
"darwin"
{
return
}
// Set up a temporary directory.
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"mount_test"
)
if
err
!=
nil
{
t
.
Fatal
(
"ioutil.TempDir: %v"
,
err
)
}
defer
os
.
RemoveAll
(
dir
)
// Add a file within it.
err
=
ioutil
.
WriteFile
(
path
.
Join
(
dir
,
"foo"
),
[]
byte
{},
0600
)
if
err
!=
nil
{
t
.
Fatalf
(
"ioutil.WriteFile: %v"
,
err
)
}
// Attempt to mount.
fs
:=
&
minimalFS
{}
mfs
,
err
:=
fuse
.
Mount
(
dir
,
fuseutil
.
NewFileSystemServer
(
fs
),
&
fuse
.
MountConfig
{})
if
err
==
nil
{
fuse
.
Unmount
(
mfs
.
Dir
())
mfs
.
Join
(
ctx
)
t
.
Fatal
(
"fuse.Mount returned nil"
)
}
const
want
=
"not empty"
if
got
:=
err
.
Error
();
!
strings
.
Contains
(
got
,
want
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
got
)
}
}
func
TestNonexistentMountPoint
(
t
*
testing
.
T
)
{
ctx
:=
context
.
Background
()
// Set up a temporary directory.
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"mount_test"
)
if
err
!=
nil
{
t
.
Fatal
(
"ioutil.TempDir: %v"
,
err
)
}
defer
os
.
RemoveAll
(
dir
)
// Attempt to mount into a sub-directory that doesn't exist.
fs
:=
&
minimalFS
{}
mfs
,
err
:=
fuse
.
Mount
(
path
.
Join
(
dir
,
"foo"
),
fuseutil
.
NewFileSystemServer
(
fs
),
&
fuse
.
MountConfig
{})
if
err
==
nil
{
fuse
.
Unmount
(
mfs
.
Dir
())
mfs
.
Join
(
ctx
)
t
.
Fatal
(
"fuse.Mount returned nil"
)
}
const
want
=
"no such file"
if
got
:=
err
.
Error
();
!
strings
.
Contains
(
got
,
want
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
got
)
}
}
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