From 899e93342a306bba89c0fe0579d707518678e1c4 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 14 Mar 2002 21:10:01 +0000 Subject: 2002-02-08 Roland McGrath * 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 * typed.c (store_find_class): New function. (store_typed_open): Use it. 2001-12-28 Roland McGrath * 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. --- libstore/typed.c | 148 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 116 insertions(+), 32 deletions(-) (limited to 'libstore') 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 This file is part of the GNU Hurd. @@ -21,6 +21,81 @@ #include "store.h" #include +#include +#include + + +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); -- cgit v1.2.3