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 }