Example #1
0
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
}
Example #2
0
func addKeysToArchive(zipWriter *zip.Writer, newKeyStore *trustmanager.KeyFileStore, subDir string) error {
	// List all files but no symlinks
	for _, relKeyPath := range newKeyStore.ListFiles(false) {
		fullKeyPath := filepath.Join(newKeyStore.BaseDir(), relKeyPath)

		fi, err := os.Stat(fullKeyPath)
		if err != nil {
			return err
		}

		infoHeader, err := zip.FileInfoHeader(fi)
		if err != nil {
			return err
		}

		infoHeader.Name = filepath.Join(subDir, relKeyPath)
		zipFileEntryWriter, err := zipWriter.CreateHeader(infoHeader)
		if err != nil {
			return err
		}

		fileContents, err := ioutil.ReadFile(fullKeyPath)
		if err != nil {
			return err
		}
		if _, err = zipFileEntryWriter.Write(fileContents); err != nil {
			return err
		}
	}

	return nil
}
Example #3
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)
	}
}
Example #4
0
// Writes this tree to the given zip file, returning an error on failure.
func (t Stream) ToZip(w *zip.Writer) error {
	for blob := range t {

		hdr, err := zip.FileInfoHeader(blob)
		if err != nil {
			return err
		}

		writer, err := w.CreateHeader(hdr)
		if err != nil {
			return err
		}

		if blob.Contents() != nil {
			_, err := io.Copy(writer, blob.Contents())
			if err != nil {
				return err
			}
		}

		if blob.Error() != nil {
			return blob.Error()
		}
	}

	w.Close()

	return nil
}
Example #5
0
File: zip.go Project: jsli/gtbox
func writeFile2Zip(zw *zip.Writer, path string, name string) error {
	file, err := os.Open(path + name)
	if err != nil {
		return err
	}
	defer file.Close()

	info, err := file.Stat()
	if err != nil {
		return err
	}

	header, err := zip.FileInfoHeader(info)
	if err != nil {
		return err
	}
	header.Name = name

	writer, err := zw.CreateHeader(header)
	if err != nil {
		return err
	}

	_, err = io.Copy(writer, file)
	return err
}
Example #6
0
func addHandlerToZip(w *zip.Writer, bf baofile.Baofile) error {
	path := "lambda/handler_example.js"
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	info, err := f.Stat()
	if err != nil {
		return err
	}
	header, err := zip.FileInfoHeader(info)
	if err != nil {
		return err
	}
	wr, err := w.CreateHeader(header)
	if err != nil {
		return err
	}
	fileBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}

	handlerTemplate := string(fileBytes)
	t := template.Must(template.New("handler").Parse(handlerTemplate))
	err = t.Execute(wr, bf)
	if err != nil {
		return err
	}
	return nil
}
Example #7
0
func writeFileToZip(zipper *zip.Writer, filename string) error {
	file, err := os.Open(filename)

	if err != nil {
		return err
	}

	defer file.Close()

	info, err := file.Stat()

	if err != nil {
		return err
	}

	header, err := zip.FileInfoHeader(info)

	if err != nil {
		return err
	}

	header.Name = helper.SanitizedName(filename)

	writer, err := zipper.CreateHeader(header)

	if err != nil {
		return err
	}

	_, err = io.Copy(writer, file)

	return err
}
Example #8
0
func foliazipdir(q *Context, zf *zip.Writer, fdir, subdir string) (ok bool) {
	dir := filepath.Join(fdir, subdir)
	files, err := ioutil.ReadDir(dir)
	if foliaErr(q, err) {
		return false
	}
	for _, file := range files {
		fname := path.Join(subdir, file.Name()) // in zip alleen forward slashes toegestaan
		if file.IsDir() {
			if !foliazipdir(q, zf, fdir, fname) {
				return false
			}
		} else {
			data, err := ioutil.ReadFile(filepath.Join(fdir, fname))
			if foliaErr(q, err) {
				return false
			}
			fh, err := zip.FileInfoHeader(file)
			if foliaErr(q, err) {
				return false
			}
			fh.Name = fname
			f, err := zf.CreateHeader(fh)
			if foliaErr(q, err) {
				return false
			}
			_, err = f.Write(data)
			if foliaErr(q, err) {
				return false
			}
		}
	}
	return true
}
Example #9
0
func addZip(filename, buildDir string, zipWriter *zip.Writer) error {
	zipfile, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer zipfile.Close()

	info, err := zipfile.Stat()
	if err != nil {
		return err
	}

	header, err := zip.FileInfoHeader(info)
	if err != nil {
		return err
	}

	r := regexp.MustCompile(buildDir + "/")
	header.Name = r.ReplaceAllString(filename, "")
	writer, err := zipWriter.CreateHeader(header)
	if err != nil {
		return err
	}

	_, err = io.Copy(writer, zipfile)
	return nil
}
Example #10
0
File: util.go Project: jquag/kempt
func addFileToZip(zipWriter *zip.Writer, fi os.FileInfo, srcPath string) error {
	fh, err := zip.FileInfoHeader(fi)
	if err != nil {
		return err
	}
	fh.Method = zip.Deflate
	destFile, err := zipWriter.CreateHeader(fh)
	if err != nil {
		return err
	}

	srcFile, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	ba, err := ioutil.ReadAll(srcFile)
	if err != nil {
		return err
	}

	//_, err = io.Copy(destFile, srcFile)
	_, err = destFile.Write(ba)
	return err
}
Example #11
0
func addFileToZIP(zw *zip.Writer, item ArchiveItem) (err error) {
	binfo, err := os.Stat(item.FileSystemPath)
	if err != nil {
		return
	}
	header, err := zip.FileInfoHeader(binfo)
	if err != nil {
		return
	}
	header.Method = zip.Deflate
	//always use forward slashes even on Windows
	header.Name = strings.Replace(item.ArchivePath, "\\", "/", -1)
	w, err := zw.CreateHeader(header)
	if err != nil {
		zw.Close()
		return
	}
	bf, err := os.Open(item.FileSystemPath)
	if err != nil {
		return
	}
	defer bf.Close()
	_, err = io.Copy(w, bf)
	return
}
Example #12
0
func addKeysToArchive(zipWriter *zip.Writer, newKeyStore *trustmanager.KeyFileStore, tempBaseDir string) error {
	// List all files but no symlinks
	for _, fullKeyPath := range newKeyStore.ListFiles(false) {
		relKeyPath := strings.TrimPrefix(fullKeyPath, tempBaseDir)
		relKeyPath = strings.TrimPrefix(relKeyPath, string(filepath.Separator))

		fi, err := os.Stat(fullKeyPath)
		if err != nil {
			return err
		}

		infoHeader, err := zip.FileInfoHeader(fi)
		if err != nil {
			return err
		}

		infoHeader.Name = relKeyPath
		zipFileEntryWriter, err := zipWriter.CreateHeader(infoHeader)
		if err != nil {
			return err
		}

		fileContents, err := ioutil.ReadFile(fullKeyPath)
		if err != nil {
			return err
		}
		if _, err = zipFileEntryWriter.Write(fileContents); err != nil {
			return err
		}
	}

	return nil
}
Example #13
0
func addFileToZip(w *zip.Writer, path string, newname string) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	info, err := f.Stat()
	if err != nil {
		return err
	}
	header, err := zip.FileInfoHeader(info)
	if err != nil {
		return err
	}
	if newname != "" {
		header.Name = newname
	}
	wr, err := w.CreateHeader(header)
	if err != nil {
		return err
	}
	fileBytes, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	_, err = wr.Write(fileBytes)
	if err != nil {
		return err
	}
	return nil
}
Example #14
0
func addZipEntry(zw *zip.Writer, f filetesting.Entry) {
	h := &zip.FileHeader{
		Name: f.GetPath(),
		// Don't bother compressing - the contents are so small that
		// it will just slow things down for no particular benefit.
		Method: zip.Store,
	}
	contents := ""
	switch f := f.(type) {
	case filetesting.Dir:
		h.SetMode(os.ModeDir | 0755)
	case filetesting.File:
		h.SetMode(f.Perm)
		contents = f.Data
	case filetesting.Symlink:
		h.SetMode(os.ModeSymlink | 0777)
		contents = f.Link
	}
	w, err := zw.CreateHeader(h)
	if err != nil {
		panic(err)
	}
	if contents != "" {
		if _, err := w.Write([]byte(contents)); err != nil {
			panic(err)
		}
	}
}
Example #15
0
// 逐个文件,写入zip包
// zipper *zip.Writer:要写入的zip包的zip.Writer
// includeFileName string:本次写入的文件的全路径+名字
func writeFileToZip(zipper *zip.Writer, includeFileName string) error {
	//打开待写入文件
	includeFile, err := os.Open(includeFileName)
	if err != nil {
		return err
	}
	defer includeFile.Close()

	//获取文件描述
	includeFileInfo, err := includeFile.Stat()
	if err != nil {
		return err
	}

	//zip.FileInfoHeader
	zipFileHeader, err := zip.FileInfoHeader(includeFileInfo)
	if err != nil {
		return err
	}

	//修改文件描述的Header,截断路径,只保留文件名
	//否则,解压的时候,可能按压缩进来时候的文件路径来解压,解压回到原来的位置,而不是当前目录
	zipFileHeader.Name = path.Base(includeFileName)

	//用zip.FileInfoHeader,创建zip包内的一个项,并获得io.Writer,准备写入文件
	zipFileWriter, err := zipper.CreateHeader(zipFileHeader)
	if err != nil {
		return err
	}

	//写入本次的文件
	_, err = io.Copy(zipFileWriter, includeFile)
	return err
}
Example #16
0
func addKeysToArchive(zipWriter *zip.Writer, newKeyStore *trustmanager.KeyFileStore) error {
	for _, relKeyPath := range newKeyStore.ListFiles() {
		fullKeyPath := filepath.Join(newKeyStore.BaseDir(), relKeyPath)

		fi, err := os.Lstat(fullKeyPath)
		if err != nil {
			return err
		}

		infoHeader, err := zip.FileInfoHeader(fi)
		if err != nil {
			return err
		}

		infoHeader.Name = relKeyPath

		zipFileEntryWriter, err := zipWriter.CreateHeader(infoHeader)
		if err != nil {
			return err
		}

		fileContents, err := ioutil.ReadFile(fullKeyPath)
		if err != nil {
			return err
		}

		if _, err = zipFileEntryWriter.Write(fileContents); err != nil {
			return err
		}
	}

	return nil
}
func addKeysToArchive(zipWriter *zip.Writer, newKeyStore *trustmanager.KeyFileStore, subDir string) error {
	for _, relKeyPath := range newKeyStore.ListFiles(true) {
		fullKeyPath := filepath.Join(newKeyStore.BaseDir(), relKeyPath)

		fi, err := os.Lstat(fullKeyPath)
		if err != nil {
			return err
		}

		infoHeader, err := zip.FileInfoHeader(fi)
		if err != nil {
			return err
		}

		infoHeader.Name = filepath.Join(subDir, relKeyPath)

		// Is this a symlink? If so, encode properly in the zip file.
		if (fi.Mode() & os.ModeSymlink) != 0 {
			infoHeader.CreatorVersion = zipMadeByUNIX
			infoHeader.ExternalAttrs = zipSymlinkAttr

			zipFileEntryWriter, err := zipWriter.CreateHeader(infoHeader)
			if err != nil {
				return err
			}

			target, err := os.Readlink(fullKeyPath)
			if err != nil {
				return err
			}

			// Write relative path
			if _, err = zipFileEntryWriter.Write([]byte(target)); err != nil {
				return err
			}
		} else {
			zipFileEntryWriter, err := zipWriter.CreateHeader(infoHeader)
			if err != nil {
				return err
			}

			fileContents, err := ioutil.ReadFile(fullKeyPath)
			if err != nil {
				return err
			}

			if _, err = zipFileEntryWriter.Write(fileContents); err != nil {
				return err
			}
		}
	}

	return nil
}
/*
   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
}
Example #19
0
func addFileToZIP(zw *zip.Writer, item ArchiveItem) error {
	//fmt.Printf("Adding %s\n", item.FileSystemPath)
	binfo, err := os.Stat(item.FileSystemPath)
	if err != nil {
		return err
	}
	if binfo.IsDir() {
		header, err := zip.FileInfoHeader(binfo)
		if err != nil {
			return err
		}
		header.Method = zip.Deflate
		header.Name = item.ArchivePath
		_, err = zw.CreateHeader(header)
		if err != nil {
			return err
		}
		file, err := os.Open(item.FileSystemPath)
		if err != nil {
			return err
		}
		fis, err := file.Readdir(0)
		for _, fi := range fis {
			err = addFileToZIP(zw, ArchiveItem{filepath.Join(item.FileSystemPath, fi.Name()), filepath.Join(item.ArchivePath, fi.Name()), nil})
			if err != nil {
				return err
			}
		}
	} else {
		header, err := zip.FileInfoHeader(binfo)
		if err != nil {
			return err
		}
		header.Method = zip.Deflate
		header.Name = item.ArchivePath
		w, err := zw.CreateHeader(header)
		if err != nil {
			return err
		}
		bf, err := os.Open(item.FileSystemPath)
		if err != nil {
			return err
		}
		defer bf.Close()
		_, err = io.Copy(w, bf)
		if err != nil {
			return err
		}
	}
	return err
}
func createZipSymlinkEntry(archive *zip.Writer, fh *zip.FileHeader) error {
	fw, err := archive.CreateHeader(fh)
	if err != nil {
		return err
	}

	link, err := os.Readlink(fh.Name)
	if err != nil {
		return err
	}

	_, err = io.WriteString(fw, link)
	return err
}
Example #21
0
func addZipFileMust(w *zip.Writer, path string) {
	fi, err := os.Stat(path)
	fataliferr(err)
	fih, err := zip.FileInfoHeader(fi)
	fataliferr(err)
	fih.Name = filepath.Base(path)
	d, err := ioutil.ReadFile(path)
	fataliferr(err)
	f, err := w.CreateHeader(fih)
	fataliferr(err)
	_, err = f.Write(d)
	fataliferr(err)
	// no need to close f. It's implicitly closed by the next Create(), CreateHeader() or Close() call
}
Example #22
0
// CreateNW creates a node-webkit .nw file
func (p Package) CreateNW(zw *zip.Writer, templates Templates, myapp io.Reader, includes string) error {
	// Add in a couple of package defaults
	p.Main = "index.html"
	p.EnvVar = nw.EnvVar

	if w, err := zw.Create("package.json"); err != nil {
		return err
	} else {
		if _, err := p.writeJsonTo(w); err != nil {
			return err
		}
	}

	filenameTemplates := map[string]string{
		"index.html": templates.IndexHtml,
		"client.js":  templates.ClientJs,
		"script.js":  templates.ScriptJs}
	for filename, str := range filenameTemplates {
		if w, err := zw.Create(filename); err != nil {
			return err
		} else {
			if t, err := template.New(filename).Parse(str); err != nil {
				return err
			} else {
				if err := t.Execute(w, p); err != nil {
					return err
				}
			}
		}
	}

	if includes != "" {
		if err := copyIncludes(zw, includes); err != nil {
			return err
		}
	}

	binHeader := zip.FileHeader{Name: p.Bin}
	binHeader.SetMode(0755) // Make it executable
	if w, err := zw.CreateHeader(&binHeader); err != nil {
		return err
	} else {
		if _, err := io.Copy(w, myapp); err != nil {
			return err
		}
	}

	return nil
}
Example #23
0
File: logs.go Project: vmware/vic
func zipEntries(readers map[string]entryReader, out *zip.Writer) error {
	defer trace.End(trace.Begin(""))
	defer out.Close()
	defer out.Flush()

	for name, r := range readers {
		log.Infof("Collecting log with reader %s(%#v)", name, r)

		e, err := r.open()
		if err != nil {
			log.Warningf("error reading %s(%s): %s\n", name, r, err)
			continue
		}
		sz := e.Size()
		header := &zip.FileHeader{
			Name:   name,
			Method: zip.Deflate,
		}

		header.SetModTime(time.Now())
		header.SetMode(0644)
		if sz > uint32max {
			header.UncompressedSize = uint32max
		} else {
			header.UncompressedSize = uint32(e.Size())
		}

		w, err := out.CreateHeader(header)

		if err != nil {
			log.Errorf("Failed to create Zip writer for %s: %s", header.Name, err)
			continue
		}

		log.Infof("%s has size %d", header.Name, sz)

		// be explicit about the number of bytes to copy as the log files will likely
		// be written to during this exercise
		_, err = io.CopyN(w, e, sz)
		_ = e.Close()
		if err != nil {
			log.Errorf("Failed to write content for %s: %s", header.Name, err)
			continue
		}
		log.Infof("Wrote %d bytes to %s", sz, header.Name)
	}
	return nil
}
Example #24
0
func addZipDataMust(zw *zip.Writer, path string, d []byte, zipName string) {
	fmt.Printf("adding data (%d bytes) as '%s'\n", len(d), zipName)
	fi, err := os.Stat(path)
	fataliferr(err)
	fih, err := zip.FileInfoHeader(fi)
	fataliferr(err)
	fih.Name = zipName
	fih.Method = zip.Store
	fw, err := zw.CreateHeader(fih)
	fataliferr(err)
	_, err = fw.Write(d)
	fataliferr(err)
	// fw is just a io.Writer so we can't Close() it. It's not necessary as
	// it's implicitly closed by the next Create(), CreateHeader()
	// or Close() call on zip.Writer
}
Example #25
0
File: main.go Project: mpdroog/sla
func zipAdd(w *zip.Writer, name string, path string) error {
	in, e := os.Open(path)
	if e != nil {
		return e
	}

	head := &zip.FileHeader{Name: name}
	head.SetModTime(time.Now())
	f, e := w.CreateHeader(head)
	if e != nil {
		return e
	}
	if _, e := io.Copy(f, bufio.NewReader(in)); e != nil {
		return e
	}
	return nil
}
Example #26
0
func addZipFileMust(w *zip.Writer, path string) {
	fi, err := os.Stat(path)
	fataliferr(err)
	fih, err := zip.FileInfoHeader(fi)
	fataliferr(err)
	fih.Name = filepath.Base(path)
	fih.Method = zip.Deflate
	d, err := ioutil.ReadFile(path)
	fataliferr(err)
	fw, err := w.CreateHeader(fih)
	fataliferr(err)
	_, err = fw.Write(d)
	fataliferr(err)
	// fw is just a io.Writer so we can't Close() it. It's not necessary as
	// it's implicitly closed by the next Create(), CreateHeader()
	// or Close() call on zip.Writer
}
Example #27
0
// packFile packs a file or directory to zip.Writer.
func packFile(srcFile string, recPath string, zw *zip.Writer, fi os.FileInfo) error {
	if fi.IsDir() {
		fh, err := zip.FileInfoHeader(fi)
		if err != nil {
			return err
		}
		fh.Name = recPath + "/"
		if _, err = zw.CreateHeader(fh); err != nil {
			return err
		}
	} else {
		fh, err := zip.FileInfoHeader(fi)
		if err != nil {
			return err
		}
		fh.Name = recPath
		fh.Method = zip.Deflate

		fw, err := zw.CreateHeader(fh)
		if err != nil {
			return err
		}

		if fi.Mode()&os.ModeSymlink != 0 {
			target, err := os.Readlink(srcFile)
			if err != nil {
				return err
			}
			if _, err = fw.Write([]byte(target)); err != nil {
				return err
			}
		} else {
			f, err := os.Open(srcFile)
			if err != nil {
				return err
			}
			defer f.Close()

			if _, err = io.Copy(fw, f); err != nil {
				return err
			}
		}
	}
	return nil
}
Example #28
0
func addZipFileMust(zw *zip.Writer, path, zipName string) {
	fi, err := os.Stat(path)
	fataliferr(err)
	fmt.Printf("adding '%s' (%d bytes) as '%s'\n", path, fi.Size(), zipName)
	fih, err := zip.FileInfoHeader(fi)
	fataliferr(err)
	fih.Name = zipName
	fih.Method = zip.Deflate
	d, err := ioutil.ReadFile(path)
	fataliferr(err)
	fw, err := zw.CreateHeader(fih)
	fataliferr(err)
	_, err = fw.Write(d)
	fataliferr(err)
	// fw is just a io.Writer so we can't Close() it. It's not necessary as
	// it's implicitly closed by the next Create(), CreateHeader()
	// or Close() call on zip.Writer
}
func createZipFileEntry(archive *zip.Writer, fh *zip.FileHeader) error {
	fh.Method = zip.Deflate
	fw, err := archive.CreateHeader(fh)
	if err != nil {
		return err
	}

	file, err := os.Open(fh.Name)
	if err != nil {
		return err
	}

	_, err = io.Copy(fw, file)
	file.Close()
	if err != nil {
		return err
	}
	return nil
}
Example #30
0
// ZipWalker returns a filepath.WalkFunc that adds every filesystem node
// to the given *zip.Writer.
func ZipWalker(zw *zip.Writer) filepath.WalkFunc {
	var base string
	return func(path string, info os.FileInfo, err error) error {
		if base == "" {
			base = path
		}

		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		if header.Name, err = filepath.Rel(base, path); err != nil {
			return err
		} else if info.IsDir() {
			header.Name = header.Name + string(filepath.Separator)
		} else {
			header.Method = zip.Deflate
		}

		w, err := zw.CreateHeader(header)
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		f, err := os.Open(path)
		if err != nil {
			return err
		}

		_, err = io.Copy(w, f)
		f.Close()
		return err
	}
}