package main import ( "archive/zip" "bufio" "fmt" "io" "os" "os/exec" "path/filepath" "strings" "time" "github.com/pelletier/go-toml" ) var backup_locations []string func parsePacmanConf() (string, error) { var err error var path string file, err := os.Open("/etc/pacman.conf") if err != nil { return "", err } scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, "DBPath") { continue } path = strings.TrimSpace(strings.Split(line, "=")[1]) break } err = file.Close() if err != nil { return "", err } return fmt.Sprint(path, "local"), nil } func zipIt(pathToZip string, pathToFiles string) error { var err error zipFile, err := os.Create(pathToZip) if err != nil { return err } zipWriter := zip.NewWriter(zipFile) walker := func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } file, err := os.Open(path) if err != nil { return err } defer file.Close() f, err := zipWriter.Create(path[len(pathToFiles):]) if err != nil { return err } _, err = io.Copy(f, file) if err != nil { return err } return nil } err = filepath.Walk(pathToFiles, walker) if err != nil { return err } err = zipWriter.Close() if err != nil { return err } err = zipFile.Close() if err != nil { return err } return nil } func backup(when string) error { var err error tmpPath := fmt.Sprint("/tmp/update/", when, "_backup") pacmanDb, err := parsePacmanConf() if err != nil { return err } err = os.MkdirAll(tmpPath, 0755) if err != nil { return err } defer func() { os.RemoveAll("/tmp/update") }() output, err := exec.Command("pacman", "--verbose", "--query").Output() if err != nil { return err } err = os.WriteFile(fmt.Sprint(tmpPath, fmt.Sprint(when, "_pacman.txt")), output, 0644) if err != nil { return err } if when != "post" { err = CopyDir(pacmanDb, fmt.Sprint(tmpPath, "/", pacmanDb)) if err != nil { return err } } current_time := time.Now().Format(time.RFC3339) pathToZip := fmt.Sprint(tmpPath, "_", current_time, ".zip") err = zipIt(pathToZip, tmpPath) if err != nil { return err } for _, backup_location := range backup_locations { err = CopyFile(pathToZip, fmt.Sprint(backup_location, "/", when, "_backup_", current_time, ".zip")) if err != nil { return err } } return nil } func main() { os.RemoveAll("/tmp/update") tree, err := toml.LoadFile("/etc/update.toml") if err != nil { fmt.Println("backup failed for the following reason: ", err) os.Exit(1) } backup_locations = tree.GetArray("backup.locations").([]string) err = backup(os.Args[1]) if err != nil { fmt.Println("backup failed for the following reason: ", err) os.Exit(1) } }