You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.9 KiB
133 lines
3.9 KiB
//go:build ignore
|
|
|
|
// Prints src/lib/dkc/testing/zip-vectors.json: how archive/zip of the Go
|
|
// standard library reads the ZIP samples that the page writes (plan of
|
|
// format 3 in datekeys-ts, step 5), which scripts/zip-ts-samples.mjs wrote
|
|
// into a directory. For each archive it records the SHA-256 of its bytes,
|
|
// the number of its entries and, for each entry, a line with its name,
|
|
// whether bit 11 marks the name as UTF-8, its method, its CRC-32, its sizes,
|
|
// the time archive/zip reads from its extra fields, in UTC, and the SHA-256
|
|
// of its content, read with the CRC-32 checked. It keeps the lines of an
|
|
// archive of 20 entries at most, and the SHA-256 of all of them joined by
|
|
// newlines for any archive, so that the archive of 65535 entries, which is
|
|
// ZIP64 by its number of entries, weighs little. zipsink.test.ts writes each
|
|
// archive again, requires its SHA-256, and computes the lines it must give.
|
|
//
|
|
// It needs only the standard library:
|
|
//
|
|
// node scripts/zip-ts-samples.mjs DIR > zip-samples.json
|
|
// go run zip-go-read.go DIR zip-samples.json > zip-vectors.json
|
|
package main
|
|
|
|
import (
|
|
"archive/zip"
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type sampleIn struct {
|
|
Name string `json:"name"`
|
|
File string `json:"file"`
|
|
SHA256 string `json:"sha256"`
|
|
}
|
|
|
|
type sampleOut struct {
|
|
Name string `json:"name"`
|
|
SHA256 string `json:"sha256"`
|
|
Count int `json:"count"`
|
|
LinesSHA256 string `json:"lines_sha256"`
|
|
Lines []string `json:"lines,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
type output struct {
|
|
Description string `json:"description"`
|
|
Generator string `json:"generator"`
|
|
SamplesGenerator string `json:"samples_generator"`
|
|
Go string `json:"go"`
|
|
Samples []sampleOut `json:"samples"`
|
|
}
|
|
|
|
func must[T any](v T, err error) T {
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return v
|
|
}
|
|
|
|
// read reads an archive with archive/zip, and gives one line for each entry.
|
|
func read(b []byte) ([]string, error) {
|
|
r, err := zip.NewReader(bytes.NewReader(b), int64(len(b)))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var lines []string
|
|
for _, f := range r.File {
|
|
rc, err := f.Open()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s: %w", f.Name, err)
|
|
}
|
|
data, err := io.ReadAll(rc)
|
|
rc.Close()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s: %w", f.Name, err)
|
|
}
|
|
sum := sha256.Sum256(data)
|
|
lines = append(lines, fmt.Sprintf("%s\t%t\t%d\t%08x\t%d\t%d\t%s\t%s",
|
|
f.Name, f.Flags&0x800 != 0, f.Method, f.CRC32, f.UncompressedSize64, f.CompressedSize64,
|
|
f.Modified.UTC().Format(time.RFC3339), hex.EncodeToString(sum[:])))
|
|
}
|
|
return lines, nil
|
|
}
|
|
|
|
func main() {
|
|
dir := os.Args[1]
|
|
var in struct {
|
|
Generator string `json:"generator"`
|
|
Samples []sampleIn `json:"samples"`
|
|
}
|
|
if err := json.Unmarshal(must(os.ReadFile(os.Args[2])), &in); err != nil {
|
|
panic(err)
|
|
}
|
|
out := output{
|
|
Description: "How archive/zip of Go reads the ZIP samples of the page; see the header of scripts/zip-go-read.go.",
|
|
Generator: "scripts/zip-go-read.go",
|
|
SamplesGenerator: in.Generator,
|
|
Go: runtime.Version(),
|
|
}
|
|
for _, s := range in.Samples {
|
|
b := must(os.ReadFile(filepath.Join(dir, s.File)))
|
|
sum := sha256.Sum256(b)
|
|
so := sampleOut{Name: s.Name, SHA256: hex.EncodeToString(sum[:])}
|
|
if so.SHA256 != s.SHA256 {
|
|
panic(fmt.Sprintf("%s: the file is not the sample written", s.Name))
|
|
}
|
|
lines, err := read(b)
|
|
if err != nil {
|
|
so.Error = err.Error()
|
|
}
|
|
so.Count = len(lines)
|
|
all := sha256.Sum256([]byte(strings.Join(lines, "\n")))
|
|
so.LinesSHA256 = hex.EncodeToString(all[:])
|
|
if len(lines) <= 20 {
|
|
so.Lines = lines
|
|
}
|
|
out.Samples = append(out.Samples, so)
|
|
}
|
|
e := json.NewEncoder(os.Stdout)
|
|
e.SetEscapeHTML(false)
|
|
e.SetIndent("", " ")
|
|
if err := e.Encode(out); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|