From ddc92b8846d0fa0d10c9034b4ebe07f697b62d37 Mon Sep 17 00:00:00 2001 From: Justin Cormack Date: Mon, 8 May 2017 16:15:50 +0100 Subject: [PATCH] Code in the initrd generator to split a single tarball In the WIP code in `moby` we now have a standard base tarball format, that includes the kernel and cmdline as files in `/boot` so that the entire output of the yaml file can default to a single tarball. Then this can be split back up by LinuxKit into initrd, kernel and cmdline as needed. This will probably become the only output of the `moby build` stage, with a `moby package` stage dealing with output formats. We may remove the output format specification from the yaml file as well, and just have it in the command. Signed-off-by: Justin Cormack --- src/initrd/initrd.go | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/initrd/initrd.go b/src/initrd/initrd.go index 187b48d5e..acd8bde63 100644 --- a/src/initrd/initrd.go +++ b/src/initrd/initrd.go @@ -6,6 +6,7 @@ import ( "compress/gzip" "errors" "io" + "io/ioutil" "github.com/linuxkit/linuxkit/src/pad4" "github.com/surma/gocpio" @@ -92,6 +93,68 @@ func CopyTar(w *Writer, r *tar.Reader) (written int64, err error) { } } +// CopySplitTar copies a tar stream into an initrd, but splits out kernel and cmdline +func CopySplitTar(w *Writer, r *tar.Reader) (kernel []byte, cmdline string, err error) { + for { + var thdr *tar.Header + thdr, err = r.Next() + if err == io.EOF { + return kernel, cmdline, nil + } + if err != nil { + return + } + tp := typeconv(thdr) + if tp == -1 { + return kernel, cmdline, errors.New("cannot convert tar file") + } + switch thdr.Name { + case "boot/kernel": + kernel, err = ioutil.ReadAll(r) + if err != nil { + return + } + case "boot/cmdline": + var buf []byte + buf, err = ioutil.ReadAll(r) + if err != nil { + return + } + cmdline = string(buf) + case "boot": + default: + size := thdr.Size + if tp == cpio.TYPE_SYMLINK { + size = int64(len(thdr.Linkname)) + } + chdr := cpio.Header{ + Mode: thdr.Mode, + Uid: thdr.Uid, + Gid: thdr.Gid, + Mtime: thdr.ModTime.Unix(), + Size: size, + Devmajor: thdr.Devmajor, + Devminor: thdr.Devminor, + Type: tp, + Name: thdr.Name, + } + err = w.WriteHeader(&chdr) + if err != nil { + return + } + if tp == cpio.TYPE_SYMLINK { + buffer := bytes.NewBufferString(thdr.Linkname) + _, err = io.Copy(w, buffer) + } else { + _, err = io.Copy(w, r) + } + if err != nil { + return + } + } + } +} + // NewWriter creates a writer that will output an initrd stream func NewWriter(w io.Writer) *Writer { initrd := new(Writer)