1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package main 6 7import ( 8 "flag" 9 "fmt" 10 "log" 11 "os" 12 "strings" 13 14 "cmd/internal/buildid" 15 "cmd/internal/telemetry/counter" 16) 17 18func usage() { 19 fmt.Fprintf(os.Stderr, "usage: go tool buildid [-w] file\n") 20 flag.PrintDefaults() 21 os.Exit(2) 22} 23 24var wflag = flag.Bool("w", false, "write build ID") 25 26func main() { 27 log.SetPrefix("buildid: ") 28 log.SetFlags(0) 29 counter.Open() 30 flag.Usage = usage 31 flag.Parse() 32 counter.Inc("buildid/invocations") 33 counter.CountFlags("buildid/flag:", *flag.CommandLine) 34 if flag.NArg() != 1 { 35 usage() 36 } 37 38 file := flag.Arg(0) 39 id, err := buildid.ReadFile(file) 40 if err != nil { 41 log.Fatal(err) 42 } 43 if !*wflag { 44 fmt.Printf("%s\n", id) 45 return 46 } 47 48 // Keep in sync with src/cmd/go/internal/work/buildid.go:updateBuildID 49 50 f, err := os.Open(file) 51 if err != nil { 52 log.Fatal(err) 53 } 54 matches, hash, err := buildid.FindAndHash(f, id, 0) 55 f.Close() 56 if err != nil { 57 log.Fatal(err) 58 } 59 60 // <= go 1.7 doesn't embed the contentID or actionID, so no slash is present 61 if !strings.Contains(id, "/") { 62 log.Fatalf("%s: build ID is a legacy format...binary too old for this tool", file) 63 } 64 65 newID := id[:strings.LastIndex(id, "/")] + "/" + buildid.HashToString(hash) 66 if len(newID) != len(id) { 67 log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID) 68 } 69 70 if len(matches) == 0 { 71 return 72 } 73 74 f, err = os.OpenFile(file, os.O_RDWR, 0) 75 if err != nil { 76 log.Fatal(err) 77 } 78 if err := buildid.Rewrite(f, matches, newID); err != nil { 79 log.Fatal(err) 80 } 81 if err := f.Close(); err != nil { 82 log.Fatal(err) 83 } 84} 85