2015-06-20 10:33:14 -04:00
|
|
|
package storage
|
|
|
|
|
2015-09-23 15:50:23 -04:00
|
|
|
import "unicode/utf8"
|
|
|
|
|
2015-06-20 10:33:14 -04:00
|
|
|
// Entries is for sorting by Position
|
|
|
|
type Entries []Entry
|
|
|
|
|
|
|
|
func (e Entries) Len() int { return len(e) }
|
|
|
|
func (e Entries) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
|
|
|
func (e Entries) Less(i, j int) bool { return e[i].Position < e[j].Position }
|
|
|
|
|
|
|
|
// Type of Entry
|
|
|
|
type Type int
|
|
|
|
|
|
|
|
const (
|
|
|
|
// FileType represents a file payload from the tar stream.
|
|
|
|
//
|
|
|
|
// This will be used to map to relative paths on disk. Only Size > 0 will get
|
|
|
|
// read into a resulting output stream (due to hardlinks).
|
|
|
|
FileType Type = 1 + iota
|
|
|
|
// SegmentType represents a raw bytes segment from the archive stream. These raw
|
|
|
|
// byte segments consist of the raw headers and various padding.
|
|
|
|
//
|
2015-08-11 16:27:05 -04:00
|
|
|
// Its payload is to be marshalled base64 encoded.
|
2015-06-20 10:33:14 -04:00
|
|
|
SegmentType
|
|
|
|
)
|
|
|
|
|
2015-08-11 16:27:05 -04:00
|
|
|
// Entry is the structure for packing and unpacking the information read from
|
2015-06-20 10:33:14 -04:00
|
|
|
// the Tar archive.
|
|
|
|
//
|
|
|
|
// FileType Payload checksum is using `hash/crc64` for basic file integrity,
|
|
|
|
// _not_ for cryptography.
|
|
|
|
// From http://www.backplane.com/matt/crc64.html, CRC32 has almost 40,000
|
|
|
|
// collisions in a sample of 18.2 million, CRC64 had none.
|
|
|
|
type Entry struct {
|
|
|
|
Type Type `json:"type"`
|
2015-08-11 16:27:05 -04:00
|
|
|
Name string `json:"name,omitempty"`
|
2015-09-23 15:50:23 -04:00
|
|
|
NameRaw []byte `json:"name_raw,omitempty"`
|
2015-08-11 16:27:05 -04:00
|
|
|
Size int64 `json:"size,omitempty"`
|
|
|
|
Payload []byte `json:"payload"` // SegmentType stores payload here; FileType stores crc64 checksum here;
|
2015-06-20 10:33:14 -04:00
|
|
|
Position int `json:"position"`
|
|
|
|
}
|
2015-09-23 15:50:23 -04:00
|
|
|
|
|
|
|
// SetName will check name for valid UTF-8 string, and set the appropriate
|
|
|
|
// field. See https://github.com/vbatts/tar-split/issues/17
|
|
|
|
func (e *Entry) SetName(name string) {
|
|
|
|
if utf8.ValidString(name) {
|
|
|
|
e.Name = name
|
|
|
|
} else {
|
|
|
|
e.NameRaw = []byte(name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetNameBytes will check name for valid UTF-8 string, and set the appropriate
|
|
|
|
// field
|
|
|
|
func (e *Entry) SetNameBytes(name []byte) {
|
|
|
|
if utf8.Valid(name) {
|
|
|
|
e.Name = string(name)
|
|
|
|
} else {
|
|
|
|
e.NameRaw = name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetName returns the string for the entry's name, regardless of the field stored in
|
|
|
|
func (e *Entry) GetName() string {
|
|
|
|
if len(e.NameRaw) > 0 {
|
|
|
|
return string(e.NameRaw)
|
|
|
|
}
|
|
|
|
return e.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNameBytes returns the bytes for the entry's name, regardless of the field stored in
|
|
|
|
func (e *Entry) GetNameBytes() []byte {
|
|
|
|
if len(e.NameRaw) > 0 {
|
|
|
|
return e.NameRaw
|
|
|
|
}
|
|
|
|
return []byte(e.Name)
|
|
|
|
}
|