2 * libudev - interface to udev device information
4 * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "libudev-private.h"
30 struct udev_list_entry {
32 struct list_node node;
33 struct list_node *list;
38 /* list head point to itself if empty */
39 void list_init(struct list_node *list)
45 static int list_is_empty(struct list_node *list)
47 return list->next == list;
50 static void list_node_insert_between(struct list_node *new,
51 struct list_node *prev,
52 struct list_node *next)
60 static void list_node_remove(struct list_node *entry)
62 struct list_node *prev = entry->prev;
63 struct list_node *next = entry->next;
72 /* return list entry which embeds this node */
73 static struct udev_list_entry *list_node_to_entry(struct list_node *node)
78 list -= offsetof(struct udev_list_entry, node);
79 return (struct udev_list_entry *)list;
82 /* insert entry into a list as the last element */
83 static void list_entry_append(struct udev_list_entry *new, struct list_node *list)
85 /* inserting before the list head make the node the last node in the list */
86 list_node_insert_between(&new->node, list->prev, list);
90 /* insert entry into a list, before a given existing entry */
91 static void list_entry_insert_before(struct udev_list_entry *new, struct udev_list_entry *entry)
93 list_node_insert_between(&new->node, entry->node.prev, &entry->node);
94 new->list = entry->list;
97 void list_entry_remove(struct udev_list_entry *entry)
99 list_node_remove(&entry->node);
103 struct udev_list_entry *list_entry_add(struct udev *udev, struct list_node *list,
104 const char *name, const char *value,
105 int unique, int sort)
107 struct udev_list_entry *entry_loop = NULL;
108 struct udev_list_entry *entry_new;
111 udev_list_entry_foreach(entry_loop, list_get_entry(list)) {
112 if (strcmp(entry_loop->name, name) == 0) {
113 info(udev, "'%s' is already in the list\n", name);
115 free(entry_loop->value);
116 entry_loop->value = strdup(value);
117 if (entry_loop->value == NULL)
119 info(udev, "'%s' value replaced with '%s'\n", name, value);
126 udev_list_entry_foreach(entry_loop, list_get_entry(list)) {
127 if (strcmp(entry_loop->name, name) > 0)
131 entry_new = malloc(sizeof(struct udev_list_entry));
132 if (entry_new == NULL)
134 memset(entry_new, 0x00, sizeof(struct udev_list_entry));
135 entry_new->udev = udev;
136 entry_new->name = strdup(name);
137 if (entry_new->name == NULL) {
142 entry_new->value = strdup(value);
143 if (entry_new->value == NULL) {
144 free(entry_new->name);
149 if (entry_loop != NULL)
150 list_entry_insert_before(entry_new, entry_loop);
152 list_entry_append(entry_new, list);
156 void list_entry_move_to_end(struct udev_list_entry *list_entry)
158 list_node_remove(&list_entry->node);
159 list_node_insert_between(&list_entry->node, list_entry->list->prev, list_entry->list);
162 void list_cleanup(struct udev *udev, struct list_node *list)
164 struct udev_list_entry *entry_loop;
165 struct udev_list_entry *entry_tmp;
167 list_entry_foreach_safe(entry_loop, entry_tmp, list_get_entry(list)) {
168 list_entry_remove(entry_loop);
169 free(entry_loop->name);
170 free(entry_loop->value);
175 struct udev_list_entry *list_get_entry(struct list_node *list)
177 if (list_is_empty(list))
179 return list_node_to_entry(list->next);
182 struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry)
184 struct list_node *next;
186 if (list_entry == NULL)
188 next = list_entry->node.next;
189 /* empty list or no more entries */
190 if (next == list_entry->list)
192 return list_node_to_entry(next);
195 struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name)
197 struct udev_list_entry *entry;
199 udev_list_entry_foreach(entry, list_entry)
200 if (strcmp(udev_list_entry_get_name(entry), name) == 0)
205 const char *udev_list_entry_get_name(struct udev_list_entry *list_entry)
207 if (list_entry == NULL)
209 return list_entry->name;
212 const char *udev_list_entry_get_value(struct udev_list_entry *list_entry)
214 if (list_entry == NULL)
216 return list_entry->value;