From 02fb021161cf36cf7326380fb1ff9239cd195067 Mon Sep 17 00:00:00 2001 From: Gustavo Niemeyer Date: Mon, 6 Feb 2012 11:58:32 -0200 Subject: [PATCH] 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 --- src/pkg/archive/zip/reader_test.go | 19 ++++++- src/pkg/archive/zip/struct.go | 63 ++++++++++++++++++----- src/pkg/archive/zip/testdata/symlink.zip | Bin 0 -> 173 bytes src/pkg/archive/zip/writer_test.go | 6 +-- 4 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 src/pkg/archive/zip/testdata/symlink.zip 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 0000000000000000000000000000000000000000..af846938cde293ccc3dfb310fdfbda641382dd3f GIT binary patch literal 173 zcmWIWW@h1H00D{l&JGuU&FkX?vO$=gL588YGB+nPFFQ1ZlYv@nk^pZ;COKwYW=Vjo0E7PvK@{9%R*1=HrUrPkvVoK_0--OE_5yJj E01XfzDgXcg literal 0 HcmV?d00001 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, }, }