]> Cypherpunks repositories - gostls13.git/commitdiff
archive/zip: add new type ReadCloser, make OpenReader return it.
authorDmitry Chestnykh <dchest@gmail.com>
Sun, 10 Apr 2011 01:23:23 +0000 (11:23 +1000)
committerAndrew Gerrand <adg@golang.org>
Sun, 10 Apr 2011 01:23:23 +0000 (11:23 +1000)
Fixes #1678.

R=adg, rsc
CC=golang-dev
https://golang.org/cl/4372047

src/pkg/archive/zip/reader.go
src/pkg/archive/zip/reader_test.go

index 543007abfe058405b931cf41d2ab7fddc338ce83..0391d6441f84dcbc56e01ba2fa44410fd820bbcd 100644 (file)
@@ -35,6 +35,11 @@ type Reader struct {
        Comment string
 }
 
+type ReadCloser struct {
+       f *os.File
+       Reader
+}
+
 type File struct {
        FileHeader
        zipr         io.ReaderAt
@@ -47,43 +52,60 @@ func (f *File) hasDataDescriptor() bool {
        return f.Flags&0x8 != 0
 }
 
-// OpenReader will open the Zip file specified by name and return a Reader.
-func OpenReader(name string) (*Reader, os.Error) {
+// OpenReader will open the Zip file specified by name and return a ReaderCloser.
+func OpenReader(name string) (*ReadCloser, os.Error) {
        f, err := os.Open(name)
        if err != nil {
                return nil, err
        }
        fi, err := f.Stat()
        if err != nil {
+               f.Close()
+               return nil, err
+       }
+       r := new(ReadCloser)
+       if err := r.init(f, fi.Size); err != nil {
+               f.Close()
                return nil, err
        }
-       return NewReader(f, fi.Size)
+       return r, nil
 }
 
 // NewReader returns a new Reader reading from r, which is assumed to
 // have the given size in bytes.
 func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
-       end, err := readDirectoryEnd(r, size)
-       if err != nil {
+       zr := new(Reader)
+       if err := zr.init(r, size); err != nil {
                return nil, err
        }
-       z := &Reader{
-               r:       r,
-               File:    make([]*File, end.directoryRecords),
-               Comment: end.comment,
+       return zr, nil
+}
+
+func (z *Reader) init(r io.ReaderAt, size int64) os.Error {
+       end, err := readDirectoryEnd(r, size)
+       if err != nil {
+               return err
        }
+       z.r = r
+       z.File = make([]*File, end.directoryRecords)
+       z.Comment = end.comment
        rs := io.NewSectionReader(r, 0, size)
        if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
-               return nil, err
+               return err
        }
        buf := bufio.NewReader(rs)
        for i := range z.File {
                z.File[i] = &File{zipr: r, zipsize: size}
                if err := readDirectoryHeader(z.File[i], buf); err != nil {
-                       return nil, err
+                       return err
                }
        }
-       return z, nil
+       return nil
+}
+
+// Close closes the Zip file, rendering it unusable for I/O.
+func (rc *ReadCloser) Close() os.Error {
+       return rc.f.Close()
 }
 
 // Open returns a ReadCloser that provides access to the File's contents.
index 72e8cccfd47dc58c5e33e449cf13772d01cf0b43..c72cd9a2347b48162795d8535077c27640145cc5 100644 (file)
@@ -76,6 +76,12 @@ func readTestZip(t *testing.T, zt ZipTest) {
                return
        }
 
+       // bail if file is not zip
+       if err == FormatError {
+               return
+       }
+       defer z.Close()
+
        // bail here if no Files expected to be tested
        // (there may actually be files in the zip, but we don't care)
        if zt.File == nil {