-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathusage.go
151 lines (129 loc) · 4.38 KB
/
usage.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"flag"
"fmt"
"os"
"os/exec"
)
type usageErr struct {
message string
}
func (e *usageErr) Error() string {
return e.message
}
func newUsageErr(msg string) error {
return &usageErr{
message: msg,
}
}
func isUsageErr(e error) bool {
_, ok := e.(*usageErr)
return ok
}
func showUsage() {
// prog is the name of the program invoked
//prog := path.Base(os.Args[0])
usage := `Usage:
emount --init FOLDER [--from srcFolder]
Initialize a new encrypted volume at FOLDER. Either the path FOLDER must not exist
or it must be an empty directory. If srcFolder is specified, the volume is
populated with a recursive copy from the source folder.
The user is prompted to enter a new password, and the password is rejected
if it is too weak (according to the minEntropy setting in emount.go)
emount --run FOLDER [--mount mountpoint] command args...
Run the command (with optional arguments), providing access to decrypted FOLDER
mounted in a temporary location. When the command completes, the decrypted volume
is unmounted. The 'command' term should be a program in your PATH
or an absolute path to an executable.
The default mount point is a dynamically-created temporary folder (inside TMPDIR),
owned by the calling user with permission mode 0700. The dynamic folder name
is passed to the command executable through the environment variable EMOUNT_FOLDER.
The default mount point can be overridden by the --mount/-m flag.
For automation or to avoid interactive prompting for password, the encryption
password can be provided via the environment variable EMOUNT_PASSWORD.
`
fmt.Println(usage)
}
func parseArgs(opt *options) error {
flag.StringVar(&opt.run, "run", "", "run command")
flag.StringVar(&opt.run, "r", "", "run command (shorthand)")
flag.StringVar(&opt.init, "init", "", "initialize a new folder")
flag.StringVar(&opt.init, "i", "", "initialize a new folder (shorthand)")
flag.StringVar(&opt.srcFolder, "from", "", "folder to copy from")
flag.StringVar(&opt.srcFolder, "f", "", "folder to copy from (shorthand)")
flag.BoolVar(&opt.verbose, "v", false, "show progress messages")
flag.StringVar(&opt.mountPoint, "mount", "",
"mount point for decrypted content")
flag.StringVar(&opt.mountPoint, "m", "",
"mount point for decrypted content (shorthand)")
flag.Parse()
// exactly one of run or init
if (opt.run != "" && opt.init != "") || (opt.run == "" && opt.init == "") {
return newUsageErr(
"One of the flags (--run/-r) or (--init/-i) must be specified.")
}
if opt.init != "" {
cf := checkFolder(opt.init)
if cf == isNotDir {
return fmt.Errorf("invalid init path: not a directory %v", opt.init)
}
if cf == isDir {
if err := checkEmptyDir(opt.init); err != nil {
return err
}
} else {
if err := os.MkdirAll(opt.init, 0700); err != nil {
return fmt.Errorf("creating init path %s: %v", opt.init, err)
}
}
if opt.srcFolder != "" {
if cf := checkFolder(opt.srcFolder); cf != isDir {
return fmt.Errorf("init from srcFolder %s invalid", opt.srcFolder)
}
}
if opt.mountPoint != "" {
return fmt.Errorf("mountPoint arg is not used with init")
}
}
// run command validation
if opt.run != "" {
if checkFolder(opt.run) != isDir {
return fmt.Errorf("invalid run folder %s", opt.run)
}
if opt.srcFolder != "" {
return fmt.Errorf("the -f srcFolder is not used with --run")
}
// if mount point specified, it should already exist and be empty
if opt.mountPoint != "" {
if err := checkEmptyDir(opt.mountPoint); err != nil {
return fmt.Errorf("Mountpoint %s error: %v", opt.mountPoint, err)
}
}
if opt.mountPoint == opt.run {
return fmt.Errorf("mountPoint may not be same as run folder")
}
opt.runCmd = flag.Args()
if len(opt.runCmd) == 0 {
// check that command[0] is a valid binary, or in the PATH
return newUsageErr("Command required for -run")
}
runExePath := opt.runCmd[0]
reInfo, err := os.Stat(runExePath)
if err != nil {
// see if we can find it with path lookup
foundPath, err := exec.LookPath(runExePath)
if err == nil && foundPath != runExePath {
opt.runCmd[0] = foundPath
return nil
}
return fmt.Errorf("run program %s not found: %v", runExePath, err)
}
mode := reInfo.Mode()
if !mode.IsRegular() || ((mode & 0111) == 0) {
return fmt.Errorf(
"run program %s permission error or not executable: %v",
runExePath, err)
}
}
return nil
}