aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Niemeyer <gustavo@niemeyer.net>2012-02-06 11:58:32 -0200
committerGustavo Niemeyer <gustavo@niemeyer.net>2012-02-06 11:58:32 -0200
commit02fb021161cf36cf7326380fb1ff9239cd195067 (patch)
treed8ff41f7d9402eb516259267370e12f6714628d1
parent419c53af30c1898a75ac0ef5ba49533ea91ddcfc (diff)
downloadgo-02fb021161cf36cf7326380fb1ff9239cd195067.tar.gz
go-02fb021161cf36cf7326380fb1ff9239cd195067.zip
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
-rw-r--r--src/pkg/archive/zip/reader_test.go19
-rw-r--r--src/pkg/archive/zip/struct.go63
-rw-r--r--src/pkg/archive/zip/testdata/symlink.zipbin0 -> 173 bytes
-rw-r--r--src/pkg/archive/zip/writer_test.go6
4 files changed, 71 insertions, 17 deletions
diff --git a/src/pkg/archive/zip/reader_test.go b/src/pkg/archive/zip/reader_test.go
index 9407e35d5c..935860e791 100644
--- a/src/pkg/archive/zip/reader_test.go
+++ b/src/pkg/archive/zip/reader_test.go
@@ -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",
File: []ZipTestFile{
diff --git a/src/pkg/archive/zip/struct.go b/src/pkg/archive/zip/struct.go
index abbe635e28..35dcec6468 100644
--- a/src/pkg/archive/zip/struct.go
+++ b/src/pkg/archive/zip/struct.go
@@ -152,13 +152,20 @@ func (h *FileHeader) SetModTime(t time.Time) {
h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t)
}
-// traditional names for Unix constants
const (
- s_IFMT = 0xf000
- s_IFDIR = 0x4000
- s_IFREG = 0x8000
- s_ISUID = 0x800
- s_ISGID = 0x400
+ // Unix constants. The specification doesn't mention them,
+ // but these seem to be the values agreed on by tools.
+ s_IFMT = 0xf000
+ s_IFSOCK = 0xc000
+ s_IFLNK = 0xa000
+ s_IFREG = 0x8000
+ s_IFBLK = 0x6000
+ s_IFDIR = 0x4000
+ s_IFCHR = 0x2000
+ s_IFIFO = 0x1000
+ s_ISUID = 0x800
+ s_ISGID = 0x400
+ s_ISVTX = 0x200
msdosDir = 0x10
msdosReadOnly = 0x01
@@ -206,10 +213,23 @@ func msdosModeToFileMode(m uint32) (mode os.FileMode) {
func fileModeToUnixMode(mode os.FileMode) uint32 {
var m uint32
- if mode&os.ModeDir != 0 {
- m = s_IFDIR
- } else {
+ switch mode & os.ModeType {
+ default:
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 {
m |= s_ISUID
@@ -217,13 +237,29 @@ func fileModeToUnixMode(mode os.FileMode) uint32 {
if mode&os.ModeSetgid != 0 {
m |= s_ISGID
}
+ if mode&os.ModeSticky != 0 {
+ m |= s_ISVTX
+ }
return m | uint32(mode&0777)
}
func unixModeToFileMode(m uint32) os.FileMode {
- var mode os.FileMode
- if m&s_IFMT == s_IFDIR {
+ mode := os.FileMode(m & 0777)
+ switch m & s_IFMT {
+ case s_IFBLK:
+ mode |= os.ModeDevice
+ case s_IFCHR:
+ mode |= os.ModeDevice | os.ModeCharDevice
+ case s_IFDIR:
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 {
mode |= os.ModeSetgid
@@ -231,5 +267,8 @@ func unixModeToFileMode(m uint32) os.FileMode {
if m&s_ISUID != 0 {
mode |= os.ModeSetuid
}
- return mode | os.FileMode(m&0777)
+ if m&s_ISVTX != 0 {
+ mode |= os.ModeSticky
+ }
+ return mode
}
diff --git a/src/pkg/archive/zip/testdata/symlink.zip b/src/pkg/archive/zip/testdata/symlink.zip
new file mode 100644
index 0000000000..af846938cd
--- /dev/null
+++ b/src/pkg/archive/zip/testdata/symlink.zip
Binary files differ
diff --git a/src/pkg/archive/zip/writer_test.go b/src/pkg/archive/zip/writer_test.go
index 5a576b1c32..ce93fae19e 100644
--- a/src/pkg/archive/zip/writer_test.go
+++ b/src/pkg/archive/zip/writer_test.go
@@ -47,10 +47,10 @@ var writeTests = []WriteTest{
Mode: 0755 | os.ModeSetgid,
},
{
- Name: "setgid",
- Data: []byte("setgid file"),
+ Name: "symlink",
+ Data: []byte("../link/target"),
Method: Deflate,
- Mode: 0755 | os.ModeSetgid,
+ Mode: 0755 | os.ModeSymlink,
},
}