// zipExeReaderMacho treats the file as a Mach-O binary
// (Mac OS X / Darwin executable) and attempts to find a zip archive.
766384
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())
}
232506
func archive(ctx context.Context, client *isolatedclient.Client, opts *isolate.ArchiveOptions, dumpJSON string, concurrentChecks, concurrentUploads int, al archiveLogger) error {
	// Parse the incoming isolate file.
	deps, rootDir, isol, err := isolate.ProcessIsolate(opts)
	if err != nil {
		return fmt.Errorf("isolate %s: failed to process: %v", opts.Isolate, err)
	}
	log.Printf("Isolate %s referenced %d deps", opts.Isolate, len(deps))

	// Set up a checker and uploader.
	checker := archiver.NewChecker(ctx, client, concurrentChecks)
	uploader := archiver.NewUploader(ctx, client, concurrentUploads)
	archiver := archiver.NewTarringArchiver(checker, uploader)

	isolSummary, err := archiver.Archive(deps, rootDir, isol, opts.Blacklist, opts.Isolated)
	if err != nil {
		return fmt.Errorf("isolate %s: %v", opts.Isolate, err)
	}

	// Make sure that all pending items have been checked.
	if err := checker.Close(); err != nil {
		return err
	}

	// Make sure that all the uploads have completed successfully.
	if err := uploader.Close(); err != nil {
		return err
	}

	printSummary(al, isolSummary)
	if err := dumpSummaryJSON(dumpJSON, isolSummary); err != nil {
		return err
	}

	al.LogSummary(ctx, int64(checker.Hit.Count()), int64(checker.Miss.Count()), units.Size(checker.Hit.Bytes()), units.Size(checker.Miss.Bytes()), []string{string(isolSummary.Digest)})
	return nil
}
848063
func parseICMPEcho(b []byte) (*icmpEcho, error) {
	bodylen := len(b)
	p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
	if bodylen > 4 {
		p.Data = make([]byte, bodylen-4)
		copy(p.Data, b[4:])
	}
	return p, nil
}
1249604
func (e *ClientExecutor) Archive(fromFS bool, src, dst string, allowDownload bool, excludes []string) (io.Reader, io.Closer, error) {
	var check DirectoryCheck
	if e.Container != nil {
		check = newDirectoryCheck(e.Client, e.Container.ID)
	}
	if isURL(src) {
		if !allowDownload {
			return nil, nil, fmt.Errorf("source can't be a URL")
		}
		glog.V(5).Infof("Archiving %s -> %s from URL", src, dst)
		return archiveFromURL(src, dst, e.TempDir, check)
	}
	// the input is from the filesystem, use the source as the input
	if fromFS {
		glog.V(5).Infof("Archiving %s %s -> %s from a filesystem location", src, ".", dst)
		return archiveFromDisk(src, ".", dst, allowDownload, excludes, check)
	}
	// if the context is in archive form, read from it without decompressing
	if len(e.ContextArchive) > 0 {
		glog.V(5).Infof("Archiving %s %s -> %s from context archive", e.ContextArchive, src, dst)
		return archiveFromFile(e.ContextArchive, src, dst, excludes, check)
	}
	// if the context is a directory, we only allow relative includes
	glog.V(5).Infof("Archiving %q %q -> %q from disk", e.Directory, src, dst)
	return archiveFromDisk(e.Directory, src, dst, allowDownload, excludes, check)
}
41849
func Archive(sources []string, destination string) error {
	aIface, err := ByExtension(destination)
	if err != nil {
		return err
	}
	a, ok := aIface.(Archiver)
	if !ok {
		return fmt.Errorf("format specified by destination filename is not an archive format: %s (%T)", destination, aIface)
	}
	return a.Archive(sources, destination)
}
352297
func ReadZip(f *zip.ReadCloser) (*File, error) {
	defer f.Close()
	return ReadZipReader(&f.Reader)
}
253415
func (z *ZipArchive) ExtractToFunc(destPath string, fn cae.HookFunc, entries ...string) (err error) {
	destPath = strings.Replace(destPath, "\\", "/", -1)
	isHasEntry := len(entries) > 0
	if Verbose {
		fmt.Println("Unzipping " + z.FileName + "...")
	}
	os.MkdirAll(destPath, os.ModePerm)
	for _, f := range z.File {
		f.Name = strings.Replace(f.Name, "\\", "/", -1)

		// Directory.
		if strings.HasSuffix(f.Name, "/") {
			if isHasEntry {
				if cae.IsEntry(f.Name, entries) {
					if err = fn(f.Name, f.FileInfo()); err != nil {
						continue
					}
					os.MkdirAll(path.Join(destPath, f.Name), os.ModePerm)
				}
				continue
			}
			if err = fn(f.Name, f.FileInfo()); err != nil {
				continue
			}
			os.MkdirAll(path.Join(destPath, f.Name), os.ModePerm)
			continue
		}

		// File.
		if isHasEntry {
			if cae.IsEntry(f.Name, entries) {
				if err = fn(f.Name, f.FileInfo()); err != nil {
					continue
				}
				err = extractFile(f, destPath)
			}
		} else {
			if err = fn(f.Name, f.FileInfo()); err != nil {
				continue
			}
			err = extractFile(f, destPath)
		}
		if err != nil {
			return err
		}
	}
	return nil
}
519458
func (actor Actor) DownloadExecutableBinaryFromURL(pluginURL string, tempPluginDir string, proxyReader plugin.ProxyReader) (string, error) {
	tempFile, err := makeTempFile(tempPluginDir)
	if err != nil {
		return "", err
	}

	err = actor.client.DownloadPlugin(pluginURL, tempFile.Name(), proxyReader)
	if err != nil {
		return "", err
	}

	return tempFile.Name(), nil
}
880389
func isExecutable(buf []byte) bool {
	// intel Mach-O executables start with 0xCEFAEDFE or 0xCFFAEDFE
	// (old PowerPC Mach-O executables started with 0xFEEDFACE)
	if (buf[0] == 0xCE || buf[0] == 0xCF) && buf[1] == 0xFA && buf[2] == 0xED && buf[3] == 0xFE {
		return true
	}

	// Mach-O universal binaries start with 0xCAFEBABE
	// it's Apple's 'fat binary' stuff that contains multiple architectures
	if buf[0] == 0xCA && buf[1] == 0xFE && buf[2] == 0xBA && buf[3] == 0xBE {
		return true
	}

	// ELF executables start with 0x7F454C46
	// (e.g. 0x7F + 'ELF' in ASCII)
	if buf[0] == 0x7F && buf[1] == 0x45 && buf[2] == 0x4C && buf[3] == 0x46 {
		return true
	}

	// Shell scripts start with a shebang (#!)
	// https://en.wikipedia.org/wiki/Shebang_(Unix)
	if buf[0] == 0x23 && buf[1] == 0x21 {
		return true
	}

	return false
}
236504
func fileExist(filename string) (ok bool) {
	info, err := os.Stat(filename)
	if err == nil {
		if ^os.ModePerm&info.Mode() == 0 {
			ok = true
		}
	}
	return ok
}
868780
func (v Simple) Archive(filePath string) error {
	err := archiveFile(v.folderFs, v.versionsFs, filePath, TagFilename)
	if err != nil {
		return err
	}

	file := filepath.Base(filePath)
	dir := filepath.Dir(filePath)

	// Glob according to the new file~timestamp.ext pattern.
	pattern := filepath.Join(dir, TagFilename(file, TimeGlob))
	newVersions, err := v.versionsFs.Glob(pattern)
	if err != nil {
		l.Warnln("globbing:", err, "for", pattern)
		return nil
	}

	// Also according to the old file.ext~timestamp pattern.
	pattern = filepath.Join(dir, file+"~"+TimeGlob)
	oldVersions, err := v.versionsFs.Glob(pattern)
	if err != nil {
		l.Warnln("globbing:", err, "for", pattern)
		return nil
	}

	// Use all the found filenames. "~" sorts after "." so all old pattern
	// files will be deleted before any new, which is as it should be.
	versions := util.UniqueStrings(append(oldVersions, newVersions...))

	if len(versions) > v.keep {
		for _, toRemove := range versions[:len(versions)-v.keep] {
			l.Debugln("cleaning out", toRemove)
			err = v.versionsFs.Remove(toRemove)
			if err != nil {
				l.Warnln("removing old version:", err)
			}
		}
	}

	return nil
}
514635
func UnzipArchive(zipFile string, dest string) (string, error) {
	if !FileExists(zipFile) {
		return "", fmt.Errorf("ZipFile %s does not exist", zipFile)
	}

	r, err := zip.OpenReader(zipFile)
	if err != nil {
		return "", err
	}
	defer r.Close()

	for _, f := range r.File {
		rc, err := f.Open()
		if err != nil {
			return "", err
		}
		error := func() error {
			defer rc.Close()

			path := filepath.Join(dest, f.Name)
			os.MkdirAll(filepath.Dir(path), NewDirectoryPermissions)
			if f.FileInfo().IsDir() {
				os.MkdirAll(path, f.Mode())
			} else {
				f, err := os.OpenFile(
					path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
				if err != nil {
					return err
				}
				defer f.Close()

				_, err = io.Copy(f, rc)
				if err != nil {
					return err
				}
			}
			return nil
		}()
		if error != nil {
			return "", error

		}
	}

	return dest, nil
}
1204071
func (b *binary) FileExists(path ...string) bool {
	flatPath := b.Path(path...)
	_, err := os.Stat(flatPath)
	return !os.IsNotExist(err)
}
685020
func extractArchive(i interface{}, src io.Reader, dst string, opts *archive.TarOptions) error {
	if ea, ok := i.(extractor); ok {
		return ea.ExtractArchive(src, dst, opts)
	}
	return chrootarchive.Untar(src, dst, opts)
}
10269
func (e *Extractor) Zip(ctx context.Context, body io.Reader, location string, rename Renamer) error {
	// read the whole body into a buffer. Not sure this is the best way to do it
	buffer := bytes.NewBuffer([]byte{})
	copyCancel(ctx, buffer, body)

	archive, err := zip.NewReader(bytes.NewReader(buffer.Bytes()), int64(buffer.Len()))
	if err != nil {
		return errors.Annotatef(err, "Read the zip file")
	}

	files := []file{}
	links := []link{}

	// We make the first pass creating the directory structure, or we could end up
	// attempting to create a file where there's no folder
	for _, header := range archive.File {
		select {
		case <-ctx.Done():
			return errors.New("interrupted")
		default:
		}

		path := header.Name

		// Replace backslash with forward slash. There are archives in the wild made with
		// buggy compressors that use backslash as path separator. The ZIP format explicitly
		// denies the use of "\" so we just replace it with slash "/".
		// Moreover it seems that folders are stored as "files" but with a final "\" in the
		// filename... oh, well...
		forceDir := strings.HasSuffix(path, "\\")
		path = strings.Replace(path, "\\", "/", -1)

		if rename != nil {
			path = rename(path)
		}

		if path == "" {
			continue
		}

		path = filepath.Join(location, path)
		info := header.FileInfo()

		switch {
		case info.IsDir() || forceDir:
			if err := e.FS.MkdirAll(path, info.Mode()|os.ModeDir|100); err != nil {
				return errors.Annotatef(err, "Create directory %s", path)
			}
		// We only check for symlinks because hard links aren't possible
		case info.Mode()&os.ModeSymlink != 0:
			f, err := header.Open()
			if err != nil {
				return errors.Annotatef(err, "Open link %s", path)
			}
			name, err := ioutil.ReadAll(f)
			if err != nil {
				return errors.Annotatef(err, "Read address of link %s", path)
			}
			links = append(links, link{Path: path, Name: string(name)})
		default:
			f, err := header.Open()
			if err != nil {
				return errors.Annotatef(err, "Open file %s", path)
			}
			var data bytes.Buffer
			if _, err := copyCancel(ctx, &data, f); err != nil {
				return errors.Annotatef(err, "Read contents of file %s", path)
			}
			files = append(files, file{Path: path, Mode: info.Mode(), Data: data})
		}
	}

	// Now we make another pass creating the files and links
	for i := range files {
		if err := e.copy(ctx, files[i].Path, files[i].Mode, &files[i].Data); err != nil {
			return errors.Annotatef(err, "Create file %s", files[i].Path)
		}
	}

	for i := range links {
		select {
		case <-ctx.Done():
			return errors.New("interrupted")
		default:
		}
		if err := e.FS.Symlink(links[i].Name, links[i].Path); err != nil {
			return errors.Annotatef(err, "Create link %s", links[i].Path)
		}
	}

	return nil
}
276981
func parseZipMetaRow(v []byte) (m zipMetaInfo, err error) {
	row := v
	sp := bytes.IndexByte(v, ' ')
	if sp < 1 || sp == len(v)-1 {
		return zipMetaInfo{}, fmt.Errorf("invalid z: meta row %q", row)
	}
	if bytes.Count(v, singleSpace) != 4 {
		return zipMetaInfo{}, fmt.Errorf("wrong number of spaces in z: meta row %q", row)
	}
	zipSize, err := strutil.ParseUintBytes(v[:sp], 10, 32)
	if err != nil {
		return zipMetaInfo{}, fmt.Errorf("invalid zipSize %q in z: meta row: %q", v[:sp], row)
	}
	m.zipSize = uint32(zipSize)

	v = v[sp+1:]
	sp = bytes.IndexByte(v, ' ')
	wholeRef, ok := blob.ParseBytes(v[:sp])
	if !ok {
		return zipMetaInfo{}, fmt.Errorf("invalid wholeRef %q in z: meta row: %q", v[:sp], row)
	}
	m.wholeRef = wholeRef

	v = v[sp+1:]
	sp = bytes.IndexByte(v, ' ')
	wholeSize, err := strutil.ParseUintBytes(v[:sp], 10, 64)
	if err != nil {
		return zipMetaInfo{}, fmt.Errorf("invalid wholeSize %q in z: meta row: %q", v[:sp], row)
	}
	m.wholeSize = uint64(wholeSize)

	v = v[sp+1:]
	sp = bytes.IndexByte(v, ' ')
	if _, err := strutil.ParseUintBytes(v[:sp], 10, 64); err != nil {
		return zipMetaInfo{}, fmt.Errorf("invalid offset %q in z: meta row: %q", v[:sp], row)
	}

	v = v[sp+1:]
	dataSize, err := strutil.ParseUintBytes(v, 10, 32)
	if err != nil {
		return zipMetaInfo{}, fmt.Errorf("invalid dataSize %q in z: meta row: %q", v, row)
	}
	m.dataSize = uint32(dataSize)

	return m, nil
}
497859
func (z *Zip) Close() error {
	if z.zr != nil {
		z.zr = nil
	}
	if z.zw != nil {
		zw := z.zw
		z.zw = nil
		return zw.Close()
	}
	return nil
}