github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/namespace/cmd.go (about)

     1  // Copyright 2020 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 namespace
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"os"
    11  )
    12  
    13  type cmd struct {
    14  	syscall syzcall
    15  	flag    mountflag
    16  
    17  	filename string
    18  	line     string
    19  
    20  	args []string
    21  }
    22  
    23  // valid returns usages for these commands
    24  func (c cmd) valid() error {
    25  	args := c.args
    26  	switch c.syscall {
    27  	case BIND:
    28  		if len(args) < 2 {
    29  			return errors.New("usage: bind [–abcC] new old")
    30  		}
    31  	case MOUNT:
    32  		if len(args) < 2 {
    33  			return errors.New("usage: mount [–abcC] servename old [spec]")
    34  		}
    35  	case UNMOUNT:
    36  		if len(args) < 1 {
    37  			return errors.New("usage: unmount [ new ] old")
    38  		}
    39  	case RFORK:
    40  		// doesn't take args or flags, so always valid even if not.
    41  		return nil
    42  	case CHDIR:
    43  		if len(args) < 1 {
    44  			return errors.New("usage: cd dir")
    45  		}
    46  	case IMPORT:
    47  		if len(args) < 2 {
    48  			return errors.New("usage: import [–abc] host [remotepath] mountpoint")
    49  		}
    50  	case INCLUDE:
    51  		if len(args) < 1 {
    52  			return errors.New("usage: . path")
    53  		}
    54  	default:
    55  		return fmt.Errorf("%d is not implmented", c.syscall)
    56  	}
    57  	return nil
    58  }
    59  
    60  func (c cmd) Modify(ns Namespace, b *Builder) error {
    61  	args := []string{}
    62  	for _, arg := range c.args {
    63  		args = append(args, os.ExpandEnv(arg))
    64  	}
    65  	if err := c.valid(); err != nil {
    66  		return err
    67  	}
    68  	switch c.syscall {
    69  	case BIND:
    70  		return ns.Bind(args[0], args[1], c.flag)
    71  	case MOUNT:
    72  		servername := args[0]
    73  		old := args[1]
    74  		spec := ""
    75  		if len(args) == 3 {
    76  			spec = args[2]
    77  		}
    78  		return ns.Mount(servername, old, spec, c.flag)
    79  	case UNMOUNT:
    80  		new, old := "", ""
    81  		if len(args) == 2 {
    82  			new = args[0]
    83  			old = args[1]
    84  		} else {
    85  			old = args[0]
    86  		}
    87  		return ns.Unmount(new, old)
    88  	case RFORK:
    89  		return ns.Clear()
    90  	case CHDIR:
    91  		if err := ns.Chdir(args[0]); err != nil {
    92  			return err
    93  		}
    94  		b.dir = args[0]
    95  		return nil
    96  	case IMPORT:
    97  		host := ""
    98  		remotepath := ""
    99  		mountpoint := ""
   100  		if len(args) == 2 {
   101  			host = args[0]
   102  			mountpoint = args[1]
   103  		} else if len(args) == 3 {
   104  			host = args[0]
   105  			remotepath = args[1]
   106  			mountpoint = args[2]
   107  		}
   108  		return ns.Import(host, remotepath, mountpoint, c.flag)
   109  	case INCLUDE:
   110  		var nb *Builder
   111  		nb, err := newBuilder(b.dir, b.open)
   112  		if err != nil {
   113  			return err
   114  		}
   115  		if err := nb.Parse(args[0]); err != nil {
   116  			return err
   117  		}
   118  		if err := nb.buildNS(ns); err != nil {
   119  			return err
   120  		}
   121  		b.dir = nb.dir // if the new file has changed the directory we'd like to know
   122  		return nil
   123  	default:
   124  		return fmt.Errorf("%s not implmented", c.syscall)
   125  	}
   126  }
   127  
   128  func (c cmd) String() string { return fmt.Sprintf("%s(%v, %d)", c.syscall, c.args, c.flag) }