1 package storage 2 3 import "unicode/utf8" 4 5 // Entries is for sorting by Position 6 type Entries []Entry 7 8 func (e Entries) Len() int { return len(e) } 9 func (e Entries) Swap(i, j int) { e[i], e[j] = e[j], e[i] } 10 func (e Entries) Less(i, j int) bool { return e[i].Position < e[j].Position } 11 12 // Type of Entry 13 type Type int 14 15 const ( 16 // FileType represents a file payload from the tar stream. 17 // 18 // This will be used to map to relative paths on disk. Only Size > 0 will get 19 // read into a resulting output stream (due to hardlinks). 20 FileType Type = 1 + iota 21 // SegmentType represents a raw bytes segment from the archive stream. These raw 22 // byte segments consist of the raw headers and various padding. 23 // 24 // Its payload is to be marshalled base64 encoded. 25 SegmentType 26 ) 27 28 // Entry is the structure for packing and unpacking the information read from 29 // the Tar archive. 30 // 31 // FileType Payload checksum is using `hash/crc64` for basic file integrity, 32 // _not_ for cryptography. 33 // From http://www.backplane.com/matt/crc64.html, CRC32 has almost 40,000 34 // collisions in a sample of 18.2 million, CRC64 had none. 35 type Entry struct { 36 Type Type `json:"type"` 37 Name string `json:"name,omitempty"` 38 NameRaw []byte `json:"name_raw,omitempty"` 39 Size int64 `json:"size,omitempty"` 40 Payload []byte `json:"payload"` // SegmentType stores payload here; FileType stores crc64 checksum here; 41 Position int `json:"position"` 42 } 43 44 // SetName will check name for valid UTF-8 string, and set the appropriate 45 // field. See https://github.com/vbatts/tar-split/issues/17 46 func (e *Entry) SetName(name string) { 47 if utf8.ValidString(name) { 48 e.Name = name 49 } else { 50 e.NameRaw = []byte(name) 51 } 52 } 53 54 // SetNameBytes will check name for valid UTF-8 string, and set the appropriate 55 // field 56 func (e *Entry) SetNameBytes(name []byte) { 57 if utf8.Valid(name) { 58 e.Name = string(name) 59 } else { 60 e.NameRaw = name 61 } 62 } 63 64 // GetName returns the string for the entry's name, regardless of the field stored in 65 func (e *Entry) GetName() string { 66 if len(e.NameRaw) > 0 { 67 return string(e.NameRaw) 68 } 69 return e.Name 70 } 71 72 // GetNameBytes returns the bytes for the entry's name, regardless of the field stored in 73 func (e *Entry) GetNameBytes() []byte { 74 if len(e.NameRaw) > 0 { 75 return e.NameRaw 76 } 77 return []byte(e.Name) 78 } 79