/
hash-file.go
110 lines (100 loc) · 3.24 KB
/
hash-file.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
package main
import (
"github.com/csm/vapor-modules"
"github.com/csm/go-edn/types"
"bufio"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"errors"
"fmt"
"hash"
"io"
"os"
"strings"
)
type HashFile struct{}
func (this HashFile) Doc() string {
return "Hash a file on the host. Requires an input map containing at least :file, a string giving the path of the file to hash. :hash is optional, a string, keyword, or symbol naming the hash function to use; if no :hash is given, uses SHA-256."
}
func (this HashFile) TakesInput() bool {
return true
}
func (this HashFile) Exec(input types.Value) (out types.Value, err error) {
var inputMap types.Map
if i, ok := input.(types.Map); ok {
inputMap = i
} else {
err = errors.New(fmt.Sprintf("expected a map as input, got a %T", input))
return
}
var hashName string
var hashNameElement = inputMap[types.Keyword("hash")]
if hashNameElement == nil {
hashName = "sha256"
} else if h, ok := hashNameElement.(types.String); ok {
hashName = string(h)
} else if k, ok := hashNameElement.(types.Keyword); ok {
hashName = string(k)
} else if s, ok := hashNameElement.(types.Symbol); ok {
hashName = string(s)
} else {
err = errors.New(":hash must be a string, keyword, or symbol if specified")
return
}
hashName = strings.ToLower(hashName)
var hash hash.Hash
if (hashName == "md5") {
hash = md5.New()
} else if (hashName == "sha" || hashName == "sha1" || hashName == "sha-1") {
hash = sha1.New()
} else if (hashName == "sha224" || hashName == "sha-224") {
hash = sha256.New224()
} else if (hashName == "sha256" || hashName == "sha-256") {
hash = sha256.New()
} else if (hashName == "sha384" || hashName == "sha-384") {
hash = sha512.New384()
} else if (hashName == "sha512/224" || hashName == "sha-512/224") {
hash = sha512.New512_224()
} else if (hashName == "sha512/256" || hashName == "sha-512/256") {
hash = sha512.New512_256()
} else if (hashName == "sha512" || hashName == "sha-512") {
hash = sha512.New()
} else {
err = errors.New(fmt.Sprint("unknown hash name: ", hashName))
return
}
var fileName string
var fileElem = inputMap[types.Keyword("file")]
if fileElem == nil {
err = errors.New(":file argument is required")
return
} else if f, ok := fileElem.(types.String); ok {
fileName = string(f)
} else {
err = errors.New(":file argument must be a string")
return
}
file, err := os.Open(fileName)
if err != nil {
return
}
hashOut := bufio.NewWriterSize(hash, hash.BlockSize())
wrote, err := io.Copy(hashOut, file)
hashOut.Flush()
if err != nil {
return
}
out = types.Map{
types.Keyword("success"): types.Bool(true),
types.Keyword("size"): types.Int(wrote),
types.Keyword("file"): types.String(fileName),
types.Keyword("hash"): types.Keyword(hashName),
types.Keyword("digest"): types.String(fmt.Sprintf("%x", hash.Sum(nil))),
}
return
}
func main() {
vapor.RunModule(HashFile{})
}