mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-10-30 23:10:19 +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>
182 lines
3.4 KiB
Go
182 lines
3.4 KiB
Go
package cpio
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"strconv"
|
|
)
|
|
|
|
type Reader struct {
|
|
r io.Reader
|
|
pos int64
|
|
remaining_bytes int
|
|
}
|
|
|
|
func NewReader(r io.Reader) *Reader {
|
|
return &Reader{
|
|
r: r,
|
|
}
|
|
}
|
|
|
|
func disassemble(mode int64) (fmode int64, ftype int64) {
|
|
fmode = mode & 0xFFF
|
|
ftype = (mode >> 12) & 0xF
|
|
return
|
|
}
|
|
|
|
func getPrefix(buf *[]byte, len int) (pre []byte) {
|
|
pre, *buf = (*buf)[0:len], (*buf)[len:]
|
|
return
|
|
}
|
|
|
|
func Btoi(s string, base int) (int, error) {
|
|
i, e := strconv.ParseInt(s, base, 64)
|
|
return int(i), e
|
|
}
|
|
|
|
var (
|
|
ErrInvalidHeader = errors.New("Did not find valid magic number")
|
|
)
|
|
|
|
func parseHeader(buf []byte) (*Header, int64, error) {
|
|
magic := string(getPrefix(&buf, 6))
|
|
raw_inode := getPrefix(&buf, 8)
|
|
raw_mode := getPrefix(&buf, 8)
|
|
raw_uid := getPrefix(&buf, 8)
|
|
raw_gid := getPrefix(&buf, 8)
|
|
raw_nlinks := getPrefix(&buf, 8)
|
|
raw_mtime := getPrefix(&buf, 8)
|
|
raw_size := getPrefix(&buf, 8)
|
|
raw_major := getPrefix(&buf, 8)
|
|
raw_minor := getPrefix(&buf, 8)
|
|
raw_devmajor := getPrefix(&buf, 8)
|
|
raw_devminor := getPrefix(&buf, 8)
|
|
raw_namelen := getPrefix(&buf, 8)
|
|
raw_check := getPrefix(&buf, 8)
|
|
|
|
_, _, _, _, _ = raw_inode, raw_nlinks, raw_major, raw_minor, raw_check
|
|
|
|
if magic != "070701" {
|
|
return nil, 0, ErrInvalidHeader
|
|
}
|
|
|
|
hdr := &Header{}
|
|
|
|
mode, e := strconv.ParseInt(string(raw_mode), 16, 64)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
hdr.Mode, hdr.Type = disassemble(mode)
|
|
|
|
hdr.Uid, e = Btoi(string(raw_uid), 16)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
hdr.Gid, e = Btoi(string(raw_gid), 16)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
hdr.Mtime, e = strconv.ParseInt(string(raw_mtime), 16, 64)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
hdr.Size, e = strconv.ParseInt(string(raw_size), 16, 64)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
hdr.Devmajor, e = strconv.ParseInt(string(raw_devmajor), 16, 64)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
hdr.Devminor, e = strconv.ParseInt(string(raw_devminor), 16, 64)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
namelen, e := strconv.ParseInt(string(raw_namelen), 16, 64)
|
|
if e != nil {
|
|
return nil, 0, e
|
|
}
|
|
|
|
return hdr, namelen, nil
|
|
}
|
|
|
|
func (r *Reader) Next() (*Header, error) {
|
|
e := r.skipRest()
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
e = r.skipPadding(4)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
raw_hdr := make([]byte, 110)
|
|
_, e = r.countedRead(raw_hdr)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
hdr, namelen, e := parseHeader(raw_hdr)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
bname := make([]byte, namelen)
|
|
_, e = r.countedRead(bname)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
hdr.Name = string(bname[0 : namelen-1]) //Exclude terminating zero
|
|
r.remaining_bytes = int(hdr.Size)
|
|
return hdr, r.skipPadding(4)
|
|
}
|
|
|
|
func (r *Reader) skipRest() error {
|
|
buf := make([]byte, 1)
|
|
for ; r.remaining_bytes > 0; r.remaining_bytes-- {
|
|
_, e := r.countedRead(buf)
|
|
if e != nil {
|
|
return e
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Skips to the next position which is a multiple of mod.
|
|
func (r *Reader) skipPadding(mod int64) error {
|
|
numBytesToRead := ((mod - (r.pos % mod)) % mod)
|
|
buf := make([]byte, numBytesToRead)
|
|
_, e := r.countedRead(buf)
|
|
return e
|
|
}
|
|
|
|
func (r *Reader) Read(b []byte) (n int, e error) {
|
|
if r.remaining_bytes == 0 {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
if len(b) > r.remaining_bytes {
|
|
b = b[0:r.remaining_bytes]
|
|
}
|
|
n, e = r.countedRead(b)
|
|
r.remaining_bytes -= n
|
|
return
|
|
}
|
|
|
|
func (r *Reader) countedRead(b []byte) (n int, e error) {
|
|
if len(b) == 0 {
|
|
return
|
|
}
|
|
n, e = r.r.Read(b)
|
|
r.pos += int64(n)
|
|
return
|
|
}
|