summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/daaku/go.zipexe
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/daaku/go.zipexe')
-rw-r--r--vendor/github.com/daaku/go.zipexe/license21
-rw-r--r--vendor/github.com/daaku/go.zipexe/zipexe.go142
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())
+}