]> Cypherpunks repositories - gostls13.git/commitdiff
archive/zip: support full range of FileMode flags
authorGustavo Niemeyer <gustavo@niemeyer.net>
Mon, 6 Feb 2012 13:58:32 +0000 (11:58 -0200)
committerGustavo Niemeyer <gustavo@niemeyer.net>
Mon, 6 Feb 2012 13:58:32 +0000 (11:58 -0200)
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
src/pkg/archive/zip/struct.go
src/pkg/archive/zip/testdata/symlink.zip [new file with mode: 0644]
src/pkg/archive/zip/writer_test.go

index 9407e35d5c08ce4a7bbacfad0e3ec7ed2bde02c9..935860e791efdd44b4229b6208e6d999afcf8b61 100644 (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",
                File: []ZipTestFile{
index abbe635e281df11ac412ab57f220c5a09f9d0506..35dcec6468b2aff7b2dd664adb8b4abb1074d314 100644 (file)
@@ -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 (file)
index 0000000..af84693
Binary files /dev/null and b/src/pkg/archive/zip/testdata/symlink.zip differ
index 5a576b1c32c3abd36cbb9569db1ee7c16d4b3d4a..ce93fae19e53da3508c67166945b2133c5aaa72d 100644 (file)
@@ -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,
        },
 }