package main import ( "archive/zip" "bufio" "fmt" "io" "log" "os" "os/exec" "path/filepath" "strings" "time" "github.com/otiai10/copy" "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") log.Printf("tmpPath is: %s\n", tmpPath) pacmanDb, err := parsePacmanConf() if err != nil { return err } log.Printf("pacmanDB is at: %s\n", pacmanDb) 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, "/", when, "_pacman.txt"), output, 0666) if err != nil { return err } if strings.Compare(when, "post") != 0 { err = copy.Copy(pacmanDb, fmt.Sprint(tmpPath, "/", pacmanDb)) if err != nil { return err } } current_time := time.Now().Format(time.RFC3339) pathToZip := fmt.Sprint(tmpPath, "_", current_time, ".zip") log.Printf("pathToZip is: %s\n", pathToZip) err = zipIt(pathToZip, tmpPath) if err != nil { return err } for _, backup_location := range backup_locations { backup_path := fmt.Sprintf("%s/%s/%s_backup_%s.zip", backup_location, when, when, current_time) log.Printf("backup_path is: %s\n", backup_path) err = copy.Copy(pathToZip, backup_path) if err != nil { return err } } return nil } func main() { if strings.Compare(os.Args[1], "debug") != 0 { log.SetOutput(io.Discard) } else { logFile, err := os.OpenFile("/tmp/update.txt", os.O_CREATE | os.O_APPEND | os.O_RDWR, 0666) if err != nil { panic(err) } defer logFile.Close() mw := io.MultiWriter(os.Stdout, logFile) log.SetOutput(mw) fmt.Println("Logfile is /tmp/update.txt") } log.Printf("Cmdline argument is: %s\n", os.Args[1]) 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) log.Printf("backup_locations are: %s\n", backup_locations) err = backup(os.Args[1]) if err != nil { fmt.Println("backup failed for the following reason: ", err) os.Exit(1) } }