-
Notifications
You must be signed in to change notification settings - Fork 41
/
main.go
130 lines (112 loc) · 4.2 KB
/
main.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// NordVPN fileshare daemon.
package main
import (
"errors"
"log"
_ "net/http/pprof" // #nosec G108 -- http server is not run in production builds
"os"
"path/filepath"
childprocess "github.com/NordSecurity/nordvpn-linux/child_process"
"github.com/NordSecurity/nordvpn-linux/fileshare"
"github.com/NordSecurity/nordvpn-linux/fileshare/fileshare_process"
"github.com/NordSecurity/nordvpn-linux/fileshare/fileshare_startup"
"github.com/NordSecurity/nordvpn-linux/internal"
"github.com/NordSecurity/nordvpn-linux/snapconf"
"golang.org/x/net/netutil"
)
// Values set when building the application
var Environment = ""
func openLogFile(path string) (*os.File, error) {
// #nosec path is constant
logFile, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, internal.PermUserRW)
if err != nil {
return nil, err
}
return logFile, nil
}
func main() {
homeDir, err := os.UserHomeDir()
if err != nil {
os.Exit(int(childprocess.CodeFailedToEnable))
}
configDirPath, err := internal.GetConfigDirPath(homeDir)
if err == nil {
if logFile, err := openLogFile(filepath.Join(configDirPath, internal.FileshareLogFileName)); err == nil {
log.SetOutput(logFile)
log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
}
}
processStatus := fileshare_process.NewFileshareGRPCProcessManager().ProcessStatus()
if processStatus == childprocess.Running {
os.Exit(int(childprocess.CodeAlreadyRunning))
} else if processStatus == childprocess.RunningForOtherUser {
log.Println("Cannot start fileshare daemon, it is already running for another user.")
os.Exit(int(childprocess.CodeAlreadyRunningForOtherUser))
}
storagePath := filepath.Join(
configDirPath,
internal.FileshareHistoryFile,
)
eventsDBPath := filepath.Join(internal.DatFilesPath, "moose.db")
if snapconf.IsUnderSnap() {
eventsDBPath = filepath.Join(os.Getenv("SNAP_USER_COMMON"), "moose.db")
// In case of snap, if default directory is determined to be under $HOME and that
// is translated to $SNAP_USER_DATA, during the first execution Downloads directory
// will not be created yet
downloadsDir, err := fileshare.GetDefaultDownloadDirectory()
if err != nil {
log.Println("Failed to get the default downloads directory:", err)
} else {
if err := internal.EnsureDir(filepath.Join(downloadsDir, "a")); err != nil {
log.Println("Failed to ensure default downloads directory:", err)
}
}
drainStart(eventsDBPath)
}
// Before storage handling was implemented in libdrop, we had our own json implementation. It is possible that user
// still has this history file, so we need to account for that by joining new transfer history with old transfer
// history. Fileshare process was implemented after this change, so we do not need legacy storage.
legacyStoragePath := ""
if err := os.Remove(internal.FileshareSocket); err != nil && !errors.Is(err, os.ErrNotExist) {
log.Println("Failed to remove old socket file: ", err)
}
listener, err := internal.ManualListener(internal.FileshareSocket, internal.PermUserRWGroupRWOthersRW)()
if err != nil {
log.Printf("Failed to open unix socket: %s", err)
os.Exit(int(childprocess.CodeFailedToCreateUnixScoket))
}
limitedListener := netutil.LimitListener(listener, 100)
defer func() {
if err != nil {
if err := listener.Close(); err != nil {
log.Println("Failed to close socket listener on failure: ", err)
}
}
}()
fileshareHandle, err := fileshare_startup.Startup(storagePath,
legacyStoragePath,
eventsDBPath,
limitedListener,
Environment,
internal.NewFileshareAuthenticator(uint32(os.Getuid())))
if err != nil {
log.Println("Failed to start the service: ", err.Error())
if errors.Is(err, fileshare_startup.ErrMeshNotEnabled) {
os.Exit(int(childprocess.CodeMeshnetNotEnabled))
}
if errors.Is(err, fileshare_startup.ErrMeshAddressAlreadyInUse) {
os.Exit(int(childprocess.CodeAddressAlreadyInUse))
}
os.Exit(int(childprocess.CodeFailedToEnable))
}
signals := internal.GetSignalChan()
log.Println(internal.InfoPrefix, "Daemon has started")
select {
case sig := <-signals:
log.Println("Received signal: ", sig)
case <-fileshareHandle.GetShutdownChan():
}
// Teardown
log.Println("Stopping fileshare process.")
fileshareHandle.Shutdown()
}