16 type download struct {
24 func (d *download) Boot(ctx context.Context) error {
25 fi, err := os.Stat(d.Dest)
26 if os.IsNotExist(err) {
27 // fall through to fix
28 } else if err != nil {
30 } else if d.Size > 0 && fi.Size() != d.Size {
31 err = fmt.Errorf("Size mismatch: %q is %d bytes, expected %d", d.Dest, fi.Size(), d.Size)
32 } else if d.Mode > 0 && fi.Mode() != d.Mode {
33 err = fmt.Errorf("Mode mismatch: %q is %s, expected %s", d.Dest, fi.Mode(), d.Mode)
38 defer feedbackf(ctx, "downloading %s", d.URL)()
40 out, err := ioutil.TempFile(path.Dir(d.Dest), path.Base(d.Dest))
51 resp, err := http.Get(d.URL)
55 n, err := io.Copy(out, resp.Body)
61 if strings.HasSuffix(d.URL, ".zip") && !strings.HasSuffix(d.Dest, ".zip") {
62 r, err := zip.NewReader(out, n)
66 defer os.Remove(out.Name())
70 for _, f := range r.File {
71 if !strings.HasSuffix(d.Dest, "/"+f.Name) {
80 out, err = ioutil.TempFile(path.Dir(d.Dest), path.Base(d.Dest))
85 n, err = io.Copy(out, rc)
93 return fmt.Errorf("File not found in archive")
97 if d.Size > 0 && d.Size != n {
98 return fmt.Errorf("Size mismatch: got %d bytes, expected %d", n, d.Size)
99 } else if d.Size == 0 {
100 log.Printf("%s: size was %d", d, n)
102 if err = out.Close(); err != nil {
105 if err = os.Chmod(out.Name(), d.Mode); err != nil {
108 err = os.Rename(out.Name(), d.Dest)
110 // skip deferred os.Remove(out.Name())