github.com/rck/u-root@v0.0.0-20180106144920-7eb602e381bb/pkg/cpio/types.go (about)

     1  // Copyright 2013-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package cpio
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"os"
    13  	"syscall"
    14  	"time"
    15  )
    16  
    17  const Trailer = "TRAILER!!!"
    18  
    19  type Record struct {
    20  	io.ReadCloser
    21  	Info
    22  }
    23  
    24  var TrailerRecord = StaticRecord(nil, Info{Name: Trailer})
    25  
    26  type RecordReader interface {
    27  	ReadRecord() (Record, error)
    28  }
    29  
    30  type RecordWriter interface {
    31  	WriteRecord(Record) error
    32  }
    33  
    34  type RecordFormat interface {
    35  	Reader(r io.ReaderAt) RecordReader
    36  	Writer(w io.Writer) RecordWriter
    37  }
    38  
    39  func StaticRecord(contents []byte, info Info) Record {
    40  	info.FileSize = uint64(len(contents))
    41  	return Record{
    42  		ReadCloser: ioutil.NopCloser(bytes.NewReader(contents)),
    43  		Info:       info,
    44  	}
    45  }
    46  
    47  // Symlink returns a symlink record at path pointing to target.
    48  func Symlink(path string, target string) Record {
    49  	return Record{
    50  		ReadCloser: ioutil.NopCloser(bytes.NewReader([]byte(target))),
    51  		Info: Info{
    52  			FileSize: uint64(len(target)),
    53  			Mode:     syscall.S_IFLNK | 0777,
    54  			Name:     path,
    55  		},
    56  	}
    57  }
    58  
    59  func NewBytesReadCloser(contents []byte) io.ReadCloser {
    60  	return ioutil.NopCloser(bytes.NewReader(contents))
    61  }
    62  
    63  func NewReadCloser(r io.Reader) io.ReadCloser {
    64  	return ioutil.NopCloser(r)
    65  }
    66  
    67  type LazyOpen struct {
    68  	Name string
    69  	File *os.File
    70  }
    71  
    72  func (r *LazyOpen) Read(p []byte) (int, error) {
    73  	if r.File == nil {
    74  		f, err := os.Open(r.Name)
    75  		if err != nil {
    76  			return -1, err
    77  		}
    78  		r.File = f
    79  	}
    80  	return r.File.Read(p)
    81  }
    82  
    83  func (r *LazyOpen) Close() error {
    84  	return r.File.Close()
    85  }
    86  
    87  func NewDeferReadCloser(name string) io.ReadCloser {
    88  	return &LazyOpen{Name: name}
    89  }
    90  
    91  // Info holds metadata about files.
    92  type Info struct {
    93  	Ino      uint64
    94  	Mode     uint64
    95  	UID      uint64
    96  	GID      uint64
    97  	NLink    uint64
    98  	MTime    uint64
    99  	FileSize uint64
   100  	Dev      uint64
   101  	Major    uint64
   102  	Minor    uint64
   103  	Rmajor   uint64
   104  	Rminor   uint64
   105  	Name     string
   106  }
   107  
   108  func (i Info) String() string {
   109  	return fmt.Sprintf("%s: Ino %d Mode %#o UID %d GID %d NLink %d MTime %v FileSize %d Major %d Minor %d Rmajor %d Rminor %d",
   110  		i.Name,
   111  		i.Ino,
   112  		i.Mode,
   113  		i.UID,
   114  		i.GID,
   115  		i.NLink,
   116  		time.Unix(int64(i.MTime), 0).UTC(),
   117  		i.FileSize,
   118  		i.Major,
   119  		i.Minor,
   120  		i.Rmajor,
   121  		i.Rminor)
   122  }