224 lines
4.5 KiB
Go
224 lines
4.5 KiB
Go
/*
|
|
* Copyright (c) SAS Institute, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package cpio
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strconv"
|
|
)
|
|
|
|
// reference http://people.freebsd.org/~kientzle/libarchive/man/cpio.5.txt
|
|
|
|
const (
|
|
cpio_newc_header_length = 110
|
|
cpio_newc_magic = "070701"
|
|
cpio_stripped_magic = "07070X"
|
|
)
|
|
|
|
type Cpio_newc_header struct {
|
|
c_magic string
|
|
c_ino int
|
|
c_mode int
|
|
c_uid int
|
|
c_gid int
|
|
c_nlink int
|
|
c_mtime int
|
|
c_filesize int
|
|
c_devmajor int
|
|
c_devminor int
|
|
c_rdevmajor int
|
|
c_rdevminor int
|
|
c_namesize int
|
|
c_check int
|
|
|
|
stripped bool
|
|
filename string
|
|
index int
|
|
size64 int64
|
|
}
|
|
|
|
type binaryReader struct {
|
|
r io.Reader
|
|
buf [8]byte
|
|
}
|
|
|
|
func (br *binaryReader) Read16(buf *int) error {
|
|
bb := br.buf[:8]
|
|
if _, err := io.ReadFull(br.r, bb); err != nil {
|
|
return err
|
|
}
|
|
i, err := strconv.ParseInt(string(bb), 16, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*buf = int(i)
|
|
return nil
|
|
}
|
|
|
|
func readHeader(r io.Reader) (*Cpio_newc_header, error) {
|
|
logger.Debug("reading header")
|
|
hdr := Cpio_newc_header{}
|
|
br := binaryReader{r: r}
|
|
|
|
magic := make([]byte, 6)
|
|
if _, err := io.ReadFull(r, magic); err != nil {
|
|
return nil, err
|
|
}
|
|
if string(magic) == cpio_stripped_magic {
|
|
return readStrippedHeader(br)
|
|
} else if string(magic) != cpio_newc_magic {
|
|
logger.Debugf("bad magic: %s", string(magic))
|
|
return nil, fmt.Errorf("bad magic")
|
|
}
|
|
hdr.c_magic = cpio_newc_magic
|
|
|
|
if err := br.Read16(&hdr.c_ino); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_mode); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_uid); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_gid); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_nlink); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_mtime); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_filesize); err != nil {
|
|
return nil, err
|
|
}
|
|
hdr.size64 = int64(hdr.c_filesize)
|
|
if err := br.Read16(&hdr.c_devmajor); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_devminor); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_rdevmajor); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_rdevminor); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_namesize); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := br.Read16(&hdr.c_check); err != nil {
|
|
return nil, err
|
|
}
|
|
dumpHeader(&hdr)
|
|
|
|
return &hdr, nil
|
|
}
|
|
|
|
func readStrippedHeader(br binaryReader) (*Cpio_newc_header, error) {
|
|
hdr := &Cpio_newc_header{
|
|
c_magic: cpio_stripped_magic,
|
|
stripped: true,
|
|
}
|
|
if err := br.Read16(&hdr.index); err != nil {
|
|
return nil, err
|
|
}
|
|
logger.Debugf("stripped header %d\n", hdr.index)
|
|
return hdr, nil
|
|
}
|
|
|
|
func dumpHeader(hdr *Cpio_newc_header) {
|
|
logger.Debugf("header %+v", hdr)
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Magic() string {
|
|
return hdr.c_magic
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Ino() int {
|
|
return hdr.c_ino
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Mode() int {
|
|
return hdr.c_mode
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Uid() int {
|
|
return hdr.c_uid
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Gid() int {
|
|
return hdr.c_gid
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Nlink() int {
|
|
return hdr.c_nlink
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Mtime() int {
|
|
return hdr.c_mtime
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Filesize() int {
|
|
return hdr.c_filesize
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Devmajor() int {
|
|
return hdr.c_devmajor
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Devminor() int {
|
|
return hdr.c_devminor
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Rdevmajor() int {
|
|
return hdr.c_rdevmajor
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Rdevminor() int {
|
|
return hdr.c_rdevminor
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Namesize() int {
|
|
return hdr.c_namesize
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Check() int {
|
|
return hdr.c_check
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Filename() string {
|
|
return hdr.filename
|
|
}
|
|
|
|
// stripped header functions
|
|
|
|
func (hdr *Cpio_newc_header) IsStripped() bool {
|
|
return hdr.stripped
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Index() int {
|
|
return hdr.index
|
|
}
|
|
|
|
func (hdr *Cpio_newc_header) Filesize64() int64 {
|
|
return hdr.size64
|
|
}
|