1 |
/* Support for opening `typed' stores |
/* Support for opening `typed' stores |
2 |
|
|
3 |
Copyright (C) 1997,98,2001 Free Software Foundation, Inc. |
Copyright (C) 1997,98,2001,02 Free Software Foundation, Inc. |
4 |
Written by Miles Bader <miles@gnu.org> |
Written by Miles Bader <miles@gnu.org> |
5 |
|
|
6 |
This file is part of the GNU Hurd. |
This file is part of the GNU Hurd. |
21 |
|
|
22 |
#include "store.h" |
#include "store.h" |
23 |
#include <string.h> |
#include <string.h> |
24 |
|
#include <dlfcn.h> |
25 |
|
#include <link.h> |
26 |
|
|
27 |
|
|
28 |
|
const struct store_class * |
29 |
|
store_find_class (const char *name, const char *clname_end, |
30 |
|
const struct store_class *const *classes) |
31 |
|
{ |
32 |
|
const struct store_class *const *cl; |
33 |
|
|
34 |
|
if (! clname_end) |
35 |
|
clname_end = strchr (name, '\0'); |
36 |
|
|
37 |
|
if (classes != 0) |
38 |
|
{ |
39 |
|
/* The caller gave a class list, so that's is all we'll use. */ |
40 |
|
for (cl = classes; *cl != 0; ++cl) |
41 |
|
if (strlen ((*cl)->name) == (clname_end - name) |
42 |
|
&& !memcmp (name, (*cl)->name, (clname_end - name))) |
43 |
|
break; |
44 |
|
return *cl; |
45 |
|
} |
46 |
|
|
47 |
|
/* Check the statically-linked set of classes found in the |
48 |
|
"store_std_classes" section. For static linking, this is the section |
49 |
|
in the program executable itself and it has been populated by the set |
50 |
|
of -lstore_TYPE pseudo-libraries included in the link. For dynamic |
51 |
|
linking with just -lstore, these symbols will be found in libstore.so |
52 |
|
and have the set statically included when the shared object was built. |
53 |
|
If a dynamically-linked program has its own "store_std_classes" |
54 |
|
section, e.g. by -lstore_TYPE objects included in the link, this will |
55 |
|
be just that section and libstore.so itself is covered below. */ |
56 |
|
# pragma weak __start_store_std_classes |
57 |
|
# pragma weak __stop_store_std_classes |
58 |
|
for (cl = __start_store_std_classes; cl < __stop_store_std_classes; ++cl) |
59 |
|
if (strlen ((*cl)->name) == (clname_end - name) |
60 |
|
&& strncmp (name, (*cl)->name, (clname_end - name)) == 0) |
61 |
|
return *cl; |
62 |
|
|
63 |
|
/* Now we will iterate through all of the dynamic objects loaded |
64 |
|
and examine each one's "store_std_classes" section. */ |
65 |
|
# pragma weak _r_debug |
66 |
|
# pragma weak dlsym |
67 |
|
# pragma weak dlerror |
68 |
|
if (dlsym) |
69 |
|
{ |
70 |
|
struct link_map *map; |
71 |
|
for (map = _r_debug.r_map; map != 0; map = map->l_next) |
72 |
|
{ |
73 |
|
const struct store_class *const *start; |
74 |
|
const struct store_class *const *stop; |
75 |
|
start = dlsym (map, "__start_store_std_classes"); |
76 |
|
if (start == 0) |
77 |
|
{ |
78 |
|
(void) dlerror (); /* Required to avoid a leak! */ |
79 |
|
continue; |
80 |
|
} |
81 |
|
if (start == __start_store_std_classes) |
82 |
|
continue; |
83 |
|
stop = dlsym (map, "__stop_store_std_classes"); |
84 |
|
if (stop == 0) |
85 |
|
{ |
86 |
|
(void) dlerror (); /* Required to avoid a leak! */ |
87 |
|
continue; |
88 |
|
} |
89 |
|
for (cl = start; cl < stop; ++cl) |
90 |
|
if (strlen ((*cl)->name) == (clname_end - name) |
91 |
|
&& strncmp (name, (*cl)->name, (clname_end - name)) == 0) |
92 |
|
return *cl; |
93 |
|
} |
94 |
|
} |
95 |
|
|
96 |
|
return 0; |
97 |
|
} |
98 |
|
|
99 |
|
|
100 |
/* Open the store indicated by NAME, which should consist of a store type |
/* Open the store indicated by NAME, which should consist of a store type |
101 |
name followed by a ':' and any type-specific name, returning the new store |
name followed by a ':' and any type-specific name, returning the new store |
110 |
const struct store_class *const *classes, |
const struct store_class *const *classes, |
111 |
struct store **store) |
struct store **store) |
112 |
{ |
{ |
113 |
const struct store_class *const *cl; |
const struct store_class *cl; |
114 |
const char *clname_end = strchr (name, ':'); |
const char *clname_end = strchrnul (name, ':'); |
115 |
|
|
116 |
if (clname_end == name) |
if (clname_end == name) |
117 |
/* Open NAME with store_open. */ |
/* Open NAME with store_open. */ |
118 |
return store_open (name + 1, flags, classes, store); |
return store_open (name + 1, flags, classes, store); |
119 |
|
|
120 |
if (! clname_end) |
/* Try to find an existing class by the given name. */ |
121 |
clname_end = name + strlen (name); |
cl = store_find_class (name, clname_end, classes); |
122 |
|
if (cl != 0) |
|
if (! classes) |
|
|
classes = store_std_classes; |
|
|
for (cl = classes; *cl; cl++) |
|
|
if (strlen ((*cl)->name) == (clname_end - name) |
|
|
&& strncmp (name, (*cl)->name, (clname_end - name)) == 0) |
|
|
break; |
|
|
|
|
|
if (! *cl) |
|
123 |
{ |
{ |
124 |
/* No class with the given name found. */ |
if (! cl->open) |
125 |
|
/* CL cannot be opened. */ |
126 |
|
return EOPNOTSUPP; |
127 |
|
|
128 |
if (*clname_end) |
if (*clname_end) |
129 |
/* NAME really should be a class name, which doesn't exist. */ |
/* Skip the ':' separating the class-name from the device name. */ |
130 |
return EINVAL; |
clname_end++; |
|
else |
|
|
/* Try opening NAME by querying it as a file instead. */ |
|
|
return store_open (name, flags, classes, store); |
|
|
} |
|
131 |
|
|
132 |
if (! (*cl)->open) |
if (! *clname_end) |
133 |
/* CL cannot be opened. */ |
/* The class-specific portion of the name is empty, so make it *really* |
134 |
return EOPNOTSUPP; |
empty. */ |
135 |
|
clname_end = 0; |
136 |
|
|
137 |
if (*clname_end) |
return (*cl->open) (clname_end, flags, classes, store); |
138 |
/* Skip the ':' separating the class-name from the device name. */ |
} |
|
clname_end++; |
|
139 |
|
|
140 |
if (! *clname_end) |
/* Try to open a store by loading a module to define the class, if we |
141 |
/* The class-specific portion of the name is empty, so make it *really* |
have the module-loading support linked in. We don't just use |
142 |
empty. */ |
store_module_find_class, because store_module_open will unload the new |
143 |
clname_end = 0; |
module if the open doesn't succeed and we have no other way to unload |
144 |
|
it. We always leave modules loaded once a store from the module has |
145 |
|
been successfully opened and so can leave unbounded numbers of old |
146 |
|
modules loaded after closing all the stores using them. But at least |
147 |
|
we can avoid having modules loaded for stores we never even opened. */ |
148 |
|
# pragma weak store_module_open |
149 |
|
if (store_module_open) |
150 |
|
{ |
151 |
|
error_t err = store_module_open (name, flags, classes, store); |
152 |
|
if (err != ENOENT) |
153 |
|
return err; |
154 |
|
} |
155 |
|
|
156 |
return (*(*cl)->open) (clname_end, flags, classes, store); |
/* No class with the given name found. */ |
157 |
|
if (*clname_end) |
158 |
|
/* NAME really should be a class name, which doesn't exist. */ |
159 |
|
return EINVAL; |
160 |
|
else |
161 |
|
/* Try opening NAME by querying it as a file instead. */ |
162 |
|
return store_open (name, flags, classes, store); |
163 |
} |
} |
164 |
|
|
165 |
const struct store_class |
const struct store_class |
166 |
store_typed_open_class = { -1, "typed", open: store_typed_open }; |
store_typed_open_class = { -1, "typed", open: store_typed_open }; |
167 |
|
STORE_STD_CLASS (typed_open); |