From 17928296853b671405be292ddaa3b04438b3f9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 10 May 2004 00:02:20 +0000 Subject: [PATCH] Fixed prefix handling; previous version was broken. It now allows the prefix to be any size, not just full path names (even without the file name...). Optimized it to only traverse paths that match the prefix. The built-in modules now honor the prefix as well. Renamed module_iterator::path_stack to stack. The system add-on path was even wrong (but that didn't matter yet, as we're still do a recursive search for modules). The user add-on path now matches the real one - but that should probably be retrieved from calling find_directory(), anyway... git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7483 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/core/module.c | 141 ++++++++++++++++++++++++--------------- 1 file changed, 87 insertions(+), 54 deletions(-) diff --git a/src/kernel/core/module.c b/src/kernel/core/module.c index fd129cc1f0..92ef7fb102 100644 --- a/src/kernel/core/module.c +++ b/src/kernel/core/module.c @@ -86,12 +86,18 @@ typedef struct module { #define B_BUILT_IN_MODULE 2 +typedef struct module_path { + const char *name; + uint32 base_length; +} module_path; + typedef struct module_iterator { - const char **path_stack; + module_path *stack; int32 stack_size; int32 stack_current; char *prefix; + size_t prefix_length; DIR *current_dir; status_t status; int32 module_offset; @@ -100,6 +106,7 @@ typedef struct module_iterator { module_image *module_image; module_info **current_header; const char *current_path; + int32 path_base_length; const char *current_module_path; bool builtin_modules; } module_iterator; @@ -118,8 +125,8 @@ static recursive_lock gModulesLock; * ToDo: these are not yet BeOS compatible (because the current bootfs is very limited) */ static const char * const gModulePaths[] = { - "/boot/addons", - "/boot/user-addons", + "/boot/addons/kernel", + "/boot/home/config/add-ons/kernel", }; #define NUM_MODULE_PATHS (sizeof(gModulePaths) / sizeof(gModulePaths[0])) @@ -710,34 +717,34 @@ uninit_module(module *module) static const char * -iterator_pop_path_from_stack(module_iterator *iterator) +iterator_pop_path_from_stack(module_iterator *iterator, uint32 *_baseLength) { - if (iterator->stack_current > 0) - return iterator->path_stack[--iterator->stack_current]; + if (iterator->stack_current <= 0) + return NULL; - return NULL; + if (_baseLength) + *_baseLength = iterator->stack[iterator->stack_current - 1].base_length; + + return iterator->stack[--iterator->stack_current].name; } static status_t -iterator_push_path_on_stack(module_iterator *iterator, const char *path) +iterator_push_path_on_stack(module_iterator *iterator, const char *path, uint32 baseLength) { if (iterator->stack_current + 1 > iterator->stack_size) { // allocate new space on the stack - const char **stack = (const char **)malloc((iterator->stack_size + 8) * sizeof(char *)); + module_path *stack = (module_path *)realloc(iterator->stack, + (iterator->stack_size + 8) * sizeof(module_path)); if (stack == NULL) return B_NO_MEMORY; - - if (iterator->path_stack != NULL) { - memcpy(stack, iterator->path_stack, iterator->stack_current * sizeof(char *)); - free(iterator->path_stack); - } - - iterator->path_stack = stack; + + iterator->stack = stack; iterator->stack_size += 8; } - - iterator->path_stack[iterator->stack_current++] = path; + + iterator->stack[iterator->stack_current].name = path; + iterator->stack[iterator->stack_current++].base_length = baseLength; return B_OK; } @@ -750,18 +757,24 @@ iterator_get_next_module(module_iterator *iterator, char *buffer, size_t *_buffe TRACE(("iterator_get_next_module() -- start\n")); if (iterator->builtin_modules) { - if (sBuiltInModules[iterator->module_offset] != NULL) { - *_bufferSize = strlcpy(buffer, - sBuiltInModules[iterator->module_offset++]->name, *_bufferSize); + int32 i; + + for (i = iterator->module_offset; sBuiltInModules[i] != NULL; i++) { + // the module name must fit the prefix + if (strncmp(sBuiltInModules[i]->name, iterator->prefix, iterator->prefix_length)) + continue; + + *_bufferSize = strlcpy(buffer, sBuiltInModules[i]->name, *_bufferSize); + iterator->module_offset = i + 1; return B_OK; - } else - iterator->builtin_modules = false; + } + iterator->builtin_modules = false; } -nextDirectory: +nextPath: if (iterator->current_dir == NULL) { // get next directory path from the stack - const char *path = iterator_pop_path_from_stack(iterator); + const char *path = iterator_pop_path_from_stack(iterator, &iterator->path_base_length); if (path == NULL) { // we are finished, there are no more entries on the stack return B_ENTRY_NOT_FOUND; @@ -775,16 +788,17 @@ nextDirectory: if (iterator->current_dir == NULL) { // we don't throw an error here, but silently go to // the next directory on the stack - goto nextDirectory; + goto nextPath; } } nextModuleImage: if (iterator->current_header == NULL) { // get next entry from the current directory - char path[SYS_MAX_PATH_LEN]; + char path[B_PATH_NAME_LENGTH]; struct dirent *dirent; struct stat st; + int32 passedOffset, commonLength; errno = 0; @@ -795,9 +809,25 @@ nextModuleImage: if (errno < B_OK) return errno; - goto nextDirectory; + goto nextPath; } + // check if the prefix matches + passedOffset = strlen(iterator->current_path) + 1; + commonLength = iterator->path_base_length + iterator->prefix_length - passedOffset; + + if (commonLength > 0) { + // the prefix still reaches into the new path part + int32 length = strlen(dirent->d_name); + if (commonLength > length) + commonLength = length; + + if (strncmp(dirent->d_name, + iterator->prefix + passedOffset - iterator->path_base_length, commonLength)) + goto nextModuleImage; + } + + // we're not interested in traversing these again if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) goto nextModuleImage; @@ -816,7 +846,8 @@ nextModuleImage: return B_NO_MEMORY; if (S_ISDIR(st.st_mode)) { - status = iterator_push_path_on_stack(iterator, iterator->current_module_path); + status = iterator_push_path_on_stack(iterator, iterator->current_module_path, + iterator->path_base_length); if (status < B_OK) return status; @@ -840,25 +871,32 @@ nextModuleImage: iterator->module_offset = 0; } - if (*iterator->current_header == NULL) { - iterator->current_header = NULL; - free((void *)iterator->current_module_path); - iterator->current_module_path = NULL; + // search the current module image until we've got a match + while (*iterator->current_header != NULL) { + module_info *info = *iterator->current_header; - put_module_image(iterator->module_image); - iterator->module_image = NULL; + // ToDo: we might want to create a module here and cache it in the hash table - goto nextModuleImage; + iterator->current_header++; + iterator->module_offset++; + + if (strncmp(info->name, iterator->prefix, iterator->prefix_length)) + continue; + + *_bufferSize = strlcpy(buffer, info->name, *_bufferSize); + return B_OK; } - // ToDo: we might want to create a module here and cache it in the hash table + // leave this module and get the next one - *_bufferSize = strlcpy(buffer, (*iterator->current_header)->name, *_bufferSize); + iterator->current_header = NULL; + free((void *)iterator->current_module_path); + iterator->current_module_path = NULL; - iterator->current_header++; - iterator->module_offset++; + put_module_image(iterator->module_image); + iterator->module_image = NULL; - return B_OK; + goto nextModuleImage; } @@ -955,7 +993,6 @@ module_init(kernel_args *args) void * open_module_list(const char *prefix) { - char path[SYS_MAX_PATH_LEN]; module_iterator *iterator; uint32 i; @@ -973,29 +1010,25 @@ open_module_list(const char *prefix) free(iterator); return NULL; } + iterator->prefix_length = strlen(prefix); // first, we'll traverse over the built-in modules iterator->builtin_modules = true; // put all search paths on the stack for (i = 0; i < NUM_MODULE_PATHS; i++) { - const char *p; + const char *path; if (modules_disable_user_addons && i >= USER_MODULE_PATHS) break; - strcpy(path, gModulePaths[i]); - if (prefix && *prefix) { - strcat(path, "/"); - strlcat(path, prefix, sizeof(path)); - } - - p = strdup(path); - if (p == NULL) { + path = strdup(gModulePaths[i]); + if (path == NULL) { // ToDo: should we abort the whole operation here? + // if we do, don't forget to empty the stack continue; } - iterator_push_path_on_stack(iterator, p); + iterator_push_path_on_stack(iterator, path, strlen(path) + 1); } return (void *)iterator; @@ -1017,7 +1050,7 @@ close_module_list(void *cookie) return B_BAD_VALUE; // free stack - while ((path = iterator_pop_path_from_stack(iterator)) != NULL) + while ((path = iterator_pop_path_from_stack(iterator, NULL)) != NULL) free((void *)path); // close what have been left open @@ -1027,7 +1060,7 @@ close_module_list(void *cookie) if (iterator->current_dir != NULL) closedir(iterator->current_dir); - free(iterator->path_stack); + free(iterator->stack); free((void *)iterator->current_path); free((void *)iterator->current_module_path);