mirror of
https://github.com/nxshock/backuper.git
synced 2024-11-28 00:21:02 +05:00
nxshock
19e809966a
* update logger routines * add index file support * split file masks and path masks
89 lines
2.3 KiB
Go
89 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"archive/tar"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/klauspost/compress/zstd"
|
|
)
|
|
|
|
type ExtractionPlan map[string][]string // filepath - array of internal paths
|
|
|
|
func (b *Config) extractionPlan(mask string, t time.Time) (ExtractionPlan, error) {
|
|
index, err := b.index(true)
|
|
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.ArchiveFileName] = append(plan[file.ArchiveFileName], file.filePath)
|
|
}
|
|
|
|
return plan, nil
|
|
}
|
|
|
|
func (b *Config) extract(extractionPlan ExtractionPlan, toDir string) error {
|
|
for archiveFile, files := range extractionPlan {
|
|
log.Printf("Восстановление из архивного файла %s...", filepath.Join(filepath.Dir(b.filePath), archiveFile))
|
|
f, err := os.Open(filepath.Join(filepath.Dir(b.filePath), 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 {
|
|
log.Printf("Восстановление файла %s...", header.Name)
|
|
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
|
|
}
|