...
1 package main
2
3 import (
4 "flag"
5 "fmt"
6 "io"
7 "log"
8 "os"
9
10 "github.com/docker/distribution/version"
11 "github.com/opencontainers/go-digest"
12
13 _ "crypto/sha256"
14 _ "crypto/sha512"
15 )
16
17 var (
18 algorithm = digest.Canonical
19 showVersion bool
20 )
21
22 type job struct {
23 name string
24 reader io.Reader
25 }
26
27 func init() {
28 flag.Var(&algorithm, "a", "select the digest algorithm (shorthand)")
29 flag.Var(&algorithm, "algorithm", "select the digest algorithm")
30 flag.BoolVar(&showVersion, "version", false, "show the version and exit")
31
32 log.SetFlags(0)
33 log.SetPrefix(os.Args[0] + ": ")
34 }
35
36 func usage() {
37 fmt.Fprintf(os.Stderr, "usage: %s [files...]\n", os.Args[0])
38 fmt.Fprint(os.Stderr, `
39 Calculate the digest of one or more input files, emitting the result
40 to standard out. If no files are provided, the digest of stdin will
41 be calculated.
42
43 `)
44 flag.PrintDefaults()
45 }
46
47 func unsupported() {
48 log.Fatalf("unsupported digest algorithm: %v", algorithm)
49 }
50
51 func main() {
52 var jobs []job
53
54 flag.Usage = usage
55 flag.Parse()
56 if showVersion {
57 version.PrintVersion()
58 return
59 }
60
61 var fail bool
62 if flag.NArg() > 0 {
63 for _, path := range flag.Args() {
64 fp, err := os.Open(path)
65
66 if err != nil {
67 log.Printf("%s: %v", path, err)
68 fail = true
69 continue
70 }
71 defer fp.Close()
72
73 jobs = append(jobs, job{name: path, reader: fp})
74 }
75 } else {
76
77 jobs = append(jobs, job{name: "-", reader: os.Stdin})
78 }
79
80 digestFn := algorithm.FromReader
81
82 if !algorithm.Available() {
83 unsupported()
84 }
85
86 for _, job := range jobs {
87 dgst, err := digestFn(job.reader)
88 if err != nil {
89 log.Printf("%s: %v", job.name, err)
90 fail = true
91 continue
92 }
93
94 fmt.Printf("%v\t%s\n", dgst, job.name)
95 }
96
97 if fail {
98 os.Exit(1)
99 }
100 }
101
View as plain text