github.com/shaardie/u-root@v4.0.1-0.20190127173353-f24a1c26aa2e+incompatible/u-root.go (about) 1 // Copyright 2015-2018 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 main 6 7 import ( 8 "flag" 9 "fmt" 10 "io/ioutil" 11 "log" 12 "os" 13 14 "github.com/u-root/u-root/pkg/golang" 15 "github.com/u-root/u-root/pkg/uroot" 16 "github.com/u-root/u-root/pkg/uroot/builder" 17 "github.com/u-root/u-root/pkg/uroot/initramfs" 18 ) 19 20 // multiFlag is used for flags that support multiple invocations, e.g. -files 21 type multiFlag []string 22 23 func (m *multiFlag) String() string { 24 return fmt.Sprint(*m) 25 } 26 27 func (m *multiFlag) Set(value string) error { 28 *m = append(*m, value) 29 return nil 30 } 31 32 // Flags for u-root builder. 33 var ( 34 build, format, tmpDir, base, outputPath *string 35 initCmd *string 36 defaultShell *string 37 useExistingInit *bool 38 fourbins *bool 39 noCommands *bool 40 extraFiles multiFlag 41 ) 42 43 func init() { 44 fourbins = flag.Bool("fourbins", false, "build installcommand on boot, no ahead of time, so we have only four binares") 45 build = flag.String("build", "source", "u-root build format (e.g. bb or source).") 46 format = flag.String("format", "cpio", "Archival format.") 47 48 tmpDir = flag.String("tmpdir", "", "Temporary directory to put binaries in.") 49 50 base = flag.String("base", "", "Base archive to add files to. By default, this is a couple of directories like /bin, /etc, etc. u-root has a default internally supplied set of files; use base=/dev/null if you don't want any base files.") 51 useExistingInit = flag.Bool("useinit", false, "Use existing init from base archive (only if --base was specified).") 52 outputPath = flag.String("o", "", "Path to output initramfs file.") 53 54 initCmd = flag.String("initcmd", "init", "Symlink target for /init. Can be an absolute path or a u-root command name. Use initcmd=\"\" if you don't want the symlink.") 55 defaultShell = flag.String("defaultsh", "elvish", "Default shell. Can be an absolute path or a u-root command name. Use defaultsh=\"\" if you don't want the symlink.") 56 noCommands = flag.Bool("nocmd", false, "Build no Go commands; initramfs only") 57 58 flag.Var(&extraFiles, "files", "Additional files, directories, and binaries (with their ldd dependencies) to add to archive. Can be speficified multiple times.") 59 } 60 61 func main() { 62 flag.Parse() 63 64 // Main is in a separate functions so defers run on return. 65 if err := Main(); err != nil { 66 log.Fatal(err) 67 } 68 log.Printf("Successfully wrote initramfs.") 69 } 70 71 // Main is a separate function so defers are run on return, which they wouldn't 72 // on exit. 73 func Main() error { 74 env := golang.Default() 75 if *fourbins && env.GOROOT == "" { 76 log.Fatalf("You have to set GOROOT for fourbins to work") 77 } 78 if env.CgoEnabled { 79 log.Printf("Disabling CGO for u-root...") 80 env.CgoEnabled = false 81 } 82 log.Printf("Build environment: %s", env) 83 if env.GOOS != "linux" { 84 log.Printf("GOOS is not linux. Did you mean to set GOOS=linux?") 85 } 86 87 archiver, err := initramfs.GetArchiver(*format) 88 if err != nil { 89 return err 90 } 91 92 logger := log.New(os.Stderr, "", log.LstdFlags) 93 // Open the target initramfs file. 94 w, err := archiver.OpenWriter(logger, *outputPath, env.GOOS, env.GOARCH) 95 if err != nil { 96 return err 97 } 98 99 var baseFile initramfs.Reader 100 if *base != "" { 101 bf, err := os.Open(*base) 102 if err != nil { 103 return err 104 } 105 defer bf.Close() 106 baseFile = archiver.Reader(bf) 107 } else { 108 baseFile = uroot.DefaultRamfs.Reader() 109 } 110 111 tempDir := *tmpDir 112 if tempDir == "" { 113 var err error 114 tempDir, err = ioutil.TempDir("", "u-root") 115 if err != nil { 116 return err 117 } 118 defer os.RemoveAll(tempDir) 119 } else if _, err := os.Stat(tempDir); os.IsNotExist(err) { 120 if err := os.MkdirAll(tempDir, 0755); err != nil { 121 return fmt.Errorf("temporary directory %q did not exist; tried to mkdir but failed: %v", tempDir, err) 122 } 123 } 124 125 var ( 126 c []uroot.Commands 127 initCommand = *initCmd 128 ) 129 if !*noCommands { 130 var b builder.Builder 131 switch *build { 132 case "bb": 133 b = builder.BBBuilder{} 134 case "binary": 135 b = builder.BinaryBuilder{} 136 case "source": 137 b = builder.SourceBuilder{ 138 FourBins: *fourbins, 139 } 140 default: 141 return fmt.Errorf("could not find builder %q", *build) 142 } 143 144 // Resolve globs into package imports. 145 // 146 // Currently allowed formats: 147 // Go package imports; e.g. github.com/u-root/u-root/cmds/ls (must be in $GOPATH) 148 // Paths to Go package directories; e.g. $GOPATH/src/github.com/u-root/u-root/cmds/* 149 var pkgs []string 150 for _, a := range flag.Args() { 151 p, ok := templates[a] 152 if !ok { 153 pkgs = append(pkgs, a) 154 continue 155 } 156 pkgs = append(pkgs, p...) 157 } 158 if len(pkgs) == 0 { 159 pkgs = []string{"github.com/u-root/u-root/cmds/*"} 160 } 161 162 if *fourbins && *build == "source" { 163 initCommand = "/go/bin/go" 164 } 165 166 // The command-line tool only allows specifying one build mode 167 // right now. 168 c = append(c, uroot.Commands{ 169 Builder: b, 170 Packages: pkgs, 171 }) 172 } 173 174 opts := uroot.Opts{ 175 Env: env, 176 Commands: c, 177 TempDir: tempDir, 178 ExtraFiles: extraFiles, 179 OutputFile: w, 180 BaseArchive: baseFile, 181 UseExistingInit: *useExistingInit, 182 InitCmd: initCommand, 183 DefaultShell: *defaultShell, 184 } 185 return uroot.CreateInitramfs(logger, opts) 186 }