diff options
author | Roland McGrath <roland@gnu.org> | 2002-03-14 21:10:01 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2002-03-14 21:10:01 +0000 |
commit | 899e93342a306bba89c0fe0579d707518678e1c4 (patch) | |
tree | 2cab796e68cd7c78cf9469d92fc607103ece83a4 /libstore | |
parent | ac52bdb19720d0e0be9cf3bd85c8011975d3857f (diff) |
2002-02-08 Roland McGrath <roland@frob.com>
* Makefile (store-types): New variable.
(all): Depend on $(store-types:%=libstore_%.a).
(libstore_%.so.$(hurd-version)): New pattern rule.
($(store-types:%=libstore_%.a): libstore_%.a): New static pattern rule
to create `-lstore_TYPE' pseudo-objects (linker scripts) for each type.
(libstore.so-LDLIBS): New variable, adds -ldl.
(GUNZIP_OBJS, BUNZIP2_OBJS): New variables.
(UNZIP_OBJS): Variable removed, replaced by those two.
(OBJS): Update use.
(libstore_gunzip.so.$(hurd-version)): Depend on PIC $(GUNZIP_OBJS).
(libstore_bunzip2.so.$(hurd-version)): Depend on PIC $(BUNZIP2_OBJS).
* unknown.c: Add STORE_STD_CLASS decl.
* bunzip2.c: Likewise.
* copy.c: Likewise.
* device.c: Likewise.
* file.c: Likewise.
* gunzip.c: Likewise.
* memobj.c: Likewise.
* module.c: Likewise.
* mvol.c: Likewise.
* nbd.c: Likewise.
* open.c: Likewise.
* part.c: Likewise.
* remap.c: Likewise.
* stripe.c: Likewise.
* stripe.c: Likewise.
* task.c: Likewise.
* typed.c: Likewise.
* typed.c: Likewise.
* unknown.c: Likewise.
* url.c: Likewise.
* zero.c: Likewise.
2002-01-19 Roland McGrath <roland@frob.com>
* typed.c (store_find_class): New function.
(store_typed_open): Use it.
2001-12-28 Roland McGrath <roland@frob.com>
* module.c: New file.
* store.h (store_module_open, store_module_find_class,
store_module_decode): Declare them.
* argp.c (parse_opt): Leave PARSED->classes null here instead
of defaulting to store_std_classes.
(find_class): Default null class-list parameter to store_std_classes
here instead. If no matches when defaulted, try calling
store_module_open_class too.
* typed.c (store_typed_open): If no match when search list is
store_std_classes, try calling store_module_open_class too.
* url.c (find_url_class): Likewise.
* decode.c (store_decode): If no match when search list is
store_std_classes, try calling store_module_decode too.
Diffstat (limited to 'libstore')
-rw-r--r-- | libstore/typed.c | 148 |
1 files changed, 116 insertions, 32 deletions
diff --git a/libstore/typed.c b/libstore/typed.c index 48dbb6b9..822f23f8 100644 --- a/libstore/typed.c +++ b/libstore/typed.c @@ -1,6 +1,6 @@ /* Support for opening `typed' stores - Copyright (C) 1997,98,2001 Free Software Foundation, Inc. + Copyright (C) 1997,98,2001,02 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.org> This file is part of the GNU Hurd. @@ -21,6 +21,81 @@ #include "store.h" #include <string.h> +#include <dlfcn.h> +#include <link.h> + + +const struct store_class * +store_find_class (const char *name, const char *clname_end, + const struct store_class *const *classes) +{ + const struct store_class *const *cl; + + if (! clname_end) + clname_end = strchr (name, '\0'); + + if (classes != 0) + { + /* The caller gave a class list, so that's is all we'll use. */ + for (cl = classes; *cl != 0; ++cl) + if (strlen ((*cl)->name) == (clname_end - name) + && !memcmp (name, (*cl)->name, (clname_end - name))) + break; + return *cl; + } + + /* Check the statically-linked set of classes found in the + "store_std_classes" section. For static linking, this is the section + in the program executable itself and it has been populated by the set + of -lstore_TYPE pseudo-libraries included in the link. For dynamic + linking with just -lstore, these symbols will be found in libstore.so + and have the set statically included when the shared object was built. + If a dynamically-linked program has its own "store_std_classes" + section, e.g. by -lstore_TYPE objects included in the link, this will + be just that section and libstore.so itself is covered below. */ +# pragma weak __start_store_std_classes +# pragma weak __stop_store_std_classes + for (cl = __start_store_std_classes; cl < __stop_store_std_classes; ++cl) + if (strlen ((*cl)->name) == (clname_end - name) + && strncmp (name, (*cl)->name, (clname_end - name)) == 0) + return *cl; + + /* Now we will iterate through all of the dynamic objects loaded + and examine each one's "store_std_classes" section. */ +# pragma weak _r_debug +# pragma weak dlsym +# pragma weak dlerror + if (dlsym) + { + struct link_map *map; + for (map = _r_debug.r_map; map != 0; map = map->l_next) + { + const struct store_class *const *start; + const struct store_class *const *stop; + start = dlsym (map, "__start_store_std_classes"); + if (start == 0) + { + (void) dlerror (); /* Required to avoid a leak! */ + continue; + } + if (start == __start_store_std_classes) + continue; + stop = dlsym (map, "__stop_store_std_classes"); + if (stop == 0) + { + (void) dlerror (); /* Required to avoid a leak! */ + continue; + } + for (cl = start; cl < stop; ++cl) + if (strlen ((*cl)->name) == (clname_end - name) + && strncmp (name, (*cl)->name, (clname_end - name)) == 0) + return *cl; + } + } + + return 0; +} + /* Open the store indicated by NAME, which should consist of a store type name followed by a ':' and any type-specific name, returning the new store @@ -35,49 +110,58 @@ store_typed_open (const char *name, int flags, const struct store_class *const *classes, struct store **store) { - const struct store_class *const *cl; - const char *clname_end = strchr (name, ':'); + const struct store_class *cl; + const char *clname_end = strchrnul (name, ':'); if (clname_end == name) /* Open NAME with store_open. */ return store_open (name + 1, flags, classes, store); - if (! clname_end) - clname_end = name + strlen (name); - - 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) + /* Try to find an existing class by the given name. */ + cl = store_find_class (name, clname_end, classes); + if (cl != 0) { - /* No class with the given name found. */ + if (! cl->open) + /* CL cannot be opened. */ + return EOPNOTSUPP; + if (*clname_end) - /* NAME really should be a class name, which doesn't exist. */ - return EINVAL; - else - /* Try opening NAME by querying it as a file instead. */ - return store_open (name, flags, classes, store); - } + /* Skip the ':' separating the class-name from the device name. */ + clname_end++; - if (! (*cl)->open) - /* CL cannot be opened. */ - return EOPNOTSUPP; + if (! *clname_end) + /* The class-specific portion of the name is empty, so make it *really* + empty. */ + clname_end = 0; - if (*clname_end) - /* Skip the ':' separating the class-name from the device name. */ - clname_end++; + return (*cl->open) (clname_end, flags, classes, store); + } - if (! *clname_end) - /* The class-specific portion of the name is empty, so make it *really* - empty. */ - clname_end = 0; + /* Try to open a store by loading a module to define the class, if we + have the module-loading support linked in. We don't just use + store_module_find_class, because store_module_open will unload the new + module if the open doesn't succeed and we have no other way to unload + it. We always leave modules loaded once a store from the module has + been successfully opened and so can leave unbounded numbers of old + modules loaded after closing all the stores using them. But at least + we can avoid having modules loaded for stores we never even opened. */ +# pragma weak store_module_open + if (store_module_open) + { + error_t err = store_module_open (name, flags, classes, store); + if (err != ENOENT) + return err; + } - return (*(*cl)->open) (clname_end, flags, classes, store); + /* No class with the given name found. */ + if (*clname_end) + /* NAME really should be a class name, which doesn't exist. */ + return EINVAL; + else + /* Try opening NAME by querying it as a file instead. */ + return store_open (name, flags, classes, store); } const struct store_class store_typed_open_class = { -1, "typed", open: store_typed_open }; +STORE_STD_CLASS (typed_open); |