-
Notifications
You must be signed in to change notification settings - Fork 2
/
securetemp_darwin.go
129 lines (109 loc) · 2.71 KB
/
securetemp_darwin.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
package securetemp
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"
)
func createRAMDisk(size int) (string, CleanupFunc, error) {
var (
mountPath, devPath string
err error
doCleanup = true
)
cleanupFunc := func() { cleanupRAMDisk(devPath, mountPath) }
defer func() {
if doCleanup {
cleanupFunc()
}
}()
mountPath, err = ioutil.TempDir("", globalPrefix)
if err != nil {
return "", nil, fmt.Errorf("failed to create temp dir: %s", err)
}
devPath, err = createDev(size)
if err != nil {
return "", nil, fmt.Errorf("failed to create device: %s", err)
}
if err := formatDev(devPath); err != nil {
return "", nil, fmt.Errorf("failed to format device: %s", err)
}
if err := mountDev(devPath, mountPath); err != nil {
return "", nil, fmt.Errorf("failed to mount device: %s", err)
}
doCleanup = false
return mountPath, cleanupFunc, nil
}
func cleanupRAMDisk(devPath, mountPath string) {
if mountPath != "" {
_ = exec.Command("umount", mountPath).Run()
defer func() {
_ = os.RemoveAll(mountPath)
}()
}
if devPath != "" {
_ = exec.Command("diskutil", "quiet", "eject", devPath).Run()
}
}
func createDev(size int) (string, error) {
path, err := exec.LookPath("hdid")
if err != nil {
return "", errors.New("did not find 'hdid'")
}
cmd := exec.Command(path,
"-drivekey",
"system-image=yes",
"-nomount",
fmt.Sprintf("ram://%d", size*2))
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Start(); err != nil {
return "", fmt.Errorf("failed to start 'hdid': %s", err)
}
if err := cmd.Wait(); err != nil {
return "", fmt.Errorf("'hdid' failed: %s, %s", err, stderr.String())
}
return strings.Split(stdout.String(), " ")[0], nil
}
func formatDev(devPath string) error {
path, err := exec.LookPath("newfs_hfs")
if err != nil {
return errors.New("did not find 'newfs_hfs'")
}
cmd := exec.Command(path,
"-M", "700",
devPath)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to start 'newfs_hfs': %s", err)
}
if err := cmd.Wait(); err != nil {
return fmt.Errorf("'newfs_hfs' failed: %s, %s", err, stderr.String())
}
return nil
}
func mountDev(devPath, mountPath string) error {
path, err := exec.LookPath("mount")
if err != nil {
return errors.New("did not find 'mount'")
}
cmd := exec.Command(path,
"-t", "hfs",
"-o", "noatime",
"-o", "nobrowse",
devPath, mountPath)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to start 'mount': %s", err)
}
if err := cmd.Wait(); err != nil {
return fmt.Errorf("'mount' failed: %s, %s", err, stderr.String())
}
return nil
}