forked from keybase/client
/
install_nix.go
89 lines (77 loc) · 2.5 KB
/
install_nix.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
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.
// +build !windows
package install
import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
"github.com/keybase/client/go/lsof"
)
// maybeKernelOpenFiles returns true if the kernel might currently
// have open files. If it returns false, the mount is definitely not
// in use.
func maybeKernelOpenFiles(mountDir string, log Log) bool {
// This file name is copied from kbfs/libfs/constants.go because
// importing that package bloats the `keybase` service binary and
// causes compilation issues.
p := filepath.Join(mountDir, ".kbfs_open_file_count")
f, err := os.Open(p)
if err != nil {
log.Debug("Couldn't check for open files in %s: %+v", p, err)
return true
}
defer f.Close()
b, err := ioutil.ReadAll(f)
if err != nil {
log.Debug("Couldn't read the open file count in %s: %+v", p, err)
return true
}
numOpenFiles, err := strconv.ParseInt(string(b), 10, 64)
if err != nil {
log.Debug("Couldn't parse the open file count (%s) in %s: %+v",
string(b), p, err)
return true
}
return numOpenFiles != 0
}
// IsInUse returns true if the mount is in use. This may be used by the updater
// to determine if it's safe to apply an update and restart.
func IsInUse(mountDir string, log Log) bool {
// Shortcut to avoid expensive lsof call if KBFS tells us that
// there are definitely no open files.
if !maybeKernelOpenFiles(mountDir, log) {
log.Debug("Definitely no open files; skipping lsof")
return false
}
// ignore error
lsofResults, _ := LsofMount(mountDir, log)
return len(lsofResults) > 0
}
// LsofMount does not return an error if it was unable to lsof
// the mountpoint or the mountpoint does not exist.
func LsofMount(mountDir string, log Log) ([]CommonLsofResult, error) {
log.Debug("Mount dir to lsof: %s", mountDir)
if mountDir == "" {
return nil, nil
}
if _, serr := os.Stat(mountDir); os.IsNotExist(serr) {
log.Debug("%s, mount dir lsof target, doesn't exist", mountDir)
return nil, nil
}
log.Debug("Checking mount (lsof)")
processes, err := lsof.MountPoint(mountDir)
if err != nil {
// If there is an error in lsof it's ok to continue
// An exit status of 1 means that the mount is not in use, and is
// not really an error.
log.Debug("Continuing despite error in lsof: %s", err)
return nil, nil
}
var ret []CommonLsofResult
for _, process := range processes {
ret = append(ret, CommonLsofResult{process.PID, process.Command})
}
return ret, nil
}