diff options
Diffstat (limited to 'vendor/github.com/daaku')
-rw-r--r-- | vendor/github.com/daaku/go.zipexe/license | 21 | ||||
-rw-r--r-- | vendor/github.com/daaku/go.zipexe/zipexe.go | 142 |
2 files changed, 163 insertions, 0 deletions
diff --git a/vendor/github.com/daaku/go.zipexe/license b/vendor/github.com/daaku/go.zipexe/license new file mode 100644 index 00000000..6a2f15c1 --- /dev/null +++ b/vendor/github.com/daaku/go.zipexe/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2012-2015 Carlos Castillo + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/daaku/go.zipexe/zipexe.go b/vendor/github.com/daaku/go.zipexe/zipexe.go new file mode 100644 index 00000000..60046062 --- /dev/null +++ b/vendor/github.com/daaku/go.zipexe/zipexe.go @@ -0,0 +1,142 @@ +// Package zipexe attempts to open an executable binary file as a zip file. +package zipexe + +import ( + "archive/zip" + "debug/elf" + "debug/macho" + "debug/pe" + "errors" + "io" + "os" +) + +// Opens a zip file by path. +func Open(path string) (*zip.Reader, error) { + _, rd, err := OpenCloser(path) + return rd, err +} + +// OpenCloser is like Open but returns an additional Closer to avoid leaking open files. +func OpenCloser(path string) (io.Closer, *zip.Reader, error) { + file, err := os.Open(path) + if err != nil { + return nil, nil, err + } + finfo, err := file.Stat() + if err != nil { + return nil, nil, err + } + zr, err := NewReader(file, finfo.Size()) + if err != nil { + return nil, nil, err + } + return file, zr, nil +} + +// Open a zip file, specially handling various binaries that may have been +// augmented with zip data. +func NewReader(rda io.ReaderAt, size int64) (*zip.Reader, error) { + handlers := []func(io.ReaderAt, int64) (*zip.Reader, error){ + zip.NewReader, + zipExeReaderMacho, + zipExeReaderElf, + zipExeReaderPe, + } + + for _, handler := range handlers { + zfile, err := handler(rda, size) + if err == nil { + return zfile, nil + } + } + return nil, errors.New("Couldn't Open As Executable") +} + +// zipExeReaderMacho treats the file as a Mach-O binary +// (Mac OS X / Darwin executable) and attempts to find a zip archive. +func zipExeReaderMacho(rda io.ReaderAt, size int64) (*zip.Reader, error) { + file, err := macho.NewFile(rda) + if err != nil { + return nil, err + } + + var max int64 + for _, load := range file.Loads { + seg, ok := load.(*macho.Segment) + if ok { + // Check if the segment contains a zip file + if zfile, err := zip.NewReader(seg, int64(seg.Filesz)); err == nil { + return zfile, nil + } + + // Otherwise move end of file pointer + end := int64(seg.Offset + seg.Filesz) + if end > max { + max = end + } + } + } + + // No zip file within binary, try appended to end + section := io.NewSectionReader(rda, max, size-max) + return zip.NewReader(section, section.Size()) +} + +// zipExeReaderPe treats the file as a Portable Exectuable binary +// (Windows executable) and attempts to find a zip archive. +func zipExeReaderPe(rda io.ReaderAt, size int64) (*zip.Reader, error) { + file, err := pe.NewFile(rda) + if err != nil { + return nil, err + } + + var max int64 + for _, sec := range file.Sections { + // Check if this section has a zip file + if zfile, err := zip.NewReader(sec, int64(sec.Size)); err == nil { + return zfile, nil + } + + // Otherwise move end of file pointer + end := int64(sec.Offset + sec.Size) + if end > max { + max = end + } + } + + // No zip file within binary, try appended to end + section := io.NewSectionReader(rda, max, size-max) + return zip.NewReader(section, section.Size()) +} + +// zipExeReaderElf treats the file as a ELF binary +// (linux/BSD/etc... executable) and attempts to find a zip archive. +func zipExeReaderElf(rda io.ReaderAt, size int64) (*zip.Reader, error) { + file, err := elf.NewFile(rda) + if err != nil { + return nil, err + } + + var max int64 + for _, sect := range file.Sections { + if sect.Type == elf.SHT_NOBITS { + continue + } + + // Check if this section has a zip file + if zfile, err := zip.NewReader(sect, int64(sect.Size)); err == nil { + return zfile, nil + } + + // Otherwise move end of file pointer + end := int64(sect.Offset + sect.Size) + if end > max { + max = end + } + } + + // No zip file within binary, try appended to end + section := io.NewSectionReader(rda, max, size-max) + return zip.NewReader(section, section.Size()) +} |