// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "flag" "fmt" "log" "os" "strings" "cmd/internal/buildid" ) func usage() { fmt.Fprintf(os.Stderr, "usage: go tool buildid [-w] file\n") flag.PrintDefaults() os.Exit(2) } var wflag = flag.Bool("w", false, "write build ID") // taken from cmd/go/internal/work/buildid.go func hashToString(h [32]byte) string { const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" const chunks = 5 var dst [chunks * 4]byte for i := 0; i < chunks; i++ { v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2]) dst[4*i+0] = b64[(v>>18)&0x3F] dst[4*i+1] = b64[(v>>12)&0x3F] dst[4*i+2] = b64[(v>>6)&0x3F] dst[4*i+3] = b64[v&0x3F] } return string(dst[:]) } func main() { log.SetPrefix("buildid: ") log.SetFlags(0) flag.Usage = usage flag.Parse() if flag.NArg() != 1 { usage() } file := flag.Arg(0) id, err := buildid.ReadFile(file) if err != nil { log.Fatal(err) } if !*wflag { fmt.Printf("%s\n", id) return } // Keep in sync with src/cmd/go/internal/work/buildid.go:updateBuildID f, err := os.Open(file) if err != nil { log.Fatal(err) } matches, hash, err := buildid.FindAndHash(f, id, 0) if err != nil { log.Fatal(err) } f.Close() newID := id[:strings.LastIndex(id, "/")] + "/" + hashToString(hash) if len(newID) != len(id) { log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID) } if len(matches) == 0 { return } f, err = os.OpenFile(file, os.O_WRONLY, 0) if err != nil { log.Fatal(err) } if err := buildid.Rewrite(f, matches, newID); err != nil { log.Fatal(err) } if err := f.Close(); err != nil { log.Fatal(err) } }