github.com/quay/claircore@v1.5.28/java/jar/fetch_testdata.go (about)

     1  //go:build tools
     2  
     3  // Fetch is the script used to populate the stuff in testdir. This extracts a
     4  // Cassandra distribution to do so, so unfortunately the URL hard-coded here
     5  // needs to be kept in sync with the one in the actual test.
     6  package main
     7  
     8  import (
     9  	"archive/tar"
    10  	"archive/zip"
    11  	"bytes"
    12  	"compress/gzip"
    13  	"errors"
    14  	"io"
    15  	"log"
    16  	"net/http"
    17  	"os"
    18  	"path/filepath"
    19  )
    20  
    21  const (
    22  	url = `https://archive.apache.org/dist/cassandra/4.0.0/apache-cassandra-4.0.0-bin.tar.gz`
    23  )
    24  
    25  func main() {
    26  	log.Println("fetching", url)
    27  	res, err := http.Get(url)
    28  	if !errors.Is(err, nil) {
    29  		log.Fatal(err)
    30  	}
    31  	defer res.Body.Close()
    32  	if res.StatusCode != http.StatusOK {
    33  		log.Fatalf("unexpected HTTP status: %v", res.Status)
    34  	}
    35  	if err := os.MkdirAll("testdata/manifest", 0755); err != nil {
    36  		log.Fatal(err)
    37  	}
    38  	if err := os.MkdirAll("testdata/properties", 0755); err != nil {
    39  		log.Fatal(err)
    40  	}
    41  
    42  	gz, err := gzip.NewReader(res.Body)
    43  	if !errors.Is(err, nil) {
    44  		log.Fatal(err)
    45  	}
    46  	defer gz.Close()
    47  	t := tar.NewReader(gz)
    48  
    49  	var h *tar.Header
    50  	var buf bytes.Buffer
    51  	for h, err = t.Next(); err == nil; h, err = t.Next() {
    52  		if filepath.Ext(h.Name) != ".jar" {
    53  			continue
    54  		}
    55  		buf.Grow(int(h.Size))
    56  		if _, err := buf.ReadFrom(t); err != nil {
    57  			log.Fatal(err)
    58  		}
    59  		rd := bytes.NewReader(buf.Bytes())
    60  		if err := extractManifest("testdata/manifest", rd, h); err != nil {
    61  			log.Fatal(err)
    62  		}
    63  		if err := extractProperties("testdata/properties", rd, h); err != nil {
    64  			log.Fatal(err)
    65  		}
    66  		buf.Reset()
    67  	}
    68  	if !errors.Is(err, io.EOF) {
    69  		log.Fatal(err)
    70  	}
    71  }
    72  
    73  func extractManifest(prefix string, rd *bytes.Reader, h *tar.Header) error {
    74  	const manifest = "META-INF/MANIFEST.MF"
    75  
    76  	z, err := zip.NewReader(rd, rd.Size())
    77  	if err != nil {
    78  		return err
    79  	}
    80  	f, err := z.Open(manifest)
    81  	if err != nil {
    82  		// ???
    83  		log.Printf("%s: no manifest", h.Name)
    84  		return nil
    85  	}
    86  	defer f.Close()
    87  
    88  	outname := filepath.Join(prefix, filepath.Base(h.Name))
    89  	o, err := os.Create(outname)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	defer o.Close()
    94  	log.Printf("%s: extracting %q to %q", h.Name, manifest, o.Name())
    95  	if _, err := io.Copy(o, f); err != nil {
    96  		return err
    97  	}
    98  	return nil
    99  }
   100  
   101  func extractProperties(prefix string, rd *bytes.Reader, h *tar.Header) error {
   102  	z, err := zip.NewReader(rd, rd.Size())
   103  	if err != nil {
   104  		return err
   105  	}
   106  	found := false
   107  	for _, f := range z.File {
   108  		if filepath.Base(f.Name) != "pom.properties" {
   109  			continue
   110  		}
   111  		rd, err := f.Open()
   112  		if err != nil {
   113  			return err
   114  		}
   115  		defer rd.Close()
   116  		outname := filepath.Join(prefix, filepath.Base(h.Name))
   117  		o, err := os.Create(outname)
   118  		if err != nil {
   119  			return err
   120  		}
   121  		defer o.Close()
   122  		log.Printf("%s: extracting %q to %q", h.Name, f.Name, o.Name())
   123  		if _, err := io.Copy(o, rd); err != nil {
   124  			return err
   125  		}
   126  		found = true
   127  		// It's bad form to let these defers pile up, but this is just a script.
   128  	}
   129  	if !found {
   130  		log.Printf("%s: no properties", h.Name)
   131  	}
   132  	return nil
   133  }