gosync/tools/scanner.go

118 lines
2.8 KiB
Go
Raw Permalink Normal View History

2023-09-07 15:20:19 +02:00
package tools
import (
"errors"
"io"
2023-09-07 15:20:19 +02:00
"io/fs"
"os"
"os/exec"
2023-09-07 15:20:19 +02:00
"path/filepath"
"strconv"
"strings"
2023-09-07 15:20:19 +02:00
"time"
"velvettear/gosync/log"
"velvettear/gosync/settings"
)
var sourceFiles map[string]int64
2023-09-07 15:20:19 +02:00
// unexported function(s)
func getSourceFiles() map[string]int64 {
2023-09-07 15:20:19 +02:00
timestamp := time.Now()
sourceFiles = map[string]int64{}
if settings.SourceIsRemote() {
log.Info("getting the list of remote source files...")
error := fillRemoteSourceFiles()
if error != nil {
log.Fatal("encountered an error getting the list of remote source files", error.Error())
}
2023-09-07 15:20:19 +02:00
} else {
source, _ := strings.CutSuffix(settings.Source, "/*")
stats, error := os.Stat(source)
if error != nil {
log.Fatal("encountered an error getting stats for source", error.Error())
}
if stats.IsDir() {
log.Info("scanning source...", source)
filepath.WalkDir(source, fillSourceFiles)
} else {
sourceFiles[settings.Source] = stats.Size()
}
2023-09-07 15:20:19 +02:00
}
log.InfoTimed("found "+strconv.Itoa(len(sourceFiles))+" source files", timestamp.UnixMilli())
2023-09-07 15:20:19 +02:00
return sourceFiles
}
func fillRemoteSourceFiles() error {
var arguments []string
if len(settings.Password) > 0 {
arguments = append(arguments, "-p", settings.Password)
}
arguments = append(arguments, "ssh")
remote, path, _ := strings.Cut(settings.Source, ":")
path, _ = strings.CutSuffix(path, "/*")
if len(settings.User) > 0 {
remote = settings.User + "@" + remote
}
arguments = append(arguments, remote, "find", "\""+path+"\"", "-type", "f", "-exec", "du", "-b", "{}", "\\;")
cmd := exec.Command("sshpass", arguments...)
stdout, stdoutError := cmd.StdoutPipe()
stderr, stderrError := cmd.StderrPipe()
cmd.Start()
if stdoutError != nil {
return stdoutError
}
if stderrError != nil {
return stderrError
}
outBytes, stdoutError := io.ReadAll(stdout)
if stdoutError != nil {
return stdoutError
}
errorBytes, stderrError := io.ReadAll(stderr)
if stderrError != nil {
return stderrError
}
cmd.Wait()
error := strings.TrimSpace(string(errorBytes))
if len(error) > 0 {
return errors.New(error)
}
for _, line := range strings.Split(string(outBytes), "\n") {
if !strings.Contains(line, "\t") {
continue
}
parts := strings.Split(line, "\t")
size, error := strconv.ParseInt(parts[0], 10, 64)
if error != nil {
log.Warning("encountered an error getting the file size for file '"+path+"'", error.Error())
}
sourceFiles[parts[1]] = size
}
return nil
}
2023-09-07 15:20:19 +02:00
func fillSourceFiles(path string, dir fs.DirEntry, err error) error {
if err != nil {
return err
}
if dir.IsDir() {
return nil
}
stats, error := os.Stat(path)
if error != nil {
log.Fatal("encountered an error getting stats for file", error.Error())
return nil
}
sourceFiles[path] = stats.Size()
2023-09-07 15:20:19 +02:00
return nil
}
func getSourceFileSize() int64 {
var total int64
for _, size := range sourceFiles {
total += size
}
return total
}