mirror of
https://github.com/golang/go
synced 2024-11-22 05:54:40 -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) {
|
func testFileMode(t *testing.T, f *File, want os.FileMode) {
|
||||||
mode, err := f.Mode()
|
mode := f.Mode()
|
||||||
if want == 0 {
|
if want == 0 {
|
||||||
if err == nil {
|
t.Errorf("%s mode: got %v, want none", f.Name, mode)
|
||||||
t.Errorf("%s mode: got %v, want none", f.Name, mode)
|
|
||||||
}
|
|
||||||
} else if err != nil {
|
|
||||||
t.Errorf("%s mode: %s", f.Name, err)
|
|
||||||
} else if mode != want {
|
} else if mode != want {
|
||||||
t.Errorf("%s mode: want %v, got %v", f.Name, want, mode)
|
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
|
package zip
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -55,6 +56,38 @@ type FileHeader struct {
|
|||||||
Comment string
|
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 {
|
type directoryEnd struct {
|
||||||
diskNbr uint16 // unused
|
diskNbr uint16 // unused
|
||||||
dirDiskNbr uint16 // unused
|
dirDiskNbr uint16 // unused
|
||||||
@ -131,8 +164,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Mode returns the permission and mode bits for the FileHeader.
|
// 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) {
|
||||||
func (h *FileHeader) Mode() (mode os.FileMode, err error) {
|
|
||||||
switch h.CreatorVersion >> 8 {
|
switch h.CreatorVersion >> 8 {
|
||||||
case creatorUnix, creatorMacOSX:
|
case creatorUnix, creatorMacOSX:
|
||||||
mode = unixModeToFileMode(h.ExternalAttrs >> 16)
|
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] == '/' {
|
if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
|
||||||
mode |= os.ModeDir
|
mode |= os.ModeDir
|
||||||
}
|
}
|
||||||
return mode, nil
|
return mode
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMode changes the permission and mode bits for the FileHeader.
|
// SetMode changes the permission and mode bits for the FileHeader.
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -66,3 +67,22 @@ func TestModTime(t *testing.T) {
|
|||||||
t.Errorf("times don't match: got %s, want %s", outTime, testTime)
|
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