35
|
1 /*
|
37
|
2 Last Change: 2019-11-25 月 13:55:58.
|
35
|
3
|
37
|
4 gf.go: Get Files (ver.0.7)
|
35
|
5
|
|
6 ./gf.json: server & file list
|
|
7 e.g.
|
|
8 {
|
|
9 "Server": {
|
36
|
10 "Address": "hoge.com",
|
35
|
11 "Port": "80"
|
|
12 },
|
|
13 "Files": [
|
|
14 "mahjong.html",
|
|
15 "gammon",
|
|
16 "gammon/backgammon.html"
|
37
|
17 ],
|
|
18 "Backup": false
|
35
|
19 }
|
|
20
|
|
21 TODO:
|
36
|
22 + reserve dirtree option [-r]
|
|
23 + gunzip/untar option
|
35
|
24 */
|
|
25 package main
|
|
26
|
|
27 import (
|
|
28 "encoding/json"
|
|
29 "fmt"
|
|
30 "flag"
|
|
31 "io/ioutil"
|
|
32 "log"
|
|
33 "os"
|
|
34 "path"
|
36
|
35 "path/filepath"
|
35
|
36 "net/http"
|
37
|
37 "time"
|
35
|
38 )
|
|
39
|
37
|
40 const version = "0.7"
|
35
|
41 const defaultjson = "gf.json"
|
36
|
42 const samplejson = `{
|
|
43 "Server": {
|
|
44 "Address": "hoge.com",
|
|
45 "Port": "80"
|
|
46 },
|
|
47 "Files": [
|
|
48 "mahjong.html",
|
|
49 "gammon/backgammon.html"
|
37
|
50 ],
|
|
51 "Backup": false
|
36
|
52 }`
|
35
|
53
|
|
54 type SV struct {
|
|
55 Address string
|
|
56 Port string
|
|
57 }
|
|
58
|
|
59 func (sv SV) String() string {
|
|
60 return sv.Address + ":" + sv.Port
|
|
61 }
|
|
62
|
|
63 type GF struct {
|
|
64 Server SV
|
|
65 Files []string
|
37
|
66 Backup bool
|
35
|
67 }
|
|
68
|
36
|
69 type HO struct { // html object
|
|
70 Status string
|
|
71 StatusCode int
|
|
72 Content []byte
|
|
73 }
|
|
74
|
|
75 // option valiables
|
35
|
76 var (
|
|
77 ver bool
|
|
78 quiet bool
|
|
79 jsonfile string
|
36
|
80 sample bool
|
|
81 somefile string
|
|
82 tdir string
|
35
|
83 )
|
|
84
|
|
85 func init() {
|
|
86 flag.BoolVar(&ver, "v", false, "version.")
|
|
87 flag.BoolVar(&quiet, "s", false, "silence.")
|
|
88 flag.StringVar(&jsonfile, "j", defaultjson, "specify json file.")
|
36
|
89 flag.BoolVar(&sample, "p", false, "print json sample.")
|
|
90 flag.StringVar(&somefile, "o", "", "get specity file.")
|
|
91 flag.StringVar(&tdir, "d", "", "specity save directory.")
|
35
|
92 }
|
|
93
|
|
94 func main() {
|
|
95 flag.Parse()
|
|
96
|
|
97 if ver {
|
|
98 fmt.Println("gf", version)
|
36
|
99 flag.PrintDefaults()
|
35
|
100 os.Exit(0)
|
|
101 }
|
|
102
|
36
|
103 if sample {
|
|
104 fmt.Println(samplejson)
|
|
105 os.Exit(0)
|
|
106 }
|
|
107
|
|
108 if somefile != "" {
|
|
109 ho, err := http_get(somefile)
|
|
110 if err != nil {
|
|
111 log.Fatal(err)
|
|
112 }
|
|
113 fmt.Print(string(ho.Content))
|
|
114 os.Exit(0)
|
|
115 }
|
|
116
|
35
|
117 content, err := ioutil.ReadFile(jsonfile)
|
|
118 if err != nil {
|
|
119 log.Fatal(err)
|
|
120 }
|
|
121
|
|
122 var gf GF
|
|
123
|
|
124 err = json.Unmarshal(content, &gf)
|
|
125 if err != nil {
|
|
126 log.Fatal(err)
|
|
127 }
|
36
|
128
|
|
129 if tdir != "" {
|
|
130 if err := os.Mkdir(tdir, 0755); err != nil {
|
|
131 log.Fatal(err)
|
|
132 }
|
|
133 }
|
|
134
|
35
|
135 n := len(gf.Files)
|
|
136 if n > 1 {
|
36
|
137 print_msg(fmt.Sprintf("%d files downloading", n))
|
35
|
138 }
|
|
139
|
37
|
140 if gf.Backup {
|
|
141 bkdir := "backup" + time.Now().Format("200601021504")
|
|
142 if err := os.Mkdir(bkdir, 0755); err != nil {
|
|
143 log.Fatal(err)
|
|
144 }
|
|
145 for _, f := range gf.Files {
|
|
146 file := path.Base(f)
|
|
147 if _, err := os.Stat(file); os.IsNotExist(err) {
|
|
148 continue
|
|
149 }
|
|
150 if err := os.Link(file, filepath.Join(bkdir, file)); err != nil {
|
|
151 log.Fatal(err)
|
|
152 }
|
|
153 }
|
|
154 files, err := ioutil.ReadDir(bkdir)
|
|
155 if err != nil {
|
|
156 log.Fatal(err)
|
|
157 }
|
|
158 if len(files) == 0 {
|
|
159 os.Remove(bkdir)
|
|
160 }
|
|
161
|
|
162 }
|
|
163
|
36
|
164 ch := make(chan string)
|
35
|
165 for _, f := range gf.Files {
|
36
|
166 go http_gets(gf.Server.String(), f, ch)
|
35
|
167 }
|
36
|
168
|
|
169 for range gf.Files {
|
|
170 print_msg(<-ch)
|
|
171 }
|
35
|
172 }
|
|
173
|
36
|
174 func http_get(url string) (HO, error) {
|
|
175 var ho HO
|
|
176
|
35
|
177 res, err := http.Get(url)
|
|
178 if err != nil {
|
36
|
179 return ho, err
|
35
|
180 }
|
|
181
|
|
182 content, err := ioutil.ReadAll(res.Body)
|
|
183 res.Body.Close()
|
|
184 if err != nil {
|
36
|
185 return ho, err
|
35
|
186 }
|
|
187
|
36
|
188 ho.Status = res.Status
|
|
189 ho.StatusCode = res.StatusCode
|
|
190 ho.Content = content
|
|
191
|
|
192 return ho, nil
|
35
|
193 }
|
|
194
|
36
|
195 func http_gets(server, file string, ch chan<- string) {
|
|
196 msg := " getting " + file + "... "
|
|
197
|
|
198 url := "http://" + server + "/" + file
|
|
199
|
|
200 ho, err := http_get(url)
|
|
201 if err != nil {
|
|
202 ch <- msg + fmt.Sprint(err)
|
|
203 return
|
|
204 }
|
|
205
|
|
206 if ho.StatusCode == http.StatusOK {
|
|
207 file = path.Base(file)
|
|
208 if tdir != "" {
|
|
209 file = filepath.Join(tdir, file)
|
|
210 }
|
|
211 if err := ioutil.WriteFile(file, ho.Content, 0644); err != nil {
|
|
212 ch <- msg + fmt.Sprint(err)
|
|
213 return
|
|
214 }
|
|
215 }
|
|
216
|
|
217 ch <- msg + "[" + ho.Status + "]"
|
|
218 }
|
|
219
|
|
220 func print_msg(msg string) {
|
|
221 if !quiet {
|
|
222 fmt.Println(msg)
|
35
|
223 }
|
|
224 }
|
|
225
|