|
@@ -1,6 +1,3 @@
|
|
|
-/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
|
|
|
-/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
|
|
|
-
|
|
|
/* Copyright (C) 2014 Stony Brook University
|
|
|
This file is part of Graphene Library OS.
|
|
|
|
|
@@ -18,191 +15,53 @@
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
/*
|
|
|
- * shim_fs_hash.c
|
|
|
- *
|
|
|
* This file contains functions to generate hash values for FS paths.
|
|
|
*/
|
|
|
|
|
|
#include <shim_internal.h>
|
|
|
-#include <shim_fs.h>
|
|
|
-#include <shim_utils.h>
|
|
|
-
|
|
|
-#include <pal.h>
|
|
|
-#include <pal_error.h>
|
|
|
-
|
|
|
-static inline unsigned int fold_hash(unsigned long hash)
|
|
|
-{
|
|
|
- hash += hash >> (8*sizeof(int));
|
|
|
- return hash;
|
|
|
-}
|
|
|
-
|
|
|
-uint64_t hash_one(const char *name, unsigned int len)
|
|
|
-{
|
|
|
- unsigned long a = 0;
|
|
|
- unsigned long mask = 0;
|
|
|
- uint64_t hash = 0;
|
|
|
|
|
|
- //debug ("Hashing %s, len %d seed %llx\n", name, len, hash);
|
|
|
+static HASHTYPE __hash(const char* p, size_t len) {
|
|
|
+ HASHTYPE hash = 0;
|
|
|
|
|
|
- for (;;) {
|
|
|
- if (len < sizeof(unsigned long)) {
|
|
|
- a = 0;
|
|
|
- while (len) {
|
|
|
- a += *name;
|
|
|
- a <<= 8;
|
|
|
- name++;
|
|
|
- len--;
|
|
|
- }
|
|
|
- } else {
|
|
|
- a = *((unsigned long *) name);
|
|
|
- len -= sizeof(unsigned long);
|
|
|
- }
|
|
|
- hash += a;
|
|
|
+ for (; len >= sizeof(hash); p += sizeof(hash), len -= sizeof(hash)) {
|
|
|
+ hash += *((HASHTYPE*)p);
|
|
|
hash *= 9;
|
|
|
- name += sizeof(unsigned long);
|
|
|
- if (!len)
|
|
|
- goto done;
|
|
|
}
|
|
|
- mask = ~(~0ul << len*8);
|
|
|
- hash += mask & a;
|
|
|
-done:
|
|
|
- hash = fold_hash(hash);
|
|
|
- //debug("Hash returning %llx\n", hash);
|
|
|
- return hash;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int __check_sep (int c, const char * sep)
|
|
|
-{
|
|
|
- if (!*sep)
|
|
|
- return 0;
|
|
|
|
|
|
- if (!*(sep + 1))
|
|
|
- return c == *sep;
|
|
|
-
|
|
|
- if (!*(sep + 2))
|
|
|
- return c == *sep || c == *(sep + 1);
|
|
|
-
|
|
|
- for (const char * t = sep ; *sep ; sep++)
|
|
|
- if (c == *t)
|
|
|
- return 1;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static inline uint64_t __hash_path (const char * path,
|
|
|
- int size, const char * sep)
|
|
|
-{
|
|
|
- uint64_t hash = 0;
|
|
|
- uint64_t digest = 0;
|
|
|
-
|
|
|
- const char * next_name = path;
|
|
|
- const char * c = path;
|
|
|
- while (c < path + size && *c) {
|
|
|
- if (__check_sep(*c, sep)) {
|
|
|
- if (next_name < c) {
|
|
|
- hash = hash_one(next_name, c - next_name);
|
|
|
- digest ^= hash;
|
|
|
- }
|
|
|
- next_name = c + 1;
|
|
|
+ if (len) {
|
|
|
+ HASHTYPE rest = 0;
|
|
|
+ for (; len > 0; p++, len--) {
|
|
|
+ rest <<= 8;
|
|
|
+ rest += (HASHTYPE)*p;
|
|
|
}
|
|
|
- c++;
|
|
|
- }
|
|
|
-
|
|
|
- if (next_name < c) {
|
|
|
- hash = hash_one(next_name, c - next_name);
|
|
|
- digest ^= hash;
|
|
|
+ hash += rest;
|
|
|
+ hash *= 9;
|
|
|
}
|
|
|
|
|
|
- return digest;
|
|
|
-}
|
|
|
-
|
|
|
-HASHTYPE hash_path (const char * path, int size,
|
|
|
- const char * sep)
|
|
|
-{
|
|
|
- return __hash_path(path, size, sep ? sep : "/");
|
|
|
+ return hash;
|
|
|
}
|
|
|
|
|
|
-HASHTYPE hash_parent_path (HASHTYPE hbuf, const char * path,
|
|
|
- int * size, const char * sep)
|
|
|
-{
|
|
|
- if (*size < 0)
|
|
|
- *size = strlen (path);
|
|
|
-
|
|
|
- if (*size == 0)
|
|
|
- goto zero;
|
|
|
-
|
|
|
- sep = sep ? sep : "/";
|
|
|
+HASHTYPE hash_path(const char* path, size_t size) {
|
|
|
+ HASHTYPE digest = 0;
|
|
|
|
|
|
- const char * last_name = path + *size;
|
|
|
- const char * last_frame_end = path + *size;
|
|
|
- while (last_name > path) {
|
|
|
- if (__check_sep(*(last_name - 1), sep)) {
|
|
|
- if (last_name < last_frame_end)
|
|
|
- break;
|
|
|
+ const char* elem_start = path;
|
|
|
+ const char* c = path;
|
|
|
|
|
|
- last_frame_end = last_name - 1;
|
|
|
+ for (; c < path + size && *c; c++) {
|
|
|
+ if (*c == '/') {
|
|
|
+ digest ^= __hash(elem_start, c - elem_start);
|
|
|
+ elem_start = c + 1;
|
|
|
}
|
|
|
- last_name--;
|
|
|
}
|
|
|
|
|
|
- const char * parent_end = last_name - 1;
|
|
|
- while (parent_end > path && !__check_sep(*parent_end, sep))
|
|
|
- parent_end--;
|
|
|
-
|
|
|
- if (parent_end <= path)
|
|
|
- goto zero;
|
|
|
-
|
|
|
- HASHTYPE hash = 0;
|
|
|
- hash = hash_one(last_name, last_frame_end - last_name);
|
|
|
-
|
|
|
- hbuf ^= hash;
|
|
|
-
|
|
|
- *size = parent_end - path;
|
|
|
-
|
|
|
- return hbuf;
|
|
|
-
|
|
|
-zero:
|
|
|
- hbuf = 0;
|
|
|
- *size = 0;
|
|
|
- return 0;
|
|
|
+ digest ^= __hash(elem_start, c - elem_start);
|
|
|
+ return digest;
|
|
|
}
|
|
|
|
|
|
-HASHTYPE rehash_name (HASHTYPE parent_hbuf,
|
|
|
- const char * name, int size)
|
|
|
-{
|
|
|
- HASHTYPE ret = 0;
|
|
|
- ret = hash_one(name, size);
|
|
|
- ret ^= parent_hbuf;
|
|
|
- return ret;
|
|
|
+HASHTYPE rehash_name(HASHTYPE parent_hbuf, const char* name, size_t size) {
|
|
|
+ return parent_hbuf ^ __hash(name, size);
|
|
|
}
|
|
|
|
|
|
-HASHTYPE rehash_path (HASHTYPE ancestor_hbuf,
|
|
|
- const char * path, int size, const char * sep)
|
|
|
-{
|
|
|
- HASHTYPE ctx = 0;
|
|
|
- HASHTYPE digest = 0;
|
|
|
- HASHTYPE hbuf;
|
|
|
-
|
|
|
- sep = sep ? : "/";
|
|
|
-
|
|
|
- const char * next_name = path;
|
|
|
- const char * c = path;
|
|
|
- while (c < path + size && *c) {
|
|
|
- if (__check_sep(*c, sep)) {
|
|
|
- if (next_name < c) {
|
|
|
- ctx = hash_one(next_name, c - next_name);
|
|
|
- digest ^= ctx;
|
|
|
- }
|
|
|
- next_name = c + 1;
|
|
|
- }
|
|
|
- c++;
|
|
|
- }
|
|
|
-
|
|
|
- if (next_name < c) {
|
|
|
- ctx = hash_one(next_name, c - next_name);
|
|
|
- digest ^= ctx;
|
|
|
- }
|
|
|
-
|
|
|
- hbuf = ancestor_hbuf ^ digest;
|
|
|
- return hbuf;
|
|
|
+HASHTYPE rehash_path(HASHTYPE ancestor_hbuf, const char* path, size_t size) {
|
|
|
+ return ancestor_hbuf ^ hash_path(path, size);
|
|
|
}
|