* Applied a patch by Siarzhuk Zharski that allows open_module_list() to be

used during early boot. Thanks!
* Fixed open_module_list() so that it can deal with a NULL prefix.
* Added a note that get_next_loaded_module_name() is implemented incorrectly.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21315 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-06-03 22:55:09 +00:00
parent 564c60d830
commit 65c61fbf2d
+80 -42
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2006, Haiku Inc. All rights reserved. * Copyright 2002-2007, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001, Thomas Kurschel. All rights reserved. * Copyright 2001, Thomas Kurschel. All rights reserved.
@@ -130,6 +130,7 @@ typedef struct module_iterator {
uint32 path_base_length; uint32 path_base_length;
const char *current_module_path; const char *current_module_path;
bool builtin_modules; bool builtin_modules;
bool loaded_modules;
} module_iterator; } module_iterator;
@@ -693,31 +694,62 @@ iterator_push_path_on_stack(module_iterator *iterator, const char *path, uint32
static status_t static status_t
iterator_get_next_module(module_iterator *iterator, char *buffer, size_t *_bufferSize) iterator_get_next_module(module_iterator *iterator, char *buffer,
size_t *_bufferSize)
{ {
status_t status; status_t status;
TRACE(("iterator_get_next_module() -- start\n")); TRACE(("iterator_get_next_module() -- start\n"));
if (iterator->builtin_modules) { if (iterator->builtin_modules) {
int32 i; for (int32 i = iterator->module_offset; sBuiltInModules[i] != NULL; i++) {
for (i = iterator->module_offset; sBuiltInModules[i] != NULL; i++) {
// the module name must fit the prefix // the module name must fit the prefix
if (strncmp(sBuiltInModules[i]->name, iterator->prefix, iterator->prefix_length)) if (strncmp(sBuiltInModules[i]->name, iterator->prefix,
iterator->prefix_length))
continue; continue;
*_bufferSize = strlcpy(buffer, sBuiltInModules[i]->name, *_bufferSize); *_bufferSize = strlcpy(buffer, sBuiltInModules[i]->name,
*_bufferSize);
iterator->module_offset = i + 1; iterator->module_offset = i + 1;
return B_OK; return B_OK;
} }
iterator->builtin_modules = false; iterator->builtin_modules = false;
} }
if (iterator->loaded_modules) {
recursive_lock_lock(&sModulesLock);
hash_iterator hashIterator;
hash_open(sModulesHash, &hashIterator);
struct module *module = (struct module *)hash_next(sModulesHash,
&hashIterator);
for (int32 i = 0; module != NULL; i++) {
if (i >= iterator->module_offset) {
if (!strncmp(module->name, iterator->prefix,
iterator->prefix_length)) {
*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
iterator->module_offset = i + 1;
hash_close(sModulesHash, &hashIterator, false);
recursive_lock_unlock(&sModulesLock);
return B_OK;
}
}
module = (struct module *)hash_next(sModulesHash, &hashIterator);
}
hash_close(sModulesHash, &hashIterator, false);
recursive_lock_unlock(&sModulesLock);
// prevent from falling into modules hash iteration again
iterator->loaded_modules = false;
}
nextPath: nextPath:
if (iterator->current_dir == NULL) { if (iterator->current_dir == NULL) {
// get next directory path from the stack // get next directory path from the stack
const char *path = iterator_pop_path_from_stack(iterator, &iterator->path_base_length); const char *path = iterator_pop_path_from_stack(iterator,
&iterator->path_base_length);
if (path == NULL) { if (path == NULL) {
// we are finished, there are no more entries on the stack // we are finished, there are no more entries on the stack
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
@@ -755,7 +787,8 @@ nextModuleImage:
// check if the prefix matches // check if the prefix matches
int32 passedOffset, commonLength; int32 passedOffset, commonLength;
passedOffset = strlen(iterator->current_path) + 1; passedOffset = strlen(iterator->current_path) + 1;
commonLength = iterator->path_base_length + iterator->prefix_length - passedOffset; commonLength = iterator->path_base_length + iterator->prefix_length
- passedOffset;
if (commonLength > 0) { if (commonLength > 0) {
// the prefix still reaches into the new path part // the prefix still reaches into the new path part
@@ -763,8 +796,8 @@ nextModuleImage:
if (commonLength > length) if (commonLength > length)
commonLength = length; commonLength = length;
if (strncmp(dirent->d_name, if (strncmp(dirent->d_name, iterator->prefix + passedOffset
iterator->prefix + passedOffset - iterator->path_base_length, commonLength)) - iterator->path_base_length, commonLength))
goto nextModuleImage; goto nextModuleImage;
} }
@@ -791,8 +824,8 @@ nextModuleImage:
return B_NO_MEMORY; return B_NO_MEMORY;
if (S_ISDIR(st.st_mode)) { 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->path_base_length); iterator->current_module_path, iterator->path_base_length);
if (status < B_OK) if (status < B_OK)
return status; return status;
@@ -1058,12 +1091,6 @@ module_init(kernel_args *args)
* contain all modules available under the prefix. * contain all modules available under the prefix.
* The structure is then used by read_next_module_name(), and * The structure is then used by read_next_module_name(), and
* must be freed by calling close_module_list(). * must be freed by calling close_module_list().
*
* During early boot, when there is no boot device accessible,
* it will only find built-in modules, not those that have
* been preloaded - use get_next_loaded_module_name() instead
* if you need to have a list of loaded modules.
* ToDo: this could be changed
*/ */
void * void *
@@ -1085,36 +1112,45 @@ open_module_list(const char *prefix)
memset(iterator, 0, sizeof(module_iterator)); memset(iterator, 0, sizeof(module_iterator));
// ToDo: possibly, the prefix don't have to be copied, just referenced iterator->prefix = strdup(prefix != NULL ? prefix : "");
iterator->prefix = strdup(prefix ? prefix : "");
if (iterator->prefix == NULL) { if (iterator->prefix == NULL) {
free(iterator); free(iterator);
return NULL; return NULL;
} }
iterator->prefix_length = strlen(prefix); iterator->prefix_length = strlen(iterator->prefix);
// first, we'll traverse over the built-in modules if (gBootDevice > 0) {
iterator->builtin_modules = true; // We do have a boot device to scan
// put all search paths on the stack // first, we'll traverse over the built-in modules
for (i = 0; i < NUM_MODULE_PATHS; i++) { iterator->builtin_modules = true;
if (sDisableUserAddOns && i >= FIRST_USER_MODULE_PATH) iterator->loaded_modules = false;
break;
// Build path component: base path + '/' + prefix // put all search paths on the stack
size_t length = strlen(sModulePaths[i]); for (i = 0; i < NUM_MODULE_PATHS; i++) {
char *path = (char *)malloc(length + iterator->prefix_length + 2); if (sDisableUserAddOns && i >= FIRST_USER_MODULE_PATH)
if (path == NULL) { break;
// ToDo: should we abort the whole operation here?
// if we do, don't forget to empty the stack // Build path component: base path + '/' + prefix
continue; size_t length = strlen(sModulePaths[i]);
char *path = (char *)malloc(length + iterator->prefix_length + 2);
if (path == NULL) {
// ToDo: should we abort the whole operation here?
// if we do, don't forget to empty the stack
continue;
}
memcpy(path, sModulePaths[i], length);
path[length] = '/';
memcpy(path + length + 1, iterator->prefix,
iterator->prefix_length + 1);
iterator_push_path_on_stack(iterator, path, length + 1);
} }
} else {
memcpy(path, sModulePaths[i], length); // include loaded modules in case there is no boot device yet
path[length] = '/'; iterator->builtin_modules = false;
memcpy(path + length + 1, prefix, iterator->prefix_length + 1); iterator->loaded_modules = true;
iterator_push_path_on_stack(iterator, path, length + 1);
} }
return (void *)iterator; return (void *)iterator;
@@ -1158,7 +1194,7 @@ close_module_list(void *cookie)
/** Return the next module name from the available list, using /** Return the next module name from the available list, using
* a structure previously created by a call to open_module_list. * a structure previously created by a call to open_module_list().
* Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND * Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND
* when done. * when done.
*/ */
@@ -1221,6 +1257,8 @@ get_next_loaded_module_name(uint32 *_cookie, char *buffer, size_t *_bufferSize)
} }
recursive_lock_lock(&sModulesLock); recursive_lock_lock(&sModulesLock);
// TODO: this is completely unsafe!!!
struct module *module = (struct module *)hash_next(sModulesHash, iterator); struct module *module = (struct module *)hash_next(sModulesHash, iterator);
if (module != NULL) { if (module != NULL) {