HAMMER 59B/Many: Stabilization pass - fixes for large file issues
[dragonfly.git] / lib / libc / uuid / uuid_name_lookup.c
bloba57f4d5eba71d83cf6a3ec16a26ecd54bdbeb9c7
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:
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.
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.
34 * $DragonFly: src/lib/libc/uuid/uuid_name_lookup.c,v 1.6 2008/01/07 01:22:30 corecode Exp $
37 * Implement UUID-to-NAME and NAME-to-UUID functions
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 #include <stdlib.h>
49 * Implement a Red-Black tree to cache the UUID table and perform lookups
51 struct uuid_rbnode {
52 RB_ENTRY(uuid_rbnode) unode;
53 RB_ENTRY(uuid_rbnode) nnode;
54 struct uuid uuid;
55 char *name;
58 static void uuid_loadcache(const char *path);
60 static int uuid_name_loaded;
62 RB_HEAD(uuid_urbtree, uuid_rbnode);
63 RB_PROTOTYPE_STATIC(uuid_urbtree, uuid_rbnode, unode, uuid_urbcmp);
64 static struct uuid_urbtree uuid_urbroot = RB_INITIALIZER(uuid_urbroot);
66 RB_HEAD(uuid_nrbtree, uuid_rbnode);
67 RB_PROTOTYPE_STATIC(uuid_nrbtree, uuid_rbnode, nnode, uuid_nrbcmp);
68 static struct uuid_nrbtree uuid_nrbroot = RB_INITIALIZER(uuid_nrbroot);
70 static int
71 uuid_urbcmp(struct uuid_rbnode *n1, struct uuid_rbnode *n2)
73 return(uuid_compare(&n1->uuid, &n2->uuid, NULL));
76 static int
77 uuid_nrbcmp(struct uuid_rbnode *n1, struct uuid_rbnode *n2)
79 return(strcasecmp(n1->name, n2->name));
82 static int
83 uuid_rbnamecmp(const char *name, struct uuid_rbnode *node)
85 return (strcasecmp(name, node->name));
88 static int
89 uuid_rbuuidcmp(const struct uuid *uuid, struct uuid_rbnode *node)
91 return(uuid_compare(uuid, &node->uuid, NULL));
94 RB_GENERATE_STATIC(uuid_urbtree, uuid_rbnode, unode, uuid_urbcmp)
95 RB_GENERATE_STATIC(uuid_nrbtree, uuid_rbnode, nnode, uuid_nrbcmp)
96 RB_GENERATE_XLOOKUP_STATIC(uuid_urbtree, UUID, uuid_rbnode, unode,
97 uuid_rbuuidcmp, const struct uuid *)
98 RB_GENERATE_XLOOKUP_STATIC(uuid_nrbtree, NAME, uuid_rbnode, nnode,
99 uuid_rbnamecmp, const char *)
103 * Look up a UUID by its address. Returns 0 on success or an error
105 void
106 uuid_addr_lookup(const uuid_t *u, char **strp, uint32_t *status)
108 struct uuid_rbnode *node;
110 if (*strp) {
111 free(*strp);
112 *strp = NULL;
114 if (u) {
115 if (uuid_name_loaded == 0) {
117 * /etc/uuids will override /etc/defaults/uuids
119 uuid_loadcache("/etc/uuids");
120 uuid_loadcache("/etc/defaults/uuids");
121 uuid_name_loaded = 1;
123 node = uuid_urbtree_RB_LOOKUP_UUID(&uuid_urbroot, u);
124 if (node) {
125 *strp = strdup(node->name);
126 if (status)
127 *status = uuid_s_ok;
128 return;
131 if (status)
132 *status = uuid_s_not_found;
136 * Look up a UUID by its name. Returns 0 on success or an error.
138 void
139 uuid_name_lookup(uuid_t *u, const char *name, uint32_t *status)
141 struct uuid_rbnode *node;
143 if (name) {
144 if (uuid_name_loaded == 0) {
145 uuid_loadcache("/etc/uuids");
146 uuid_loadcache("/etc/defaults/uuids");
147 uuid_name_loaded = 1;
149 node = uuid_nrbtree_RB_LOOKUP_NAME(&uuid_nrbroot, name);
150 if (node) {
151 if (u)
152 *u = node->uuid;
153 if (status)
154 *status = uuid_s_ok;
155 return;
158 if (u)
159 bzero(u, sizeof(*u));
160 if (status)
161 *status = uuid_s_not_found;
165 * Clear out the lookup cache. The next lookup will reload the database
166 * or re-query or whatever.
168 static
170 uuid_freenode(struct uuid_rbnode *node, void *arg __unused)
172 uuid_urbtree_RB_REMOVE(&uuid_urbroot, node);
173 uuid_nrbtree_RB_REMOVE(&uuid_nrbroot, node);
174 free(node->name);
175 free(node);
178 void
179 uuid_reset_lookup(void)
181 uuid_urbtree_RB_SCAN(&uuid_urbroot, NULL, uuid_freenode, NULL);
182 uuid_name_loaded = 0;
185 static
186 void
187 uuid_loadcache(const char *path)
189 struct uuid_rbnode *node;
190 uint32_t status;
191 FILE *fp;
192 char *line;
193 char *uuid;
194 char *name;
195 char *last;
196 size_t len;
198 if ((fp = fopen(path, "r")) == NULL)
199 return;
200 while ((line = fgetln(fp, &len)) != NULL) {
201 if (len == 0 || *line == '#')
202 continue;
203 line[len-1] = 0;
204 uuid = strtok_r(line, " \t\r", &last);
205 if (uuid == NULL)
206 continue;
207 name = strtok_r(NULL, "", &last);
208 name = strchr(name, '"');
209 if (name == NULL)
210 continue;
211 *name++ = 0;
212 if (strchr(name, '"') == NULL)
213 continue;
214 *strchr(name, '"') = 0;
215 node = malloc(sizeof(*node));
216 node->name = strdup(name);
217 uuid_from_string(uuid, &node->uuid, &status);
218 if (status == 0) {
219 if (uuid_urbtree_RB_FIND(&uuid_urbroot, node) ||
220 uuid_nrbtree_RB_FIND(&uuid_nrbroot, node))
221 status = 1;
223 if (status == 0) {
224 uuid_urbtree_RB_INSERT(&uuid_urbroot, node);
225 uuid_nrbtree_RB_INSERT(&uuid_nrbroot, node);
226 } else {
227 free(node);
228 free(node->name);
231 fclose(fp);