github.com/jlowellwofford/u-root@v1.0.0/pkg/diskboot/device.go (about) 1 // Copyright 2017-2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package diskboot 6 7 import ( 8 "fmt" 9 "io/ioutil" 10 "path/filepath" 11 "strings" 12 13 "github.com/u-root/u-root/pkg/mount" 14 "golang.org/x/sys/unix" 15 ) 16 17 // Device contains the path to a block filesystem along with its type 18 type Device struct { 19 DevPath string 20 MountPath string 21 Fstype string 22 Configs []*Config 23 } 24 25 // fstypes returns all block file system supported by the linuxboot kernel 26 func fstypes() (fstypes []string, err error) { 27 var bytes []byte 28 if bytes, err = ioutil.ReadFile("/proc/filesystems"); err != nil { 29 return nil, fmt.Errorf("Failed to read /proc/filesystems: %v", err) 30 } 31 for _, line := range strings.Split(string(bytes), "\n") { 32 if fields := strings.Fields(line); len(fields) == 1 { 33 fstypes = append(fstypes, fields[0]) 34 } 35 } 36 return fstypes, nil 37 } 38 39 // FindDevices searches for devices with bootable configs 40 func FindDevices(devicesGlob string) (devices []*Device) { 41 fstypes, err := fstypes() 42 if err != nil { 43 return nil 44 } 45 46 sysList, err := filepath.Glob(devicesGlob) 47 if err != nil { 48 return nil 49 } 50 // The Linux /sys file system is a bit, er, awkward. You can't find 51 // the device special in there; just everything else. 52 for _, sys := range sysList { 53 blk := filepath.Join("/dev", filepath.Base(sys)) 54 55 dev, _ := mountDevice(blk, fstypes) 56 if dev != nil && len(dev.Configs) > 0 { 57 devices = append(devices, dev) 58 } 59 } 60 61 return devices 62 } 63 64 // FindDevice attempts to construct a boot device at the given path 65 func FindDevice(devPath string) (*Device, error) { 66 fstypes, err := fstypes() 67 if err != nil { 68 return nil, nil 69 } 70 71 return mountDevice(devPath, fstypes) 72 } 73 74 func mountDevice(devPath string, fstypes []string) (*Device, error) { 75 mountPath, err := ioutil.TempDir("/tmp", "boot-") 76 if err != nil { 77 return nil, fmt.Errorf("Failed to create tmp mount directory: %v", err) 78 } 79 for _, fstype := range fstypes { 80 if err := mount.Mount(devPath, mountPath, fstype, "", unix.MS_RDONLY); err != nil { 81 continue 82 } 83 84 configs := FindConfigs(mountPath) 85 if len(configs) == 0 { 86 continue 87 } 88 89 return &Device{devPath, mountPath, fstype, configs}, nil 90 } 91 return nil, fmt.Errorf("Failed to find a valid boot device with configs") 92 }