github.com/ratrocket/u-root@v0.0.0-20180201221235-1cf9f48ee2cf/pkg/uroot/util/root.go (about)

     1  // Copyright 2014-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 linux
     6  
     7  // Package util contains various u-root utility functions.
     8  package util
     9  
    10  import (
    11  	"fmt"
    12  	"io/ioutil"
    13  	"log"
    14  	"os"
    15  	"runtime"
    16  	"syscall"
    17  )
    18  
    19  const (
    20  	// Not all these paths may be populated or even exist but OTOH they might.
    21  	PATHHEAD = "/ubin"
    22  	PATHMID  = "/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin:/usr/local/sbin"
    23  	PATHTAIL = "/buildbin:/bbin"
    24  	CmdsPath = "github.com/u-root/u-root/cmds"
    25  )
    26  
    27  var (
    28  	CmdsGlob = []string{"github.com/u-root/*/cmds", "*/*/*", "*/*"}
    29  )
    30  
    31  type Creator interface {
    32  	Create() error
    33  	fmt.Stringer
    34  }
    35  
    36  type Dir struct {
    37  	Name string
    38  	Mode os.FileMode
    39  }
    40  
    41  func (d Dir) Create() error {
    42  	return os.MkdirAll(d.Name, d.Mode)
    43  }
    44  
    45  func (d Dir) String() string {
    46  	return fmt.Sprintf("dir %q (mode %#o)", d.Name, d.Mode)
    47  }
    48  
    49  type File struct {
    50  	Name     string
    51  	Contents string
    52  	Mode     os.FileMode
    53  }
    54  
    55  func (f File) Create() error {
    56  	return ioutil.WriteFile(f.Name, []byte(f.Contents), f.Mode)
    57  }
    58  
    59  func (f File) String() string {
    60  	return fmt.Sprintf("file %q (mode %#o)", f.Name, f.Mode)
    61  }
    62  
    63  type Symlink struct {
    64  	Target  string
    65  	NewPath string
    66  }
    67  
    68  func (s Symlink) Create() error {
    69  	os.Remove(s.NewPath)
    70  	return os.Symlink(s.Target, s.NewPath)
    71  }
    72  
    73  func (s Symlink) String() string {
    74  	return fmt.Sprintf("symlink %q -> %q", s.NewPath, s.Target)
    75  }
    76  
    77  type Link struct {
    78  	OldPath string
    79  	NewPath string
    80  }
    81  
    82  func (s Link) Create() error {
    83  	os.Remove(s.NewPath)
    84  	return os.Link(s.OldPath, s.NewPath)
    85  }
    86  
    87  func (s Link) String() string {
    88  	return fmt.Sprintf("link %q -> %q", s.NewPath, s.OldPath)
    89  }
    90  
    91  type Dev struct {
    92  	Name string
    93  	Mode uint32
    94  	Dev  int
    95  }
    96  
    97  func (d Dev) Create() error {
    98  	os.Remove(d.Name)
    99  	return syscall.Mknod(d.Name, d.Mode, d.Dev)
   100  }
   101  
   102  func (d Dev) String() string {
   103  	return fmt.Sprintf("dev %q (mode %#o; magic %d)", d.Name, d.Mode, d.Dev)
   104  }
   105  
   106  type Mount struct {
   107  	Source string
   108  	Target string
   109  	FSType string
   110  	Flags  uintptr
   111  	Opts   string
   112  }
   113  
   114  func (m Mount) Create() error {
   115  	return syscall.Mount(m.Source, m.Target, m.FSType, m.Flags, m.Opts)
   116  }
   117  
   118  func (m Mount) String() string {
   119  	return fmt.Sprintf("mount -t %q -o %s %q %q flags %#x", m.FSType, m.Opts, m.Source, m.Target, m.Flags)
   120  }
   121  
   122  var (
   123  	namespace = []Creator{
   124  		Dir{Name: "/buildbin", Mode: 0777},
   125  		Dir{Name: "/ubin", Mode: 0777},
   126  		Dir{Name: "/tmp", Mode: 0777},
   127  		Dir{Name: "/env", Mode: 0777},
   128  		Dir{Name: "/tcz", Mode: 0777},
   129  		Dir{Name: "/lib", Mode: 0777},
   130  		Dir{Name: "/usr/lib", Mode: 0777},
   131  		Dir{Name: "/go/pkg/linux_amd64", Mode: 0777},
   132  
   133  		Dir{Name: "/etc", Mode: 0777},
   134  
   135  		Dir{Name: "/proc", Mode: 0555},
   136  		Mount{Target: "/proc", FSType: "proc"},
   137  		Mount{Target: "/tmp", FSType: "tmpfs"},
   138  
   139  		Dir{Name: "/dev", Mode: 0777},
   140  		Dev{Name: "/dev/tty", Mode: syscall.S_IFCHR | 0666, Dev: 0x0500},
   141  		Dev{Name: "/dev/urandom", Mode: syscall.S_IFCHR | 0444, Dev: 0x0109},
   142  		Dev{Name: "/dev/port", Mode: syscall.S_IFCHR | 0640, Dev: 0x0104},
   143  
   144  		// Kernel must be compiled with CONFIG_DEVTMPFS.
   145  		// Note that things kind of work even if this mount fails.
   146  		// TODO: move the Dir commands above below this line?
   147  		Mount{Target: "/dev", FSType: "devtmpfs"},
   148  
   149  		Dir{Name: "/dev/pts", Mode: 0777},
   150  		Mount{Target: "/dev/pts", FSType: "devpts", Opts: "newinstance,ptmxmode=666,gid=5,mode=620"},
   151  		Symlink{NewPath: "/dev/ptmx", Target: "/dev/pts/ptmx"},
   152  
   153  		// Note: shm is required at least for Chrome. If you don't mount
   154  		// it chrome throws a bogus "out of memory" error, not the more
   155  		// useful "I can't open /dev/shm/whatever". SAD!
   156  		Dir{Name: "/dev/shm", Mode: 0777},
   157  		Mount{Source: "tmpfs", Target: "/dev/shm", FSType: "tmpfs"},
   158  
   159  		Dir{Name: "/sys", Mode: 0555},
   160  		Mount{Source: "sys", Target: "/sys", FSType: "sysfs"},
   161  		Mount{Source: "cgroup", Target: "/sys/fs/cgroup", FSType: "tmpfs"},
   162  		Dir{Name: "/sys/fs/cgroup/memory", Mode: 0555},
   163  		Dir{Name: "/sys/fs/cgroup/freezer", Mode: 0555},
   164  		Dir{Name: "/sys/fs/cgroup/devices", Mode: 0555},
   165  		Dir{Name: "/sys/fs/cgroup/cpu,cpuacct", Mode: 0555},
   166  		Symlink{NewPath: "/sys/fs/cgroup/cpu", Target: "/sys/fs/cgroup/cpu,cpuacct"},
   167  		Symlink{NewPath: "/sys/fs/cgroup/cpuacct", Target: "/sys/fs/cgroup/cpu,cpuacct"},
   168  		Mount{Source: "cgroup", Target: "/sys/fs/cgroup/memory", FSType: "cgroup", Opts: "memory"},
   169  		Mount{Source: "cgroup", Target: "/sys/fs/cgroup/freezer", FSType: "cgroup", Opts: "freezer"},
   170  		Mount{Source: "cgroup", Target: "/sys/fs/cgroup/devices", FSType: "cgroup", Opts: "devices"},
   171  		Mount{Source: "cgroup", Target: "/sys/fs/cgroup/cpu,cpuacct", FSType: "cgroup", Opts: "cpu,cpuacct"},
   172  	}
   173  
   174  	Env = map[string]string{
   175  		"LD_LIBRARY_PATH": "/usr/local/lib",
   176  		"GOROOT":          "/go",
   177  		"GOPATH":          "/",
   178  		"GOBIN":           "/ubin",
   179  		"CGO_ENABLED":     "0",
   180  	}
   181  )
   182  
   183  func GoBin() string {
   184  	return fmt.Sprintf("/go/bin/%s_%s:/go/bin:/go/pkg/tool/%s_%s", runtime.GOOS, runtime.GOARCH, runtime.GOOS, runtime.GOARCH)
   185  }
   186  
   187  // build the root file system.
   188  func Rootfs() {
   189  	Env["PATH"] = fmt.Sprintf("%v:%v:%v:%v", GoBin(), PATHHEAD, PATHMID, PATHTAIL)
   190  	for k, v := range Env {
   191  		os.Setenv(k, v)
   192  	}
   193  
   194  	for _, c := range namespace {
   195  		if err := c.Create(); err != nil {
   196  			log.Printf("Error creating %s: %v", c, err)
   197  		} else {
   198  			log.Printf("Created %v", c)
   199  		}
   200  	}
   201  }