Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
69 lines
2.1 KiB
Go
69 lines
2.1 KiB
Go
package ar
|
|
|
|
import (
|
|
"errors"
|
|
"io/fs"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const arMagic = "!<arch>\n" // Ar magic header
|
|
|
|
var (
|
|
ErrInvalidFile error = errors.New("invalid ar file")
|
|
)
|
|
|
|
// Offset Length Name Format
|
|
// ------------------------------------------------------------------
|
|
// 0 16 File identifier ASCII
|
|
// 16 12 File modification timestamp (in seconds) Decimal
|
|
// 28 6 Owner ID Decimal
|
|
// 34 6 Group ID Decimal
|
|
// 40 8 File mode (type and permission) Octal
|
|
// 48 10 File size in bytes Decimal
|
|
// 58 2 Ending characters 0x60 0x0A
|
|
|
|
type Header struct {
|
|
Filename string // File name
|
|
Size int64 // File size
|
|
ModeTime time.Time // Mode date
|
|
Mode fs.FileMode // Mode
|
|
Owner, Group int64 // Owner and Group ID
|
|
}
|
|
|
|
func (head Header) gnuHeader() []byte {
|
|
header := make([]byte, 60)
|
|
for i := range header {
|
|
header[i] = 0x20
|
|
}
|
|
|
|
copy(header[0:16], []byte(head.Filename))
|
|
copy(header[16:28], []byte(strconv.FormatInt(head.ModeTime.Unix(), 10)))
|
|
copy(header[28:34], []byte(strconv.FormatInt(head.Owner, 10)))
|
|
copy(header[34:40], []byte(strconv.FormatInt(head.Group, 10)))
|
|
copy(header[40:48], []byte(strconv.FormatInt(int64(head.Mode), 10)))
|
|
copy(header[48:58], []byte(strconv.FormatInt(head.Size, 10)))
|
|
header[58] = 0x60
|
|
header[59] = 0x0A
|
|
|
|
return header
|
|
}
|
|
|
|
func (head *Header) parseGnuHeader(header []byte) {
|
|
head.Filename = strings.TrimSpace(string(header[0:16]))
|
|
if head.Filename[len(head.Filename)-1] == '/' {
|
|
head.Filename = head.Filename[:len(head.Filename)-1]
|
|
}
|
|
|
|
head.Size, _ = strconv.ParseInt(strings.TrimSpace(string(header[48:58])), 10, 64)
|
|
head.Owner, _ = strconv.ParseInt(strings.TrimSpace(string(header[28:34])), 10, 64)
|
|
head.Group, _ = strconv.ParseInt(strings.TrimSpace(string(header[34:40])), 10, 64)
|
|
// Mode
|
|
modeInt, _ := strconv.ParseUint(strings.TrimSpace(string(header[40:48])), 10, 32)
|
|
head.Mode = fs.FileMode(modeInt)
|
|
// Mode time
|
|
modeTime, _ := strconv.ParseInt(strings.TrimSpace(string(header[16:28])), 10, 64)
|
|
head.ModeTime = time.Unix(modeTime, 0)
|
|
}
|