mirror of
				https://github.com/linuxkit/linuxkit.git
				synced 2025-11-04 07:22:13 +00:00 
			
		
		
		
	- terrible code - lots needs changing - can build a Moby from a config yaml that boots Signed-off-by: Justin Cormack <justin.cormack@docker.com>
		
			
				
	
	
		
			137 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package initrd
 | 
						|
 | 
						|
import (
 | 
						|
	"archive/tar"
 | 
						|
	"bytes"
 | 
						|
	"compress/gzip"
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
 | 
						|
	"github.com/docker/moby/pkg/pad4"
 | 
						|
	"github.com/surma/gocpio"
 | 
						|
)
 | 
						|
 | 
						|
// Writer is an io.WriteCloser that writes to an initrd
 | 
						|
// This is a compressed cpio archive, zero padded to 4 bytes
 | 
						|
type Writer struct {
 | 
						|
	pw *pad4.Writer
 | 
						|
	gw *gzip.Writer
 | 
						|
	cw *cpio.Writer
 | 
						|
}
 | 
						|
 | 
						|
func typeconv(t byte) int64 {
 | 
						|
	switch t {
 | 
						|
	case tar.TypeReg:
 | 
						|
		return cpio.TYPE_REG
 | 
						|
	case tar.TypeRegA:
 | 
						|
		return cpio.TYPE_REG
 | 
						|
	// Currently hard links not supported
 | 
						|
	case tar.TypeLink:
 | 
						|
		return cpio.TYPE_REG
 | 
						|
	case tar.TypeSymlink:
 | 
						|
		return cpio.TYPE_SYMLINK
 | 
						|
	case tar.TypeChar:
 | 
						|
		return cpio.TYPE_CHAR
 | 
						|
	case tar.TypeBlock:
 | 
						|
		return cpio.TYPE_BLK
 | 
						|
	case tar.TypeDir:
 | 
						|
		return cpio.TYPE_DIR
 | 
						|
	case tar.TypeFifo:
 | 
						|
		return cpio.TYPE_FIFO
 | 
						|
	default:
 | 
						|
		return -1
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// CopyTar copies a tar stream into an initrd
 | 
						|
func CopyTar(w *Writer, r *tar.Reader) (written int64, err error) {
 | 
						|
	for {
 | 
						|
		var thdr *tar.Header
 | 
						|
		thdr, err = r.Next()
 | 
						|
		if err == io.EOF {
 | 
						|
			return written, nil
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
		tp := typeconv(thdr.Typeflag)
 | 
						|
		if tp == -1 {
 | 
						|
			return written, errors.New("cannot convert tar file")
 | 
						|
		}
 | 
						|
		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
 | 
						|
		}
 | 
						|
		var n int64
 | 
						|
		if tp == cpio.TYPE_SYMLINK {
 | 
						|
			buffer := bytes.NewBufferString(thdr.Linkname)
 | 
						|
			n, err = io.Copy(w, buffer)
 | 
						|
		} else {
 | 
						|
			n, err = io.Copy(w, r)
 | 
						|
		}
 | 
						|
		written += n
 | 
						|
		if err != nil {
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// NewWriter creates a writer that will output an initrd stream
 | 
						|
func NewWriter(w io.Writer) *Writer {
 | 
						|
	initrd := new(Writer)
 | 
						|
	initrd.pw = pad4.NewWriter(w)
 | 
						|
	initrd.gw = gzip.NewWriter(initrd.pw)
 | 
						|
	initrd.cw = cpio.NewWriter(initrd.gw)
 | 
						|
 | 
						|
	return initrd
 | 
						|
}
 | 
						|
 | 
						|
// WriteHeader writes a cpio header into an initrd
 | 
						|
func (w *Writer) WriteHeader(hdr *cpio.Header) error {
 | 
						|
	return w.cw.WriteHeader(hdr)
 | 
						|
}
 | 
						|
 | 
						|
// Write writes a cpio file into an initrd
 | 
						|
func (w *Writer) Write(b []byte) (n int, e error) {
 | 
						|
	return w.cw.Write(b)
 | 
						|
}
 | 
						|
 | 
						|
// Close closes the writer
 | 
						|
func (initrd *Writer) Close() error {
 | 
						|
	err1 := initrd.cw.Close()
 | 
						|
	err2 := initrd.gw.Close()
 | 
						|
	err3 := initrd.pw.Close()
 | 
						|
	if err1 != nil {
 | 
						|
		return err1
 | 
						|
	}
 | 
						|
	if err2 != nil {
 | 
						|
		return err2
 | 
						|
	}
 | 
						|
	if err3 != nil {
 | 
						|
		return err3
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Copy reads a tarball in a stream and outputs a compressed init ram disk
 | 
						|
func Copy(w *Writer, r io.Reader) (int64, error) {
 | 
						|
	tr := tar.NewReader(r)
 | 
						|
 | 
						|
	return CopyTar(w, tr)
 | 
						|
}
 |