// Deal with file func zipFile(srcFile string, recPath string, zw *zip.Writer, fi os.FileInfo) { if fi.IsDir() { // Create zip header fh := new(zip.FileHeader) fh.Name = recPath + "/" fh.UncompressedSize = 0 _, err := zw.CreateHeader(fh) handleError(err) } else { // Create zip header fh := new(zip.FileHeader) fh.Name = recPath fh.UncompressedSize = uint32(fi.Size()) fw, err := zw.CreateHeader(fh) handleError(err) // Read file data buf := make([]byte, fi.Size()) f, err := os.Open(srcFile) handleError(err) _, err = f.Read(buf) handleError(err) // Write file data to zip _, err = fw.Write(buf) handleError(err) } }
func packFile(srcFile string, recPath string, zw *zip.Writer, fi os.FileInfo) (err error) { if fi.IsDir() { // Create zip header fh := new(zip.FileHeader) fh.Name = recPath + "/" fh.UncompressedSize = 0 _, err = zw.CreateHeader(fh) } else { // Create zip header fh := new(zip.FileHeader) fh.Name = recPath fh.UncompressedSize = uint32(fi.Size()) fh.SetMode(fi.Mode()) var fw io.Writer fw, err = zw.CreateHeader(fh) if err != nil { return err } var f *os.File f, err = os.Open(srcFile) if err != nil { return err } _, err = io.Copy(fw, f) } return err }
func normalizeBuildpackArchive(inputFile *os.File, outputFile *os.File) (err error) { stats, err := inputFile.Stat() if err != nil { return } reader, err := zip.NewReader(inputFile, stats.Size()) if err != nil { return } contents := reader.File parentPath, hasBuildpack := findBuildpackPath(contents) if !hasBuildpack { return errors.New("Zip archive does not contain a buildpack") } writer := zip.NewWriter(outputFile) for _, file := range contents { name := file.Name if parentPath == "." || strings.HasPrefix(name, parentPath) { var ( r io.ReadCloser w io.Writer header *zip.FileHeader ) fileInfo := file.FileInfo() header, err = zip.FileInfoHeader(fileInfo) header.Name = strings.Replace(name, parentPath+"/", "", 1) r, err = file.Open() if err != nil { return } w, err = writer.CreateHeader(header) if err != nil { return } io.Copy(w, r) err = r.Close() if err != nil { return } } } writer.Close() outputFile.Seek(0, 0) return }
/* Helper. Recursively zip the contents of a directory tree using the zip.Writer. Filters so it only includes .rel files Note: this will not work if there are symbolic links in the src directory tree. (because Readdir does not follow links.) */ func zipSrcDirTree2(w *zip.Writer, directoryPath string, relativeDirName string) (err error) { var dir *os.File var filesInDir []os.FileInfo dir, err = gos.Open(directoryPath) filesInDir, err = dir.Readdir(0) if err != nil { return } err = dir.Close() for _, fileInfo := range filesInDir { if fileInfo.IsDir() { subItemPath := directoryPath + "/" + fileInfo.Name() subItemRelativePath := relativeDirName + "/" + fileInfo.Name() err = zipSrcDirTree2(w, subItemPath, subItemRelativePath) if err != nil { return } } else { // plain old file to be added. if strings.HasSuffix(fileInfo.Name(), ".rel") || strings.HasSuffix(fileInfo.Name(), ".txt") || strings.HasSuffix(fileInfo.Name(), ".html") || strings.HasSuffix(fileInfo.Name(), ".htm") || strings.HasSuffix(fileInfo.Name(), ".css") { subItemPath := directoryPath + "/" + fileInfo.Name() subItemRelativePath := relativeDirName + "/" + fileInfo.Name() var fh *zip.FileHeader fh, err = zip.FileInfoHeader(fileInfo) if err != nil { return } fh.Name = subItemRelativePath var zw io.Writer zw, err = w.CreateHeader(fh) if err != nil { return } var f *os.File f, err = gos.Open(subItemPath) if err != nil { return } _, err = io.Copy(zw, f) err = f.Close() if err != nil { return } } } } return }
// Zipper zips file contents at a path. Helper to prepare zipped data for upload // to S3. func Zipper(zipPath string) (*bytes.Buffer, error) { f, err := os.Open(zipPath) if err != nil { return nil, err } defer f.Close() buffer := bytes.NewBuffer(nil) w := zip.NewWriter(buffer) fh := zip.FileHeader{} fh.Name = filepath.Base(zipPath) fh.SetMode(0755) // Add some files to the archive. var files = []struct { Name string FileHandle *os.File Header *zip.FileHeader }{ {fh.Name, f, &fh}, } // Loop through all files listed above // Can be created using file.Name or a custom file.Header for flexibility. // To set permissions you need to use the file.Header construct. for _, file := range files { var zf io.Writer if file.Header == nil { zf, err = w.Create(file.Name) } else { zf, err = w.CreateHeader(file.Header) } if err != nil { return nil, err } if _, err := io.Copy(zf, f); err != nil { return nil, err } } if err := w.Close(); err != nil { return nil, err } return buffer, nil }
func dozip(archiveFile string, dir string) { // file file := create(archiveFile) defer file.Close() // zip zipWriter := zip.NewWriter(file) defer zipWriter.Close() // walk := func(path string, fileInfo os.FileInfo, err error) error { if err != nil { fail("Failed to traverse directory structure %v", err) } if fileInfo.Mode().IsDir() { return nil } print(path) fileToWrite := open(path) // var fileHeader *zip.FileHeader fileHeader, err = zip.FileInfoHeader(fileInfo) if err != nil { fail("Failed to create file info header %v", err) } fileHeader.Name = path // var w io.Writer w, err = zipWriter.CreateHeader(fileHeader) if err != nil { fail("Failed to create zip writer %v", err) } _, err = io.Copy(w, fileToWrite) if err != nil { fail("Failed to copy (zip writer) %v", err) } return nil } // err := filepath.Walk(dir, walk) if err != nil { fail("Failed to traverse directory %v %v", dir, err) } }
func createZipDirectoryEntry(archive *zip.Writer, fh *zip.FileHeader) error { fh.Name += "/" _, err := archive.CreateHeader(fh) return err }
// zipFiles adds files transferred through the channel to zip (writer) func zipFiles(dest io.Writer, skipOnError, unsafeArchFn bool, files <-chan ArchFileItem) (err error) { if dfh, ok := dest.(syncer); ok { defer func() { if e := dfh.Sync(); e != nil && err == nil && strings.Index(e.Error(), "invalid argument") < 0 { err = e } }() } zfh := zip.NewWriter(dest) defer func() { if e := zfh.Close(); e != nil && err == nil { err = e } }() var ( fi os.FileInfo zi *zip.FileHeader w io.Writer errs []error openedHere bool ) appendErr := func(err error) { if err == nil || err.Error() == "" { return } if errs == nil { errs = []error{err} } } for item := range files { openedHere = false if item.File == nil { if item.Filename == "" { continue } openedHere = true if item.File, err = os.Open(item.Filename); err != nil { err = fmt.Errorf("Zip cannot open %q: %v", item.Filename, err) if !skipOnError { return err } appendErr(err) continue } } if fi, err = item.File.Stat(); err != nil { if openedHere { _ = item.File.Close() } err = fmt.Errorf("error stating %s: %s", item.File, err) } else if fi == nil { err = fmt.Errorf("nil stat of %#v", item.File) } if err != nil { if !skipOnError { return err } appendErr(err) continue } logger.Debug("msg", "ZipFiles", "fi", fi) if zi, err = zip.FileInfoHeader(fi); err != nil { if openedHere { _ = item.File.Close() } err = fmt.Errorf("cannot convert stat %s to header: %s", item.File, err) if !skipOnError { return err } appendErr(err) continue } if item.Archive != "" { zi.Name = item.Archive } else if unsafeArchFn { zi.Name = unsafeFn(zi.Name, true) } if w, err = zfh.CreateHeader(zi); err != nil { if openedHere { _ = item.File.Close() } err = fmt.Errorf("error creating header for %q: %v", zi.Name, err) if !skipOnError { return err } appendErr(err) continue } logger.Debug("msg", "zipping", "arch", item.Archive, "name", zi.Name) _, err = io.Copy(w, item.File) if openedHere { _ = item.File.Close() } if err != nil { err = fmt.Errorf("error writing %s to zipfile: %s", item.File, err) logger.Warn("msg", "write to zip", "error", err) if !skipOnError { return err } appendErr(err) continue } } if errs == nil || len(errs) == 0 { return nil } sarr := make([]string, 0, len(errs)) for _, err = range errs { sarr = append(sarr, err.Error()) } return errors.New(strings.Join(sarr, "\n")) }