...
Source file src/pkg/cmd/go/internal/cache/hash.go
1
2
3
4
5 package cache
6
7 import (
8 "bytes"
9 "crypto/sha256"
10 "fmt"
11 "hash"
12 "io"
13 "os"
14 "runtime"
15 "sync"
16 )
17
18 var debugHash = false
19
20
21 const HashSize = 32
22
23
24
25 type Hash struct {
26 h hash.Hash
27 name string
28 buf *bytes.Buffer
29 }
30
31
32
33
34
35
36
37
38
39 var hashSalt = []byte(runtime.Version())
40
41
42
43 func Subkey(parent ActionID, desc string) ActionID {
44 h := sha256.New()
45 h.Write([]byte("subkey:"))
46 h.Write(parent[:])
47 h.Write([]byte(desc))
48 var out ActionID
49 h.Sum(out[:0])
50 if debugHash {
51 fmt.Fprintf(os.Stderr, "HASH subkey %x %q = %x\n", parent, desc, out)
52 }
53 if verify {
54 hashDebug.Lock()
55 hashDebug.m[out] = fmt.Sprintf("subkey %x %q", parent, desc)
56 hashDebug.Unlock()
57 }
58 return out
59 }
60
61
62
63 func NewHash(name string) *Hash {
64 h := &Hash{h: sha256.New(), name: name}
65 if debugHash {
66 fmt.Fprintf(os.Stderr, "HASH[%s]\n", h.name)
67 }
68 h.Write(hashSalt)
69 if verify {
70 h.buf = new(bytes.Buffer)
71 }
72 return h
73 }
74
75
76 func (h *Hash) Write(b []byte) (int, error) {
77 if debugHash {
78 fmt.Fprintf(os.Stderr, "HASH[%s]: %q\n", h.name, b)
79 }
80 if h.buf != nil {
81 h.buf.Write(b)
82 }
83 return h.h.Write(b)
84 }
85
86
87 func (h *Hash) Sum() [HashSize]byte {
88 var out [HashSize]byte
89 h.h.Sum(out[:0])
90 if debugHash {
91 fmt.Fprintf(os.Stderr, "HASH[%s]: %x\n", h.name, out)
92 }
93 if h.buf != nil {
94 hashDebug.Lock()
95 if hashDebug.m == nil {
96 hashDebug.m = make(map[[HashSize]byte]string)
97 }
98 hashDebug.m[out] = h.buf.String()
99 hashDebug.Unlock()
100 }
101 return out
102 }
103
104
105
106
107
108 var hashDebug struct {
109 sync.Mutex
110 m map[[HashSize]byte]string
111 }
112
113
114 func reverseHash(id [HashSize]byte) string {
115 hashDebug.Lock()
116 s := hashDebug.m[id]
117 hashDebug.Unlock()
118 return s
119 }
120
121 var hashFileCache struct {
122 sync.Mutex
123 m map[string][HashSize]byte
124 }
125
126
127
128
129
130
131
132 func FileHash(file string) ([HashSize]byte, error) {
133 hashFileCache.Lock()
134 out, ok := hashFileCache.m[file]
135 hashFileCache.Unlock()
136
137 if ok {
138 return out, nil
139 }
140
141 h := sha256.New()
142 f, err := os.Open(file)
143 if err != nil {
144 if debugHash {
145 fmt.Fprintf(os.Stderr, "HASH %s: %v\n", file, err)
146 }
147 return [HashSize]byte{}, err
148 }
149 _, err = io.Copy(h, f)
150 f.Close()
151 if err != nil {
152 if debugHash {
153 fmt.Fprintf(os.Stderr, "HASH %s: %v\n", file, err)
154 }
155 return [HashSize]byte{}, err
156 }
157 h.Sum(out[:0])
158 if debugHash {
159 fmt.Fprintf(os.Stderr, "HASH %s: %x\n", file, out)
160 }
161
162 SetFileHash(file, out)
163 return out, nil
164 }
165
166
167 func SetFileHash(file string, sum [HashSize]byte) {
168 hashFileCache.Lock()
169 if hashFileCache.m == nil {
170 hashFileCache.m = make(map[string][HashSize]byte)
171 }
172 hashFileCache.m[file] = sum
173 hashFileCache.Unlock()
174 }
175
View as plain text