Skip to content

Commit

Permalink
u-root: consolidate -files and -binaries flags.
Browse files Browse the repository at this point in the history
Turn main into function so defer'd functions run when errors happen.

Signed-off-by: Christopher Koch <chrisko@google.com>
  • Loading branch information
hugelgupf committed Nov 11, 2017
1 parent cf88939 commit df47eb7
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 50 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

u-root
======

Expand Down Expand Up @@ -43,28 +42,28 @@ examples:

```shell
# Build a bb-mode cpio initramfs of all the Go cmds in ./cmds/...
u-root --build=bb
u-root -build=bb

# Generate a cpio archive named initramfs.cpio.
u-root --format=cpio --build=source -o initramfs.cpio
u-root -format=cpio -build=source -o initramfs.cpio

# Generate a bb-mode archive with only these given commands.
u-root --format=cpio --build=bb ./cmds/{ls,ip,dhclient,wget,tcz,cat}
u-root -format=cpio -build=bb ./cmds/{ls,ip,dhclient,wget,tcz,cat}
```

`--format=cpio` and `--build=source` are the defaults. The default set of
packages to include is all packages in `github.com/u-root/u-root/cmds/...`.
`-format=cpio` and `-build=source` are the default flag values. The default
set of packages included is all packages in `github.com/u-root/u-root/cmds/...`.

In addition to using paths to specify Go source packages to include, you may
also use Go package import paths (e.g. "golang.org/x/tools/imports") to include
also use Go package import paths (e.g. `golang.org/x/tools/imports`) to include
commands. Only the `main` package and its dependencies in those source
directories will be included. For example:

```shell
# Both are required for the elvish shell.
go get github.com/boltdb/bolt
go get github.com/elves/elvish
u-root --build=bb ./cmds/\* github.com/elves/elvish
u-root -build=bb ./cmds/\* github.com/elves/elvish
```

Side note: `elvish` is a nicer shell than our default shell `rush`; and also
Expand All @@ -83,9 +82,10 @@ qemu-system-x86_64 -kernel path/to/kernel -initrd /tmp/initramfs.linux_amd64.cpi
Note that you do not have to build a special kernel on your own, it is
sufficient to use an existing one. Usually you can find one in `/boot`.

You may also include additional files in the initramfs using the `--files` flag.
As example for Debian, you want to add two kernel modules for testing, executing
your currently booted kernel:
You may also include additional files in the initramfs using the `-files` flag.
If you add binaries with `-files` are listed, their ldd dependencies will be
included as well. As example for Debian, you want to add two kernel modules for
testing, executing your currently booted kernel:

