]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
758dd67e | 2 | |
0c15577a | 3 | #include <stdlib.h> |
dccca82b | 4 | #include <string.h> |
3b7d3320 | 5 | #include <sys/sysmacros.h> |
dccca82b | 6 | |
758dd67e | 7 | #include "hash-funcs.h" |
46e16b34 | 8 | #include "path-util.h" |
0c15577a | 9 | #include "siphash24.h" |
52be2b43 | 10 | #include "strv.h" |
758dd67e | 11 | |
25073e50 | 12 | void string_hash_func(const char *p, struct siphash *state) { |
758dd67e LP |
13 | siphash24_compress(p, strlen(p) + 1, state); |
14 | } | |
15 | ||
0284fcc0 YW |
16 | DEFINE_HASH_OPS(string_hash_ops, |
17 | char, string_hash_func, string_compare_func); | |
18 | DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( | |
19 | string_hash_ops_free, | |
20 | char, string_hash_func, string_compare_func, free); | |
21 | DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( | |
22 | string_hash_ops_value_free, | |
23 | char, string_hash_func, string_compare_func, | |
24 | void, free); | |
25 | DEFINE_HASH_OPS_FULL( | |
26 | string_hash_ops_free_free, | |
27 | char, string_hash_func, string_compare_func, free, | |
28 | void, free); | |
29 | DEFINE_HASH_OPS_FULL( | |
30 | string_hash_ops_free_strv_free, | |
31 | char, string_hash_func, string_compare_func, free, | |
32 | char*, strv_free); | |
758dd67e | 33 | |
25073e50 | 34 | void path_hash_func(const char *q, struct siphash *state) { |
353df443 | 35 | bool add_slash = false; |
46e16b34 LP |
36 | |
37 | assert(q); | |
38 | assert(state); | |
39 | ||
40 | /* Calculates a hash for a path in a way this duplicate inner slashes don't make a differences, and also | |
41 | * whether there's a trailing slash or not. This fits well with the semantics of path_compare(), which does | |
42 | * similar checks and also doesn't care for trailing slashes. Note that relative and absolute paths (i.e. those | |
43 | * which begin in a slash or not) will hash differently though. */ | |
44 | ||
353df443 YW |
45 | /* if path is absolute, add one "/" to the hash. */ |
46 | if (path_is_absolute(q)) | |
c01a5c05 | 47 | siphash24_compress_byte('/', state); |
46e16b34 LP |
48 | |
49 | for (;;) { | |
353df443 YW |
50 | const char *e; |
51 | int r; | |
52 | ||
53 | r = path_find_first_component(&q, true, &e); | |
54 | if (r == 0) | |
55 | return; | |
56 | ||
57 | if (add_slash) | |
58 | siphash24_compress_byte('/', state); | |
59 | ||
60 | if (r < 0) { | |
61 | /* if a component is invalid, then add remaining part as a string. */ | |
62 | string_hash_func(q, state); | |
63 | return; | |
64 | } | |
65 | ||
66 | /* Add this component to the hash. */ | |
67 | siphash24_compress(e, r, state); | |
68 | ||
69 | add_slash = true; | |
46e16b34 LP |
70 | } |
71 | } | |
72 | ||
0284fcc0 YW |
73 | DEFINE_HASH_OPS(path_hash_ops, |
74 | char, path_hash_func, path_compare); | |
75 | DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( | |
76 | path_hash_ops_free, | |
77 | char, path_hash_func, path_compare, free); | |
78 | DEFINE_HASH_OPS_FULL( | |
79 | path_hash_ops_free_free, | |
80 | char, path_hash_func, path_compare, free, | |
81 | void, free); | |
46e16b34 | 82 | |
758dd67e | 83 | void trivial_hash_func(const void *p, struct siphash *state) { |
c01a5c05 | 84 | siphash24_compress_typesafe(p, state); |
758dd67e LP |
85 | } |
86 | ||
87 | int trivial_compare_func(const void *a, const void *b) { | |
a0edd02e | 88 | return CMP(a, b); |
758dd67e LP |
89 | } |
90 | ||
0284fcc0 YW |
91 | DEFINE_HASH_OPS(trivial_hash_ops, |
92 | void, trivial_hash_func, trivial_compare_func); | |
93 | DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( | |
94 | trivial_hash_ops_free, | |
95 | void, trivial_hash_func, trivial_compare_func, free); | |
96 | DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( | |
97 | trivial_hash_ops_value_free, | |
98 | void, trivial_hash_func, trivial_compare_func, | |
99 | void, free); | |
100 | DEFINE_HASH_OPS_FULL( | |
101 | trivial_hash_ops_free_free, | |
102 | void, trivial_hash_func, trivial_compare_func, free, | |
103 | void, free); | |
5e71868c | 104 | |
25073e50 | 105 | void uint64_hash_func(const uint64_t *p, struct siphash *state) { |
c01a5c05 | 106 | siphash24_compress_typesafe(*p, state); |
758dd67e LP |
107 | } |
108 | ||
25073e50 YW |
109 | int uint64_compare_func(const uint64_t *a, const uint64_t *b) { |
110 | return CMP(*a, *b); | |
758dd67e LP |
111 | } |
112 | ||
0284fcc0 YW |
113 | DEFINE_HASH_OPS(uint64_hash_ops, |
114 | uint64_t, uint64_hash_func, uint64_compare_func); | |
115 | DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( | |
116 | uint64_hash_ops_value_free, | |
117 | uint64_t, uint64_hash_func, uint64_compare_func, | |
118 | void, free); | |
758dd67e LP |
119 | |
120 | #if SIZEOF_DEV_T != 8 | |
25073e50 | 121 | void devt_hash_func(const dev_t *p, struct siphash *state) { |
c01a5c05 | 122 | siphash24_compress_typesafe(*p, state); |
758dd67e | 123 | } |
17488537 | 124 | #endif |
758dd67e | 125 | |
25073e50 | 126 | int devt_compare_func(const dev_t *a, const dev_t *b) { |
17488537 LP |
127 | int r; |
128 | ||
129 | r = CMP(major(*a), major(*b)); | |
130 | if (r != 0) | |
131 | return r; | |
132 | ||
133 | return CMP(minor(*a), minor(*b)); | |
758dd67e LP |
134 | } |
135 | ||
25073e50 | 136 | DEFINE_HASH_OPS(devt_hash_ops, dev_t, devt_hash_func, devt_compare_func); |