mirror of
https://github.com/vbatts/tar-split.git
synced 2025-02-22 10:39:03 +00:00
verify: starts of a checking function
This commit is contained in:
parent
5c8d5cacba
commit
867071d1e5
4 changed files with 158 additions and 45 deletions
31
tar/verify/example_xattr.go
Normal file
31
tar/verify/example_xattr.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
verify "."
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for _, arg := range os.Args[1:] {
|
||||||
|
keys, err := verify.Listxattr(arg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(keys) > 0 {
|
||||||
|
fmt.Printf("%s : %q\n", arg, keys)
|
||||||
|
for _, key := range keys {
|
||||||
|
buf, err := verify.Lgetxattr(arg, key)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(" ERROR: %s\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s = %s\n", key, string(buf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,20 @@
|
||||||
package verify
|
package verify
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// PosixHeader is the structure from a POSIX tar header, to be marshalled from
|
// PosixHeader is the structure from a POSIX tar header, to be marshalled from
|
||||||
// the tar stream, and available for on-disk comparison and verification
|
// the tar stream, and available for on-disk comparison and verification
|
||||||
type PosixHeader struct {
|
type PosixHeader struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Mode uint32 `json:"mode,omitempty"`
|
Mode os.FileMode `json:"mode,omitempty"`
|
||||||
UID uint32 `json:"uid,omitempty"`
|
UID uint32 `json:"uid,omitempty"`
|
||||||
GID uint32 `json:"gid,omitempty"`
|
GID uint32 `json:"gid,omitempty"`
|
||||||
Size int `json:"size,omitempty"`
|
Size int64 `json:"size,omitempty"`
|
||||||
Mtime time.Time `json:"mtime,omitempty"`
|
Mtime time.Time `json:"mtime,omitempty"`
|
||||||
Checksum []byte `json:"chksum,omitempty"`
|
Checksum []byte `json:"chksum,omitempty"`
|
||||||
LinkName string `json:"linkname,omitempty"`
|
LinkName string `json:"linkname,omitempty"`
|
||||||
|
@ -21,3 +26,75 @@ type PosixHeader struct {
|
||||||
DevMinor int `json:"devminor,omitempty"`
|
DevMinor int `json:"devminor,omitempty"`
|
||||||
Prefix string `json:"prefix,omitempty"`
|
Prefix string `json:"prefix,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PaxHeader struct {
|
||||||
|
Atime time.Time
|
||||||
|
Ctime time.Time
|
||||||
|
Xattrs map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Header struct {
|
||||||
|
// maybe I do not want these grouped like this. Maybe this should be an interface instead.
|
||||||
|
Posix PosixHeader
|
||||||
|
Pax PaxHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns file size (implements Sizer)
|
||||||
|
func (hdr Header) Size() int64 {
|
||||||
|
return int64(hdr.Posix.Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModTime returns file mtime (implements ModTimer)
|
||||||
|
func (hdr Header) ModTime() time.Time {
|
||||||
|
return hdr.Posix.Mtime
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mode returns file mode (implements Moder)
|
||||||
|
func (hdr Header) Mode() os.FileMode {
|
||||||
|
return hdr.Posix.Mode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hdr Header) LinkName() string {
|
||||||
|
return hdr.Posix.LinkName
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderFromFile takes a relative root and the filename of the file to collect
|
||||||
|
// information on.
|
||||||
|
func HeaderFromFile(rel, filename string) (*Header, error) {
|
||||||
|
absRel, err := filepath.Abs(rel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(filename, "/") {
|
||||||
|
var err error
|
||||||
|
filename, err = filepath.Abs(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stat, err := os.Lstat(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := filename
|
||||||
|
if strings.HasPrefix(filename, absRel) {
|
||||||
|
name = strings.TrimPrefix(filename, absRel)
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr := Header{
|
||||||
|
Posix: PosixHeader{
|
||||||
|
Name: name,
|
||||||
|
Size: stat.Size(),
|
||||||
|
Mode: stat.Mode(),
|
||||||
|
Mtime: stat.ModTime(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if stat.Mode()&os.ModeSymlink != 0 {
|
||||||
|
l, _ := os.Readlink(filename) // if this errors, the empty string is OK
|
||||||
|
hdr.Posix.LinkName = l
|
||||||
|
}
|
||||||
|
|
||||||
|
return &hdr, nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package verify
|
package verify
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// CheckType is how the on disk attributes will be verified against the
|
// CheckType is how the on disk attributes will be verified against the
|
||||||
// recorded header information
|
// recorded header information
|
||||||
|
@ -15,14 +19,15 @@ const (
|
||||||
CheckFileUser
|
CheckFileUser
|
||||||
CheckFileGroup
|
CheckFileGroup
|
||||||
CheckFileMtime
|
CheckFileMtime
|
||||||
CheckFileDevice
|
CheckFileDevice // major/minor
|
||||||
CheckFileLink
|
CheckFileLink // linkname
|
||||||
CheckFileCaps
|
CheckFileCaps // which is just a subset of xattrs on linux
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// DefaultChecks is the default for verfication steps against each
|
// DefaultChecks is the default for verfication steps against each
|
||||||
// storage.VerficationEntry
|
// storage.VerficationEntry.
|
||||||
|
// These may need to vary from platform to platform
|
||||||
DefaultChecks = CheckDigest | CheckFileAttributes
|
DefaultChecks = CheckDigest | CheckFileAttributes
|
||||||
// CheckFileAttributes are the group of file attribute checks done
|
// CheckFileAttributes are the group of file attribute checks done
|
||||||
CheckFileAttributes = CheckFileSize | CheckFileMode | CheckFileUser |
|
CheckFileAttributes = CheckFileSize | CheckFileMode | CheckFileUser |
|
||||||
|
@ -32,3 +37,26 @@ var (
|
||||||
// ErrNotSupportedPlatform is when the platform does not support given features
|
// ErrNotSupportedPlatform is when the platform does not support given features
|
||||||
ErrNotSupportedPlatform = fmt.Errorf("platform does not support this feature")
|
ErrNotSupportedPlatform = fmt.Errorf("platform does not support this feature")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FileAttrer exposes the functions corresponding to file attribute checks
|
||||||
|
type FileAttrer interface {
|
||||||
|
Sizer
|
||||||
|
Moder
|
||||||
|
ModTimer
|
||||||
|
LinkName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sizer returns the size of the file (see also os.FileInfo)
|
||||||
|
type Sizer interface {
|
||||||
|
Size() int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moder returns the mode of the file (see also os.FileInfo)
|
||||||
|
type Moder interface {
|
||||||
|
Mode() os.FileMode
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModTimer returns the mtime of the file (see also os.FileInfo)
|
||||||
|
type ModTimer interface {
|
||||||
|
ModTime() time.Time
|
||||||
|
}
|
||||||
|
|
|
@ -13,29 +13,6 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
func main() {
|
|
||||||
for _, arg := range os.Args[1:] {
|
|
||||||
keys, err := Listxattr(arg)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(keys) > 0 {
|
|
||||||
fmt.Printf("%s : %q\n", arg, keys)
|
|
||||||
for _, key := range keys {
|
|
||||||
buf, err := Lgetxattr(arg, key)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf(" ERROR: %s\n", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Printf(" %s = %s\n", key, string(buf))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Listxattr is a helper around the syscall.Listxattr
|
// Listxattr is a helper around the syscall.Listxattr
|
||||||
func Listxattr(path string) ([]string, error) {
|
func Listxattr(path string) ([]string, error) {
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
|
@ -48,7 +25,7 @@ func Listxattr(path string) ([]string, error) {
|
||||||
sz, err = syscall.Listxattr(path, buf)
|
sz, err = syscall.Listxattr(path, buf)
|
||||||
}
|
}
|
||||||
keys := []string{}
|
keys := []string{}
|
||||||
for _, key := range bytes.Split(bytes.TrimSpace(buf), []byte{0x0}) {
|
for _, key := range bytes.Split(bytes.Trim(buf, "\x00"), []byte{0x0}) {
|
||||||
if string(key) != "" {
|
if string(key) != "" {
|
||||||
keys = append(keys, string(key))
|
keys = append(keys, string(key))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue