gopkg.in/hugelgupf/u-root.v2@v2.0.0-20180831055005-3f8fdb0ce09d/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  }