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
2ed9350a
Commit
2ed9350a
authored
Jul 24, 2015
by
Aaron Jacobs
Browse files
Options
Browse Files
Download
Plain Diff
Made mounting work on Linux, too.
parents
9b4cfc81
e9529e8d
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
158 additions
and
0 deletions
+158
-0
mount_linux.go
mount_linux.go
+158
-0
No files found.
mount_linux.go
0 → 100644
View file @
2ed9350a
package
fuse
import
(
"bufio"
"fmt"
"io"
"log"
"net"
"os"
"os/exec"
"sync"
"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
// 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
// service the connection in order for mounting to complete.
func
mount
(
dir
string
,
cfg
*
MountConfig
,
ready
chan
<-
error
)
(
dev
*
os
.
File
,
err
error
)
{
// On linux, mounting is never delayed.
ready
<-
nil
// Create a socket pair.
fds
,
err
:=
syscall
.
Socketpair
(
syscall
.
AF_FILE
,
syscall
.
SOCK_STREAM
,
0
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"Socketpair: %v"
,
err
)
return
}
// Wrap the sockets into os.File objects that we will pass off to fusermount.
writeFile
:=
os
.
NewFile
(
uintptr
(
fds
[
0
]),
"fusermount-child-writes"
)
defer
writeFile
.
Close
()
readFile
:=
os
.
NewFile
(
uintptr
(
fds
[
1
]),
"fusermount-parent-reads"
)
defer
readFile
.
Close
()
// Start fusermount, passing it pipes for stdout and stderr.
cmd
:=
exec
.
Command
(
"fusermount"
,
"-o"
,
cfg
.
toOptionsString
(),
"--"
,
dir
,
)
cmd
.
Env
=
append
(
os
.
Environ
(),
"_FUSE_COMMFD=3"
)
cmd
.
ExtraFiles
=
[]
*
os
.
File
{
writeFile
}
stdout
,
err
:=
cmd
.
StdoutPipe
()
if
err
!=
nil
{
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
{
err
=
fmt
.
Errorf
(
"fusermount: %v"
,
err
)
return
}
// Wrap the socket file in a connection.
c
,
err
:=
net
.
FileConn
(
readFile
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"FileConn: %v"
,
err
)
return
}
defer
c
.
Close
()
// We expect to have a Unix domain socket.
uc
,
ok
:=
c
.
(
*
net
.
UnixConn
)
if
!
ok
{
err
=
fmt
.
Errorf
(
"Expected UnixConn, got %T"
,
c
)
return
}
// Read a message.
buf
:=
make
([]
byte
,
32
)
// expect 1 byte
oob
:=
make
([]
byte
,
32
)
// expect 24 bytes
_
,
oobn
,
_
,
_
,
err
:=
uc
.
ReadMsgUnix
(
buf
,
oob
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"ReadMsgUnix: %v"
,
err
)
return
}
// Parse the message.
scms
,
err
:=
syscall
.
ParseSocketControlMessage
(
oob
[
:
oobn
])
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"ParseSocketControlMessage: %v"
,
err
)
return
}
// We expect one message.
if
len
(
scms
)
!=
1
{
err
=
fmt
.
Errorf
(
"expected 1 SocketControlMessage; got scms = %#v"
,
scms
)
return
}
scm
:=
scms
[
0
]
// Pull out the FD returned by fusermount
gotFds
,
err
:=
syscall
.
ParseUnixRights
(
&
scm
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"syscall.ParseUnixRights: %v"
,
err
)
return
}
if
len
(
gotFds
)
!=
1
{
err
=
fmt
.
Errorf
(
"wanted 1 fd; got %#v"
,
gotFds
)
return
}
// Turn the FD into an os.File.
dev
=
os
.
NewFile
(
uintptr
(
gotFds
[
0
]),
"/dev/fuse"
)
return
}
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