forked from terra-farm/go-virtualbox
-
Notifications
You must be signed in to change notification settings - Fork 6
/
disk.go
70 lines (61 loc) · 1.45 KB
/
disk.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
package virtualbox
import (
"fmt"
"io"
"os"
"os/exec"
)
// MakeDiskImage makes a disk image at dest with the given size in MB. If r is
// not nil, it will be read as a raw disk image to convert from.
func MakeDiskImage(dest string, size uint, r io.Reader) error {
// Convert a raw image from stdin to the dest VMDK image.
sizeBytes := int64(size) << 20 // usually won't fit in 32-bit int (max 2GB)
cmd := exec.Command(VBM, "convertfromraw", "stdin", dest,
fmt.Sprintf("%d", sizeBytes), "--format", "VMDK")
if Verbose {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
if err := cmd.Start(); err != nil {
return err
}
n, err := io.Copy(stdin, r)
if err != nil {
return err
}
// The total number of bytes written to stdin must match sizeBytes, or
// VBoxManage.exe on Windows will fail. Fill remaining with zeros.
if left := sizeBytes - n; left > 0 {
if err := ZeroFill(stdin, left); err != nil {
return err
}
}
// cmd won't exit until the stdin is closed.
if err := stdin.Close(); err != nil {
return err
}
return cmd.Wait()
}
// ZeroFill writes n zero bytes into w.
func ZeroFill(w io.Writer, n int64) error {
const blocksize = 32 << 10
zeros := make([]byte, blocksize)
var k int
var err error
for n > 0 {
if n > blocksize {
k, err = w.Write(zeros)
} else {
k, err = w.Write(zeros[:n])
}
if err != nil {
return err
}
n -= int64(k)
}
return nil
}