2015-08-20 19:39:50 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
|
2020-08-24 11:18:39 +00:00
|
|
|
"github.com/distribution/distribution/v3/version"
|
2016-12-17 00:28:34 +00:00
|
|
|
"github.com/opencontainers/go-digest"
|
2017-10-14 04:31:21 +00:00
|
|
|
|
|
|
|
_ "crypto/sha256"
|
|
|
|
_ "crypto/sha512"
|
2015-08-20 19:39:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
algorithm = digest.Canonical
|
|
|
|
showVersion bool
|
|
|
|
)
|
|
|
|
|
|
|
|
type job struct {
|
|
|
|
name string
|
|
|
|
reader io.Reader
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
flag.Var(&algorithm, "a", "select the digest algorithm (shorthand)")
|
|
|
|
flag.Var(&algorithm, "algorithm", "select the digest algorithm")
|
|
|
|
flag.BoolVar(&showVersion, "version", false, "show the version and exit")
|
|
|
|
|
|
|
|
log.SetFlags(0)
|
|
|
|
log.SetPrefix(os.Args[0] + ": ")
|
|
|
|
}
|
|
|
|
|
|
|
|
func usage() {
|
|
|
|
fmt.Fprintf(os.Stderr, "usage: %s [files...]\n", os.Args[0])
|
2017-02-16 02:57:21 +00:00
|
|
|
fmt.Fprint(os.Stderr, `
|
2015-08-20 19:39:50 +00:00
|
|
|
Calculate the digest of one or more input files, emitting the result
|
|
|
|
to standard out. If no files are provided, the digest of stdin will
|
|
|
|
be calculated.
|
|
|
|
|
|
|
|
`)
|
|
|
|
flag.PrintDefaults()
|
|
|
|
}
|
|
|
|
|
|
|
|
func unsupported() {
|
|
|
|
log.Fatalf("unsupported digest algorithm: %v", algorithm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
var jobs []job
|
|
|
|
|
|
|
|
flag.Usage = usage
|
|
|
|
flag.Parse()
|
|
|
|
if showVersion {
|
|
|
|
version.PrintVersion()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var fail bool // if we fail on one item, foul the exit code
|
|
|
|
if flag.NArg() > 0 {
|
|
|
|
for _, path := range flag.Args() {
|
|
|
|
fp, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("%s: %v", path, err)
|
|
|
|
fail = true
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
defer fp.Close()
|
|
|
|
|
|
|
|
jobs = append(jobs, job{name: path, reader: fp})
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// just read stdin
|
|
|
|
jobs = append(jobs, job{name: "-", reader: os.Stdin})
|
|
|
|
}
|
|
|
|
|
|
|
|
digestFn := algorithm.FromReader
|
|
|
|
|
|
|
|
if !algorithm.Available() {
|
2015-12-16 01:18:13 +00:00
|
|
|
unsupported()
|
2015-08-20 19:39:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, job := range jobs {
|
|
|
|
dgst, err := digestFn(job.reader)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("%s: %v", job.name, err)
|
|
|
|
fail = true
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("%v\t%s\n", dgst, job.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
if fail {
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|