2020-03-27 22:52:54 +00:00
|
|
|
package tarstream
|
|
|
|
|
|
|
|
import (
|
2023-04-26 12:06:56 +00:00
|
|
|
"archive/tar"
|
2020-03-27 22:52:54 +00:00
|
|
|
"io"
|
2023-04-26 12:06:56 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2020-03-27 22:52:54 +00:00
|
|
|
)
|
|
|
|
|
2023-04-26 12:06:56 +00:00
|
|
|
// Send рекурсивно обходит директорию и сериализует её содержимое в поток w.
|
2020-03-27 22:52:54 +00:00
|
|
|
func Send(dir string, w io.Writer) error {
|
2023-04-26 12:06:56 +00:00
|
|
|
tw := tar.NewWriter(w)
|
|
|
|
|
|
|
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
rel, err := filepath.Rel(dir, path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if rel == "." {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case info.IsDir():
|
|
|
|
return tw.WriteHeader(&tar.Header{
|
|
|
|
Name: rel,
|
|
|
|
Typeflag: tar.TypeDir,
|
|
|
|
})
|
|
|
|
|
|
|
|
default:
|
|
|
|
h := &tar.Header{
|
|
|
|
Typeflag: tar.TypeReg,
|
|
|
|
Name: rel,
|
|
|
|
Size: info.Size(),
|
|
|
|
Mode: int64(info.Mode()),
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tw.WriteHeader(h); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(tw, f)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return tw.Close()
|
2020-03-27 22:52:54 +00:00
|
|
|
}
|
|
|
|
|
2023-04-26 12:06:56 +00:00
|
|
|
// Receive читает поток r и материализует содержимое потока внутри dir.
|
2020-03-27 22:52:54 +00:00
|
|
|
func Receive(dir string, r io.Reader) error {
|
2023-04-26 12:06:56 +00:00
|
|
|
tr := tar.NewReader(r)
|
|
|
|
|
|
|
|
for {
|
|
|
|
h, err := tr.Next()
|
|
|
|
if err == io.EOF {
|
|
|
|
return nil
|
|
|
|
} else if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
absPath := filepath.Join(dir, h.Name)
|
|
|
|
|
|
|
|
if h.Typeflag == tar.TypeDir {
|
|
|
|
if err := os.Mkdir(absPath, 0777); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
writeFile := func() error {
|
|
|
|
f, err := os.OpenFile(absPath, os.O_CREATE|os.O_WRONLY, os.FileMode(h.Mode))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(f, tr)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := writeFile(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-27 22:52:54 +00:00
|
|
|
}
|