1
0
mirror of https://github.com/golang/go synced 2024-11-19 21:04:43 -07:00

archive/zip: support full range of FileMode flags

Zip files may actually store symlinks, and that's represented
as a file with unix flag S_IFLNK and with its data containing
the symlink target name.

The other flags are being supported too. Now that the os package
has the full range of flags in a system agnostic manner, there's
no reason to discard that information.

R=golang-dev, adg, rogpeppe
CC=golang-dev
https://golang.org/cl/5624048
This commit is contained in:
Gustavo Niemeyer 2012-02-06 11:58:32 -02:00
parent 419c53af30
commit 02fb021161
4 changed files with 71 additions and 17 deletions

View File

@ -69,8 +69,23 @@ var tests = []ZipTest{
}, },
}, },
}, },
{Name: "readme.zip"}, {
{Name: "readme.notzip", Error: ErrFormat}, Name: "symlink.zip",
File: []ZipTestFile{
{
Name: "symlink",
Content: []byte("../target"),
Mode: 0777 | os.ModeSymlink,
},
},
},
{
Name: "readme.zip",
},
{
Name: "readme.notzip",
Error: ErrFormat,
},
{ {
Name: "dd.zip", Name: "dd.zip",
File: []ZipTestFile{ File: []ZipTestFile{

View File

@ -152,13 +152,20 @@ func (h *FileHeader) SetModTime(t time.Time) {
h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t) h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t)
} }
// traditional names for Unix constants
const ( const (
// Unix constants. The specification doesn't mention them,
// but these seem to be the values agreed on by tools.
s_IFMT = 0xf000 s_IFMT = 0xf000
s_IFDIR = 0x4000 s_IFSOCK = 0xc000
s_IFLNK = 0xa000
s_IFREG = 0x8000 s_IFREG = 0x8000
s_IFBLK = 0x6000
s_IFDIR = 0x4000
s_IFCHR = 0x2000
s_IFIFO = 0x1000
s_ISUID = 0x800 s_ISUID = 0x800
s_ISGID = 0x400 s_ISGID = 0x400
s_ISVTX = 0x200
msdosDir = 0x10 msdosDir = 0x10
msdosReadOnly = 0x01 msdosReadOnly = 0x01
@ -206,10 +213,23 @@ func msdosModeToFileMode(m uint32) (mode os.FileMode) {
func fileModeToUnixMode(mode os.FileMode) uint32 { func fileModeToUnixMode(mode os.FileMode) uint32 {
var m uint32 var m uint32
if mode&os.ModeDir != 0 { switch mode & os.ModeType {
m = s_IFDIR default:
} else {
m = s_IFREG m = s_IFREG
case os.ModeDir:
m = s_IFDIR
case os.ModeSymlink:
m = s_IFLNK
case os.ModeNamedPipe:
m = s_IFIFO
case os.ModeSocket:
m = s_IFSOCK
case os.ModeDevice:
if mode&os.ModeCharDevice != 0 {
m = s_IFCHR
} else {
m = s_IFBLK
}
} }
if mode&os.ModeSetuid != 0 { if mode&os.ModeSetuid != 0 {
m |= s_ISUID m |= s_ISUID
@ -217,13 +237,29 @@ func fileModeToUnixMode(mode os.FileMode) uint32 {
if mode&os.ModeSetgid != 0 { if mode&os.ModeSetgid != 0 {
m |= s_ISGID m |= s_ISGID
} }
if mode&os.ModeSticky != 0 {
m |= s_ISVTX
}
return m | uint32(mode&0777) return m | uint32(mode&0777)
} }
func unixModeToFileMode(m uint32) os.FileMode { func unixModeToFileMode(m uint32) os.FileMode {
var mode os.FileMode mode := os.FileMode(m & 0777)
if m&s_IFMT == s_IFDIR { switch m & s_IFMT {
case s_IFBLK:
mode |= os.ModeDevice
case s_IFCHR:
mode |= os.ModeDevice | os.ModeCharDevice
case s_IFDIR:
mode |= os.ModeDir mode |= os.ModeDir
case s_IFIFO:
mode |= os.ModeNamedPipe
case s_IFLNK:
mode |= os.ModeSymlink
case s_IFREG:
// nothing to do
case s_IFSOCK:
mode |= os.ModeSocket
} }
if m&s_ISGID != 0 { if m&s_ISGID != 0 {
mode |= os.ModeSetgid mode |= os.ModeSetgid
@ -231,5 +267,8 @@ func unixModeToFileMode(m uint32) os.FileMode {
if m&s_ISUID != 0 { if m&s_ISUID != 0 {
mode |= os.ModeSetuid mode |= os.ModeSetuid
} }
return mode | os.FileMode(m&0777) if m&s_ISVTX != 0 {
mode |= os.ModeSticky
}
return mode
} }

BIN
src/pkg/archive/zip/testdata/symlink.zip vendored Normal file

Binary file not shown.

View File

@ -47,10 +47,10 @@ var writeTests = []WriteTest{
Mode: 0755 | os.ModeSetgid, Mode: 0755 | os.ModeSetgid,
}, },
{ {
Name: "setgid", Name: "symlink",
Data: []byte("setgid file"), Data: []byte("../link/target"),
Method: Deflate, Method: Deflate,
Mode: 0755 | os.ModeSetgid, Mode: 0755 | os.ModeSymlink,
}, },
} }