```shell
u-root -files "$HOME/hello.ko $HOME/hello2.ko"
Expand Down
73 changes: 34 additions & 39 deletions u-root.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ var (
base = flag.String("base", "", "Base archive to add files to")
useExistingInit = flag.Bool("useinit", false, "Use existing init from base archive (only if --base was specified).")

extraFiles = flag.String("files", "", "Additional files and directories to add to archive.")
binaries = flag.String("binaries", "", "Additional binaries and their ldd dependencies to add to archive.")
extraFiles = flag.String("files", "", "Additional files, directories, and binaries (with their ldd dependencies) to add to archive.")

outputPath = flag.String("o", "", "Path to output initramfs file.")
)
Expand All @@ -39,25 +38,31 @@ func main() {

env := golang.Default()
if env.CgoEnabled {
log.Printf("Disabling CGO for u-root...")
env.CgoEnabled = false
}
log.Printf("Build environment: %s", env)

builder, err := uroot.GetBuilder(*build)
if err := Build(env, flag.Args(), *build, *format, *tmpDir, *base, *outputPath, strings.Fields(*extraFiles), *useExistingInit); err != nil {
log.Fatalf("u-root: %v", err)
}
}

func Build(env golang.Environ, pkgs []string, build, format, tempDir, base, outputPath string, extraFiles []string, useExistingInit bool) error {
builder, err := uroot.GetBuilder(build)
if err != nil {
log.Fatalf("%v", err)
return err
}
archiver, err := uroot.GetArchiver(*format)
archiver, err := uroot.GetArchiver(format)
if err != nil {
log.Fatalf("%v", err)
return err
}

tempDir := *tmpDir
if tempDir == "" {
var err error
tempDir, err = ioutil.TempDir("", "u-root")
if err != nil {
log.Fatalf("%v", err)
return err
}
defer os.RemoveAll(tempDir)
}
Expand All @@ -67,12 +72,11 @@ func main() {
// Currently allowed formats:
// Go package imports; e.g. github.com/u-root/u-root/cmds/ls
// Paths to Go package directories; e.g. $GOPATH/src/github.com/u-root/u-root/cmds/*
pkgs := flag.Args()
if len(pkgs) == 0 {
var err error
pkgs, err = uroot.DefaultPackageImports(env)
if err != nil {
log.Fatalf("%v", err)
return err
}
}

Expand All @@ -82,7 +86,7 @@ func main() {
importPath, err := env.FindPackageByPath(pkg)
if err != nil {
if _, perr := env.FindPackageDir(pkg); perr != nil {
log.Fatalf("%q is neither package or path: %v / %v", pkg, err, perr)
return fmt.Errorf("%q is neither package or path: %v / %v", pkg, err, perr)
}
importPath = pkg
}
Expand All @@ -97,26 +101,25 @@ func main() {
}
files, err := builder(bOpts)
if err != nil {
log.Fatalf("Error building %#v: %v", bOpts, err)
return fmt.Errorf("error building %#v: %v", bOpts, err)
}

// Open the target initramfs file.
filename := *outputPath
if filename == "" {
filename = fmt.Sprintf("/tmp/initramfs.%s_%s.%s", env.GOOS, env.GOARCH, archiver.DefaultExtension())
if outputPath == "" {
outputPath = fmt.Sprintf("/tmp/initramfs.%s_%s.%s", env.GOOS, env.GOARCH, archiver.DefaultExtension())
}
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
f, err := os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
log.Fatalf("Couldn't open file %q: %v", filename, err)
return err
}
defer f.Close()

var baseFile *os.File
if *base != "" {
if base != "" {
var err error
baseFile, err = os.Open(*base)
baseFile, err = os.Open(base)
if err != nil {
log.Fatalf("Couldn't open %q: %v", *base, err)
return err
}
defer baseFile.Close()
}
Expand All @@ -125,45 +128,37 @@ func main() {
ArchiveFiles: files,
OutputFile: f,
BaseArchive: baseFile,
UseExistingInit: *useExistingInit,
UseExistingInit: useExistingInit,
}

// Add files from command line.
for _, file := range strings.Fields(*extraFiles) {
for _, file := range extraFiles {
path, err := filepath.Abs(file)
if err != nil {
log.Fatalf("Couldn't find absolute path for %q: %v", file, err)
}
if err := archive.AddFile(path, path[1:]); err != nil {
log.Fatalf("Couldn't add %q to archive: %v", file, err)
}
}

// Add binaries from command line.
for _, binary := range strings.Fields(*binaries) {
path, err := filepath.Abs(binary)
if err != nil {
log.Fatalf("Couldn't find absolute path for %q: %v", binary, err)
return fmt.Errorf("couldn't find absolute path for %q: %v", file, err)
}
if err := archive.AddFile(path, path[1:]); err != nil {
log.Fatalf("Couldn't add %q to archive: %v", binary, err)
return fmt.Errorf("couldn't add %q to archive: %v", file, err)
}

// Pull dependencies in the case of binaries. If `path` is not
// a binary, `libs` will just be empty.
libs, err := ldd.List([]string{path})
if err != nil {
log.Fatalf("Couldn't list dependencies for %q: %v", binary, err)
return fmt.Errorf("couldn't list ldd dependencies for %q: %v", file, err)
}
for _, lib := range libs {
if err := archive.AddFile(lib, lib[1:]); err != nil {
log.Fatalf("Couldn't add %q to archive: %v", lib, err)
return fmt.Errorf("couldn't add %q to archive: %v", lib, err)
}
}
}

// Finally, write the archive.
if err := archiver.Archive(archive); err != nil {
log.Fatalf("Error archiving: %v", err)
return fmt.Errorf("error archiving: %v", err)
}

log.Printf("Filename is %s", filename)
log.Printf("Filename is %s", outputPath)
return nil
}

0 comments on commit df47eb7

Please sign in to comment.