clean up and fix init permissions handling
Jeromy committed
May 20, 2015 at 08:55 UTC
8ea502f1b37dc103c988f13e7ac3fe3ec81f1d51
5 files changed
+82
-19
cmd/ipfs/init.go
+47
-12
@@ -5,6 +5,8 @@ import (
5
"errors"
6
"fmt"
7
"io"
8
+ "os"
9
+ "path"
10
11
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
12
assets "github.com/ipfs/go-ipfs/assets"
@@ -36,7 +38,10 @@ var initCmd = &cmds.Command{
38
// TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs"),
39
},
40
PreRun: func(req cmds.Request) error {
39
- daemonLocked := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
41
+ daemonLocked, err := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
42
+ if err != nil {
43
+ return err
44
+ }
45
46
log.Info("checking if daemon is running...")
47
if daemonLocked {
@@ -47,6 +52,10 @@ var initCmd = &cmds.Command{
52
return nil
53
},
54
Run: func(req cmds.Request, res cmds.Response) {
55
+ if req.Context().Online {
56
+ res.SetError(errors.New("init must be run offline only!"), cmds.ErrNormal)
57
+ return
58
+ }
59
60
force, _, err := req.Option("f").Bool() // if !found, it's okay force == false
61
if err != nil {
@@ -64,15 +73,10 @@ var initCmd = &cmds.Command{
73
nBitsForKeypair = nBitsForKeypairDefault
74
}
75
67
- rpipe, wpipe := io.Pipe()
68
- go func() {
69
- defer wpipe.Close()
70
- if err := doInit(wpipe, req.Context().ConfigRoot, force, nBitsForKeypair); err != nil {
71
- res.SetError(err, cmds.ErrNormal)
72
- return
73
- }
74
- }()
75
- res.SetOutput(rpipe)
76
+ if err := doInit(os.Stdout, req.Context().ConfigRoot, force, nBitsForKeypair); err != nil {
77
+ res.SetError(err, cmds.ErrNormal)
78
+ return
79
+ }
80
},
81
}
82
@@ -82,8 +86,7 @@ Reinitializing would overwrite your keys.
86
`)
87
88
func initWithDefaults(out io.Writer, repoRoot string) error {
85
- err := doInit(out, repoRoot, false, nBitsForKeypairDefault)
86
- return err
89
+ return doInit(out, repoRoot, false, nBitsForKeypairDefault)
90
}
91
92
func doInit(out io.Writer, repoRoot string, force bool, nBitsForKeypair int) error {
@@ -91,6 +94,10 @@ func doInit(out io.Writer, repoRoot string, force bool, nBitsForKeypair int) err
94
return err
95
}
96
97
+ if err := checkWriteable(repoRoot); err != nil {
98
+ return err
99
+ }
100
+
101
if fsrepo.IsInitialized(repoRoot) && !force {
102
return errRepoExists
103
}
@@ -117,6 +124,34 @@ func doInit(out io.Writer, repoRoot string, force bool, nBitsForKeypair int) err
124
return initializeIpnsKeyspace(repoRoot)
125
}
126
127
+func checkWriteable(dir string) error {
128
+ _, err := os.Stat(dir)
129
+ if err == nil {
130
+ // dir exists, make sure we can write to it
131
+ testfile := path.Join(dir, "test")
132
+ fi, err := os.Create(testfile)
133
+ if err != nil {
134
+ if os.IsPermission(err) {
135
+ return fmt.Errorf("%s is not writeable by the current user", dir)
136
+ }
137
+ return fmt.Errorf("unexpected error while checking writeablility of repo root: %s", err)
138
+ }
139
+ fi.Close()
140
+ return os.Remove(testfile)
141
+ }
142
+
143
+ if os.IsNotExist(err) {
144
+ // dir doesnt exist, check that we can create it
145
+ return os.Mkdir(dir, 0775)
146
+ }
147
+
148
+ if os.IsPermission(err) {
149
+ return fmt.Errorf("cannot write to %s, incorrect permissions", err)
150
+ }
151
+
152
+ return err
153
+}
154
+
155
func addDefaultAssets(out io.Writer, repoRoot string) error {
156
ctx, cancel := context.WithCancel(context.Background())
157
defer cancel()
cmd/ipfs/main.go
+4
-1
@@ -387,7 +387,10 @@ func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.C
387
388
// at this point need to know whether daemon is running. we defer
389
// to this point so that some commands dont open files unnecessarily.
390
- daemonLocked := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
390
+ daemonLocked, err := fsrepo.LockedByOtherProcess(req.Context().ConfigRoot)
391
+ if err != nil {
392
+ return false, err
393
+ }
394
395
if daemonLocked {
396
repo/fsrepo/fsrepo.go
+1
-1
@@ -283,7 +283,7 @@ func Remove(repoPath string) error {
283
284
// LockedByOtherProcess returns true if the FSRepo is locked by another
285
// process. If true, then the repo cannot be opened by this process.
286
-func LockedByOtherProcess(repoPath string) bool {
286
+func LockedByOtherProcess(repoPath string) (bool, error) {
287
repoPath = path.Clean(repoPath)
288
289
// TODO replace this with the "api" file
repo/fsrepo/lock/lock.go
+8
-4
@@ -2,6 +2,7 @@ package lock
2
3
import (
4
"io"
5
+ "os"
6
"path"
7
8
lock "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/camlistore/lock"
@@ -17,14 +18,17 @@ func Lock(confdir string) (io.Closer, error) {
18
return c, err
19
}
20
20
-func Locked(confdir string) bool {
21
+func Locked(confdir string) (bool, error) {
22
if !util.FileExists(path.Join(confdir, LockFile)) {
22
- return false
23
+ return false, nil
24
}
25
if lk, err := Lock(confdir); err != nil {
25
- return true
26
+ if os.IsPermission(err) {
27
+ return false, err
28
+ }
29
+ return true, nil
30
} else {
31
lk.Close()
28
- return false
32
+ return false, nil
33
}
34
}
test/sharness/t0020-init.sh
+22
-1
@@ -8,6 +8,22 @@ test_description="Test init command"
8
9
. lib/test-lib.sh
10
11
+# test that ipfs fails to init if IPFS_PATH isnt writeable
12
+test_expect_success "create dir and change perms succeeds" '
13
+ export IPFS_PATH="$(pwd)/.badipfs" &&
14
+ mkdir "$IPFS_PATH" &&
15
+ chmod 000 "$IPFS_PATH"
16
+'
17
+
18
+test_expect_success "ipfs init fails" '
19
+ test_must_fail ipfs init 2> init_fail_out
20
+'
21
+
22
+test_expect_success "ipfs init output looks good" '
23
+ echo "Error: open $IPFS_PATH/repo.lock: permission denied" > init_fail_exp &&
24
+ test_cmp init_fail_out init_fail_exp
25
+'
26
+
27
test_expect_success "ipfs init succeeds" '
28
export IPFS_PATH="$(pwd)/.ipfs" &&
29
BITS="2048" &&
@@ -17,7 +33,8 @@ test_expect_success "ipfs init succeeds" '
33
test_expect_success ".ipfs/ has been created" '
34
test -d ".ipfs" &&
35
test -f ".ipfs/config" &&
20
- test -d ".ipfs/datastore" ||
36
+ test -d ".ipfs/datastore" &&
37
+ test -d ".ipfs/blocks" ||
38
test_fsh ls -al .ipfs
39
'
40
@@ -44,6 +61,10 @@ test_expect_success "ipfs init output looks good" '
61
test_cmp expected actual_init
62
'
63
64
+test_expect_success "clean up ipfs dir" '
65
+ rm -rf "$IPFS_PATH"
66
+'
67
+
68
test_init_ipfs
69
70
test_launch_ipfs_daemon