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