github.com/insomniacslk/u-root@v0.0.0-20200717035308-96b791510d76/cmds/core/mount/mount.go (about)

     1  // Copyright 2012-2017 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  // mount mounts a filesystem at the specified path.
     6  //
     7  // Synopsis:
     8  //     mount [-r] [-o options] [-t FSTYPE] DEV PATH
     9  //
    10  // Options:
    11  //     -r: read only
    12  package main
    13  
    14  import (
    15  	"flag"
    16  	"io/ioutil"
    17  	"log"
    18  	"os"
    19  	"strings"
    20  
    21  	"github.com/u-root/u-root/pkg/mount"
    22  	"github.com/u-root/u-root/pkg/mount/loop"
    23  	"golang.org/x/sys/unix"
    24  )
    25  
    26  type mountOptions []string
    27  
    28  func (o *mountOptions) String() string {
    29  	return strings.Join(*o, ",")
    30  }
    31  
    32  func (o *mountOptions) Set(value string) error {
    33  	for _, option := range strings.Split(value, ",") {
    34  		*o = append(*o, option)
    35  	}
    36  	return nil
    37  }
    38  
    39  var (
    40  	ro      = flag.Bool("r", false, "Read only mount")
    41  	fsType  = flag.String("t", "", "File system type")
    42  	options mountOptions
    43  )
    44  
    45  func init() {
    46  	flag.Var(&options, "o", "Comma separated list of mount options")
    47  }
    48  
    49  func loopSetup(filename string) (loopDevice string, err error) {
    50  	loopDevice, err = loop.FindDevice()
    51  	if err != nil {
    52  		return "", err
    53  	}
    54  	if err := loop.SetFile(loopDevice, filename); err != nil {
    55  		return "", err
    56  	}
    57  	return loopDevice, nil
    58  }
    59  
    60  // extended from boot.go
    61  func getSupportedFilesystem(originFS string) ([]string, bool, error) {
    62  	var known bool
    63  	var err error
    64  	fs, err := ioutil.ReadFile("/proc/filesystems")
    65  	if err != nil {
    66  		return nil, known, err
    67  	}
    68  	var returnValue []string
    69  	for _, f := range strings.Split(string(fs), "\n") {
    70  		n := strings.Fields(f)
    71  		last := len(n) - 1
    72  		if last < 0 {
    73  			continue
    74  		}
    75  		if n[last] == originFS {
    76  			known = true
    77  		}
    78  		returnValue = append(returnValue, n[last])
    79  	}
    80  	return returnValue, known, err
    81  
    82  }
    83  
    84  func informIfUnknownFS(originFS string) {
    85  	knownFS, known, err := getSupportedFilesystem(originFS)
    86  	if err != nil {
    87  		// just don't make things even worse...
    88  		return
    89  	}
    90  	if !known {
    91  		log.Printf("Hint: unknown filesystem %s. Known are: %v", originFS, knownFS)
    92  	}
    93  }
    94  
    95  func main() {
    96  	flag.Parse()
    97  	a := flag.Args()
    98  	if len(a) < 2 {
    99  		flag.Usage()
   100  		os.Exit(1)
   101  	}
   102  
   103  	dev := a[0]
   104  	path := a[1]
   105  	var flags uintptr
   106  	var data []string
   107  	var err error
   108  	for _, option := range options {
   109  		switch option {
   110  		case "loop":
   111  			dev, err = loopSetup(dev)
   112  			if err != nil {
   113  				log.Fatal("Error setting loop device:", err)
   114  			}
   115  		default:
   116  			if f, ok := opts[option]; ok {
   117  				flags |= f
   118  			} else {
   119  				data = append(data, option)
   120  			}
   121  		}
   122  	}
   123  	if *ro {
   124  		flags |= unix.MS_RDONLY
   125  	}
   126  	if *fsType == "" {
   127  		if _, err := mount.TryMount(dev, path, strings.Join(data, ","), flags); err != nil {
   128  			log.Fatalf("%v", err)
   129  		}
   130  	} else {
   131  		if _, err := mount.Mount(dev, path, *fsType, strings.Join(data, ","), flags); err != nil {
   132  			log.Printf("%v", err)
   133  			informIfUnknownFS(*fsType)
   134  			os.Exit(1)
   135  		}
   136  	}
   137  }