diff --git a/repo/fsrepo/lock/lock.go b/repo/fsrepo/lock/lock.go index 98387aceb6d..c10521deeed 100644 --- a/repo/fsrepo/lock/lock.go +++ b/repo/fsrepo/lock/lock.go @@ -1,9 +1,12 @@ package lock import ( + "fmt" "io" "os" "path" + "strings" + "syscall" lock "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/camlistore/lock" "github.com/ipfs/go-ipfs/util" @@ -13,6 +16,10 @@ import ( // TODO rename repo lock and hide name const LockFile = "repo.lock" +func errPerm(path string) error { + return fmt.Errorf("failed to take lock at %s: permission denied", path) +} + func Lock(confdir string) (io.Closer, error) { c, err := lock.Lock(path.Join(confdir, LockFile)) return c, err @@ -23,12 +30,28 @@ func Locked(confdir string) (bool, error) { return false, nil } if lk, err := Lock(confdir); err != nil { + // EAGAIN == someone else has the lock + if err == syscall.EAGAIN { + return true, nil + } + + // lock fails on permissions error if os.IsPermission(err) { - return false, err + return false, errPerm(confdir) } - return true, nil + if isLockCreatePermFail(err) { + return false, errPerm(confdir) + } + + // otherwise, we cant guarantee anything, error out + return false, err } else { lk.Close() return false, nil } } + +func isLockCreatePermFail(err error) bool { + s := err.Error() + return strings.Contains(s, "Lock Create of") && strings.Contains(s, "permission denied") +} diff --git a/test/sharness/t0020-init.sh b/test/sharness/t0020-init.sh index 306dbf6adb1..6ca20af0aa7 100755 --- a/test/sharness/t0020-init.sh +++ b/test/sharness/t0020-init.sh @@ -20,7 +20,7 @@ test_expect_success "ipfs init fails" ' ' test_expect_success "ipfs init output looks good" ' - echo "Error: open $IPFS_PATH/repo.lock: permission denied" > init_fail_exp && + echo "Error: failed to take lock at $IPFS_PATH: permission denied" > init_fail_exp && test_cmp init_fail_out init_fail_exp '