mirror of
https://github.com/golang/go
synced 2024-11-21 23:44:39 -07:00
archive/zip: add functions to convert between os.FileInfo & FileHeader
Fixes #2186 R=golang-dev, gri, adg CC=golang-dev https://golang.org/cl/5579044
This commit is contained in:
parent
2a22f35598
commit
b62a5099e4
@ -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)
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user