-
Notifications
You must be signed in to change notification settings - Fork 41
/
taxi_check.go
129 lines (111 loc) · 2.74 KB
/
taxi_check.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
/*
Write a function that gets an index file with names of files and sha256
signatures in the following format
0c4ccc63a912bbd6d45174251415c089522e5c0e75286794ab1f86cb8e2561fd taxi-01.csv
f427b5880e9164ec1e6cda53aa4b2d1f1e470da973e5b51748c806ea5c57cbdf taxi-02.csv
4e251e9e98c5cb7be8b34adfcb46cc806a4ef5ec8c95ba9aac5ff81449fc630c taxi-03.csv
...
You should compute concurrently sha256 signatures of these files and see if
they math the ones in the index file.
- Print the number of processed files
- If there's a mismatch, print the offending file(s) and exit the program with
non-zero value
Get taxi-sha256.zip from the web site and open it. The index file is sha256sum.txt
*/
package main
import (
"bufio"
"compress/bzip2"
"crypto/sha256"
"fmt"
"io"
"log"
"os"
"path"
"strings"
"time"
)
func fileSig(path string) (string, error) {
file, err := os.Open(path)
if err != nil {
return "", err
}
defer file.Close()
hash := sha256.New()
_, err = io.Copy(hash, bzip2.NewReader(file))
if err != nil {
return "", err
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
}
// Parse signature file. Return map of path->signature
func parseSigFile(r io.Reader) (map[string]string, error) {
sigs := make(map[string]string)
scanner := bufio.NewScanner(r)
for scanner.Scan() {
// Line example
// 6c6427da7893932731901035edbb9214 nasa-00.log
fields := strings.Fields(scanner.Text())
if len(fields) != 2 {
// TODO: line number
return nil, fmt.Errorf("bad line: %q", scanner.Text())
}
sigs[fields[1]] = fields[0]
}
if err := scanner.Err(); err != nil {
return nil, err
}
return sigs, nil
}
func main() {
rootDir := "/tmp/taxi" // Change to where to unzipped taxi-sha256.zip
file, err := os.Open(path.Join(rootDir, "sha256sum.txt"))
if err != nil {
log.Fatalf("error: %s", err)
}
defer file.Close()
sigs, err := parseSigFile(file)
if err != nil {
log.Fatalf("error: %s", err)
}
start := time.Now()
ok := true
ch := make(chan result)
for name, signature := range sigs {
fileName := path.Join(rootDir, name) + ".bz2"
// sig, err := fileSig(fileName)
go sigWorker(fileName, signature, ch)
}
for range sigs {
r := <-ch
if r.err != nil {
fmt.Fprintf(os.Stderr, "error: %s - %s\n", r.fileName, err)
ok = false
continue
}
if !r.match {
ok = false
fmt.Printf("error: %s mismatch\n", r.fileName)
}
}
duration := time.Since(start)
fmt.Printf("processed %d files in %v\n", len(sigs), duration)
if !ok {
os.Exit(1)
}
}
func sigWorker(fileName, signature string, ch chan<- result) {
r := result{fileName: fileName}
sig, err := fileSig(fileName)
if err != nil {
r.err = err
} else {
r.match = sig == signature
}
ch <- r
}
type result struct {
fileName string
err error
match bool
}