/src/systemd/src/basic/hash-funcs.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | |
3 | | #include <stdlib.h> |
4 | | #include <string.h> |
5 | | #include <sys/sysmacros.h> |
6 | | |
7 | | #include "hash-funcs.h" |
8 | | #include "path-util.h" |
9 | | #include "siphash24.h" |
10 | | #include "strv.h" |
11 | | |
12 | 42.5M | void string_hash_func(const char *p, struct siphash *state) { |
13 | 42.5M | siphash24_compress(p, strlen(p) + 1, state); |
14 | 42.5M | } |
15 | | |
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); |
33 | | |
34 | 2.33M | void path_hash_func(const char *p, struct siphash *state) { |
35 | 2.33M | bool add_slash = false; |
36 | | |
37 | 2.33M | assert(p); |
38 | 2.33M | 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 | | |
45 | | /* if path is absolute, add one "/" to the hash. */ |
46 | 2.33M | if (path_is_absolute(p)) |
47 | 2.27M | siphash24_compress_byte('/', state); |
48 | | |
49 | 20.7M | for (;;) { |
50 | 20.7M | const char *e; |
51 | 20.7M | int r; |
52 | | |
53 | 20.7M | r = path_find_first_component(&p, true, &e); |
54 | 20.7M | if (r == 0) |
55 | 2.33M | return; |
56 | | |
57 | 18.4M | if (add_slash) |
58 | 16.0M | siphash24_compress_byte('/', state); |
59 | | |
60 | 18.4M | if (r < 0) { |
61 | | /* if a component is invalid, then add remaining part as a string. */ |
62 | 1.61k | string_hash_func(p, state); |
63 | 1.61k | return; |
64 | 1.61k | } |
65 | | |
66 | | /* Add this component to the hash. */ |
67 | 18.4M | siphash24_compress(e, r, state); |
68 | | |
69 | 18.4M | add_slash = true; |
70 | 18.4M | } |
71 | 2.33M | } |
72 | | |
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); |
82 | | |
83 | 37.7M | void trivial_hash_func(const void *p, struct siphash *state) { |
84 | 37.7M | siphash24_compress_typesafe(p, state); |
85 | 37.7M | } |
86 | | |
87 | 30.7M | int trivial_compare_func(const void *a, const void *b) { |
88 | 30.7M | return CMP(a, b); |
89 | 30.7M | } |
90 | | |
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); |
104 | | |
105 | 10.4M | void uint64_hash_func(const uint64_t *p, struct siphash *state) { |
106 | 10.4M | assert(p); |
107 | | |
108 | 10.4M | siphash24_compress_typesafe(*p, state); |
109 | 10.4M | } |
110 | | |
111 | 10.4M | int uint64_compare_func(const uint64_t *a, const uint64_t *b) { |
112 | 10.4M | assert(a); |
113 | 10.4M | assert(b); |
114 | | |
115 | 10.4M | return CMP(*a, *b); |
116 | 10.4M | } |
117 | | |
118 | | DEFINE_HASH_OPS(uint64_hash_ops, |
119 | | uint64_t, uint64_hash_func, uint64_compare_func); |
120 | | DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( |
121 | | uint64_hash_ops_value_free, |
122 | | uint64_t, uint64_hash_func, uint64_compare_func, |
123 | | void, free); |
124 | | |
125 | | #if SIZEOF_DEV_T != 8 |
126 | | void devt_hash_func(const dev_t *p, struct siphash *state) { |
127 | | assert(p); |
128 | | |
129 | | siphash24_compress_typesafe(*p, state); |
130 | | } |
131 | | #endif |
132 | | |
133 | 0 | int devt_compare_func(const dev_t *a, const dev_t *b) { |
134 | 0 | int r; |
135 | |
|
136 | 0 | assert(a); |
137 | 0 | assert(b); |
138 | |
|
139 | 0 | r = CMP(major(*a), major(*b)); |
140 | 0 | if (r != 0) |
141 | 0 | return r; |
142 | | |
143 | 0 | return CMP(minor(*a), minor(*b)); |
144 | 0 | } |
145 | | |
146 | | DEFINE_HASH_OPS(devt_hash_ops, dev_t, devt_hash_func, devt_compare_func); |