/
kpartx.go
78 lines (68 loc) · 1.74 KB
/
kpartx.go
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
package image
import (
"bufio"
"fmt"
"os"
"os/exec"
"sort"
"strconv"
"strings"
log "github.com/sirupsen/logrus"
)
func addDevMappings(path string) error {
cmd := exec.Command("kpartx", "-s", "-a", path)
cmd.Stdout = os.Stdout
return cmd.Run()
}
func getDevMappings(path string) ([]string, error) {
out, err := exec.Command("kpartx", "-l", path).Output()
if err != nil {
return []string{}, err
}
return mustParseDevMappings(string(out)), nil
}
func removeDevMappings(path string) error {
log.Debugf("Unmap %s as a device", path)
cmd := exec.Command("kpartx", "-d", path)
cmd.Stdout = os.Stdout
return cmd.Run()
}
// mustParseDevMappings parse 'kpartx -l <img file>' output and resolves
// what are the '/dev/mapper' paths for the partitions
func mustParseDevMappings(raw string) []string {
scanner := bufio.NewScanner(strings.NewReader(raw))
lines := []string{}
for scanner.Scan() {
line := scanner.Text()
if line != "" && !strings.Contains(line, "deleted") {
lines = append(lines, line)
}
}
partitions := make([]struct {
start int
path string
}, len(lines))
for i, line := range lines {
parts := strings.SplitN(line, ":", 2)
if parts[0] != "" {
info := strings.SplitN(strings.TrimSpace(parts[1]), " ", 4)
size, err := strconv.Atoi(info[3])
if err != nil {
log.Fatalf("Failed to parse kpartx output line: %s", line)
}
partitions[i] = struct {
start int
path string
}{
start: size,
path: fmt.Sprintf("/dev/mapper/%s", strings.TrimSpace(parts[0])),
}
}
}
sort.Slice(partitions, func(i, j int) bool { return partitions[i].start < partitions[j].start })
result := make([]string, len(partitions))
for i, device := range partitions {
result[i] = device.path
}
return result
}