keywords: added experimental "xattr" keyword

Initially only on linux platform, but could accommodate BSDs as well.
The keyword is rather a prefix of the key. So xattr keyword will have a
prefix of "xattr." followed by a suffix of its namespace and name.
The value stored in the manifest is the SHA1 digest of the extended
attribute's data.

Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
Vincent Batts 2016-03-17 13:54:59 -04:00
parent 2d3aea8623
commit 211687bcc4
5 changed files with 34 additions and 2 deletions

View file

@ -55,6 +55,12 @@ var (
"sha384digest": hasherKeywordFunc("sha384digest", sha512.New384), // A synonym for `sha384` "sha384digest": hasherKeywordFunc("sha384digest", sha512.New384), // A synonym for `sha384`
"sha512": hasherKeywordFunc("sha512", sha512.New), // The SHA512 message digest of the file "sha512": hasherKeywordFunc("sha512", sha512.New), // The SHA512 message digest of the file
"sha512digest": hasherKeywordFunc("sha512digest", sha512.New), // A synonym for `sha512` "sha512digest": hasherKeywordFunc("sha512digest", sha512.New), // A synonym for `sha512`
// This is not an upstreamed keyword, but a needed attribute for file validation.
// The pattern for this keyword key is prefixed by "xattr." followed by the extended attribute "namespace.key".
// The keyword value is the SHA1 digest of the extended attribute's value.
// In this way, the order of the keys does not matter, and the contents of the value is not revealed.
"xattr": xattrKeywordFunc,
} }
) )

View file

@ -3,10 +3,14 @@
package mtree package mtree
import ( import (
"crypto/sha1"
"fmt" "fmt"
"os" "os"
"os/user" "os/user"
"strings"
"syscall" "syscall"
"./xattr"
) )
var ( var (
@ -30,4 +34,20 @@ var (
stat := info.Sys().(*syscall.Stat_t) stat := info.Sys().(*syscall.Stat_t)
return fmt.Sprintf("nlink=%d", stat.Nlink), nil return fmt.Sprintf("nlink=%d", stat.Nlink), nil
} }
xattrKeywordFunc = func(path string, info os.FileInfo) (string, error) {
xlist, err := xattr.List(path)
if err != nil {
return "", err
}
klist := make([]string, len(xlist))
for i := range xlist {
data, err := xattr.Get(path, xlist[i])
if err != nil {
return "", err
}
println(string(data))
klist[i] = fmt.Sprintf("xattr.%s=%x", xlist[i], sha1.Sum(data))
}
return strings.Join(klist, " "), nil
}
) )

View file

@ -17,4 +17,7 @@ var (
nlinkKeywordFunc = func(path string, info os.FileInfo) (string, error) { nlinkKeywordFunc = func(path string, info os.FileInfo) (string, error) {
return "", nil return "", nil
} }
xattrKeywordFunc = func(path string, info os.FileInfo) (string, error) {
return "", nil
}
) )

View file

@ -15,6 +15,8 @@ type ExcludeFunc func(path string, info os.FileInfo) bool
// need a more linear walk, which this can not ensure. // need a more linear walk, which this can not ensure.
func Walk(root string, exlcudes []ExcludeFunc, keywords []string) (*DirectoryHierarchy, error) { func Walk(root string, exlcudes []ExcludeFunc, keywords []string) (*DirectoryHierarchy, error) {
dh := DirectoryHierarchy{} dh := DirectoryHierarchy{}
count := 0
// TODO insert signature and metadata comments first
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
@ -27,6 +29,7 @@ func Walk(root string, exlcudes []ExcludeFunc, keywords []string) (*DirectoryHie
e := Entry{} e := Entry{}
//e.Name = filepath.Base(path) //e.Name = filepath.Base(path)
e.Name = path e.Name = path
e.Pos = count
for _, keyword := range keywords { for _, keyword := range keywords {
if str, err := KeywordFuncs[keyword](path, info); err == nil && str != "" { if str, err := KeywordFuncs[keyword](path, info); err == nil && str != "" {
e.Keywords = append(e.Keywords, str) e.Keywords = append(e.Keywords, str)
@ -34,8 +37,8 @@ func Walk(root string, exlcudes []ExcludeFunc, keywords []string) (*DirectoryHie
return err return err
} }
} }
// XXX
dh.Entries = append(dh.Entries, e) dh.Entries = append(dh.Entries, e)
count++
return nil return nil
}) })
return &dh, err return &dh, err

View file

@ -6,7 +6,7 @@ import (
) )
func TestWalk(t *testing.T) { func TestWalk(t *testing.T) {
dh, err := Walk(".", nil, append(DefaultKeywords, "cksum", "md5", "rmd160digest", "sha1", "sha256", "sha512")) dh, err := Walk(".", nil, append(DefaultKeywords, "xattr"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }