starting from scratch
This commit is contained in:
parent
6fce70ba3c
commit
0cf266dd87
120
backup.go
Normal file
120
backup.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseEnvironment(key string) string {
|
||||||
|
value := os.Getenv(key)
|
||||||
|
if value == "" {
|
||||||
|
log.Panicf("%s is not set\n", key)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(value); err != nil {
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
log.Panicf("%s does not point to a valid path\n", key)
|
||||||
|
}
|
||||||
|
log.Panicf("trying to stat %s produced an unkown error\n", value)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePacmanConf() string {
|
||||||
|
var path string
|
||||||
|
|
||||||
|
file, err := os.Open("/etc/pacman.conf")
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := file.Close(); err != nil {
|
||||||
|
log.Panicln(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
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
log.Panicln("DBPath in /etc/pacman.conf does not point to a valid path")
|
||||||
|
}
|
||||||
|
log.Panicf("trying to stat %s produced an unkown error\n", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s%s", path, "local")
|
||||||
|
}
|
||||||
|
|
||||||
|
func preBackup() {
|
||||||
|
pacmanDb := parsePacmanConf()
|
||||||
|
log.Printf("pacmanDb: %s\n", pacmanDb)
|
||||||
|
tmpPath := "/tmp/update/pre_backup"
|
||||||
|
|
||||||
|
output, err := exec.Command("pacman", "--verbose", "--query").Output()
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(tmpPath, 0755)
|
||||||
|
|
||||||
|
err = os.WriteFile(fmt.Sprintf("%s/%s", tmpPath, "pre_pacman.txt"), output, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err := os.RemoveAll(tmpPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CopyDir(pacmanDb, fmt.Sprintf("%s/%s", tmpPath, pacmanDb))
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("recovered successfully")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = CopyDir(pacmanDb, fmt.Sprintf("%s/%s", tmpPath, pacmanDb))
|
||||||
|
if err != nil {
|
||||||
|
log.Panicln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func postBackup() {
|
||||||
|
/*
|
||||||
|
* basic logic for post:
|
||||||
|
* create new pkg list and delete all lines which are the same as pre
|
||||||
|
*/
|
||||||
|
panic("unimplemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// backup_dir := parseEnvironment("UPDATE_BACKUP_DIR")
|
||||||
|
cmdlineArg := os.Args[1]
|
||||||
|
log.Printf("cmdlineArg: %s\n", cmdlineArg)
|
||||||
|
|
||||||
|
if cmdlineArg == "pre" {
|
||||||
|
preBackup()
|
||||||
|
} else if cmdlineArg == "post" {
|
||||||
|
postBackup()
|
||||||
|
} else {
|
||||||
|
log.Panicf("invalid cmdline argument. supplied value was: %s\n", cmdlineArg)
|
||||||
|
}
|
||||||
|
}
|
134
copy.go
Normal file
134
copy.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Roland Singer [roland.singer@desertbit.com]
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CopyFile copies the contents of the file named src to the file named
|
||||||
|
// by dst. The file will be created if it does not already exist. If the
|
||||||
|
// destination file exists, all it's contents will be replaced by the contents
|
||||||
|
// of the source file. The file mode will be copied from the source and
|
||||||
|
// the copied data is synced/flushed to stable storage.
|
||||||
|
func CopyFile(src, dst string) (err error) {
|
||||||
|
in, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer in.Close()
|
||||||
|
|
||||||
|
out, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if e := out.Close(); e != nil {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = io.Copy(out, in)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = out.Sync()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
si, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Chmod(dst, si.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyDir recursively copies a directory tree, attempting to preserve permissions.
|
||||||
|
// Source directory must exist, destination directory must *not* exist.
|
||||||
|
// Symlinks are ignored and skipped.
|
||||||
|
func CopyDir(src string, dst string) (err error) {
|
||||||
|
src = filepath.Clean(src)
|
||||||
|
dst = filepath.Clean(dst)
|
||||||
|
|
||||||
|
si, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !si.IsDir() {
|
||||||
|
return fmt.Errorf("source is not a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = os.Stat(dst)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("destination already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(dst, si.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := ioutil.ReadDir(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
srcPath := filepath.Join(src, entry.Name())
|
||||||
|
dstPath := filepath.Join(dst, entry.Name())
|
||||||
|
|
||||||
|
if entry.IsDir() {
|
||||||
|
err = CopyDir(srcPath, dstPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Skip symlinks.
|
||||||
|
if entry.Mode()&os.ModeSymlink != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CopyFile(srcPath, dstPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
11
post_backup.hook
Normal file
11
post_backup.hook
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Trigger]
|
||||||
|
Operation = Install
|
||||||
|
Operation = Upgrade
|
||||||
|
Operation = Remove
|
||||||
|
Type = Path
|
||||||
|
Target = /usr/local/bin/backup
|
||||||
|
|
||||||
|
[Action]
|
||||||
|
Description = Backing up the pacman db...
|
||||||
|
When = PostTransaction
|
||||||
|
Exec = /usr/local/bin/backup post
|
12
pre_backup.hook
Normal file
12
pre_backup.hook
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[Trigger]
|
||||||
|
Operation = Install
|
||||||
|
Operation = Upgrade
|
||||||
|
Operation = Remove
|
||||||
|
Type = Path
|
||||||
|
Target = /usr/local/bin/backup
|
||||||
|
|
||||||
|
[Action]
|
||||||
|
Description = Backing up the pacman db...
|
||||||
|
When = PreTransaction
|
||||||
|
Exec = /usr/local/bin/backup pre
|
||||||
|
AbortOnFail
|
Loading…
Reference in New Issue
Block a user