]> Cypherpunks repositories - gostls13.git/commitdiff
archive/zip: add functions to convert between os.FileInfo & FileHeader
authorBrad Fitzpatrick <bradfitz@golang.org>
Thu, 26 Jan 2012 23:31:09 +0000 (15:31 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 26 Jan 2012 23:31:09 +0000 (15:31 -0800)
Fixes #2186

R=golang-dev, gri, adg
CC=golang-dev
https://golang.org/cl/5579044

src/pkg/archive/zip/reader_test.go
src/pkg/archive/zip/struct.go
src/pkg/archive/zip/zip_test.go

index b34f5bf1efed6cfeda432b50540f858893b28721..9407e35d5c08ce4a7bbacfad0e3ec7ed2bde02c9 100644 (file)
@@ -250,13 +250,9 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
 }
 
 func testFileMode(t *testing.T, f *File, want os.FileMode) {
-       mode, err := f.Mode()
+       mode := f.Mode()
        if want == 0 {
-               if err == nil {
-                       t.Errorf("%s mode: got %v, want none", f.Name, mode)
-               }
-       } else if err != nil {
-               t.Errorf("%s mode: %s", f.Name, err)
+               t.Errorf("%s mode: got %v, want none", f.Name, mode)
        } else if mode != want {
                t.Errorf("%s mode: want %v, got %v", f.Name, want, mode)
        }
index 34a87fae5b330596cf05d7221b939a7c8078fee6..67e9658629419a06bdbf064254735012fdd71372 100644 (file)
@@ -12,6 +12,7 @@ This package does not support ZIP64 or disk spanning.
 package zip
 
 import (
+       "errors"
        "os"
        "time"
 )
@@ -55,6 +56,38 @@ type FileHeader struct {
        Comment          string
 }
 
+// FileInfo returns an os.FileInfo for the FileHeader.
+func (fh *FileHeader) FileInfo() os.FileInfo {
+       return headerFileInfo{fh}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+       fh *FileHeader
+}
+
+func (fi headerFileInfo) Name() string       { return fi.fh.Name }
+func (fi headerFileInfo) Size() int64        { return int64(fi.fh.UncompressedSize) }
+func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
+func (fi headerFileInfo) Mode() os.FileMode  { return fi.fh.Mode() }
+
+// FileInfoHeader creates a partially-populated FileHeader from an
+// os.FileInfo.
+func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
+       size := fi.Size()
+       if size > (1<<32 - 1) {
+               return nil, errors.New("zip: file over 4GB")
+       }
+       fh := &FileHeader{
+               Name:             fi.Name(),
+               UncompressedSize: uint32(size),
+       }
+       fh.SetModTime(fi.ModTime())
+       fh.SetMode(fi.Mode())
+       return fh, nil
+}
+
 type directoryEnd struct {
        diskNbr            uint16 // unused
        dirDiskNbr         uint16 // unused
@@ -131,8 +164,7 @@ const (
 )
 
 // Mode returns the permission and mode bits for the FileHeader.
-// An error is returned in case the information is not available.
-func (h *FileHeader) Mode() (mode os.FileMode, err error) {
+func (h *FileHeader) Mode() (mode os.FileMode) {
        switch h.CreatorVersion >> 8 {
        case creatorUnix, creatorMacOSX:
                mode = unixModeToFileMode(h.ExternalAttrs >> 16)
@@ -142,7 +174,7 @@ func (h *FileHeader) Mode() (mode os.FileMode, err error) {
        if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
                mode |= os.ModeDir
        }
-       return mode, nil
+       return mode
 }
 
 // SetMode changes the permission and mode bits for the FileHeader.
index 8aab2b68123f704c4e1a255f99a3daf8f49d59b2..acd3d938218eddb9399408320a7e6a694d9e9e4a 100644 (file)
@@ -10,6 +10,7 @@ import (
        "bytes"
        "fmt"
        "io"
+       "reflect"
        "testing"
        "time"
 )
@@ -66,3 +67,22 @@ func TestModTime(t *testing.T) {
                t.Errorf("times don't match: got %s, want %s", outTime, testTime)
        }
 }
+
+func TestFileHeaderRoundTrip(t *testing.T) {
+       fh := &FileHeader{
+               Name:             "foo.txt",
+               UncompressedSize: 987654321,
+               ModifiedTime:     1234,
+               ModifiedDate:     5678,
+       }
+       fi := fh.FileInfo()
+       fh2, err := FileInfoHeader(fi)
+
+       // Ignore these fields:
+       fh2.CreatorVersion = 0
+       fh2.ExternalAttrs = 0
+
+       if !reflect.DeepEqual(fh, fh2) {
+               t.Errorf("mismatch\n input=%#v\noutput=%#v\nerr=%v", fh, fh2, err)
+       }
+}