1 /*
2 * Copyright (c) 2015, 2021 Vladimir Kondratyev <vladimir@kondratyev.su>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include "config.h"
27
28 #include <stddef.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "libudev.h"
34 #include "udev-list.h"
35 #include "udev-utils.h"
36 #include "utils.h"
37
38 struct udev_list_entry {
39 struct udev_list *list;
40 RB_ENTRY(udev_list_entry) link;
41 char *value;
42 char name[];
43 };
44
45 void udev_list_entry_free(struct udev_list_entry *ule);
46
47 RB_PROTOTYPE(udev_list, udev_list_entry, link, udev_list_entry_cmp);
48
49 void
udev_list_init(struct udev_list * ul)50 udev_list_init(struct udev_list *ul)
51 {
52
53 RB_INIT(ul);
54 }
55
56 int
udev_list_insert(struct udev_list * ul,char const * name,char const * value)57 udev_list_insert(struct udev_list *ul, char const *name, char const *value)
58 {
59 struct udev_list_entry *ule, *old_ule;
60 size_t namelen, valuelen;
61
62 namelen = strlen(name) + 1;
63 valuelen = value == NULL ? 0 : strlen(value) + 1;
64 ule = calloc
65 (1, offsetof(struct udev_list_entry, name) + namelen + valuelen);
66 if (!ule)
67 return (-1);
68
69 ule->list = ul;
70 strcpy(ule->name, name);
71 ule->value = NULL;
72 if (value != NULL) {
73 ule->value = ule->name + namelen;
74 strcpy(ule->value, value);
75 }
76
77 old_ule = RB_FIND(udev_list, ul, ule);
78 if (old_ule != NULL) {
79 RB_REMOVE(udev_list, ul, old_ule);
80 udev_list_entry_free(old_ule);
81 }
82
83 RB_INSERT(udev_list, ul, ule);
84 return (0);
85 }
86
87 void
udev_list_free(struct udev_list * ul)88 udev_list_free(struct udev_list *ul)
89 {
90 struct udev_list_entry *ule1, *ule2;
91
92 RB_FOREACH_SAFE (ule1, udev_list, ul, ule2) {
93 RB_REMOVE(udev_list, ul, ule1);
94 udev_list_entry_free(ule1);
95 }
96
97 RB_INIT(ul);
98 }
99
100 void
udev_list_entry_free(struct udev_list_entry * ule)101 udev_list_entry_free(struct udev_list_entry *ule)
102 {
103
104 free(ule);
105 }
106
107 struct udev_list_entry *
udev_list_entry_get_first(struct udev_list * ul)108 udev_list_entry_get_first(struct udev_list *ul)
109 {
110
111 return (RB_MIN(udev_list, ul));
112 }
113
114 LIBUDEV_EXPORT struct udev_list_entry *
udev_list_entry_get_next(struct udev_list_entry * ule)115 udev_list_entry_get_next(struct udev_list_entry *ule)
116 {
117
118 return (RB_NEXT(udev_list,, ule));
119 }
120
121 const char *
_udev_list_entry_get_name(struct udev_list_entry * ule)122 _udev_list_entry_get_name(struct udev_list_entry *ule)
123 {
124
125 return (ule->name);
126 }
127
128 LIBUDEV_EXPORT const char *
udev_list_entry_get_name(struct udev_list_entry * ule)129 udev_list_entry_get_name(struct udev_list_entry *ule)
130 {
131 const char *name;
132
133 name = _udev_list_entry_get_name(ule);
134 TRC("() %s", name);
135 return (name);
136 }
137
138 const char *
_udev_list_entry_get_value(struct udev_list_entry * ule)139 _udev_list_entry_get_value(struct udev_list_entry *ule)
140 {
141
142 return (ule->value);
143 }
144
145 LIBUDEV_EXPORT const char *
udev_list_entry_get_value(struct udev_list_entry * ule)146 udev_list_entry_get_value(struct udev_list_entry *ule)
147 {
148 const char *value;
149
150 value = _udev_list_entry_get_value(ule);
151 TRC("() %s", value);
152 return (value);
153 }
154
155 static int
udev_list_entry_cmp(struct udev_list_entry * le1,struct udev_list_entry * le2)156 udev_list_entry_cmp (struct udev_list_entry *le1, struct udev_list_entry *le2)
157 {
158
159 return (strcmp(le1->name, le2->name));
160 }
161
162 LIBUDEV_EXPORT struct udev_list_entry *
udev_list_entry_get_by_name(struct udev_list_entry * ule,const char * name)163 udev_list_entry_get_by_name(struct udev_list_entry *ule, const char *name)
164 {
165 struct udev_list_entry *find, *ret;
166
167 find = calloc
168 (1, offsetof(struct udev_list_entry, name) + strlen(name) + 1);
169
170 ret = RB_FIND(udev_list, ule->list, find);
171 udev_list_entry_free(find);
172
173 return (ret);
174 }
175
176 RB_GENERATE(udev_list, udev_list_entry, link, udev_list_entry_cmp);
177