udev: String substitutions can be done in ENV, too
[systemd_ALT.git] / src / basic / hash-funcs.c
blob5fac467185710bc8f73038d4c33bb84cfd08293f
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <string.h>
5 #include "hash-funcs.h"
6 #include "path-util.h"
7 #include "strv.h"
9 void string_hash_func(const char *p, struct siphash *state) {
10 siphash24_compress(p, strlen(p) + 1, state);
13 DEFINE_HASH_OPS(string_hash_ops, char, string_hash_func, string_compare_func);
14 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(string_hash_ops_free,
15 char, string_hash_func, string_compare_func, free);
16 DEFINE_HASH_OPS_FULL(string_hash_ops_free_free,
17 char, string_hash_func, string_compare_func, free,
18 void, free);
19 DEFINE_HASH_OPS_FULL(string_hash_ops_free_strv_free,
20 char, string_hash_func, string_compare_func, free,
21 char*, strv_free);
23 void path_hash_func(const char *q, struct siphash *state) {
24 bool add_slash = false;
26 assert(q);
27 assert(state);
29 /* Calculates a hash for a path in a way this duplicate inner slashes don't make a differences, and also
30 * whether there's a trailing slash or not. This fits well with the semantics of path_compare(), which does
31 * similar checks and also doesn't care for trailing slashes. Note that relative and absolute paths (i.e. those
32 * which begin in a slash or not) will hash differently though. */
34 /* if path is absolute, add one "/" to the hash. */
35 if (path_is_absolute(q))
36 siphash24_compress("/", 1, state);
38 for (;;) {
39 const char *e;
40 int r;
42 r = path_find_first_component(&q, true, &e);
43 if (r == 0)
44 return;
46 if (add_slash)
47 siphash24_compress_byte('/', state);
49 if (r < 0) {
50 /* if a component is invalid, then add remaining part as a string. */
51 string_hash_func(q, state);
52 return;
55 /* Add this component to the hash. */
56 siphash24_compress(e, r, state);
58 add_slash = true;
62 DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare);
63 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(path_hash_ops_free,
64 char, path_hash_func, path_compare, free);
65 DEFINE_HASH_OPS_FULL(path_hash_ops_free_free,
66 char, path_hash_func, path_compare, free,
67 void, free);
69 void trivial_hash_func(const void *p, struct siphash *state) {
70 siphash24_compress(&p, sizeof(p), state);
73 int trivial_compare_func(const void *a, const void *b) {
74 return CMP(a, b);
77 const struct hash_ops trivial_hash_ops = {
78 .hash = trivial_hash_func,
79 .compare = trivial_compare_func,
82 const struct hash_ops trivial_hash_ops_free = {
83 .hash = trivial_hash_func,
84 .compare = trivial_compare_func,
85 .free_key = free,
88 const struct hash_ops trivial_hash_ops_free_free = {
89 .hash = trivial_hash_func,
90 .compare = trivial_compare_func,
91 .free_key = free,
92 .free_value = free,
95 void uint64_hash_func(const uint64_t *p, struct siphash *state) {
96 siphash24_compress(p, sizeof(uint64_t), state);
99 int uint64_compare_func(const uint64_t *a, const uint64_t *b) {
100 return CMP(*a, *b);
103 DEFINE_HASH_OPS(uint64_hash_ops, uint64_t, uint64_hash_func, uint64_compare_func);
105 #if SIZEOF_DEV_T != 8
106 void devt_hash_func(const dev_t *p, struct siphash *state) {
107 siphash24_compress(p, sizeof(dev_t), state);
109 #endif
111 int devt_compare_func(const dev_t *a, const dev_t *b) {
112 int r;
114 r = CMP(major(*a), major(*b));
115 if (r != 0)
116 return r;
118 return CMP(minor(*a), minor(*b));
121 DEFINE_HASH_OPS(devt_hash_ops, dev_t, devt_hash_func, devt_compare_func);