2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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
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>
49 * Implement a Red-Black tree to cache the UUID table and perform lookups
52 RB_ENTRY(uuid_rbnode
) unode
;
53 RB_ENTRY(uuid_rbnode
) nnode
;
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
);
71 uuid_urbcmp(struct uuid_rbnode
*n1
, struct uuid_rbnode
*n2
)
73 return(uuid_compare(&n1
->uuid
, &n2
->uuid
, NULL
));
77 uuid_nrbcmp(struct uuid_rbnode
*n1
, struct uuid_rbnode
*n2
)
79 return(strcasecmp(n1
->name
, n2
->name
));
83 uuid_rbnamecmp(const char *name
, struct uuid_rbnode
*node
)
85 return (strcasecmp(name
, node
->name
));
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
106 uuid_addr_lookup(const uuid_t
*u
, char **strp
, uint32_t *status
)
108 struct uuid_rbnode
*node
;
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
);
125 *strp
= strdup(node
->name
);
132 *status
= uuid_s_not_found
;
136 * Look up a UUID by its name. Returns 0 on success or an error.
139 uuid_name_lookup(uuid_t
*u
, const char *name
, uint32_t *status
)
141 struct uuid_rbnode
*node
;
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
);
159 bzero(u
, sizeof(*u
));
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.
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
);
179 uuid_reset_lookup(void)
181 uuid_urbtree_RB_SCAN(&uuid_urbroot
, NULL
, uuid_freenode
, NULL
);
182 uuid_name_loaded
= 0;
187 uuid_loadcache(const char *path
)
189 struct uuid_rbnode
*node
;
198 if ((fp
= fopen(path
, "r")) == NULL
)
200 while ((line
= fgetln(fp
, &len
)) != NULL
) {
201 if (len
== 0 || *line
== '#')
204 uuid
= strtok_r(line
, " \t\r", &last
);
207 name
= strtok_r(NULL
, "", &last
);
208 name
= strchr(name
, '"');
212 if (strchr(name
, '"') == NULL
)
214 *strchr(name
, '"') = 0;
215 node
= malloc(sizeof(*node
));
216 node
->name
= strdup(name
);
217 uuid_from_string(uuid
, &node
->uuid
, &status
);
219 if (uuid_urbtree_RB_FIND(&uuid_urbroot
, node
) ||
220 uuid_nrbtree_RB_FIND(&uuid_nrbroot
, node
))
224 uuid_urbtree_RB_INSERT(&uuid_urbroot
, node
);
225 uuid_nrbtree_RB_INSERT(&uuid_nrbroot
, node
);