forked from ipfs/kubo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mount_unix.go
114 lines (93 loc) · 2.58 KB
/
mount_unix.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// +build linux darwin freebsd netbsd openbsd
// +build !nofuse
package node
import (
"errors"
"fmt"
"strings"
"sync"
core "github.com/ipfs/go-ipfs/core"
ipns "github.com/ipfs/go-ipfs/fuse/ipns"
mount "github.com/ipfs/go-ipfs/fuse/mount"
rofs "github.com/ipfs/go-ipfs/fuse/readonly"
logging "gx/ipfs/QmRb5jh8z2E8hMGN2tkvs1yHynUanqnZ3UeKwgN1i9P1F8/go-log"
)
var log = logging.Logger("node")
// fuseNoDirectory used to check the returning fuse error
const fuseNoDirectory = "fusermount: failed to access mountpoint"
// fuseExitStatus1 used to check the returning fuse error
const fuseExitStatus1 = "fusermount: exit status 1"
// platformFuseChecks can get overridden by arch-specific files
// to run fuse checks (like checking the OSXFUSE version)
var platformFuseChecks = func(*core.IpfsNode) error {
return nil
}
func Mount(node *core.IpfsNode, fsdir, nsdir string) error {
// check if we already have live mounts.
// if the user said "Mount", then there must be something wrong.
// so, close them and try again.
if node.Mounts.Ipfs != nil && node.Mounts.Ipfs.IsActive() {
node.Mounts.Ipfs.Unmount()
}
if node.Mounts.Ipns != nil && node.Mounts.Ipns.IsActive() {
node.Mounts.Ipns.Unmount()
}
if err := platformFuseChecks(node); err != nil {
return err
}
return doMount(node, fsdir, nsdir)
}
func doMount(node *core.IpfsNode, fsdir, nsdir string) error {
fmtFuseErr := func(err error, mountpoint string) error {
s := err.Error()
if strings.Contains(s, fuseNoDirectory) {
s = strings.Replace(s, `fusermount: "fusermount:`, "", -1)
s = strings.Replace(s, `\n", exit status 1`, "", -1)
return errors.New(s)
}
if s == fuseExitStatus1 {
s = fmt.Sprintf("fuse failed to access mountpoint %s", mountpoint)
return errors.New(s)
}
return err
}
// this sync stuff is so that both can be mounted simultaneously.
var fsmount, nsmount mount.Mount
var err1, err2 error
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
fsmount, err1 = rofs.Mount(node, fsdir)
}()
if node.OnlineMode() {
wg.Add(1)
go func() {
defer wg.Done()
nsmount, err2 = ipns.Mount(node, nsdir, fsdir)
}()
}
wg.Wait()
if err1 != nil {
log.Errorf("error mounting: %s", err1)
}
if err2 != nil {
log.Errorf("error mounting: %s", err2)
}
if err1 != nil || err2 != nil {
if fsmount != nil {
fsmount.Unmount()
}
if nsmount != nil {
nsmount.Unmount()
}
if err1 != nil {
return fmtFuseErr(err1, fsdir)
}
return fmtFuseErr(err2, nsdir)
}
// setup node state, so that it can be cancelled
node.Mounts.Ipfs = fsmount
node.Mounts.Ipns = nsmount
return nil
}