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.4 2007/06/17 07:56:58 dillon Exp $
37 * Implement UUID-to-NAME and NAME-to-UUID functions
40 #include <sys/types.h>
48 * Implement a Red-Black tree to cache the UUID table and perform lookups
51 RB_ENTRY(uuid_rbnode
) unode
;
52 RB_ENTRY(uuid_rbnode
) nnode
;
57 static void uuid_loadcache(const char *path
);
59 static int uuid_name_loaded
;
61 RB_HEAD(uuid_urbtree
, uuid_rbnode
);
62 RB_STATIC_PROTOTYPE(uuid_urbtree
, uuid_rbnode
, unode
, uuid_urbcmp
);
63 static struct uuid_urbtree uuid_urbroot
= RB_INITIALIZER(uuid_urbroot
);
65 RB_HEAD(uuid_nrbtree
, uuid_rbnode
);
66 RB_STATIC_PROTOTYPE(uuid_nrbtree
, uuid_rbnode
, nnode
, uuid_nrbcmp
);
67 static struct uuid_nrbtree uuid_nrbroot
= RB_INITIALIZER(uuid_nrbroot
);
70 uuid_urbcmp(struct uuid_rbnode
*n1
, struct uuid_rbnode
*n2
)
72 return(uuid_compare(&n1
->uuid
, &n2
->uuid
, NULL
));
76 uuid_nrbcmp(struct uuid_rbnode
*n1
, struct uuid_rbnode
*n2
)
78 return(strcasecmp(n1
->name
, n2
->name
));
82 uuid_rbnamecmp(const char *name
, struct uuid_rbnode
*node
)
84 return (strcasecmp(name
, node
->name
));
88 uuid_rbuuidcmp(const struct uuid
*uuid
, struct uuid_rbnode
*node
)
90 return(uuid_compare(uuid
, &node
->uuid
, NULL
));
93 RB_STATIC_GENERATE(uuid_urbtree
, uuid_rbnode
, unode
, uuid_urbcmp
)
94 RB_STATIC_GENERATE(uuid_nrbtree
, uuid_rbnode
, nnode
, uuid_nrbcmp
)
95 RB_STATIC_GENERATE_XLOOKUP(uuid_urbtree
, UUID
, uuid_rbnode
, unode
,
96 uuid_rbuuidcmp
, const struct uuid
*)
97 RB_STATIC_GENERATE_XLOOKUP(uuid_nrbtree
, NAME
, uuid_rbnode
, nnode
,
98 uuid_rbnamecmp
, const char *)
102 * Look up a UUID by its address. Returns 0 on success or an error
105 uuid_addr_lookup(const uuid_t
*u
, char **strp
, uint32_t *status
)
107 struct uuid_rbnode
*node
;
114 if (uuid_name_loaded
== 0) {
116 * /etc/uuids will override /etc/defaults/uuids
118 uuid_loadcache("/etc/uuids");
119 uuid_loadcache("/etc/defaults/uuids");
120 uuid_name_loaded
= 1;
122 node
= uuid_urbtree_RB_LOOKUP_UUID(&uuid_urbroot
, u
);
124 *strp
= strdup(node
->name
);
131 *status
= uuid_s_not_found
;
135 * Look up a UUID by its name. Returns 0 on success or an error.
138 uuid_name_lookup(uuid_t
*u
, const char *name
, uint32_t *status
)
140 struct uuid_rbnode
*node
;
143 if (uuid_name_loaded
== 0) {
144 uuid_loadcache("/etc/uuids");
145 uuid_loadcache("/etc/defaults/uuids");
146 uuid_name_loaded
= 1;
148 node
= uuid_nrbtree_RB_LOOKUP_NAME(&uuid_nrbroot
, name
);
158 bzero(u
, sizeof(*u
));
160 *status
= uuid_s_not_found
;
164 * Clear out the lookup cache. The next lookup will reload the database
165 * or re-query or whatever.
169 uuid_freenode(struct uuid_rbnode
*node
, void *arg __unused
)
171 uuid_urbtree_RB_REMOVE(&uuid_urbroot
, node
);
172 uuid_nrbtree_RB_REMOVE(&uuid_nrbroot
, node
);
178 uuid_reset_lookup(void)
180 uuid_urbtree_RB_SCAN(&uuid_urbroot
, NULL
, uuid_freenode
, NULL
);
181 uuid_name_loaded
= 0;
186 uuid_loadcache(const char *path
)
188 struct uuid_rbnode
*node
;
197 if ((fp
= fopen(path
, "r")) == NULL
)
199 while ((line
= fgetln(fp
, &len
)) != NULL
) {
200 if (len
== 0 || *line
== '#')
203 uuid
= strtok_r(line
, " \t\r", &last
);
206 name
= strtok_r(NULL
, "", &last
);
207 name
= strchr(name
, '"');
211 if (strchr(name
, '"') == NULL
)
213 *strchr(name
, '"') = 0;
214 node
= malloc(sizeof(*node
));
215 node
->name
= strdup(name
);
216 uuid_from_string(uuid
, &node
->uuid
, &status
);
218 if (uuid_urbtree_RB_FIND(&uuid_urbroot
, node
) ||
219 uuid_nrbtree_RB_FIND(&uuid_nrbroot
, node
))
223 uuid_urbtree_RB_INSERT(&uuid_urbroot
, node
);
224 uuid_nrbtree_RB_INSERT(&uuid_nrbroot
, node
);