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 }