1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
// This file is part of the adequate Debian-native package, and is available
// under the Expat license. For the full terms please see debian/copyright.
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
"strings"
"syscall"
)
const pendingPath = "/var/lib/adequate/pending"
func aptHookReader() *bufio.Reader {
return bufio.NewReader(os.Stdin)
}
func aptHookIsEnabled(reader *bufio.Reader) bool {
var enabled, defined bool
loop:
for {
line, err := reader.ReadString('\n')
if err != nil {
// We're only supposed to read the configuration
// section, which ends with an empty line, so we
// shouldn't hit EOF.
if err == io.EOF {
log.Fatal("Found EOF while reading apt configuration section.")
}
log.Fatal("Read error: ", err)
}
switch line {
case "Adequate::Enabled=true\n":
enabled = true
defined = true
case "Adequate::Enabled=false\n":
enabled = false
defined = true
case "\n":
break loop
}
}
if !defined {
log.Println("apt hook is not enabled")
return false
}
return enabled
}
func readPkgs(reader *bufio.Reader) []string {
var pkgs []string
for {
line, err := reader.ReadString('\n')
if err != nil && err != io.EOF {
log.Fatal("Read error: ", err)
}
if line == "" || err == io.EOF {
break
}
// We're looking for files with this structure:
// pkg, fromVer, operator, toVer, debFilePath
// Sample line:
// libparted-fs-resize0 3.5-3 = 3.5-3 /var/cache/apt/archives/libparted-fs-resize0_3.5-3_amd64.deb
fields := strings.Fields(line)
if n := len(fields); n != 5 || !strings.HasSuffix(line, ".deb\n") {
continue
}
pkgs = append(pkgs, fields[0])
}
return pkgs
}
type pendingHandler struct {
fi *os.File
}
func newPendingHandler() (*pendingHandler, error) {
fi, err := os.OpenFile(pendingPath, os.O_APPEND|os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
return nil, fmt.Errorf("%s: %w", pendingPath, err)
}
if err := syscall.Flock(int(fi.Fd()), syscall.LOCK_EX); err != nil {
return nil, fmt.Errorf("%s: %w", pendingPath, err)
}
return &pendingHandler{
fi: fi,
}, nil
}
func (ph *pendingHandler) read() ([]string, error) {
if _, err := ph.fi.Seek(0, 0); err != nil {
fmt.Errorf("failed to seek %s: %w", pendingPath, err)
}
return readLines(ph.fi)
}
func (ph *pendingHandler) truncatePendingOrDie() {
ph.writePendingOrDie(nil)
}
func (ph *pendingHandler) writePendingOrDie(pkgs []string) {
if ph.fi == nil {
log.Fatal("writePendingOrDie() called with nil file handler")
}
if err := ph.fi.Truncate(0); err != nil {
log.Fatalf("Failed to truncate %s: %v", pendingPath, err)
}
if _, err := ph.fi.Seek(0, 0); err != nil {
log.Fatalf("Failed to seek %s: %v", pendingPath, err)
}
for _, pkg := range pkgs {
if _, err := ph.fi.WriteString(pkg + "\n"); err != nil {
log.Fatalf("Failed to write %s: %v", pendingPath, err)
}
}
}
func (ph *pendingHandler) cleanupOrDie() error {
if err := syscall.Flock(int(ph.fi.Fd()), syscall.LOCK_UN); err != nil {
log.Fatalf("Failed to release file lock for %s: %v", pendingPath, err)
}
return ph.fi.Close()
}
|