Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3585160
hash-func: add generic hash_ops implementation for hashing paths
poettering Feb 8, 2018
0c2c0e7
test/udev-test.pl: create /dev/null
mwilck Apr 23, 2018
daa4a62
test/udev-test.pl: allow multiple devices per test
mwilck Apr 20, 2018
5da06c2
test/udev-test.pl: create rules only once
mwilck Apr 23, 2018
3775b8f
test/udev-test.pl: allow concurrent additions and removals
mwilck Apr 23, 2018
4b2f92c
test/udev-test.pl: use computed devnode name
mwilck Apr 24, 2018
2ab3fac
test/udev-test.pl: test correctness of symlink targets
mwilck Apr 24, 2018
07a3bfd
test/udev-test.pl: allow checking multiple symlinks
mwilck Apr 24, 2018
9456d95
test/udev-test.pl: fix wrong test descriptions
mwilck Apr 24, 2018
a5fa208
test/udev-test.pl: last_rule is unsupported
mwilck Apr 24, 2018
883c9b7
test/udev-test.pl: Make some tests a little harder
mwilck Apr 24, 2018
2dcff87
test/udev-test.pl: remove bogus rules from magic subsys test
mwilck Apr 24, 2018
e05e088
test/udev-test.pl: merge "space and var with space" tests
mwilck Apr 24, 2018
acda625
test/udev-test.pl: merge import parent tests into one
mwilck Apr 24, 2018
a9843cb
test/udev-test.pl: count "good" results
mwilck Apr 24, 2018
ab04725
test/sys-script.py: add missing DEVNAME entries to uevents
mwilck Apr 24, 2018
3b98463
tests/udev-test.pl: add multiple device test
mwilck Apr 24, 2018
4ffc1c2
test/udev-test.pl: add repeat count
mwilck Apr 24, 2018
68af9be
test/udev-test.pl: generator for large list of block devices
mwilck Apr 25, 2018
e2ef663
test/sd-script.py: new helper script for udev testing
mwilck Apr 25, 2018
ddd24ee
test/udev-test.pl: suppress umount error message at startup
mwilck Apr 26, 2018
d73118a
test/udev_test.pl: add "expected good" count
mwilck Apr 26, 2018
b921171
udev: lock symlink directories in link_update()
mwilck Apr 5, 2018
8f3b1cb
udev: change structure in /run/udev/links to improve efficiency
mwilck Apr 20, 2018
b68d104
udev: Add migration code for /run/udev/links
mwilck Jul 9, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/basic/hash-funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
***/

#include "hash-funcs.h"
#include "path-util.h"

void string_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, strlen(p) + 1, state);
Expand All @@ -33,6 +34,55 @@ const struct hash_ops string_hash_ops = {
.compare = string_compare_func
};


void path_hash_func(const void *p, struct siphash *state) {
const char *q = p;
size_t n;

assert(q);
assert(state);

/* Calculates a hash for a path in a way this duplicate inner slashes don't make a differences, and also
* whether there's a trailing slash or not. This fits well with the semantics of path_compare(), which does
* similar checks and also doesn't care for trailing slashes. Note that relative and absolute paths (i.e. those
* which begin in a slash or not) will hash differently though. */

n = strspn(q, "/");
if (n > 0) { /* Eat up initial slashes, and add one "/" to the hash for all of them */
siphash24_compress(q, 1, state);
q += n;
}

for (;;) {
/* Determine length of next component */
n = strcspn(q, "/");
if (n == 0) /* Reached the end? */
break;

/* Add this component to the hash and skip over it */
siphash24_compress(q, n, state);
q += n;

/* How many slashes follow this component? */
n = strspn(q, "/");
if (q[n] == 0) /* Is this a trailing slash? If so, we are at the end, and don't care about the slashes anymore */
break;

/* We are not add the end yet. Hash exactly one slash for all of the ones we just encountered. */
siphash24_compress(q, 1, state);
q += n;
}
}

int path_compare_func(const void *a, const void *b) {
return path_compare(a, b);
}

const struct hash_ops path_hash_ops = {
.hash = path_hash_func,
.compare = path_compare_func
};

void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state);
}
Expand Down
9 changes: 6 additions & 3 deletions src/basic/hash-funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ void string_hash_func(const void *p, struct siphash *state);
int string_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops string_hash_ops;

/* This will compare the passed pointers directly, and will not
* dereference them. This is hence not useful for strings or
* suchlike. */
void path_hash_func(const void *p, struct siphash *state);
int path_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops path_hash_ops;

/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings
* or suchlike. */
void trivial_hash_func(const void *p, struct siphash *state);
int trivial_compare_func(const void *a, const void *b) _const_;
extern const struct hash_ops trivial_hash_ops;
Expand Down
31 changes: 31 additions & 0 deletions src/test/test-hashmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,34 @@ static void test_string_compare_func(void) {
assert_se(string_compare_func("fred", "fred") == 0);
}

static void test_path_hashmap(void) {
_cleanup_(hashmap_freep) Hashmap *h = NULL;

assert_se(h = hashmap_new(&path_hash_ops));

assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0);
assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0);
assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST);
assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0);
assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST);
assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0);
assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST);

assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1));
assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1));
assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1));
assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2));
assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2));
assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2));
assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4));
assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4));
assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4));
assert_se(!hashmap_get(h, "foox"));
assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6));
assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6));
assert_se(!hashmap_get(h, "/foo////bar////quux/////"));
}

int main(int argc, const char *argv[]) {
test_hashmap_funcs();
test_ordered_hashmap_funcs();
Expand All @@ -64,4 +92,7 @@ int main(int argc, const char *argv[]) {
test_uint64_compare_func();
test_trivial_compare_func();
test_string_compare_func();
test_path_hashmap();

return 0;
}
Loading