-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathargs.go
166 lines (149 loc) · 3.92 KB
/
args.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"path/filepath"
"github.com/declan94/secret-share/internal/exitcode"
"github.com/declan94/secret-share/internal/tlog"
)
var flagSet *flag.FlagSet
// CliArgs contains cli args value
type CliArgs struct {
Src string
Parts []string
Recover bool
Directory bool
KNum int
Version bool
}
func printMyFlagSet(avoid map[string]bool) {
flagSet.VisitAll(func(f *flag.Flag) {
if avoid[f.Name] {
return
}
s := fmt.Sprintf(" -%s", f.Name) // Two spaces before -; see next two comments.
_, usage := flag.UnquoteUsage(f)
// Boolean flags of one ASCII letter are so common we
// treat them specially, putting their usage on the same line.
s += "\n \t"
s += strings.Replace(usage, "\n", "\n \t", -1)
fmt.Println(s)
})
}
func usage() {
fmt.Printf("Usage: %s [options] SRC/DST PART1 PART2 PART3 ...\n", path.Base(os.Args[0]))
fmt.Printf(" There must be at least two sharing parts.")
fmt.Printf("\noptions:\n")
printMyFlagSet(map[string]bool{"debug": true})
os.Exit(exitcode.Usage)
}
// ParseArgs parse args from cli args
func ParseArgs() (args CliArgs) {
var debug bool
flagSet = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
flagSet.BoolVar(&args.Recover, "r", false, "Recover mode, recover dst file(directory) from sharing parts.")
flagSet.IntVar(&args.KNum, "k", 0, "Sufficent count for recovering. Default all sharing parts are needed.")
flagSet.BoolVar(&args.Version, "v", false, "Show version info.")
flagSet.BoolVar(&debug, "debug", false, "Log out debug info.")
flagSet.Usage = usage
flagSet.Parse(os.Args[1:])
tlog.Debug.Enabled = debug
if args.Version {
return args
}
if flagSet.NArg() < 3 {
usage()
}
args.Src = flagSet.Arg(0)
args.Parts = flagSet.Args()[1:]
info, err := os.Stat(args.Src)
if args.Recover {
if err == nil {
tlog.Fatal.Printf("[%s] Already exists. Change another place to recover.\n", args.Src)
os.Exit(exitcode.DstErr)
}
if !os.IsNotExist(err) {
tlog.Fatal.Printf("Stat error: %v\n", err)
os.Exit(exitcode.DstErr)
}
infos := make([]os.FileInfo, len(args.Parts))
for i, part := range args.Parts {
info, err := os.Stat(part)
if err != nil {
tlog.Fatal.Printf("stat [%s] failed: %v", part, err)
os.Exit(exitcode.SrcErr)
}
if info.IsDir() {
args.Directory = true
}
infos[i] = info
}
for _, info := range infos {
if info.IsDir() != args.Directory {
tlog.Fatal.Printf("Mixed file and directory parts")
os.Exit(exitcode.Usage)
}
}
} else {
if len(args.Parts) > 255 || len(args.Parts) < 2 {
tlog.Fatal.Printf("the number of sharing parts should satisfy 2 <= n <= 255.")
os.Exit(exitcode.Usage)
}
if args.KNum == 0 {
args.KNum = len(args.Parts)
} else if args.KNum < 2 || args.KNum > len(args.Parts) {
tlog.Fatal.Printf("k should satisfy 2 <= k <= n. (n is the count of total sharing parts)")
os.Exit(exitcode.Usage)
}
if err != nil {
tlog.Fatal.Printf("Stat source file failed: %v", err)
os.Exit(exitcode.SrcErr)
}
if info.IsDir() {
args.Directory = true
for _, d := range args.Parts {
os.MkdirAll(d, os.FileMode(0774))
err := checkDirEmpty(d)
if err != nil {
tlog.Fatal.Println(err)
os.Exit(exitcode.DstErr)
}
}
} else {
for _, p := range args.Parts {
os.MkdirAll(filepath.Dir(p), os.FileMode(0774))
}
}
}
return args
}
// checkDirEmpty - check if "dir" exists and is an empty directory
func checkDirEmpty(dir string) error {
err := checkDir(dir)
if err != nil {
return err
}
entries, err := ioutil.ReadDir(dir)
if err != nil {
return err
}
if len(entries) == 0 {
return nil
}
return fmt.Errorf("directory %s not empty", dir)
}
// checkDir - check if "dir" exists and is a directory
func checkDir(dir string) error {
fi, err := os.Stat(dir)
if err != nil {
return err
}
if !fi.IsDir() {
return fmt.Errorf("%s is not a directory", dir)
}
return nil
}