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