예제 #1
0
// 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)
	}
}
예제 #2
0
파일: write.go 프로젝트: matm/gobuild
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
}
예제 #3
0
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
}
예제 #5
0
// 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
}
예제 #6
0
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)
	}
}
예제 #7
0
func createZipDirectoryEntry(archive *zip.Writer, fh *zip.FileHeader) error {
	fh.Name += "/"
	_, err := archive.CreateHeader(fh)
	return err
}
예제 #8
0
// 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"))
}