OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 // Read an ar file with BSD formatted file names. |
| 6 |
| 7 package ar |
| 8 |
| 9 import ( |
| 10 "bytes" |
| 11 "errors" |
| 12 "fmt" |
| 13 "io" |
| 14 "os" |
| 15 "time" |
| 16 ) |
| 17 |
| 18 type arFileInfo struct { |
| 19 // os.FileInfo parts |
| 20 name string |
| 21 size int64 |
| 22 mode uint32 |
| 23 modtime uint64 |
| 24 // Extra parts |
| 25 uid int |
| 26 gid int |
| 27 } |
| 28 |
| 29 // os.FileInfo interface |
| 30 func (fi *arFileInfo) Name() string { return fi.name } |
| 31 func (fi *arFileInfo) Size() int64 { return fi.size } |
| 32 func (fi *arFileInfo) Mode() os.FileMode { return os.FileMode(fi.mode) } |
| 33 func (fi *arFileInfo) ModTime() time.Time { return time.Unix(int64(fi.modtime),
0) } |
| 34 func (fi *arFileInfo) IsDir() bool { return fi.Mode().IsDir() } |
| 35 func (fi *arFileInfo) Sys() interface{} { return fi } |
| 36 |
| 37 // Extra |
| 38 func (fi *arFileInfo) UserId() int { return fi.uid } |
| 39 func (fi *arFileInfo) GroupId() int { return fi.gid } |
| 40 |
| 41 var ( |
| 42 ErrHeader = errors.New("archive/ar: invalid ar header") |
| 43 ) |
| 44 |
| 45 type ReaderStage uint |
| 46 |
| 47 const ( |
| 48 READ_HEADER ReaderStage = iota |
| 49 READ_BODY |
| 50 READ_CLOSED |
| 51 ) |
| 52 |
| 53 type Reader struct { |
| 54 stage ReaderStage |
| 55 r io.Reader |
| 56 bytesrequired int64 |
| 57 needspadding bool |
| 58 } |
| 59 |
| 60 func NewReader(r io.Reader) (*Reader, error) { |
| 61 reader := Reader{r: r, bytesrequired: 0, needspadding: false} |
| 62 err := reader.checkBytes("header", []byte("!<arch>\n")) |
| 63 if err != nil { |
| 64 return nil, err |
| 65 } else { |
| 66 return &reader, nil |
| 67 } |
| 68 } |
| 69 |
| 70 func (ar *Reader) checkBytes(name string, str []byte) error { |
| 71 buffer := make([]byte, len(str)) |
| 72 |
| 73 count, err := io.ReadFull(ar.r, buffer) |
| 74 if err != nil { |
| 75 return err |
| 76 } |
| 77 |
| 78 if count != len(buffer) { |
| 79 return errors.New(fmt.Sprintf("%s: Not enough data read (only %d
, needed %d)", name, count, len(buffer))) |
| 80 } |
| 81 |
| 82 if bytes.Equal(str, buffer) { |
| 83 return nil |
| 84 } else { |
| 85 return errors.New(fmt.Sprintf("%s: error in bytes (wanted: %v go
t: %v)", name, buffer, str)) |
| 86 } |
| 87 } |
| 88 |
| 89 func (ar *Reader) Close() error { |
| 90 switch ar.stage { |
| 91 case READ_HEADER: |
| 92 // Good |
| 93 case READ_BODY: |
| 94 return errors.New("Usage error, reading a file.") |
| 95 case READ_CLOSED: |
| 96 return errors.New("Usage error, archive already closed.") |
| 97 default: |
| 98 panic(fmt.Sprintf("Unknown reader mode: %d", ar.stage)) |
| 99 } |
| 100 //ar.r.Close() |
| 101 ar.stage = READ_CLOSED |
| 102 return nil |
| 103 } |
| 104 |
| 105 func (ar *Reader) readBytes(numbytes int64) error { |
| 106 if numbytes > ar.bytesrequired { |
| 107 return errors.New(fmt.Sprintf("To much data read! Needed %d, got
%d", ar.bytesrequired, numbytes)) |
| 108 } |
| 109 |
| 110 ar.bytesrequired -= numbytes |
| 111 if ar.bytesrequired != 0 { |
| 112 return nil |
| 113 } |
| 114 |
| 115 // Padding to 16bit boundary |
| 116 if ar.needspadding { |
| 117 err := ar.checkBytes("padding", []byte("\n")) |
| 118 if err != nil { |
| 119 return err |
| 120 } |
| 121 ar.needspadding = false |
| 122 } |
| 123 ar.stage = READ_HEADER |
| 124 return nil |
| 125 } |
| 126 |
| 127 // Check you can write bytes to the ar at this moment. |
| 128 func (ar *Reader) checkRead() error { |
| 129 switch ar.stage { |
| 130 case READ_HEADER: |
| 131 return errors.New("Usage error, need to read header first.") |
| 132 // Good |
| 133 case READ_BODY: |
| 134 return nil |
| 135 case READ_CLOSED: |
| 136 return errors.New("Usage error, archive closed.") |
| 137 default: |
| 138 panic(fmt.Sprintf("Unknown reader mode: %d", ar.stage)) |
| 139 } |
| 140 } |
| 141 |
| 142 // Check we have finished writing bytes |
| 143 func (ar *Reader) checkFinished() error { |
| 144 if ar.bytesrequired != 0 { |
| 145 return errors.New(fmt.Sprintf("Didn't read enough bytes %d still
needed!", ar.bytesrequired)) |
| 146 } |
| 147 return nil |
| 148 } |
| 149 |
| 150 func (ar *Reader) readPartial(name string, data []byte) error { |
| 151 err := ar.checkRead() |
| 152 if err != nil { |
| 153 return err |
| 154 } |
| 155 |
| 156 datalen := int64(len(data)) |
| 157 if datalen > ar.bytesrequired { |
| 158 return errors.New(fmt.Sprintf("To much data! Wanted %d, but had
%d", ar.bytesrequired, datalen)) |
| 159 } |
| 160 |
| 161 count, err := io.ReadFull(ar.r, data) |
| 162 ar.readBytes(int64(count)) |
| 163 return nil |
| 164 } |
| 165 |
| 166 func (ar *Reader) readHeaderBytes(name string, bytes int, formatstr string) (int
64, error) { |
| 167 data := make([]byte, bytes) |
| 168 _, err := io.ReadFull(ar.r, data) |
| 169 if err != nil { |
| 170 return -1, err |
| 171 } |
| 172 |
| 173 var output int64 = 0 |
| 174 _, err = fmt.Sscanf(string(data), formatstr, &output) |
| 175 if err != nil { |
| 176 return -1, err |
| 177 } |
| 178 |
| 179 if output <= 0 { |
| 180 return -1, errors.New(fmt.Sprintf("%s: bad value %d", name, outp
ut)) |
| 181 } |
| 182 return output, nil |
| 183 } |
| 184 |
| 185 func (ar *Reader) readHeader() (*arFileInfo, error) { |
| 186 switch ar.stage { |
| 187 case READ_HEADER: |
| 188 // Good |
| 189 case READ_BODY: |
| 190 return nil, errors.New("Usage error, already writing a file.") |
| 191 case READ_CLOSED: |
| 192 return nil, errors.New("Usage error, archive closed.") |
| 193 default: |
| 194 panic(fmt.Sprintf("Unknown writer mode: %d", ar.stage)) |
| 195 } |
| 196 |
| 197 var fi arFileInfo |
| 198 |
| 199 // File name length prefixed with '#1/' (BSD variant), 16 bytes |
| 200 namelen, err := ar.readHeaderBytes("filename length", 16, "#1/%13d") |
| 201 if err != nil { |
| 202 return nil, err |
| 203 } |
| 204 |
| 205 // Modtime, 12 bytes |
| 206 modtime, err := ar.readHeaderBytes("modtime", 12, "%12d") |
| 207 if err != nil { |
| 208 return nil, err |
| 209 } |
| 210 fi.modtime = uint64(modtime) |
| 211 |
| 212 // Owner ID, 6 bytes |
| 213 ownerid, err := ar.readHeaderBytes("ownerid", 6, "%6d") |
| 214 if err != nil { |
| 215 return nil, err |
| 216 } |
| 217 fi.uid = int(ownerid) |
| 218 |
| 219 // Group ID, 6 bytes |
| 220 groupid, err := ar.readHeaderBytes("groupid", 6, "%6d") |
| 221 if err != nil { |
| 222 return nil, err |
| 223 } |
| 224 fi.gid = int(groupid) |
| 225 |
| 226 // File mode, 8 bytes |
| 227 filemod, err := ar.readHeaderBytes("groupid", 8, "%8o") |
| 228 if err != nil { |
| 229 return nil, err |
| 230 } |
| 231 fi.mode = uint32(filemod) |
| 232 |
| 233 // File size, 10 bytes |
| 234 size, err := ar.readHeaderBytes("datasize", 10, "%10d") |
| 235 if err != nil { |
| 236 return nil, err |
| 237 } |
| 238 fi.size = size - namelen |
| 239 |
| 240 ar.stage = READ_BODY |
| 241 ar.bytesrequired = size |
| 242 ar.needspadding = (ar.bytesrequired%2 != 0) |
| 243 |
| 244 // File magic, 2 bytes |
| 245 err = ar.checkBytes("filemagic", []byte("\x60\n")) |
| 246 if err != nil { |
| 247 return nil, err |
| 248 } |
| 249 |
| 250 // Filename - BSD variant |
| 251 filename := make([]byte, namelen) |
| 252 err = ar.readPartial("filename", filename) |
| 253 if err != nil { |
| 254 return nil, err |
| 255 } |
| 256 fi.name = string(filename) |
| 257 |
| 258 return &fi, nil |
| 259 } |
| 260 |
| 261 func (ar *Reader) Read(b []byte) (n int, err error) { |
| 262 err = ar.readPartial("data", b) |
| 263 if err != nil { |
| 264 return -1, err |
| 265 } |
| 266 err = ar.checkFinished() |
| 267 if err != nil { |
| 268 return -1, err |
| 269 } |
| 270 return len(b), nil |
| 271 } |
| 272 func (ar *Reader) Next() (*arFileInfo, error) { |
| 273 return ar.readHeader() |
| 274 } |
OLD | NEW |