github.com/dara-project/godist@v0.0.0-20200823115410-e0c80c8f0c78/src/cmd/buildid/buildid.go (about)

     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  
     5  package main
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"log"
    11  	"os"
    12  	"strings"
    13  
    14  	"cmd/internal/buildid"
    15  )
    16  
    17  func usage() {
    18  	fmt.Fprintf(os.Stderr, "usage: go tool buildid [-w] file\n")
    19  	flag.PrintDefaults()
    20  	os.Exit(2)
    21  }
    22  
    23  var wflag = flag.Bool("w", false, "write build ID")
    24  
    25  // taken from cmd/go/internal/work/buildid.go
    26  func hashToString(h [32]byte) string {
    27  	const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
    28  	const chunks = 5
    29  	var dst [chunks * 4]byte
    30  	for i := 0; i < chunks; i++ {
    31  		v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2])
    32  		dst[4*i+0] = b64[(v>>18)&0x3F]
    33  		dst[4*i+1] = b64[(v>>12)&0x3F]
    34  		dst[4*i+2] = b64[(v>>6)&0x3F]
    35  		dst[4*i+3] = b64[v&0x3F]
    36  	}
    37  	return string(dst[:])
    38  }
    39  
    40  func main() {
    41  	log.SetPrefix("buildid: ")
    42  	log.SetFlags(0)
    43  	flag.Usage = usage
    44  	flag.Parse()
    45  	if flag.NArg() != 1 {
    46  		usage()
    47  	}
    48  
    49  	file := flag.Arg(0)
    50  	id, err := buildid.ReadFile(file)
    51  	if err != nil {
    52  		log.Fatal(err)
    53  	}
    54  	if !*wflag {
    55  		fmt.Printf("%s\n", id)
    56  		return
    57  	}
    58  
    59  	// Keep in sync with src/cmd/go/internal/work/buildid.go:updateBuildID
    60  
    61  	f, err := os.Open(file)
    62  	if err != nil {
    63  		log.Fatal(err)
    64  	}
    65  	matches, hash, err := buildid.FindAndHash(f, id, 0)
    66  	if err != nil {
    67  		log.Fatal(err)
    68  	}
    69  	f.Close()
    70  
    71  	newID := id[:strings.LastIndex(id, "/")] + "/" + hashToString(hash)
    72  	if len(newID) != len(id) {
    73  		log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID)
    74  	}
    75  
    76  	if len(matches) == 0 {
    77  		return
    78  	}
    79  
    80  	f, err = os.OpenFile(file, os.O_WRONLY, 0)
    81  	if err != nil {
    82  		log.Fatal(err)
    83  	}
    84  	if err := buildid.Rewrite(f, matches, newID); err != nil {
    85  		log.Fatal(err)
    86  	}
    87  	if err := f.Close(); err != nil {
    88  		log.Fatal(err)
    89  	}
    90  }