mirror of
https://github.com/nxshock/backuper.git
synced 2024-11-28 00:21:02 +05:00
86 lines
2.0 KiB
Go
86 lines
2.0 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"archive/tar"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"time"
|
||
|
|
||
|
"github.com/klauspost/compress/zstd"
|
||
|
)
|
||
|
|
||
|
type ExtractionPlan map[string][]string // filepath - array of internal paths
|
||
|
|
||
|
func (b *Backuper) extractionPlan(mask string, t time.Time) (ExtractionPlan, error) {
|
||
|
index, err := b.Config.index()
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("extractionPlan: %v", err)
|
||
|
}
|
||
|
|
||
|
files, err := index.GetFilesLocation(mask, t)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("extractionPlan: %v", err)
|
||
|
}
|
||
|
|
||
|
plan := make(ExtractionPlan)
|
||
|
|
||
|
for _, file := range files {
|
||
|
plan[file.ArchiveFile] = append(plan[file.ArchiveFile], file.DestinationPath)
|
||
|
}
|
||
|
|
||
|
return plan, nil
|
||
|
}
|
||
|
|
||
|
func (b *Backuper) extract(extractionPlan ExtractionPlan, toDir string) error {
|
||
|
for archiveFile, files := range extractionPlan {
|
||
|
f, err := os.Open(archiveFile)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("ошибка при чтении файла архива: %v", err)
|
||
|
}
|
||
|
defer f.Close()
|
||
|
|
||
|
decoder, err := zstd.NewReader(f)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("ошибка при инициализации разархиватора: %v", err)
|
||
|
}
|
||
|
defer decoder.Close()
|
||
|
|
||
|
tarReader := tar.NewReader(decoder)
|
||
|
|
||
|
for {
|
||
|
header, err := tarReader.Next()
|
||
|
if err == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("ошибка при чтении tar-содержимого: %v", err)
|
||
|
}
|
||
|
if inArr, i := stringIn(header.Name, files); inArr {
|
||
|
resultFilePath := filepath.Join(toDir, clean(header.Name))
|
||
|
os.MkdirAll(filepath.Dir(resultFilePath), 0644)
|
||
|
f, err := os.Create(resultFilePath)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
_, err = io.Copy(f, tarReader)
|
||
|
if err != nil {
|
||
|
f.Close() // TODO: удалять частичный файл?
|
||
|
return fmt.Errorf("ошибка при извлечении файла из tar-архива: %v", err)
|
||
|
}
|
||
|
|
||
|
f.Close()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
files[i] = files[len(files)-1]
|
||
|
files = files[:len(files)-1]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|