forked from concourse/baggageclaim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
btrfs.go
131 lines (104 loc) · 2.31 KB
/
btrfs.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
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
package fs
import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"
"code.cloudfoundry.org/lager"
)
type BtrfsFilesystem struct {
imagePath string
mountPath string
mkfsBin string
logger lager.Logger
}
func New(logger lager.Logger, imagePath string, mountPath string, mkfsBin string) *BtrfsFilesystem {
return &BtrfsFilesystem{
imagePath: imagePath,
mountPath: mountPath,
mkfsBin: mkfsBin,
logger: logger,
}
}
// lower your expectations
func (fs *BtrfsFilesystem) Create(bytes uint64) error {
// significantly
idempotent := exec.Command("bash", "-e", "-x", "-c", `
if [ ! -e $IMAGE_PATH ] || [ "$(stat --printf="%s" $IMAGE_PATH)" != "$SIZE_IN_BYTES" ]; then
touch $IMAGE_PATH
truncate -s ${SIZE_IN_BYTES} $IMAGE_PATH
fi
lo="$(losetup -j $IMAGE_PATH | cut -d':' -f1)"
if [ -z "$lo" ]; then
lo="$(losetup -f --show $IMAGE_PATH)"
fi
if ! file $IMAGE_PATH | grep BTRFS; then
`+fs.mkfsBin+` --nodiscard $IMAGE_PATH
fi
mkdir -p $MOUNT_PATH
if ! mountpoint -q $MOUNT_PATH; then
mount -t btrfs $lo $MOUNT_PATH
fi
`)
idempotent.Env = []string{
"PATH=" + os.Getenv("PATH"),
"MOUNT_PATH=" + fs.mountPath,
"IMAGE_PATH=" + fs.imagePath,
fmt.Sprintf("SIZE_IN_BYTES=%d", bytes),
}
_, err := fs.run(idempotent)
return err
}
func (fs *BtrfsFilesystem) Delete() error {
_, err := fs.run(exec.Command(
"umount",
fs.mountPath,
))
if err != nil {
return err
}
if err := os.RemoveAll(fs.mountPath); err != nil {
return err
}
loopbackOutput, err := fs.run(exec.Command(
"losetup",
"-j",
fs.imagePath,
))
if err != nil {
return err
}
loopbackDevice := strings.Split(loopbackOutput, ":")[0]
_, err = fs.run(exec.Command(
"losetup",
"-d",
loopbackDevice,
))
if err != nil {
return err
}
return os.Remove(fs.imagePath)
}
func (fs *BtrfsFilesystem) run(cmd *exec.Cmd) (string, error) {
logger := fs.logger.Session("run-command", lager.Data{
"command": cmd.Path,
"args": cmd.Args,
"env": cmd.Env,
})
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
cmd.Stdout = stdout
cmd.Stderr = stderr
err := cmd.Run()
loggerData := lager.Data{
"stdout": stdout.String(),
"stderr": stderr.String(),
}
if err != nil {
logger.Error("failed", err, loggerData)
return "", err
}
logger.Debug("ran", loggerData)
return stdout.String(), nil
}