github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/pkg/storage/filesystem.go (about)

     1  // Copyright 2017-2019 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 storage
     6  
     7  import (
     8  	"fmt"
     9  	"io/ioutil"
    10  	"log"
    11  	"os"
    12  	"strings"
    13  	"syscall"
    14  )
    15  
    16  // Mountpoint holds mount point information for a given device
    17  type Mountpoint struct {
    18  	DeviceName string
    19  	Path       string
    20  	FsType     string
    21  }
    22  
    23  // GetSupportedFilesystems returns the supported file systems for block devices
    24  func GetSupportedFilesystems() (fstypes []string, err error) {
    25  	return internalGetFilesystems("/proc/filesystems")
    26  }
    27  
    28  func internalGetFilesystems(file string) (fstypes []string, err error) {
    29  	var bytes []byte
    30  	if bytes, err = ioutil.ReadFile(file); err != nil {
    31  		return nil, fmt.Errorf("failed to read %s: %v", file, err)
    32  	}
    33  	for _, line := range strings.Split(string(bytes), "\n") {
    34  		//len(fields)==1, 2 possibilites for fs: "nodev" fs and
    35  		// fs's. "nodev" fs cannot be mounted through devices.
    36  		// len(fields)==1 prevents this from occurring.
    37  		if fields := strings.Fields(line); len(fields) == 1 {
    38  			fstypes = append(fstypes, fields[0])
    39  		}
    40  	}
    41  	return fstypes, nil
    42  }
    43  
    44  // Mount tries to mount a block device on the given mountpoint, trying in order
    45  // the provided file system types. It returns a Mountpoint structure, or an error
    46  // if the device could not be mounted. If the mount point does not exist, it will
    47  // be created.
    48  func Mount(devname, mountpath string, filesystems []string) (*Mountpoint, error) {
    49  	if err := os.MkdirAll(mountpath, 0744); err != nil {
    50  		return nil, err
    51  	}
    52  	for _, fstype := range filesystems {
    53  		log.Printf(" * trying %s on %s", fstype, devname)
    54  		// MS_RDONLY should be enough. See mount(2)
    55  		flags := uintptr(syscall.MS_RDONLY)
    56  		// no options
    57  		data := ""
    58  		if err := syscall.Mount(devname, mountpath, fstype, flags, data); err != nil {
    59  			log.Printf("    failed with %v", err)
    60  			continue
    61  		}
    62  		log.Printf(" * mounted %s on %s with filesystem type %s", devname, mountpath, fstype)
    63  		return &Mountpoint{DeviceName: devname, Path: mountpath, FsType: fstype}, nil
    64  	}
    65  	return nil, fmt.Errorf("no suitable filesystem type found to mount %s", devname)
    66  }