mirror of
https://github.com/clearlinux/mixer-tools.git
synced 2026-09-06 05:31:50 +00:00
Add better support for hash calculations
Now does directory and symlinks. Appears to agree with swupd hashdump No longer imports golang.org/x/sys/unix Added support for the 0 value of hashval to map to the 0000000000000000000000000000000000000000000000000000000000000000 string. Updated tests. Added resetHash function to testing to enforce this. Added setHashZero method for file to set this zero hash. Signed-off-by: Icarus Sparry <icarus.w.sparry@intel.com>
This commit is contained in:
@@ -180,6 +180,10 @@ func (f *File) setHash(hash string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *File) setHashZero() {
|
||||
f.Hash = 0
|
||||
}
|
||||
|
||||
func (f *File) getHashString() string {
|
||||
return *Hashes[f.Hash]
|
||||
}
|
||||
|
||||
+4
-2
@@ -2,9 +2,11 @@ package swupd
|
||||
|
||||
type hashval int
|
||||
|
||||
const AllZeroHash = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
|
||||
// Hashes is a global map of indices to hashes
|
||||
var Hashes = []*string{}
|
||||
var invHash = make(map[string]hashval)
|
||||
var Hashes = []*string{&AllZeroHash}
|
||||
var invHash = map[string]hashval{AllZeroHash: 0}
|
||||
|
||||
// internHash adds only new hashes to the Hashes slice and returns the index at
|
||||
// which they are located
|
||||
|
||||
+15
-9
@@ -5,21 +5,27 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func resetHash() {
|
||||
Hashes = []*string{&allzero}
|
||||
invHash = map[string]hashval{allzero: 0}
|
||||
}
|
||||
|
||||
func TestInternHash(t *testing.T) {
|
||||
// reset Hashes so we get the expected indices
|
||||
Hashes = []*string{}
|
||||
resetHash()
|
||||
testCases := []struct {
|
||||
hash string
|
||||
expected hashval
|
||||
}{
|
||||
{"9bcc1718757db298fb656ae6e2ee143dde746f49fbf6805db7683cb574c36728", 0},
|
||||
{"33ccead640727d66c62be03e089a3ca3f4ef7c374a3eeab79764f9509075b0d8", 1},
|
||||
{"33ccead640727d66c62be03e089a3ca3f4ef7c374a3eeab79764f9509075b0d8", 1},
|
||||
{"b26f85ffaf3595ecd9a8b1e0c894f1b9e6e3ed0e8c3f28bcde3d66e63bfedd4d", 2},
|
||||
{"a49e68b3e2230855586e9ffd1b2962a2282411a488b80e3bd65851f068394c0a", 3},
|
||||
{"a49e68b3e2230855586e9ffd1b2962a2282411a488b80e3bd65851f068394c0a", 3},
|
||||
{"a49e68b3e2230855586e9ffd1b2962a2282411a488b80e3bd65851f068394c0a", 3},
|
||||
{"864f78102661c05b61cafcb59785349fd2fb7a956ec00a77198fe5bc2432de76", 4},
|
||||
{"9bcc1718757db298fb656ae6e2ee143dde746f49fbf6805db7683cb574c36728", 1},
|
||||
{"33ccead640727d66c62be03e089a3ca3f4ef7c374a3eeab79764f9509075b0d8", 2},
|
||||
{"33ccead640727d66c62be03e089a3ca3f4ef7c374a3eeab79764f9509075b0d8", 2},
|
||||
{"b26f85ffaf3595ecd9a8b1e0c894f1b9e6e3ed0e8c3f28bcde3d66e63bfedd4d", 3},
|
||||
{"a49e68b3e2230855586e9ffd1b2962a2282411a488b80e3bd65851f068394c0a", 4},
|
||||
{"a49e68b3e2230855586e9ffd1b2962a2282411a488b80e3bd65851f068394c0a", 4},
|
||||
{"a49e68b3e2230855586e9ffd1b2962a2282411a488b80e3bd65851f068394c0a", 4},
|
||||
{"0000000000000000000000000000000000000000000000000000000000000000", 0},
|
||||
{"864f78102661c05b61cafcb59785349fd2fb7a956ec00a77198fe5bc2432de76", 5},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
@@ -9,8 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -29,18 +28,30 @@ func main() {
|
||||
}
|
||||
|
||||
func Hashcalc(filename string) string {
|
||||
key, err := hmac_compute_key(filename)
|
||||
key, ftype, err := hmac_compute_key(filename)
|
||||
var result, data []byte
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error stating file '%s' %v\n", filename, err)
|
||||
return ""
|
||||
}
|
||||
// Only handle files for now..
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Read error for '%s' %v\n", filename, err)
|
||||
return ""
|
||||
switch ftype {
|
||||
case '-':
|
||||
data, err = ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Read error for '%s' %v\n", filename, err)
|
||||
return ""
|
||||
}
|
||||
case 'd':
|
||||
data = []byte("DIRECTORY") // fixed magic string
|
||||
case 'l':
|
||||
if target, err := os.Readlink(filename); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error readlink file '%s' %v\n", filename, err)
|
||||
return ""
|
||||
} else {
|
||||
data = []byte(target)
|
||||
}
|
||||
}
|
||||
result := hmac_sha256_for_data(key, data)
|
||||
result = hmac_sha256_for_data(key, data)
|
||||
return string(result[:])
|
||||
}
|
||||
|
||||
@@ -71,21 +82,36 @@ func set(out []byte, in int64) {
|
||||
}
|
||||
}
|
||||
|
||||
// return what should be an ascii string as an array of byte
|
||||
func hmac_compute_key(filename string) ([]byte, error) {
|
||||
// hmac_compute_key returns what should be an ascii string as an array of byte
|
||||
// it is really ugly to be compatible with the C implementation. It is not portable
|
||||
// as the C version isn't portable.
|
||||
func hmac_compute_key(filename string) ([]byte, rune, error) {
|
||||
// Create the key
|
||||
updatestat := [40]byte{}
|
||||
var info unix.Stat_t
|
||||
if err := unix.Stat(filename, &info); err != nil {
|
||||
return nil, err
|
||||
var info syscall.Stat_t
|
||||
if err := syscall.Lstat(filename, &info); err != nil {
|
||||
return nil, 'x', err
|
||||
}
|
||||
ftype := '-'
|
||||
// Get magic constants out of /usr/include/bits/stat.h
|
||||
switch info.Mode & 0170000 {
|
||||
case 0100000: // Regular file
|
||||
case 0040000: // Directory
|
||||
ftype = 'd'
|
||||
info.Size = 0
|
||||
case 0120000:
|
||||
ftype = 'l'
|
||||
info.Mode = 0
|
||||
default:
|
||||
return nil, 'x', fmt.Errorf("%s is not a file, directory or symlink %o", filename, info.Mode&0170000)
|
||||
}
|
||||
set(updatestat[24:32], 0)
|
||||
set(updatestat[0:8], int64(info.Mode))
|
||||
set(updatestat[8:16], int64(info.Uid))
|
||||
set(updatestat[16:24], int64(info.Gid))
|
||||
// 24:32 is rdev, but this is always zero
|
||||
set(updatestat[32:40], int64(info.Size))
|
||||
set(updatestat[24:32], 0)
|
||||
set(updatestat[32:40], info.Size)
|
||||
// fmt.Printf("key is %v\n", updatestat)
|
||||
key := hmac_sha256_for_data(updatestat[:], nil)
|
||||
return key, nil
|
||||
return key, ftype, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user