...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package zipslicer
18
19 import (
20 "archive/tar"
21 "errors"
22 "fmt"
23 "io"
24 "io/ioutil"
25 "os"
26 )
27
28 const (
29 TarMemberCD = "zipdir.bin"
30 TarMemberZip = "contents.zip"
31 )
32
33
34
35
36
37
38 func ZipToTar(r *os.File, w io.Writer) error {
39 size, err := r.Seek(0, io.SeekEnd)
40 if err != nil {
41 return err
42 }
43 dirLoc, err := FindDirectory(r, size)
44 if err != nil {
45 return err
46 }
47 tw := tar.NewWriter(w)
48 r.Seek(dirLoc, 0)
49 if err := tarAddStream(tw, r, TarMemberCD, size-dirLoc); err != nil {
50 return err
51 }
52 r.Seek(0, 0)
53 if err := tarAddStream(tw, r, TarMemberZip, size); err != nil {
54 return err
55 }
56 return tw.Close()
57 }
58
59 func tarAddStream(tw *tar.Writer, r io.Reader, name string, size int64) error {
60 hdr := &tar.Header{Name: name, Mode: 0644, Size: size}
61 if err := tw.WriteHeader(hdr); err != nil {
62 return err
63 }
64 if _, err := io.CopyN(tw, r, size); err != nil {
65 return err
66 }
67 return nil
68 }
69
70
71
72 func ReadZipTar(r io.Reader) (*Directory, error) {
73 tr := tar.NewReader(r)
74 hdr, err := tr.Next()
75 if err != nil {
76 return nil, fmt.Errorf("error reading tar: %s", err)
77 } else if hdr.Name != TarMemberCD {
78 return nil, errors.New("invalid tarzip")
79 }
80 zipdir, err := ioutil.ReadAll(tr)
81 if err != nil {
82 return nil, fmt.Errorf("error reading tar: %s", err)
83 }
84 hdr, err = tr.Next()
85 if err != nil {
86 return nil, err
87 } else if hdr.Name != TarMemberZip {
88 return nil, errors.New("invalid tarzip")
89 }
90 zr := &zipTarReader{tr: tr}
91 return ReadStream(zr, hdr.Size, zipdir)
92 }
93
94 type zipTarReader struct {
95 tr *tar.Reader
96 }
97
98 func (z *zipTarReader) Read(d []byte) (int, error) {
99 if z.tr == nil {
100 return 0, io.EOF
101 }
102 n, err := z.tr.Read(d)
103 if err == io.EOF {
104 _, err2 := z.tr.Next()
105 if err2 == nil {
106 err = errors.New("invalid tarzip")
107 } else if err2 != io.EOF {
108 err = err2
109 }
110 z.tr = nil
111 }
112 return n, err
113 }
114
View as plain text