mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
archive/zip: make zip understand os.FileMode.
Fixes implicit dependency on underlying os file modes. R=rsc, r, n13m3y3r, gustavo, adg CC=golang-dev https://golang.org/cl/5440130
This commit is contained in:
parent
68ec347c16
commit
2cb1aa4681
5 changed files with 153 additions and 23 deletions
|
|
@ -12,7 +12,7 @@ This package does not support ZIP64 or disk spanning.
|
|||
package zip
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -32,7 +32,11 @@ const (
|
|||
dataDescriptorLen = 12
|
||||
|
||||
// Constants for the first byte in CreatorVersion
|
||||
creatorUnix = 3
|
||||
creatorFAT = 0
|
||||
creatorUnix = 3
|
||||
creatorNTFS = 11
|
||||
creatorVFAT = 14
|
||||
creatorMacOSX = 19
|
||||
)
|
||||
|
||||
type FileHeader struct {
|
||||
|
|
@ -98,17 +102,85 @@ func (h *FileHeader) ModTime() time.Time {
|
|||
return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
|
||||
}
|
||||
|
||||
// traditional names for Unix constants
|
||||
const (
|
||||
s_IFMT = 0xf000
|
||||
s_IFDIR = 0x4000
|
||||
s_IFREG = 0x8000
|
||||
s_ISUID = 0x800
|
||||
s_ISGID = 0x400
|
||||
|
||||
msdosDir = 0x10
|
||||
msdosReadOnly = 0x01
|
||||
)
|
||||
|
||||
// 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 uint32, err error) {
|
||||
if h.CreatorVersion>>8 == creatorUnix {
|
||||
return h.ExternalAttrs >> 16, nil
|
||||
func (h *FileHeader) Mode() (mode os.FileMode, err error) {
|
||||
switch h.CreatorVersion >> 8 {
|
||||
case creatorUnix, creatorMacOSX:
|
||||
mode = unixModeToFileMode(h.ExternalAttrs >> 16)
|
||||
case creatorNTFS, creatorVFAT, creatorFAT:
|
||||
mode = msdosModeToFileMode(h.ExternalAttrs)
|
||||
}
|
||||
return 0, errors.New("file mode not available")
|
||||
if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
|
||||
mode |= os.ModeDir
|
||||
}
|
||||
return mode, nil
|
||||
}
|
||||
|
||||
// SetMode changes the permission and mode bits for the FileHeader.
|
||||
func (h *FileHeader) SetMode(mode uint32) {
|
||||
func (h *FileHeader) SetMode(mode os.FileMode) {
|
||||
h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
|
||||
h.ExternalAttrs = mode << 16
|
||||
h.ExternalAttrs = fileModeToUnixMode(mode) << 16
|
||||
|
||||
// set MSDOS attributes too, as the original zip does.
|
||||
if mode&os.ModeDir != 0 {
|
||||
h.ExternalAttrs |= msdosDir
|
||||
}
|
||||
if mode&0200 == 0 {
|
||||
h.ExternalAttrs |= msdosReadOnly
|
||||
}
|
||||
}
|
||||
|
||||
func msdosModeToFileMode(m uint32) (mode os.FileMode) {
|
||||
if m&msdosDir != 0 {
|
||||
mode = os.ModeDir | 0777
|
||||
} else {
|
||||
mode = 0666
|
||||
}
|
||||
if m&msdosReadOnly != 0 {
|
||||
mode &^= 0222
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
func fileModeToUnixMode(mode os.FileMode) uint32 {
|
||||
var m uint32
|
||||
if mode&os.ModeDir != 0 {
|
||||
m = s_IFDIR
|
||||
} else {
|
||||
m = s_IFREG
|
||||
}
|
||||
if mode&os.ModeSetuid != 0 {
|
||||
m |= s_ISUID
|
||||
}
|
||||
if mode&os.ModeSetgid != 0 {
|
||||
m |= s_ISGID
|
||||
}
|
||||
return m | uint32(mode&0777)
|
||||
}
|
||||
|
||||
func unixModeToFileMode(m uint32) os.FileMode {
|
||||
var mode os.FileMode
|
||||
if m&s_IFMT == s_IFDIR {
|
||||
mode |= os.ModeDir
|
||||
}
|
||||
if m&s_ISGID != 0 {
|
||||
mode |= os.ModeSetgid
|
||||
}
|
||||
if m&s_ISUID != 0 {
|
||||
mode |= os.ModeSetuid
|
||||
}
|
||||
return mode | os.FileMode(m&0777)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue