Change the location of the files to /etc/defaults/uuids and /etc/uuids.
[dragonfly.git] / lib / libc / uuid / uuid_name_lookup.c
CommitLineData
e2427cb7
MD
1/*
2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
2eb5ed28 34 * $DragonFly: src/lib/libc/uuid/uuid_name_lookup.c,v 1.3 2007/06/17 07:47:32 dillon Exp $
e2427cb7
MD
35 */
36/*
37 * Implement UUID-to-NAME and NAME-to-UUID functions
38 */
39
40#include <sys/types.h>
41#include <sys/tree.h>
42#include <uuid.h>
43#include <errno.h>
44#include <string.h>
45#include <stdio.h>
46
47/*
48 * Implement a Red-Black tree to cache the UUID table and perform lookups
49 */
50struct uuid_rbnode {
51 RB_ENTRY(uuid_rbnode) unode;
52 RB_ENTRY(uuid_rbnode) nnode;
53 struct uuid uuid;
54 char *name;
55};
56
57static void uuid_loadcache(const char *path);
58
59static int uuid_name_loaded;
60
61RB_HEAD(uuid_urbtree, uuid_rbnode);
62RB_STATIC_PROTOTYPE(uuid_urbtree, uuid_rbnode, unode, uuid_urbcmp);
63static struct uuid_urbtree uuid_urbroot = RB_INITIALIZER(uuid_urbroot);
64
65RB_HEAD(uuid_nrbtree, uuid_rbnode);
66RB_STATIC_PROTOTYPE(uuid_nrbtree, uuid_rbnode, nnode, uuid_nrbcmp);
67static struct uuid_nrbtree uuid_nrbroot = RB_INITIALIZER(uuid_nrbroot);
68
69static int
70uuid_urbcmp(struct uuid_rbnode *n1, struct uuid_rbnode *n2)
71{
72 return(uuid_compare(&n1->uuid, &n2->uuid, NULL));
73}
74
75static int
76uuid_nrbcmp(struct uuid_rbnode *n1, struct uuid_rbnode *n2)
77{
78 return(strcasecmp(n1->name, n2->name));
79}
80
81static int
82uuid_rbnamecmp(const char *name, struct uuid_rbnode *node)
83{
84 return (strcasecmp(name, node->name));
85}
86
87static int
88uuid_rbuuidcmp(const struct uuid *uuid, struct uuid_rbnode *node)
89{
90 return(uuid_compare(uuid, &node->uuid, NULL));
91}
92
93RB_STATIC_GENERATE(uuid_urbtree, uuid_rbnode, unode, uuid_urbcmp)
94RB_STATIC_GENERATE(uuid_nrbtree, uuid_rbnode, nnode, uuid_nrbcmp)
95RB_STATIC_GENERATE_XLOOKUP(uuid_urbtree, UUID, uuid_rbnode, unode,
96 uuid_rbuuidcmp, const struct uuid *)
97RB_STATIC_GENERATE_XLOOKUP(uuid_nrbtree, NAME, uuid_rbnode, nnode,
98 uuid_rbnamecmp, const char *)
99
100
101/*
102 * Look up a UUID by its address. Returns 0 on success or an error
103 */
104void
105uuid_addr_lookup(const uuid_t *u, char **strp, uint32_t *status)
106{
107 struct uuid_rbnode *node;
108
109 if (*strp) {
110 free(*strp);
111 *strp = NULL;
112 }
113 if (u) {
114 if (uuid_name_loaded == 0) {
2eb5ed28
MD
115 /*
116 * /etc/uuids will override /etc/defaults/uuids
117 */
e2427cb7 118 uuid_loadcache("/etc/uuids");
2eb5ed28 119 uuid_loadcache("/etc/defaults/uuids");
e2427cb7
MD
120 uuid_name_loaded = 1;
121 }
122 node = uuid_urbtree_RB_LOOKUP_UUID(&uuid_urbroot, u);
123 if (node) {
124 *strp = strdup(node->name);
125 if (status)
126 *status = uuid_s_ok;
127 return;
128 }
129 }
130 if (status)
131 *status = uuid_s_not_found;
132}
133
134/*
135 * Look up a UUID by its name. Returns 0 on success or an error.
136 */
137void
138uuid_name_lookup(uuid_t *u, const char *name, uint32_t *status)
139{
140 struct uuid_rbnode *node;
141
142 if (name) {
143 if (uuid_name_loaded == 0) {
144 uuid_loadcache("/etc/uuids");
145 uuid_loadcache("/etc/uuids.local");
146 uuid_name_loaded = 1;
147 }
148 node = uuid_nrbtree_RB_LOOKUP_NAME(&uuid_nrbroot, name);
149 if (node) {
150 if (u)
151 *u = node->uuid;
152 if (status)
153 *status = uuid_s_ok;
154 return;
155 }
156 }
157 if (u)
158 bzero(u, sizeof(*u));
159 if (status)
160 *status = uuid_s_not_found;
161}
162
163/*
164 * Clear out the lookup cache. The next lookup will reload the database
165 * or re-query or whatever.
166 */
167static
168int
169uuid_freenode(struct uuid_rbnode *node, void *arg __unused)
170{
171 uuid_urbtree_RB_REMOVE(&uuid_urbroot, node);
172 uuid_nrbtree_RB_REMOVE(&uuid_nrbroot, node);
173 free(node->name);
174 free(node);
175}
176
177void
178uuid_reset_lookup(void)
179{
180 uuid_urbtree_RB_SCAN(&uuid_urbroot, NULL, uuid_freenode, NULL);
181 uuid_name_loaded = 0;
182}
183
184static
185void
186uuid_loadcache(const char *path)
187{
188 struct uuid_rbnode *node;
189 uint32_t status;
190 FILE *fp;
191 char *line;
192 char *uuid;
193 char *name;
194 char *last;
195 size_t len;
196
197 if ((fp = fopen(path, "r")) == NULL)
198 return;
199 while ((line = fgetln(fp, &len)) != NULL) {
0d63d043 200 if (len == 0 || *line == '#')
e2427cb7
MD
201 continue;
202 line[len-1] = 0;
203 uuid = strtok_r(line, " \t\r", &last);
204 if (uuid == NULL)
205 continue;
206 name = strtok_r(NULL, "", &last);
207 name = strchr(name, '"');
208 if (name == NULL)
209 continue;
210 *name++ = 0;
211 if (strchr(name, '"') == NULL)
212 continue;
213 *strchr(name, '"') = 0;
214 node = malloc(sizeof(*node));
215 node->name = strdup(name);
216 uuid_from_string(uuid, &node->uuid, &status);
217 if (status == 0) {
218 if (uuid_urbtree_RB_FIND(&uuid_urbroot, node) ||
219 uuid_nrbtree_RB_FIND(&uuid_nrbroot, node))
220 status = 1;
221 }
222 if (status == 0) {
223 uuid_urbtree_RB_INSERT(&uuid_urbroot, node);
224 uuid_nrbtree_RB_INSERT(&uuid_nrbroot, node);
225 } else {
226 free(node);
227 free(node->name);
228 }
229 }
230 fclose(fp);
231}
232
233