Пример #1
0
// StreamFile streams a file or directory entry into StreamArchive.
func (s *StreamArchive) StreamFile(relPath string, fi os.FileInfo, data []byte) error {
	if fi.IsDir() {
		fh, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			return err
		}
		fh.Name = relPath + "/"
		if err = s.Writer.WriteHeader(fh); err != nil {
			return err
		}
	} else {
		target := ""
		if fi.Mode()&os.ModeSymlink != 0 {
			target = string(data)
		}

		fh, err := tar.FileInfoHeader(fi, target)
		if err != nil {
			return err
		}
		fh.Name = filepath.Join(relPath, fi.Name())
		if err = s.Writer.WriteHeader(fh); err != nil {
			return err
		}

		if _, err = s.Writer.Write(data); err != nil {
			return err
		}
	}
	return nil
}
Пример #2
0
func addFileToTar(zw *tar.Writer, item someutils.ArchiveItem, isVerbose bool, outPipe io.Writer) error {
	if isVerbose {
		fmt.Fprintf(outPipe, "Adding %s\n", item.FileSystemPath)
	}
	binfo, err := os.Stat(item.FileSystemPath)
	if err != nil {
		return err
	}
	if binfo.IsDir() {
		header, err := tar.FileInfoHeader(binfo, "")
		if err != nil {
			return err
		}
		header.Name = item.ArchivePath
		err = zw.WriteHeader(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 = addFileToTar(zw, someutils.ArchiveItem{filepath.Join(item.FileSystemPath, fi.Name()), filepath.Join(item.ArchivePath, fi.Name()), nil}, isVerbose, outPipe)
			if err != nil {
				return err
			}
		}
	} else {
		header, err := tar.FileInfoHeader(binfo, "")
		if err != nil {
			return err
		}
		header.Name = item.ArchivePath
		err = zw.WriteHeader(header)
		if err != nil {
			return err
		}
		bf, err := os.Open(item.FileSystemPath)
		if err != nil {
			return err
		}
		defer bf.Close()
		_, err = io.Copy(zw, bf)
		if err != nil {
			return err
		}
		err = zw.Flush()
		if err != nil {
			return err
		}
		err = bf.Close()
		if err != nil {
			return err
		}
	}
	return err
}
Пример #3
0
func addDir(writer *tar.Writer, dirpath string) error {
	dir, err := os.Open(dirpath)
	if err != nil {
		return err
	}
	defer dir.Close()
	fi, err := dir.Stat()
	if err != nil {
		return err
	}
	header, err := tar.FileInfoHeader(fi, "")
	if err != nil {
		return err
	}
	header.Name = dirpath
	err = writer.WriteHeader(header)
	if err != nil {
		return err
	}
	fis, err := dir.Readdir(0)
	if err != nil {
		return err
	}
	for _, fi := range fis {
		if fi.IsDir() {
			err = addDir(writer, path.Join(dirpath, fi.Name()))
		} else {
			err = addFile(writer, path.Join(dirpath, fi.Name()))
		}
		if err != nil {
			return err
		}
	}
	return nil
}
func writeFileToTarWriter(tarWriter *tar.Writer, info os.FileInfo, absoluteFilePath, overwriteFileName string, isOnlyFile bool) {
	hdr, err := tar.FileInfoHeader(info, "")
	CheckError(err)
	if overwriteFileName != "" {
		hdr.Name = overwriteFileName
	}

	if hdr.Xattrs == nil {
		hdr.Xattrs = map[string]string{}
	}
	hdr.Xattrs["SIZE"] = fmt.Sprintf("%d", info.Size())
	if isOnlyFile {
		hdr.Xattrs["SINGLE_FILE_ONLY"] = "1"
	}

	err = tarWriter.WriteHeader(hdr)
	CheckError(err)

	if !info.IsDir() {
		file, err := os.Open(absoluteFilePath)
		CheckError(err)
		defer file.Close()

		_, err = io.Copy(tarWriter, file)
		CheckError(err)
	}
}
Пример #5
0
func createTarArchive(files []string, output io.WriteCloser) error {
	archive := tar.NewWriter(output)
	defer archive.Close()

	for _, path := range files {
		file, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Unable to read file %s: %s", path, err)
		}
		defer file.Close()

		fi, err := file.Stat()
		if err != nil {
			return fmt.Errorf("Unable to get fileinfo for %s: %s", path, err)
		}

		header, err := tar.FileInfoHeader(fi, path)
		if err != nil {
			return fmt.Errorf("Failed to create tar header for %s: %s", path, err)
		}

		if err := archive.WriteHeader(header); err != nil {
			return fmt.Errorf("Failed to write tar header for %s: %s", path, err)
		}

		if _, err := io.Copy(archive, file); err != nil {
			return fmt.Errorf("Failed to copy %s data to archive: %s", path, err)
		}
	}
	return nil
}
Пример #6
0
Файл: pack.go Проект: Linvas/ant
func (wft *tarWalk) compress(name, fpath string, fi os.FileInfo) (bool, error) {
	isSym := fi.Mode()&os.ModeSymlink > 0
	link := ""
	if isSym {
		link, _ = os.Readlink(fpath)
	}

	hdr, err := tar.FileInfoHeader(fi, link)
	if err != nil {
		return false, err
	}
	hdr.Name = name

	tw := wft.tw
	err = tw.WriteHeader(hdr)
	if err != nil {
		return false, err
	}

	if isSym == false {
		fr, err := os.Open(fpath)
		if err != nil {
			return false, err
		}
		defer fr.Close()
		_, err = io.Copy(tw, fr)
		if err != nil {
			return false, err
		}
		tw.Flush()
	}

	return true, nil
}
Пример #7
0
func (t *tarRenderer) Walk(path string, finfo os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	fh, err := tar.FileInfoHeader(finfo, "")
	if err != nil {
		return err
	}

	fh.Name = "download/" + path
	err = t.w.WriteHeader(fh)
	if err != nil {
		return err
	}

	if finfo.IsDir() {
		return nil
	}

	f, err := os.Open(filepath.Join(t.root, path))
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = io.Copy(t.w, f)
	return err
}
Пример #8
0
func WriteToTar(tarWriter *tar.Writer, file *TarFile) error {
	hdr, err := tar.FileInfoHeader(file.Info, "")
	if err != nil {
		return fmt.Errorf("Unable to get tar FileInfoHeader of tar file '%s', error: %s", file.FileName, err.Error())
	}

	hdr.Name = file.FileName

	if hdr.Xattrs == nil {
		hdr.Xattrs = map[string]string{}
	}
	hdr.Xattrs["SIZE"] = fmt.Sprintf("%d", file.Info.Size())

	if file.IsOnlyFile {
		hdr.Xattrs["SINGLE_FILE_ONLY"] = "1"
	}

	err = tarWriter.WriteHeader(hdr)
	if err != nil {
		return fmt.Errorf("Unable to write tar header for file '%s', error: %s", file.FileName, err.Error())
	}

	if !file.HasContent() {
		return nil
	}

	defer file.ContentReadCloser.Close()
	_, err = io_throttler.CopyThrottled(io_throttler.DefaultIOThrottlingBandwidth, tarWriter, file.ContentReadCloser)
	return err
}
Пример #9
0
func (ctx *runContext) createTarArchive(fd *os.File, dir string) error {
	tarFd := tar.NewWriter(fd)
	defer tarFd.Close()
	err := filepath.Walk(dir, func(name string, info os.FileInfo, err error) error {
		if err != nil {
			return errgo.Mask(err, errgo.Any)
		}
		if info.IsDir() {
			return nil
		}
		tarHeader, err := tar.FileInfoHeader(info, name)
		if err != nil {
			return fmt.Errorf("fail to build tar header: %v", err)
		}
		err = tarFd.WriteHeader(tarHeader)
		if err != nil {
			return fmt.Errorf("fail to write tar header: %v", err)
		}
		fileFd, err := os.OpenFile(name, os.O_RDONLY, 0600)
		if err != nil {
			return errgo.Mask(err, errgo.Any)
		}
		_, err = stdio.Copy(tarFd, fileFd)
		if err != nil {
			return errgo.Mask(err, errgo.Any)
		}
		return nil
	})
	if err != nil {
		return errgo.Mask(err, errgo.Any)
	}
	return nil
}
Пример #10
0
func addFile(writer *tar.Writer, filepath string) error {
	f, err := os.Open(filepath)
	if err != nil {
		return err
	}
	defer f.Close()
	fi, err := os.Lstat(filepath)
	if err != nil {
		return err
	}
	if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
		target, err := os.Readlink(filepath)
		if err != nil {
			return err
		}
		return addSymlink(writer, filepath, target)
	}
	header, err := tar.FileInfoHeader(fi, "")
	if err != nil {
		return err
	}
	header.Name = filepath
	err = writer.WriteHeader(header)
	if err != nil {
		return err
	}
	n, err := io.Copy(writer, f)
	if err != nil {
		return err
	}
	if n != fi.Size() {
		return io.ErrShortWrite
	}
	return nil
}
Пример #11
0
func _tar_compress(call otto.FunctionCall) otto.Value {
	var (
		baseDir string
	)
	source, _ := call.Argument(0).ToString()
	target, _ := call.Argument(1).ToString()

	filename := filepath.Base(source)
	target = filepath.Join(target, fmt.Sprintf("%s.tar", filename))
	tarfile, err := os.Create(target)
	if err != nil {
		jsThrow(call, err)
	}
	defer tarfile.Close()

	tarball := tar.NewWriter(tarfile)
	defer tarball.Close()

	info, err := os.Stat(source)
	if err != nil {
		jsThrow(call, err)
	}

	if info.IsDir() {
		baseDir = filepath.Base(source)
	}

	err = filepath.Walk(source,
		func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}

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

			if baseDir != "" {
				header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
			}

			if err := tarball.WriteHeader(header); err != nil {
				return err
			}

			if info.IsDir() {
				return nil
			}

			file, err := os.Open(path)
			if err != nil {
				return err
			}
			defer file.Close()
			_, err = io.Copy(tarball, file)
			return err
		})
	return otto.Value{}
}
Пример #12
0
func recursiveTar(base, file string, tw *tar.Writer) error {
	filepath := path.Join(base, file)
	stat, err := os.Stat(filepath)
	if err != nil {
		return err
	}
	if stat.IsDir() {
		files, err := ioutil.ReadDir(filepath)
		if err != nil {
			return err
		}
		for _, f := range files {
			if err := recursiveTar(base, path.Join(file, f.Name()), tw); err != nil {
				return err
			}
		}
		return nil
	}
	hdr, err := tar.FileInfoHeader(stat, filepath)
	if err != nil {
		return err
	}
	hdr.Name = file
	if err := tw.WriteHeader(hdr); err != nil {
		return err
	}
	f, err := os.Open(filepath)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(tw, f)
	return err
}
Пример #13
0
Файл: slug.go Проект: ktec/slug
func targzWalk(dirPath string, tw *tar.Writer) {
	var walkfunc filepath.WalkFunc

	walkfunc = func(path string, fi os.FileInfo, err error) error {
		h, err := tar.FileInfoHeader(fi, "")
		handleError(err)

		h.Name = "./app/" + path

		if fi.Mode()&os.ModeSymlink != 0 {
			linkPath, err := os.Readlink(path)
			handleError(err)
			h.Linkname = linkPath
		}

		err = tw.WriteHeader(h)
		handleError(err)

		if fi.Mode()&os.ModeDir == 0 && fi.Mode()&os.ModeSymlink == 0 {
			fr, err := os.Open(path)
			handleError(err)
			defer fr.Close()

			_, err = io.Copy(tw, fr)
			handleError(err)
		}
		return nil
	}

	filepath.Walk(dirPath, walkfunc)
}
Пример #14
0
func Tar(base string, w io.Writer) error {
	tw := tar.NewWriter(w)
	err := filepath.Walk(base, func(path string, info os.FileInfo, err error) error {
		name, _ := filepath.Rel(base, path)
		if name == "." {
			return nil
		}

		hdr, err := tar.FileInfoHeader(info, "")
		if err != nil {
			return err
		}
		hdr.Name = name

		tw.WriteHeader(hdr)
		if info.IsDir() {
			return nil
		}

		// write file content
		f, err := os.Open(path)
		if err != nil {
			return err
		}
		_, err = io.Copy(tw, f)
		f.Close()
		return err
	})
	if err != nil {
		return err
	}
	return tw.Close()

}
Пример #15
0
func _getFileData(fpath string) (*bytes.Buffer, error) {
	if data, err := ioutil.ReadFile(fpath); err != nil {
		return nil, err
	} else {
		if fi, err := os.Stat(fpath); err != nil {
			return nil, err
		} else {
			reads := bytes.NewReader(data)
			var buff bytes.Buffer
			gw := gzip.NewWriter(&buff)
			defer gw.Close()
			tw := tar.NewWriter(gw)
			defer tw.Close()
			hdr, err := tar.FileInfoHeader(fi, "")
			if err != nil {
				return nil, err
			}
			if err := tw.WriteHeader(hdr); err != nil {
				return nil, err
			}
			if _, err := io.Copy(tw, reads); err != nil {
				return nil, err
			}
			return &buff, nil
		}
	}
}
//addFile adds the file named name as a tar entry named tarname
func addFile(name string, tarname string, tw *tar.Writer) error {
	if tarname == "" {
		tarname = name
	}
	fi, err := os.Stat(name)
	if err != nil {
		return err
	}
	hdr, err := tar.FileInfoHeader(fi, "")
	if err != nil {
		return err
	}
	hdr.Name = tarname

	err = tw.WriteHeader(hdr)
	if err != nil {
		return err
	}

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

	_, err = io.Copy(tw, f)
	if err != nil {
		return err
	}
	tw.Flush()
	return nil
}
Пример #17
0
func (i *dockerInput) addFile(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}
	th, err := tar.FileInfoHeader(info, path)
	if err != nil {
		return err
	}
	th.Name = path[1:] //filepath.Join(cpath, path)
	if si, ok := info.Sys().(*syscall.Stat_t); ok {
		th.Uid = int(si.Uid)
		th.Gid = int(si.Gid)
	}

	if err := i.tw.WriteHeader(th); err != nil {
		return err
	}

	if !info.Mode().IsDir() {
		file, err := os.Open(path)
		if err != nil {
			return err
		}
		if _, err := io.Copy(i.tw, file); err != nil {
			return err
		}
	}
	return nil
}
Пример #18
0
func walkTarFunc(tw *tar.Writer) filepath.WalkFunc {
	fn := func(path string, info os.FileInfo, err error) error {
		if info.Mode().IsDir() {
			return nil
		}
		f, err := os.Open(path)
		if err != nil {
			return err
		}
		defer f.Close()
		hdr, err := tar.FileInfoHeader(info, "")
		hdr.Name = path
		if err != nil {
			return err
		}
		err = tw.WriteHeader(hdr)
		if err != nil {
			return err
		}
		_, err = io.Copy(tw, f)
		if err != nil {
			return err
		}
		return nil
	}
	return fn
}
func addFileToTar(fileWriter *os.File, tarWriter *tar.Writer, info os.FileInfo, containingPath string, fullPath string) error {
	var (
		relpath string
		err     error
	)

	if relpath, err = filepath.Rel(containingPath, fullPath); err != nil {
		return err
	}

	if relpath == fileWriter.Name() || relpath == "." || relpath == ".." {
		return nil
	}

	if h, _ := tar.FileInfoHeader(info, fullPath); h != nil {
		h.Name = relpath
		if err := tarWriter.WriteHeader(h); err != nil {
			return err
		}
	}

	if !info.IsDir() {
		fr, err := os.Open(fullPath)
		if err != nil {
			return err
		}
		defer fr.Close()
		if _, err := io.Copy(tarWriter, fr); err != nil {
			return err
		}
	}

	return nil
}
Пример #20
0
// 因为要在 defer 中关闭文件,所以要单独创建一个函数
func tarFile(srcBase, srcRelative string, tw *tar.Writer, fi os.FileInfo) (err error) {
	// 获取完整路径
	srcFull := srcBase + srcRelative

	// 写入文件信息
	hdr, er := tar.FileInfoHeader(fi, "")
	if er != nil {
		return er
	}
	hdr.Name = srcRelative

	if er = tw.WriteHeader(hdr); er != nil {
		return er
	}

	// 打开要打包的文件,准备读取
	fr, er := os.Open(srcFull)
	if er != nil {
		return er
	}
	defer fr.Close()

	// 将文件数据写入 tw 中
	if _, er = io.Copy(tw, fr); er != nil {
		return er
	}
	return nil
}
Пример #21
0
// copyFile copies src to tar file dst.
func copyFile(tw *tar.Writer, dst, src string) error {
	s, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("unable to open %v: %v", src, err)
	}
	defer s.Close()
	fi, err := s.Stat()
	if err != nil {
		return fmt.Errorf("unable to stat %v: %v", src, err)
	}

	hdr, err := tar.FileInfoHeader(fi, dst)
	if err != nil {
		return fmt.Errorf("unable to create tar header for %v: %v", dst, err)
	}
	hdr.Name = dst
	if err := tw.WriteHeader(hdr); err != nil {
		return fmt.Errorf("unable to write header for %v: %v", dst, err)
	}
	_, err = io.Copy(tw, s)
	if err != nil {
		return fmt.Errorf("unable to copy %v to %v: %v", src, dst, err)
	}
	return nil
}
Пример #22
0
// AddFile add file from dir in archive tar
func (t *TarFile) AddFileWithName(name string, filename string) error {
	bytearq, err := ioutil.ReadFile(name)
	if err != nil {
		return err
	}

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

	header, err := tar.FileInfoHeader(info, "")
	if err != nil {
		return err
	}
	header.Name = filename

	err = t.Writer.WriteHeader(header)
	if err != nil {
		return err
	}
	_, err = t.Writer.Write(bytearq)
	if err != nil {
		return err
	}
	return nil
}
Пример #23
0
//WriteStreamToPackage writes bytes (from a file reader) to the tarball
func WriteStreamToPackage(is io.Reader, localpath string, packagepath string, tw *tar.Writer) error {
	info, err := os.Stat(localpath)
	if err != nil {
		return fmt.Errorf("%s: %s", localpath, err)
	}
	header, err := tar.FileInfoHeader(info, localpath)
	if err != nil {
		return fmt.Errorf("Error getting FileInfoHeader: %s", err)
	}

	//Let's take the variance out of the tar, make headers identical by using zero time
	oldname := header.Name
	var zeroTime time.Time
	header.AccessTime = zeroTime
	header.ModTime = zeroTime
	header.ChangeTime = zeroTime
	header.Name = packagepath

	if err = tw.WriteHeader(header); err != nil {
		return fmt.Errorf("Error write header for (path: %s, oldname:%s,newname:%s,sz:%d) : %s", localpath, oldname, packagepath, header.Size, err)
	}
	if _, err := io.Copy(tw, is); err != nil {
		return fmt.Errorf("Error copy (path: %s, oldname:%s,newname:%s,sz:%d) : %s", localpath, oldname, packagepath, header.Size, err)
	}

	return nil
}
Пример #24
0
// AddAll adds all files from dir in archive
// Tar does not support directories
func (t *TarFile) AddAll(dir string, includeCurrentFolder bool) error {
	dir = path.Clean(dir)
	return addAll(dir, dir, includeCurrentFolder, func(info os.FileInfo, file io.Reader, entryName string) (err error) {

		// Skip directory entries
		if file == nil {
			return nil
		}

		// Create a header based off of the fileinfo
		header, err := tar.FileInfoHeader(info, "")
		if err != nil {
			return err
		}

		// Set the header's name to what we want--it may not include the top folder
		header.Name = entryName

		// Write the header into the tar file
		if err := t.Writer.WriteHeader(header); err != nil {
			return err
		}

		// Pipe the file into the tar
		if _, err := io.Copy(t.Writer, file); err != nil {
			return err
		}

		return nil
	})
}
Пример #25
0
func tarDir(srcBase, srcRelative string, tw *tar.Writer, fi os.FileInfo) (err error) {
	srcFull := srcBase + srcRelative
	fis, er := ioutil.ReadDir(srcFull)
	if er != nil {
		return er
	}

	for _, fi := range fis {
		if fi.IsDir() {
			tarDir(srcBase, srcRelative+"/"+fi.Name(), tw, fi)
		} else {
			tarFile(srcBase, srcRelative+"/"+fi.Name(), tw, fi)
		}
	}

	if len(srcRelative) > 0 {
		hdr, er := tar.FileInfoHeader(fi, "")
		if er != nil {
			return er
		}
		hdr.Name = srcRelative
		if er = tw.WriteHeader(hdr); er != nil {
			return er
		}
	}

	return nil
}
Пример #26
0
//compress the file (if compress to the zip file , using the similar package: zip.FileInfoHeader)
func Filecompress(tw *tar.Writer, dir string, fi os.FileInfo) error {

	//打开文件 open当中是 目录名称/文件名称 构成的组合
	log.Println(dir + fi.Name())
	fr, err := os.Open(dir + fi.Name())
	log.Println(fr.Name())
	if err != nil {
		return err
	}
	defer fr.Close()

	hdr, err := tar.FileInfoHeader(fi, "")

	hdr.Name = fr.Name()
	if err = tw.WriteHeader(hdr); err != nil {
		return err
	}

	_, err = io.Copy(tw, fr)
	if err != nil {
		return err
	}
	//打印文件名称
	log.Println("add the file: " + fi.Name())
	return nil

}
Пример #27
0
// writeTarHeader writes tar header for given file, returns error if operation fails
func (t *stiTar) writeTarHeader(tarWriter *tar.Writer, dir string, path string, info os.FileInfo, includeDirInPath bool) error {
	var (
		link string
		err  error
	)
	if info.Mode()&os.ModeSymlink != 0 {
		link, err = os.Readlink(path)
		if err != nil {
			return err
		}
	}
	header, err := tar.FileInfoHeader(info, link)
	if err != nil {
		return err
	}
	prefix := dir
	if includeDirInPath {
		prefix = filepath.Dir(prefix)
	}
	header.Name = filepath.ToSlash(path[1+len(prefix):])
	glog.V(5).Infof("Adding to tar: %s as %s", path, header.Name)
	if err = tarWriter.WriteHeader(header); err != nil {
		return err
	}

	return nil
}
func addFileToTar(fileWriter *os.File, tarWriter *tar.Writer, info os.FileInfo, relativePath, fullPath string) error {
	if relativePath == fileWriter.Name() || relativePath == "." || relativePath == ".." {
		return nil
	}

	if h, err := tar.FileInfoHeader(info, fullPath); err == nil {
		h.Name = relativePath
		if err := tarWriter.WriteHeader(h); err != nil {
			return err
		}
	}

	if info.IsDir() {
		return nil
	}

	li, err := os.Lstat(fullPath)
	if err != nil {
		return err
	}
	if li.Mode()&os.ModeSymlink == os.ModeSymlink {
		return nil
	}

	fr, err := os.Open(fullPath)
	if err != nil {
		return err
	}
	defer fr.Close()
	if _, err := io.Copy(tarWriter, fr); err != nil {
		return err
	}

	return nil
}
Пример #29
0
func (t *tarmonster) walk(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	if !info.Mode().IsRegular() || info.Size() == 0 {
		return nil
	}

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

	// Get tar.Header
	fih, err := tar.FileInfoHeader(info, "")
	if err != nil {
		return err
	}
	fih.Name = strings.TrimPrefix(path, t.src+string(filepath.Separator))

	// Begin a new file
	if err := t.writer.WriteHeader(fih); err != nil {
		return err
	}

	// Write the file
	if _, err := io.CopyBuffer(t.writer, file, t.buffer); err != nil {
		return err
	}

	return err
}
Пример #30
0
func (t *Tar) Add(filename string) error {
	info, rdc, err := statFile(filename)
	if err != nil {
		return err
	}
	defer rdc.Close()

	link := ""
	if info.Mode()&os.ModeSymlink != 0 {
		link, _ = os.Readlink(filename)
	}
	// header
	hdr, err := tar.FileInfoHeader(info, link)
	if err != nil {
		return err
	}
	hdr.Name = sanitizedName(filename)
	if info.IsDir() {
		hdr.Name += "/"
	}
	if err = t.WriteHeader(hdr); err != nil {
		return fmt.Errorf("header: %v", err)
	}
	if info.Mode().IsRegular() {
		_, err = io.Copy(t, rdc)
	}
	return err
}