Source file src/cmd/go/internal/fips140/mkzip.go

     1  // Copyright 2024 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  //go:build ignore
     6  
     7  // Mkzip creates a FIPS snapshot zip file.
     8  // See GOROOT/lib/fips140/README.md and GOROOT/lib/fips140/Makefile
     9  // for more details about when and why to use this.
    10  //
    11  // Usage:
    12  //
    13  //	cd GOROOT/lib/fips140
    14  //	go run ../../src/cmd/go/internal/fips140/mkzip.go [-b branch] v1.2.3
    15  //
    16  // Mkzip creates a zip file named for the version on the command line
    17  // using the sources in the named branch (default origin/master,
    18  // to avoid accidentally including local commits).
    19  package main
    20  
    21  import (
    22  	"archive/zip"
    23  	"bytes"
    24  	"flag"
    25  	"fmt"
    26  	"io"
    27  	"log"
    28  	"os"
    29  	"path/filepath"
    30  	"regexp"
    31  	"strings"
    32  
    33  	"golang.org/x/mod/module"
    34  	modzip "golang.org/x/mod/zip"
    35  )
    36  
    37  var flagBranch = flag.String("b", "origin/master", "branch to use")
    38  
    39  func usage() {
    40  	fmt.Fprintf(os.Stderr, "usage: go run mkzip.go [-b branch] vX.Y.Z\n")
    41  	os.Exit(2)
    42  }
    43  
    44  func main() {
    45  	log.SetFlags(0)
    46  	log.SetPrefix("mkzip: ")
    47  	flag.Usage = usage
    48  	flag.Parse()
    49  	if flag.NArg() != 1 {
    50  		usage()
    51  	}
    52  
    53  	// Must run in the lib/fips140 directory, where the snapshots live.
    54  	wd, err := os.Getwd()
    55  	if err != nil {
    56  		log.Fatal(err)
    57  	}
    58  	if !strings.HasSuffix(filepath.ToSlash(wd), "lib/fips140") {
    59  		log.Fatalf("must be run in lib/fips140 directory")
    60  	}
    61  
    62  	// Must have valid version, and must not overwrite existing file.
    63  	version := flag.Arg(0)
    64  	if !regexp.MustCompile(`^v\d+\.\d+\.\d+$`).MatchString(version) {
    65  		log.Fatalf("invalid version %q; must be vX.Y.Z", version)
    66  	}
    67  	if _, err := os.Stat(version + ".zip"); err == nil {
    68  		log.Fatalf("%s.zip already exists", version)
    69  	}
    70  
    71  	// Make standard module zip file in memory.
    72  	// The module path "golang.org/fips140" needs to be a valid module name,
    73  	// and it is the path where the zip file will be unpacked in the module cache.
    74  	// The path must begin with a domain name to satisfy the module validation rules,
    75  	// but otherwise the path is not used. The cmd/go code using these zips
    76  	// knows that the zip contains crypto/internal/fips140.
    77  	goroot := "../.."
    78  	var zbuf bytes.Buffer
    79  	err = modzip.CreateFromVCS(&zbuf,
    80  		module.Version{Path: "golang.org/fips140", Version: version},
    81  		goroot, *flagBranch, "src/crypto/internal/fips140")
    82  	if err != nil {
    83  		log.Fatal(err)
    84  	}
    85  
    86  	// Write new zip file with longer paths: fips140/v1.2.3/foo.go instead of foo.go.
    87  	// That way we can bind the fips140 directory onto the
    88  	// GOROOT/src/crypto/internal/fips140 directory and get a
    89  	// crypto/internal/fips140/v1.2.3 with the snapshot code
    90  	// and an otherwise empty crypto/internal/fips140 directory.
    91  	zr, err := zip.NewReader(bytes.NewReader(zbuf.Bytes()), int64(zbuf.Len()))
    92  	if err != nil {
    93  		log.Fatal(err)
    94  	}
    95  
    96  	var zbuf2 bytes.Buffer
    97  	zw := zip.NewWriter(&zbuf2)
    98  	for _, f := range zr.File {
    99  		// golang.org/fips140@v1.2.3/dir/file.go ->
   100  		// golang.org/fips140@v1.2.3/fips140/v1.2.3/dir/file.go
   101  		if f.Name != "golang.org/fips140@"+version+"/LICENSE" {
   102  			f.Name = "golang.org/fips140@" + version + "/fips140/" + version +
   103  				strings.TrimPrefix(f.Name, "golang.org/fips140@"+version)
   104  		}
   105  		wf, err := zw.CreateRaw(&f.FileHeader)
   106  		if err != nil {
   107  			log.Fatal(err)
   108  		}
   109  		rf, err := f.OpenRaw()
   110  		if err != nil {
   111  			log.Fatal(err)
   112  		}
   113  		if _, err := io.Copy(wf, rf); err != nil {
   114  			log.Fatal(err)
   115  		}
   116  	}
   117  	if err := zw.Close(); err != nil {
   118  		log.Fatal(err)
   119  	}
   120  
   121  	err = os.WriteFile(version+".zip", zbuf2.Bytes(), 0666)
   122  	if err != nil {
   123  		log.Fatal(err)
   124  	}
   125  
   126  	log.Printf("wrote %s.zip", version)
   127  }
   128  

View as plain text