File: device.go

package info (click to toggle)
packer 1.6.6%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 32,016 kB
  • sloc: sh: 1,154; python: 619; makefile: 251; ruby: 205; xml: 97
file content (70 lines) | stat: -rw-r--r-- 1,647 bytes parent folder | download | duplicates (4)
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 chroot

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// AvailableDevice finds an available device and returns it. Note that
// you should externally hold a flock or something in order to guarantee
// that this device is available across processes.
func AvailableDevice() (string, error) {
	prefix, err := devicePrefix()
	if err != nil {
		return "", err
	}

	letters := "fghijklmnop"
	for _, letter := range letters {
		device := fmt.Sprintf("/dev/%s%c", prefix, letter)

		// If the block device itself, i.e. /dev/sf, exists, then we
		// can't use any of the numbers either.
		if _, err := os.Stat(device); err == nil {
			continue
		}

		// To be able to build both Paravirtual and HVM images, the unnumbered
		// device and the first numbered one must be available.
		// E.g. /dev/xvdf  and  /dev/xvdf1
		numbered_device := fmt.Sprintf("%s%d", device, 1)
		if _, err := os.Stat(numbered_device); err != nil {
			return device, nil
		}
	}

	return "", errors.New("available device could not be found")
}

// devicePrefix returns the prefix ("sd" or "xvd" or so on) of the devices
// on the system.
func devicePrefix() (string, error) {
	available := []string{"sd", "xvd"}

	f, err := os.Open("/sys/block")
	if err != nil {
		return "", err
	}
	defer f.Close()

	dirs, err := f.Readdirnames(-1)
	if dirs != nil && len(dirs) > 0 {
		for _, dir := range dirs {
			dirBase := filepath.Base(dir)
			for _, prefix := range available {
				if strings.HasPrefix(dirBase, prefix) {
					return prefix, nil
				}
			}
		}
	}

	if err != nil {
		return "", err
	}

	return "", errors.New("device prefix could not be detected")
}