xref: /haiku/src/system/kernel/module.cpp (revision adb0d19d561947362090081e81d90dde59142026)
1 /*
2  * Copyright 2002-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001, Thomas Kurschel. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 /*!	Manages kernel add-ons and their exported modules. */
10 
11 
12 #include <kmodule.h>
13 
14 #include <errno.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 
19 #include <FindDirectory.h>
20 #include <NodeMonitor.h>
21 
22 #include <dirent_private.h>
23 
24 #include <boot_device.h>
25 #include <boot/elf.h>
26 #include <elf.h>
27 #include <fs/KPath.h>
28 #include <fs/node_monitor.h>
29 #include <lock.h>
30 #include <Notifications.h>
31 #include <safemode.h>
32 #include <syscalls.h>
33 #include <util/AutoLock.h>
34 #include <util/khash.h>
35 #include <util/Stack.h>
36 #include <vfs.h>
37 
38 
39 //#define TRACE_MODULE
40 #ifdef TRACE_MODULE
41 #	define TRACE(x) dprintf x
42 #else
43 #	define TRACE(x) ;
44 #endif
45 #define FATAL(x) dprintf x
46 
47 
48 #define MODULE_HASH_SIZE 16
49 
50 /*! The modules referenced by this structure are built-in
51 	modules that can't be loaded from disk.
52 */
53 extern module_info gDeviceManagerModule;
54 extern module_info gDeviceRootModule;
55 extern module_info gDeviceGenericModule;
56 extern module_info gFrameBufferConsoleModule;
57 
58 // file systems
59 extern module_info gRootFileSystem;
60 extern module_info gDeviceFileSystem;
61 
62 static module_info* sBuiltInModules[] = {
63 	&gDeviceManagerModule,
64 	&gDeviceRootModule,
65 	&gDeviceGenericModule,
66 	&gFrameBufferConsoleModule,
67 
68 	&gRootFileSystem,
69 	&gDeviceFileSystem,
70 	NULL
71 };
72 
73 enum module_state {
74 	MODULE_QUERIED = 0,
75 	MODULE_LOADED,
76 	MODULE_INIT,
77 	MODULE_READY,
78 	MODULE_UNINIT,
79 	MODULE_ERROR
80 };
81 
82 
83 /* Each loaded module image (which can export several modules) is put
84  * in a hash (gModuleImagesHash) to be easily found when you search
85  * for a specific file name.
86  * TODO: Could use only the inode number for hashing. Would probably be
87  * a little bit slower, but would lower the memory foot print quite a lot.
88  */
89 
90 struct module_image {
91 	struct module_image* next;
92 	module_info**		info;		// the module_info we use
93 	module_dependency*	dependencies;
94 	char*				path;		// the full path for the module
95 	image_id			image;
96 	int32				ref_count;	// how many ref's to this file
97 };
98 
99 /* Each known module will have this structure which is put in the
100  * gModulesHash, and looked up by name.
101  */
102 
103 struct module {
104 	struct module*		next;
105 	::module_image*		module_image;
106 	char*				name;
107 	int32				ref_count;
108 	module_info*		info;		// will only be valid if ref_count > 0
109 	int32				offset;		// this is the offset in the headers
110 	module_state		state;
111 	uint32				flags;
112 };
113 
114 #define B_BUILT_IN_MODULE	2
115 
116 typedef struct module_path {
117 	const char*			name;
118 	uint32				base_length;
119 } module_path;
120 
121 typedef struct module_iterator {
122 	module_path*		stack;
123 	int32				stack_size;
124 	int32				stack_current;
125 
126 	char*				prefix;
127 	size_t				prefix_length;
128 	const char*			suffix;
129 	size_t				suffix_length;
130 	DIR*				current_dir;
131 	status_t			status;
132 	int32				module_offset;
133 		// This is used to keep track of which module_info
134 		// within a module we're addressing.
135 	::module_image*		module_image;
136 	module_info**		current_header;
137 	const char*			current_path;
138 	uint32				path_base_length;
139 	const char*			current_module_path;
140 	bool				builtin_modules;
141 	bool				loaded_modules;
142 } module_iterator;
143 
144 namespace Module {
145 
146 struct entry {
147 	dev_t				device;
148 	ino_t				node;
149 };
150 
151 struct hash_entry : entry {
152 	~hash_entry()
153 	{
154 		free((char*)path);
155 	}
156 
157 	HashTableLink<hash_entry> link;
158 	const char*			path;
159 };
160 
161 struct NodeHashDefinition {
162 	typedef entry* KeyType;
163 	typedef hash_entry ValueType;
164 
165 	size_t Hash(ValueType* entry) const
166 		{ return HashKey(entry); }
167 	HashTableLink<ValueType>* GetLink(ValueType* entry) const
168 		{ return &entry->link; }
169 
170 	size_t HashKey(KeyType key) const
171 	{
172 		return ((uint32)(key->node >> 32) + (uint32)key->node) ^ key->device;
173 	}
174 
175 	bool Compare(KeyType key, ValueType* entry) const
176 	{
177 		return key->device == entry->device
178 			&& key->node == entry->node;
179 	}
180 };
181 
182 typedef OpenHashTable<NodeHashDefinition> NodeHash;
183 
184 struct module_listener : DoublyLinkedListLinkImpl<module_listener> {
185 	~module_listener()
186 	{
187 		free((char*)prefix);
188 	}
189 
190 	NotificationListener* listener;
191 	const char*			prefix;
192 };
193 
194 typedef DoublyLinkedList<module_listener> ModuleListenerList;
195 
196 struct module_notification : DoublyLinkedListLinkImpl<module_notification> {
197 	~module_notification()
198 	{
199 		free((char*)name);
200 	}
201 
202 	int32		opcode;
203 	dev_t		device;
204 	ino_t		directory;
205 	ino_t		node;
206 	const char*	name;
207 };
208 
209 typedef DoublyLinkedList<module_notification> NotificationList;
210 
211 class DirectoryWatcher : public NotificationListener {
212 public:
213 						DirectoryWatcher();
214 	virtual				~DirectoryWatcher();
215 
216 	virtual void		EventOccured(NotificationService& service,
217 							const KMessage* event);
218 };
219 
220 class ModuleWatcher : public NotificationListener {
221 public:
222 						ModuleWatcher();
223 	virtual				~ModuleWatcher();
224 
225 	virtual void		EventOccured(NotificationService& service,
226 							const KMessage* event);
227 };
228 
229 class ModuleNotificationService : public NotificationService {
230 public:
231 						ModuleNotificationService();
232 	virtual				~ModuleNotificationService();
233 
234 			status_t	InitCheck();
235 
236 			status_t	AddListener(const KMessage* eventSpecifier,
237 							NotificationListener& listener);
238 			status_t	UpdateListener(const KMessage* eventSpecifier,
239 							NotificationListener& listener);
240 			status_t	RemoveListener(const KMessage* eventSpecifier,
241 							NotificationListener& listener);
242 
243 			bool		HasNode(dev_t device, ino_t node);
244 
245 			void		Notify(int32 opcode, dev_t device, ino_t directory,
246 							ino_t node, const char* name);
247 
248 	virtual const char*	Name() { return "modules"; }
249 
250 	static	void		HandleNotifications(void *data, int iteration);
251 
252 private:
253 			status_t	_RemoveNode(dev_t device, ino_t node);
254 			status_t	_AddNode(dev_t device, ino_t node, const char* path,
255 							uint32 flags, NotificationListener& listener);
256 			status_t	_AddDirectoryNode(dev_t device, ino_t node);
257 			status_t	_AddModuleNode(dev_t device, ino_t node, int fd,
258 							const char* name);
259 
260 			status_t	_AddDirectory(const char* prefix);
261 			status_t	_ScanDirectory(char* directoryPath, const char* prefix,
262 							size_t& prefixPosition);
263 			status_t	_ScanDirectory(Stack<DIR*>& stack, DIR* dir,
264 							const char* prefix, size_t prefixPosition);
265 
266 			void		_Notify(int32 opcode, dev_t device, ino_t directory,
267 							ino_t node, const char* name);
268 			void		_HandleNotifications();
269 
270 	recursive_lock		fLock;
271 	ModuleListenerList	fListeners;
272 	NodeHash			fNodes;
273 	DirectoryWatcher	fDirectoryWatcher;
274 	ModuleWatcher		fModuleWatcher;
275 	NotificationList	fNotifications;
276 };
277 
278 }	// namespace Module
279 
280 using namespace Module;
281 
282 /* These are the standard base paths where we start to look for modules
283  * to load. Order is important, the last entry here will be searched
284  * first.
285  */
286 static const directory_which kModulePaths[] = {
287 	B_BEOS_ADDONS_DIRECTORY,
288 	B_COMMON_ADDONS_DIRECTORY,
289 	B_USER_ADDONS_DIRECTORY,
290 };
291 
292 static const uint32 kNumModulePaths = sizeof(kModulePaths)
293 	/ sizeof(kModulePaths[0]);
294 static const uint32 kFirstNonSystemModulePath = 1;
295 
296 
297 static ModuleNotificationService sModuleNotificationService;
298 static bool sDisableUserAddOns = false;
299 
300 /*	Locking scheme: There is a global lock only; having several locks
301 	makes trouble if dependent modules get loaded concurrently ->
302 	they have to wait for each other, i.e. we need one lock per module;
303 	also we must detect circular references during init and not dead-lock.
304 
305 	Reference counting: get_module() increments the ref count of a module,
306 	put_module() decrements it. When a B_KEEP_LOADED module is initialized
307 	the ref count is incremented once more, so it never gets
308 	uninitialized/unloaded. A referenced module, unless it's built-in, has a
309 	non-null module_image and owns a reference to the image. When the last
310 	module reference is put, the image's reference is released and module_image
311 	zeroed (as long as the boot volume has not been mounted, it is not zeroed).
312 	An unreferenced module image is unloaded (when the boot volume is mounted).
313 */
314 static recursive_lock sModulesLock;
315 
316 /* We store the loaded modules by directory path, and all known modules
317  * by module name in a hash table for quick access
318  */
319 static hash_table* sModuleImagesHash;
320 static hash_table* sModulesHash;
321 
322 
323 /*!	Calculates hash for a module using its name */
324 static uint32
325 module_hash(void* _module, const void* _key, uint32 range)
326 {
327 	module* module = (struct module*)_module;
328 	const char* name = (const char*)_key;
329 
330 	if (module != NULL)
331 		return hash_hash_string(module->name) % range;
332 
333 	if (name != NULL)
334 		return hash_hash_string(name) % range;
335 
336 	return 0;
337 }
338 
339 
340 /*!	Compares a module to a given name */
341 static int
342 module_compare(void* _module, const void* _key)
343 {
344 	module* module = (struct module*)_module;
345 	const char* name = (const char*)_key;
346 	if (name == NULL)
347 		return -1;
348 
349 	return strcmp(module->name, name);
350 }
351 
352 
353 /*!	Calculates the hash of a module image using its path */
354 static uint32
355 module_image_hash(void* _module, const void* _key, uint32 range)
356 {
357 	module_image* image = (module_image*)_module;
358 	const char* path = (const char*)_key;
359 
360 	if (image != NULL)
361 		return hash_hash_string(image->path) % range;
362 
363 	if (path != NULL)
364 		return hash_hash_string(path) % range;
365 
366 	return 0;
367 }
368 
369 
370 /*!	Compares a module image to a path */
371 static int
372 module_image_compare(void* _module, const void* _key)
373 {
374 	module_image* image = (module_image*)_module;
375 	const char* path = (const char*)_key;
376 	if (path == NULL)
377 		return -1;
378 
379 	return strcmp(image->path, path);
380 }
381 
382 
383 /*!	Try to load the module image at the specified \a path.
384 	If it could be loaded, it returns \c B_OK, and stores a pointer
385 	to the module_image object in \a _moduleImage.
386 	Needs to be called with the sModulesLock held.
387 */
388 static status_t
389 load_module_image(const char* path, module_image** _moduleImage)
390 {
391 	module_image* moduleImage;
392 	status_t status;
393 	image_id image;
394 
395 	TRACE(("load_module_image(path = \"%s\", _image = %p)\n", path,
396 		_moduleImage));
397 	ASSERT_LOCKED_RECURSIVE(&sModulesLock);
398 	ASSERT(_moduleImage != NULL);
399 
400 	image = load_kernel_add_on(path);
401 	if (image < 0) {
402 		dprintf("load_module_image(%s) failed: %s\n", path, strerror(image));
403 		return image;
404 	}
405 
406 	moduleImage = (module_image*)malloc(sizeof(module_image));
407 	if (moduleImage == NULL) {
408 		status = B_NO_MEMORY;
409 		goto err;
410 	}
411 
412 	if (get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
413 			(void**)&moduleImage->info) != B_OK) {
414 		TRACE(("load_module_image: Failed to load \"%s\" due to lack of "
415 			"'modules' symbol\n", path));
416 		status = B_BAD_TYPE;
417 		goto err1;
418 	}
419 
420 	moduleImage->dependencies = NULL;
421 	get_image_symbol(image, "module_dependencies", B_SYMBOL_TYPE_DATA,
422 		(void**)&moduleImage->dependencies);
423 		// this is allowed to be NULL
424 
425 	moduleImage->path = strdup(path);
426 	if (!moduleImage->path) {
427 		status = B_NO_MEMORY;
428 		goto err1;
429 	}
430 
431 	moduleImage->image = image;
432 	moduleImage->ref_count = 0;
433 
434 	hash_insert(sModuleImagesHash, moduleImage);
435 
436 	TRACE(("load_module_image(\"%s\"): image loaded: %p\n", path, moduleImage));
437 
438 	*_moduleImage = moduleImage;
439 	return B_OK;
440 
441 err1:
442 	free(moduleImage);
443 err:
444 	unload_kernel_add_on(image);
445 
446 	return status;
447 }
448 
449 
450 /*!	Unloads the module's kernel add-on. The \a image will be freed.
451 	Needs to be called with the sModulesLock held.
452 */
453 static status_t
454 unload_module_image(module_image* moduleImage, bool remove)
455 {
456 	TRACE(("unload_module_image(image %p, remove %d)\n", moduleImage, remove));
457 	ASSERT_LOCKED_RECURSIVE(&sModulesLock);
458 
459 	if (moduleImage->ref_count != 0) {
460 		FATAL(("Can't unload %s due to ref_cnt = %ld\n", moduleImage->path,
461 			moduleImage->ref_count));
462 		return B_ERROR;
463 	}
464 
465 	if (remove)
466 		hash_remove(sModuleImagesHash, moduleImage);
467 
468 	unload_kernel_add_on(moduleImage->image);
469 	free(moduleImage->path);
470 	free(moduleImage);
471 
472 	return B_OK;
473 }
474 
475 
476 static void
477 put_module_image(module_image* image)
478 {
479 	RecursiveLocker locker(sModulesLock);
480 
481 	int32 refCount = atomic_add(&image->ref_count, -1);
482 	ASSERT(refCount > 0);
483 
484 	// Don't unload anything when there is no boot device yet
485 	// (because chances are that we will never be able to access it again)
486 
487 	if (refCount == 1 && gBootDevice > 0)
488 		unload_module_image(image, true);
489 }
490 
491 
492 static status_t
493 get_module_image(const char* path, module_image** _image)
494 {
495 	struct module_image* image;
496 
497 	TRACE(("get_module_image(path = \"%s\")\n", path));
498 
499 	RecursiveLocker _(sModulesLock);
500 
501 	image = (module_image*)hash_lookup(sModuleImagesHash, path);
502 	if (image == NULL) {
503 		status_t status = load_module_image(path, &image);
504 		if (status < B_OK)
505 			return status;
506 	}
507 
508 	atomic_add(&image->ref_count, 1);
509 	*_image = image;
510 
511 	return B_OK;
512 }
513 
514 
515 /*!	Extract the information from the module_info structure pointed at
516 	by "info" and create the entries required for access to it's details.
517 */
518 static status_t
519 create_module(module_info* info, int offset, module** _module)
520 {
521 	module* module;
522 
523 	TRACE(("create_module(info = %p, offset = %d, _module = %p)\n",
524 		info, offset, _module));
525 
526 	if (!info->name)
527 		return B_BAD_VALUE;
528 
529 	module = (struct module*)hash_lookup(sModulesHash, info->name);
530 	if (module) {
531 		FATAL(("Duplicate module name (%s) detected... ignoring new one\n",
532 			info->name));
533 		return B_FILE_EXISTS;
534 	}
535 
536 	if ((module = (struct module*)malloc(sizeof(struct module))) == NULL)
537 		return B_NO_MEMORY;
538 
539 	TRACE(("create_module: name = \"%s\"\n", info->name));
540 
541 	module->module_image = NULL;
542 	module->name = strdup(info->name);
543 	if (module->name == NULL) {
544 		free(module);
545 		return B_NO_MEMORY;
546 	}
547 
548 	module->state = MODULE_QUERIED;
549 	module->info = info;
550 	module->offset = offset;
551 		// record where the module_info can be found in the module_info array
552 	module->ref_count = 0;
553 	module->flags = info->flags;
554 
555 	recursive_lock_lock(&sModulesLock);
556 	hash_insert(sModulesHash, module);
557 	recursive_lock_unlock(&sModulesLock);
558 
559 	if (_module)
560 		*_module = module;
561 
562 	return B_OK;
563 }
564 
565 
566 /*!	Loads the file at \a path and scans all modules contained therein.
567 	Returns \c B_OK if \a searchedName could be found under those modules,
568 	and will return the referenced image in \a _moduleImage.
569 	Returns \c B_ENTRY_NOT_FOUND if the module could not be found.
570 
571 	Must only be called for files that haven't been scanned yet.
572 	\a searchedName is allowed to be \c NULL (if all modules should be scanned)
573 */
574 static status_t
575 check_module_image(const char* path, const char* searchedName,
576 	module_image** _moduleImage)
577 {
578 	status_t status = B_ENTRY_NOT_FOUND;
579 	module_image* image;
580 	module_info** info;
581 	int index = 0;
582 
583 	TRACE(("check_module_image(path = \"%s\", searchedName = \"%s\")\n", path,
584 		searchedName));
585 
586 	if (get_module_image(path, &image) < B_OK)
587 		return B_ENTRY_NOT_FOUND;
588 
589 	for (info = image->info; *info; info++) {
590 		// try to create a module for every module_info, check if the
591 		// name matches if it was a new entry
592 		bool freshModule = false;
593 		struct module* module = (struct module*)hash_lookup(sModulesHash,
594 			(*info)->name);
595 		if (module != NULL) {
596 			// Module does already exist
597 			if (module->module_image == NULL && module->ref_count == 0) {
598 				module->info = *info;
599 				module->offset = index;
600 				module->flags = (*info)->flags;
601 				module->state = MODULE_QUERIED;
602 				freshModule = true;
603 			}
604 		} else if (create_module(*info, index, NULL) == B_OK)
605 			freshModule = true;
606 
607 		if (freshModule && searchedName != NULL
608 			&& strcmp((*info)->name, searchedName) == 0) {
609 			status = B_OK;
610 		}
611 
612 		index++;
613 	}
614 
615 	if (status != B_OK) {
616 		// decrement the ref we got in get_module_image
617 		put_module_image(image);
618 		return status;
619 	}
620 
621 	*_moduleImage = image;
622 	return B_OK;
623 }
624 
625 
626 static module*
627 search_module(const char* name, module_image** _moduleImage)
628 {
629 	status_t status = B_ENTRY_NOT_FOUND;
630 	uint32 i;
631 
632 	TRACE(("search_module(%s)\n", name));
633 
634 	for (i = kNumModulePaths; i-- > 0;) {
635 		if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
636 			continue;
637 
638 		// let the VFS find that module for us
639 
640 		KPath basePath;
641 		if (find_directory(kModulePaths[i], gBootDevice, true,
642 				basePath.LockBuffer(), basePath.BufferSize()) != B_OK)
643 			continue;
644 
645 		basePath.UnlockBuffer();
646 		basePath.Append("kernel");
647 
648 		KPath path;
649 		status = vfs_get_module_path(basePath.Path(), name, path.LockBuffer(),
650 			path.BufferSize());
651 		if (status == B_OK) {
652 			path.UnlockBuffer();
653 			status = check_module_image(path.Path(), name, _moduleImage);
654 			if (status == B_OK)
655 				break;
656 		}
657 	}
658 
659 	if (status != B_OK)
660 		return NULL;
661 
662 	return (module*)hash_lookup(sModulesHash, name);
663 }
664 
665 
666 static status_t
667 put_dependent_modules(struct module* module)
668 {
669 	module_image* image = module->module_image;
670 	module_dependency* dependencies;
671 
672 	// built-in modules don't have a module_image structure
673 	if (image == NULL
674 		|| (dependencies = image->dependencies) == NULL)
675 		return B_OK;
676 
677 	for (int32 i = 0; dependencies[i].name != NULL; i++) {
678 		status_t status = put_module(dependencies[i].name);
679 		if (status < B_OK)
680 			return status;
681 	}
682 
683 	return B_OK;
684 }
685 
686 
687 static status_t
688 get_dependent_modules(struct module* module)
689 {
690 	module_image* image = module->module_image;
691 	module_dependency* dependencies;
692 
693 	// built-in modules don't have a module_image structure
694 	if (image == NULL
695 		|| (dependencies = image->dependencies) == NULL)
696 		return B_OK;
697 
698 	TRACE(("resolving module dependencies...\n"));
699 
700 	for (int32 i = 0; dependencies[i].name != NULL; i++) {
701 		status_t status = get_module(dependencies[i].name,
702 			dependencies[i].info);
703 		if (status < B_OK) {
704 			dprintf("loading dependent module %s of %s failed!\n",
705 				dependencies[i].name, module->name);
706 			return status;
707 		}
708 	}
709 
710 	return B_OK;
711 }
712 
713 
714 /*!	Initializes a loaded module depending on its state */
715 static inline status_t
716 init_module(module* module)
717 {
718 	switch (module->state) {
719 		case MODULE_QUERIED:
720 		case MODULE_LOADED:
721 		{
722 			status_t status;
723 			module->state = MODULE_INIT;
724 
725 			// resolve dependencies
726 
727 			status = get_dependent_modules(module);
728 			if (status < B_OK) {
729 				module->state = MODULE_LOADED;
730 				return status;
731 			}
732 
733 			// init module
734 
735 			TRACE(("initializing module %s (at %p)... \n", module->name,
736 				module->info->std_ops));
737 
738 			if (module->info->std_ops != NULL)
739 				status = module->info->std_ops(B_MODULE_INIT);
740 
741 			TRACE(("...done (%s)\n", strerror(status)));
742 
743 			if (status >= B_OK)
744 				module->state = MODULE_READY;
745 			else {
746 				put_dependent_modules(module);
747 				module->state = MODULE_LOADED;
748 			}
749 
750 			return status;
751 		}
752 
753 		case MODULE_READY:
754 			return B_OK;
755 
756 		case MODULE_INIT:
757 			FATAL(("circular reference to %s\n", module->name));
758 			return B_ERROR;
759 
760 		case MODULE_UNINIT:
761 			FATAL(("tried to load module %s which is currently unloading\n",
762 				module->name));
763 			return B_ERROR;
764 
765 		case MODULE_ERROR:
766 			FATAL(("cannot load module %s because its earlier unloading "
767 				"failed\n", module->name));
768 			return B_ERROR;
769 
770 		default:
771 			return B_ERROR;
772 	}
773 	// never trespasses here
774 }
775 
776 
777 /*!	Uninitializes a module depeding on its state */
778 static inline int
779 uninit_module(module* module)
780 {
781 	TRACE(("uninit_module(%s)\n", module->name));
782 
783 	switch (module->state) {
784 		case MODULE_QUERIED:
785 		case MODULE_LOADED:
786 			return B_NO_ERROR;
787 
788 		case MODULE_INIT:
789 			panic("Trying to unload module %s which is initializing\n",
790 				module->name);
791 			return B_ERROR;
792 
793 		case MODULE_UNINIT:
794 			panic("Trying to unload module %s which is un-initializing\n",
795 				module->name);
796 			return B_ERROR;
797 
798 		case MODULE_READY:
799 		{
800 			status_t status = B_OK;
801 			module->state = MODULE_UNINIT;
802 
803 			TRACE(("uninitializing module %s...\n", module->name));
804 
805 			if (module->info->std_ops != NULL)
806 				status = module->info->std_ops(B_MODULE_UNINIT);
807 
808 			TRACE(("...done (%s)\n", strerror(status)));
809 
810 			if (status == B_OK) {
811 				module->state = MODULE_LOADED;
812 				put_dependent_modules(module);
813 				return B_OK;
814 			}
815 
816 			FATAL(("Error unloading module %s (%s)\n", module->name,
817 				strerror(status)));
818 
819 			module->state = MODULE_ERROR;
820 			module->flags |= B_KEEP_LOADED;
821 			module->ref_count++;
822 
823 			return status;
824 		}
825 		default:
826 			return B_ERROR;
827 	}
828 	// never trespasses here
829 }
830 
831 
832 static const char*
833 iterator_pop_path_from_stack(module_iterator* iterator, uint32* _baseLength)
834 {
835 	if (iterator->stack_current <= 0)
836 		return NULL;
837 
838 	if (_baseLength)
839 		*_baseLength = iterator->stack[iterator->stack_current - 1].base_length;
840 
841 	return iterator->stack[--iterator->stack_current].name;
842 }
843 
844 
845 static status_t
846 iterator_push_path_on_stack(module_iterator* iterator, const char* path,
847 	uint32 baseLength)
848 {
849 	if (iterator->stack_current + 1 > iterator->stack_size) {
850 		// allocate new space on the stack
851 		module_path* stack = (module_path*)realloc(iterator->stack,
852 			(iterator->stack_size + 8) * sizeof(module_path));
853 		if (stack == NULL)
854 			return B_NO_MEMORY;
855 
856 		iterator->stack = stack;
857 		iterator->stack_size += 8;
858 	}
859 
860 	iterator->stack[iterator->stack_current].name = path;
861 	iterator->stack[iterator->stack_current++].base_length = baseLength;
862 	return B_OK;
863 }
864 
865 
866 static bool
867 match_iterator_suffix(module_iterator* iterator, const char* name)
868 {
869 	if (iterator->suffix == NULL || iterator->suffix_length == 0)
870 		return true;
871 
872 	size_t length = strlen(name);
873 	if (length <= iterator->suffix_length)
874 		return false;
875 
876 	return name[length - iterator->suffix_length - 1] == '/'
877 		&& !strcmp(name + length - iterator->suffix_length, iterator->suffix);
878 }
879 
880 
881 static status_t
882 iterator_get_next_module(module_iterator* iterator, char* buffer,
883 	size_t* _bufferSize)
884 {
885 	status_t status;
886 
887 	TRACE(("iterator_get_next_module() -- start\n"));
888 
889 	if (iterator->builtin_modules) {
890 		for (int32 i = iterator->module_offset; sBuiltInModules[i] != NULL;
891 				i++) {
892 			// the module name must fit the prefix
893 			if (strncmp(sBuiltInModules[i]->name, iterator->prefix,
894 					iterator->prefix_length)
895 				|| !match_iterator_suffix(iterator, sBuiltInModules[i]->name))
896 				continue;
897 
898 			*_bufferSize = strlcpy(buffer, sBuiltInModules[i]->name,
899 				*_bufferSize);
900 			iterator->module_offset = i + 1;
901 			return B_OK;
902 		}
903 		iterator->builtin_modules = false;
904 	}
905 
906 	if (iterator->loaded_modules) {
907 		recursive_lock_lock(&sModulesLock);
908 		hash_iterator hashIterator;
909 		hash_open(sModulesHash, &hashIterator);
910 
911 		struct module* module = (struct module*)hash_next(sModulesHash,
912 			&hashIterator);
913 		for (int32 i = 0; module != NULL; i++) {
914 			if (i >= iterator->module_offset) {
915 				if (!strncmp(module->name, iterator->prefix,
916 						iterator->prefix_length)
917 					&& match_iterator_suffix(iterator, module->name)) {
918 					*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
919 					iterator->module_offset = i + 1;
920 
921 					hash_close(sModulesHash, &hashIterator, false);
922 					recursive_lock_unlock(&sModulesLock);
923 					return B_OK;
924 				}
925 			}
926 			module = (struct module*)hash_next(sModulesHash, &hashIterator);
927 		}
928 
929 		hash_close(sModulesHash, &hashIterator, false);
930 		recursive_lock_unlock(&sModulesLock);
931 
932 		// prevent from falling into modules hash iteration again
933 		iterator->loaded_modules = false;
934 	}
935 
936 nextPath:
937 	if (iterator->current_dir == NULL) {
938 		// get next directory path from the stack
939 		const char* path = iterator_pop_path_from_stack(iterator,
940 			&iterator->path_base_length);
941 		if (path == NULL) {
942 			// we are finished, there are no more entries on the stack
943 			return B_ENTRY_NOT_FOUND;
944 		}
945 
946 		free((char*)iterator->current_path);
947 		iterator->current_path = path;
948 		iterator->current_dir = opendir(path);
949 		TRACE(("open directory at %s -> %p\n", path, iterator->current_dir));
950 
951 		if (iterator->current_dir == NULL) {
952 			// we don't throw an error here, but silently go to
953 			// the next directory on the stack
954 			goto nextPath;
955 		}
956 	}
957 
958 nextModuleImage:
959 	if (iterator->current_header == NULL) {
960 		// get next entry from the current directory
961 
962 		errno = 0;
963 
964 		struct dirent* dirent;
965 		if ((dirent = readdir(iterator->current_dir)) == NULL) {
966 			closedir(iterator->current_dir);
967 			iterator->current_dir = NULL;
968 
969 			if (errno < B_OK)
970 				return errno;
971 
972 			goto nextPath;
973 		}
974 
975 		// check if the prefix matches
976 		int32 passedOffset, commonLength;
977 		passedOffset = strlen(iterator->current_path) + 1;
978 		commonLength = iterator->path_base_length + iterator->prefix_length
979 			- passedOffset;
980 
981 		if (commonLength > 0) {
982 			// the prefix still reaches into the new path part
983 			int32 length = strlen(dirent->d_name);
984 			if (commonLength > length)
985 				commonLength = length;
986 
987 			if (strncmp(dirent->d_name, iterator->prefix + passedOffset
988 					- iterator->path_base_length, commonLength))
989 				goto nextModuleImage;
990 		}
991 
992 		// we're not interested in traversing these again
993 		if (!strcmp(dirent->d_name, ".")
994 			|| !strcmp(dirent->d_name, ".."))
995 			goto nextModuleImage;
996 
997 		// build absolute path to current file
998 		KPath path(iterator->current_path);
999 		if (path.InitCheck() != B_OK)
1000 			return B_NO_MEMORY;
1001 
1002 		if (path.Append(dirent->d_name) != B_OK)
1003 			return B_BUFFER_OVERFLOW;
1004 
1005 		// find out if it's a directory or a file
1006 		struct stat stat;
1007 		if (::stat(path.Path(), &stat) < 0)
1008 			return errno;
1009 
1010 		iterator->current_module_path = strdup(path.Path());
1011 		if (iterator->current_module_path == NULL)
1012 			return B_NO_MEMORY;
1013 
1014 		if (S_ISDIR(stat.st_mode)) {
1015 			status = iterator_push_path_on_stack(iterator,
1016 				iterator->current_module_path, iterator->path_base_length);
1017 			if (status < B_OK)
1018 				return status;
1019 
1020 			iterator->current_module_path = NULL;
1021 			goto nextModuleImage;
1022 		}
1023 
1024 		if (!S_ISREG(stat.st_mode))
1025 			return B_BAD_TYPE;
1026 
1027 		TRACE(("open module at %s\n", path.Path()));
1028 
1029 		status = get_module_image(path.Path(), &iterator->module_image);
1030 		if (status < B_OK) {
1031 			free((char*)iterator->current_module_path);
1032 			iterator->current_module_path = NULL;
1033 			goto nextModuleImage;
1034 		}
1035 
1036 		iterator->current_header = iterator->module_image->info;
1037 		iterator->module_offset = 0;
1038 	}
1039 
1040 	// search the current module image until we've got a match
1041 	while (*iterator->current_header != NULL) {
1042 		module_info* info = *iterator->current_header;
1043 
1044 		// TODO: we might want to create a module here and cache it in the
1045 		// hash table
1046 
1047 		iterator->current_header++;
1048 		iterator->module_offset++;
1049 
1050 		if (strncmp(info->name, iterator->prefix, iterator->prefix_length)
1051 			|| !match_iterator_suffix(iterator, info->name))
1052 			continue;
1053 
1054 		*_bufferSize = strlcpy(buffer, info->name, *_bufferSize);
1055 		return B_OK;
1056 	}
1057 
1058 	// leave this module and get the next one
1059 
1060 	iterator->current_header = NULL;
1061 	free((char*)iterator->current_module_path);
1062 	iterator->current_module_path = NULL;
1063 
1064 	put_module_image(iterator->module_image);
1065 	iterator->module_image = NULL;
1066 
1067 	goto nextModuleImage;
1068 }
1069 
1070 
1071 static void
1072 register_builtin_modules(struct module_info** info)
1073 {
1074 	for (; *info; info++) {
1075 		(*info)->flags |= B_BUILT_IN_MODULE;
1076 			// this is an internal flag, it doesn't have to be set by modules
1077 			// itself
1078 
1079 		if (create_module(*info, -1, NULL) != B_OK) {
1080 			dprintf("creation of built-in module \"%s\" failed!\n",
1081 				(*info)->name);
1082 		}
1083 	}
1084 }
1085 
1086 
1087 static status_t
1088 register_preloaded_module_image(struct preloaded_image* image)
1089 {
1090 	module_image* moduleImage;
1091 	struct module_info** info;
1092 	status_t status;
1093 	int32 index = 0;
1094 
1095 	TRACE(("register_preloaded_module_image(image = %p, name = \"%s\")\n",
1096 		image, image->name));
1097 
1098 	image->is_module = false;
1099 
1100 	if (image->id < 0)
1101 		return B_BAD_VALUE;
1102 
1103 	moduleImage = (module_image*)malloc(sizeof(module_image));
1104 	if (moduleImage == NULL)
1105 		return B_NO_MEMORY;
1106 
1107 	if (get_image_symbol(image->id, "modules", B_SYMBOL_TYPE_DATA,
1108 			(void**)&moduleImage->info) != B_OK) {
1109 		status = B_BAD_TYPE;
1110 		goto error;
1111 	}
1112 
1113 	image->is_module = true;
1114 
1115 	if (moduleImage->info[0] == NULL) {
1116 		status = B_BAD_DATA;
1117 		goto error;
1118 	}
1119 
1120 	moduleImage->dependencies = NULL;
1121 	get_image_symbol(image->id, "module_dependencies", B_SYMBOL_TYPE_DATA,
1122 		(void**)&moduleImage->dependencies);
1123 		// this is allowed to be NULL
1124 
1125 	moduleImage->path = strdup(image->name);
1126 	if (moduleImage->path == NULL) {
1127 		status = B_NO_MEMORY;
1128 		goto error;
1129 	}
1130 
1131 	moduleImage->image = image->id;
1132 	moduleImage->ref_count = 0;
1133 
1134 	hash_insert(sModuleImagesHash, moduleImage);
1135 
1136 	for (info = moduleImage->info; *info; info++) {
1137 		struct module* module = NULL;
1138 		if (create_module(*info, index++, &module) == B_OK)
1139 			module->module_image = moduleImage;
1140 	}
1141 
1142 	return B_OK;
1143 
1144 error:
1145 	free(moduleImage);
1146 
1147 	// We don't need this image anymore. We keep it, if it doesn't look like
1148 	// a module at all. It might be an old-style driver.
1149 	if (image->is_module)
1150 		unload_kernel_add_on(image->id);
1151 
1152 	return status;
1153 }
1154 
1155 
1156 static int
1157 dump_modules(int argc, char** argv)
1158 {
1159 	hash_iterator iterator;
1160 	struct module_image* image;
1161 	struct module* module;
1162 
1163 	hash_rewind(sModulesHash, &iterator);
1164 	kprintf("-- known modules:\n");
1165 
1166 	while ((module = (struct module*)hash_next(sModulesHash, &iterator))
1167 			!= NULL) {
1168 		kprintf("%p: \"%s\", \"%s\" (%ld), refcount = %ld, state = %d, "
1169 			"mimage = %p\n", module, module->name,
1170 			module->module_image ? module->module_image->path : "",
1171 			module->offset, module->ref_count, module->state,
1172 			module->module_image);
1173 	}
1174 
1175 	hash_rewind(sModuleImagesHash, &iterator);
1176 	kprintf("\n-- loaded module images:\n");
1177 
1178 	while ((image = (struct module_image*)hash_next(sModuleImagesHash,
1179 				&iterator)) != NULL) {
1180 		kprintf("%p: \"%s\" (image_id = %ld), info = %p, refcount = %ld\n",
1181 			image, image->path, image->image, image->info, image->ref_count);
1182 	}
1183 	return 0;
1184 }
1185 
1186 
1187 //	#pragma mark - DirectoryWatcher
1188 
1189 
1190 DirectoryWatcher::DirectoryWatcher()
1191 {
1192 }
1193 
1194 
1195 DirectoryWatcher::~DirectoryWatcher()
1196 {
1197 }
1198 
1199 
1200 void
1201 DirectoryWatcher::EventOccured(NotificationService& service,
1202 	const KMessage* event)
1203 {
1204 	int32 opcode = event->GetInt32("opcode", -1);
1205 	dev_t device = event->GetInt32("device", -1);
1206 	ino_t directory = event->GetInt64("directory", -1);
1207 	ino_t node = event->GetInt64("node", -1);
1208 	const char *name = event->GetString("name", NULL);
1209 
1210 	if (opcode == B_ENTRY_MOVED) {
1211 		// Determine wether it's a move within, out of, or into one
1212 		// of our watched directories.
1213 		directory = event->GetInt64("to directory", -1);
1214 		if (!sModuleNotificationService.HasNode(device, directory)) {
1215 			directory = event->GetInt64("from directory", -1);
1216 			opcode = B_ENTRY_REMOVED;
1217 		} else {
1218 			// Move within, doesn't sound like a good idea for modules
1219 			opcode = B_ENTRY_CREATED;
1220 		}
1221 	}
1222 
1223 	sModuleNotificationService.Notify(opcode, device, directory, node, name);
1224 }
1225 
1226 
1227 //	#pragma mark - ModuleWatcher
1228 
1229 
1230 ModuleWatcher::ModuleWatcher()
1231 {
1232 }
1233 
1234 
1235 ModuleWatcher::~ModuleWatcher()
1236 {
1237 }
1238 
1239 
1240 void
1241 ModuleWatcher::EventOccured(NotificationService& service, const KMessage* event)
1242 {
1243 	if (event->GetInt32("opcode", -1) != B_STAT_CHANGED
1244 		|| (event->GetInt32("fields", 0) & B_STAT_MODIFICATION_TIME) == 0)
1245 		return;
1246 
1247 	dev_t device = event->GetInt32("device", -1);
1248 	ino_t node = event->GetInt64("node", -1);
1249 
1250 	sModuleNotificationService.Notify(B_STAT_CHANGED, device, -1, node, NULL);
1251 }
1252 
1253 
1254 //	#pragma mark - ModuleNotificationService
1255 
1256 
1257 ModuleNotificationService::ModuleNotificationService()
1258 {
1259 	recursive_lock_init(&fLock, "module notifications");
1260 }
1261 
1262 
1263 ModuleNotificationService::~ModuleNotificationService()
1264 {
1265 	recursive_lock_destroy(&fLock);
1266 }
1267 
1268 
1269 status_t
1270 ModuleNotificationService::AddListener(const KMessage* eventSpecifier,
1271 	NotificationListener& listener)
1272 {
1273 	const char* prefix = eventSpecifier->GetString("prefix", NULL);
1274 	if (prefix == NULL)
1275 		return B_BAD_VALUE;
1276 
1277 	module_listener* moduleListener = new(std::nothrow) module_listener;
1278 	if (moduleListener == NULL)
1279 		return B_NO_MEMORY;
1280 
1281 	moduleListener->prefix = strdup(prefix);
1282 	if (moduleListener->prefix == NULL) {
1283 		delete moduleListener;
1284 		return B_NO_MEMORY;
1285 	}
1286 
1287 	status_t status = _AddDirectory(prefix);
1288 	if (status != B_OK) {
1289 		delete moduleListener;
1290 		return status;
1291 	}
1292 
1293 	moduleListener->listener = &listener;
1294 	fListeners.Add(moduleListener);
1295 
1296 	return B_OK;
1297 }
1298 
1299 
1300 status_t
1301 ModuleNotificationService::UpdateListener(const KMessage* eventSpecifier,
1302 	NotificationListener& listener)
1303 {
1304 	return B_ERROR;
1305 }
1306 
1307 
1308 status_t
1309 ModuleNotificationService::RemoveListener(const KMessage* eventSpecifier,
1310 	NotificationListener& listener)
1311 {
1312 	return B_ERROR;
1313 }
1314 
1315 
1316 bool
1317 ModuleNotificationService::HasNode(dev_t device, ino_t node)
1318 {
1319 	RecursiveLocker _(fLock);
1320 
1321 	struct entry entry = {device, node};
1322 	return fNodes.Lookup(&entry) != NULL;
1323 }
1324 
1325 
1326 status_t
1327 ModuleNotificationService::_RemoveNode(dev_t device, ino_t node)
1328 {
1329 	RecursiveLocker _(fLock);
1330 
1331 	struct entry key = {device, node};
1332 	hash_entry* entry = fNodes.Lookup(&key);
1333 	if (entry == NULL)
1334 		return B_ENTRY_NOT_FOUND;
1335 
1336 	remove_node_listener(device, node, entry->path != NULL
1337 		? (NotificationListener&)fModuleWatcher
1338 		: (NotificationListener&)fDirectoryWatcher);
1339 
1340 	fNodes.Remove(entry);
1341 	delete entry;
1342 
1343 	return B_OK;
1344 }
1345 
1346 
1347 status_t
1348 ModuleNotificationService::_AddNode(dev_t device, ino_t node, const char* path,
1349 	uint32 flags, NotificationListener& listener)
1350 {
1351 	RecursiveLocker locker(fLock);
1352 
1353 	if (HasNode(device, node))
1354 		return B_OK;
1355 
1356 	struct hash_entry* entry = new(std::nothrow) hash_entry;
1357 	if (entry == NULL)
1358 		return B_NO_MEMORY;
1359 
1360 	if (path != NULL) {
1361 		entry->path = strdup(path);
1362 		if (entry->path == NULL) {
1363 			delete entry;
1364 			return B_NO_MEMORY;
1365 		}
1366 	} else
1367 		entry->path = NULL;
1368 
1369 	status_t status = add_node_listener(device, node, flags, listener);
1370 	if (status != B_OK) {
1371 		delete entry;
1372 		return status;
1373 	}
1374 
1375 	//dprintf("  add %s %ld:%Ld (%s)\n", flags == B_WATCH_DIRECTORY
1376 	//	? "dir" : "file", device, node, path);
1377 
1378 	entry->device = device;
1379 	entry->node = node;
1380 	fNodes.Insert(entry);
1381 
1382 	return B_OK;
1383 }
1384 
1385 
1386 status_t
1387 ModuleNotificationService::_AddDirectoryNode(dev_t device, ino_t node)
1388 {
1389 	return _AddNode(device, node, NULL, B_WATCH_DIRECTORY, fDirectoryWatcher);
1390 }
1391 
1392 
1393 status_t
1394 ModuleNotificationService::_AddModuleNode(dev_t device, ino_t node, int fd,
1395 	const char* name)
1396 {
1397 	struct vnode* vnode;
1398 	status_t status = vfs_get_vnode_from_fd(fd, true, &vnode);
1399 	if (status != B_OK)
1400 		return status;
1401 
1402 	ino_t directory;
1403 	vfs_vnode_to_node_ref(vnode, &device, &directory);
1404 
1405 	KPath path;
1406 	status = path.InitCheck();
1407 	if (status == B_OK) {
1408 		status = vfs_entry_ref_to_path(device, directory, name,
1409 			path.LockBuffer(), path.BufferSize());
1410 	}
1411 	if (status != B_OK)
1412 		return status;
1413 
1414 	path.UnlockBuffer();
1415 
1416 	return _AddNode(device, node, path.Path(), B_WATCH_STAT, fModuleWatcher);
1417 }
1418 
1419 
1420 status_t
1421 ModuleNotificationService::_AddDirectory(const char* prefix)
1422 {
1423 	status_t status = B_ERROR;
1424 
1425 	for (uint32 i = 0; i < kNumModulePaths; i++) {
1426 		if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
1427 			break;
1428 
1429 		KPath pathBuffer;
1430 		if (find_directory(kModulePaths[i], gBootDevice, true,
1431 				pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
1432 			continue;
1433 
1434 		pathBuffer.UnlockBuffer();
1435 		pathBuffer.Append("kernel");
1436 		pathBuffer.Append(prefix);
1437 
1438 		size_t prefixPosition = strlen(prefix);
1439 		status_t scanStatus = _ScanDirectory(pathBuffer.LockBuffer(), prefix,
1440 			prefixPosition);
1441 
1442 		pathBuffer.UnlockBuffer();
1443 
1444 		// It's enough if we succeed for one directory
1445 		if (status != B_OK)
1446 			status = scanStatus;
1447 	}
1448 
1449 	return status;
1450 }
1451 
1452 
1453 status_t
1454 ModuleNotificationService::_ScanDirectory(char* directoryPath,
1455 	const char* prefix, size_t& prefixPosition)
1456 {
1457 	DIR* dir = NULL;
1458 	while (true) {
1459 		dir = opendir(directoryPath);
1460 		if (dir != NULL || prefixPosition == 0)
1461 			break;
1462 
1463 		// the full prefix is not accessible, remove path components
1464 		const char* parentPrefix = prefix + prefixPosition - 1;
1465 		while (parentPrefix != prefix && parentPrefix[0] != '/')
1466 			parentPrefix--;
1467 
1468 		size_t cutPosition = parentPrefix - prefix;
1469 		size_t length = strlen(directoryPath);
1470 		directoryPath[length - prefixPosition + cutPosition] = '\0';
1471 		prefixPosition = cutPosition;
1472 	}
1473 
1474 	if (dir == NULL)
1475 		return B_ERROR;
1476 
1477 	Stack<DIR*> stack;
1478 	stack.Push(dir);
1479 
1480 	while (stack.Pop(&dir)) {
1481 		status_t status = _ScanDirectory(stack, dir, prefix, prefixPosition);
1482 		if (status != B_OK)
1483 			return status;
1484 	}
1485 
1486 	return B_OK;
1487 }
1488 
1489 
1490 status_t
1491 ModuleNotificationService::_ScanDirectory(Stack<DIR*>& stack, DIR* dir,
1492 	const char* prefix, size_t prefixPosition)
1493 {
1494 	bool directMatchAdded = false;
1495 	struct dirent* dirent;
1496 
1497 	while ((dirent = readdir(dir)) != NULL) {
1498 		if (dirent->d_name[0] == '.')
1499 			continue;
1500 
1501 		bool directMatch = false;
1502 
1503 		if (prefix[prefixPosition] != '\0') {
1504 			// the start must match
1505 			const char* startPrefix = prefix + prefixPosition;
1506 			if (startPrefix[0] == '/')
1507 				startPrefix++;
1508 
1509 			const char* endPrefix = strchr(startPrefix, '/');
1510 			size_t length;
1511 
1512 			if (endPrefix != NULL)
1513 				length = endPrefix - startPrefix;
1514 			else
1515 				length = strlen(startPrefix);
1516 
1517 			if (strncmp(dirent->d_name, startPrefix, length))
1518 				continue;
1519 
1520 			if (dirent->d_name[length] == '\0')
1521 				directMatch = true;
1522 		}
1523 
1524 		struct stat stat;
1525 		status_t status = vfs_read_stat(dir->fd, dirent->d_name, true, &stat,
1526 			true);
1527 		if (status != B_OK)
1528 			continue;
1529 
1530 		if (S_ISDIR(stat.st_mode)) {
1531 			int fd = _kern_open_dir(dir->fd, dirent->d_name);
1532 			if (fd < 0)
1533 				continue;
1534 
1535 			DIR* subDir = (DIR*)malloc(DIR_BUFFER_SIZE);
1536 			if (subDir == NULL) {
1537 				close(fd);
1538 				continue;
1539 			}
1540 
1541 			subDir->fd = fd;
1542 			subDir->entries_left = 0;
1543 
1544 			stack.Push(subDir);
1545 
1546 			if (_AddDirectoryNode(stat.st_dev, stat.st_ino) == B_OK
1547 				&& directMatch)
1548 				directMatchAdded = true;
1549 		} else if (S_ISREG(stat.st_mode)) {
1550 			if (_AddModuleNode(stat.st_dev, stat.st_ino, dir->fd,
1551 					dirent->d_name) == B_OK && directMatch)
1552 				directMatchAdded = true;
1553 		}
1554 	}
1555 
1556 	if (!directMatchAdded) {
1557 		// We need to monitor this directory to see if a matching file
1558 		// is added.
1559 		struct stat stat;
1560 		status_t status = vfs_read_stat(dir->fd, NULL, true, &stat, true);
1561 		if (status == B_OK)
1562 			_AddDirectoryNode(stat.st_dev, stat.st_ino);
1563 	}
1564 
1565 	closedir(dir);
1566 	return B_OK;
1567 }
1568 
1569 
1570 void
1571 ModuleNotificationService::_Notify(int32 opcode, dev_t device, ino_t directory,
1572 	ino_t node, const char* name)
1573 {
1574 	// construct path
1575 
1576 	KPath pathBuffer;
1577 	const char* path;
1578 
1579 	if (name != NULL) {
1580 		// we have an entry ref
1581 		if (pathBuffer.InitCheck() != B_OK
1582 			|| vfs_entry_ref_to_path(device, directory, name,
1583 				pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
1584 			return;
1585 
1586 		pathBuffer.UnlockBuffer();
1587 		path = pathBuffer.Path();
1588 	} else {
1589 		// we only have a node ref
1590 		RecursiveLocker _(fLock);
1591 
1592 		struct entry key = {device, node};
1593 		hash_entry* entry = fNodes.Lookup(&key);
1594 		if (entry == NULL || entry->path == NULL)
1595 			return;
1596 
1597 		path = entry->path;
1598 	}
1599 
1600 	// remove kModulePaths from path
1601 
1602 	for (uint32 i = 0; i < kNumModulePaths; i++) {
1603 		KPath modulePath;
1604 		if (find_directory(kModulePaths[i], gBootDevice, true,
1605 				modulePath.LockBuffer(), modulePath.BufferSize()) != B_OK)
1606 			continue;
1607 
1608 		modulePath.UnlockBuffer();
1609 		modulePath.Append("kernel");
1610 
1611 		if (strncmp(path, modulePath.Path(), modulePath.Length()))
1612 			continue;
1613 
1614 		path += modulePath.Length();
1615 		if (path[i] == '/')
1616 			path++;
1617 
1618 		break;
1619 	}
1620 
1621 	KMessage event;
1622 
1623 	// find listeners by prefix/path
1624 
1625 	ModuleListenerList::Iterator iterator = fListeners.GetIterator();
1626 	while (iterator.HasNext()) {
1627 		module_listener* listener = iterator.Next();
1628 
1629 		if (strncmp(path, listener->prefix, strlen(listener->prefix)))
1630 			continue;
1631 
1632 		if (event.IsEmpty()) {
1633 			// construct message only when needed
1634 			event.AddInt32("opcode", opcode);
1635 			event.AddString("path", path);
1636 		}
1637 
1638 		// notify them!
1639 		listener->listener->EventOccured(*this, &event);
1640 
1641 		// we might need to watch new files now
1642 		if (opcode == B_ENTRY_CREATED)
1643 			_AddDirectory(listener->prefix);
1644 
1645 	}
1646 
1647 	// remove notification listeners, if needed
1648 
1649 	if (opcode == B_ENTRY_REMOVED)
1650 		_RemoveNode(device, node);
1651 }
1652 
1653 
1654 void
1655 ModuleNotificationService::_HandleNotifications()
1656 {
1657 	RecursiveLocker _(fLock);
1658 
1659 	NotificationList::Iterator iterator = fNotifications.GetIterator();
1660 	while (iterator.HasNext()) {
1661 		module_notification* notification = iterator.Next();
1662 
1663 		_Notify(notification->opcode, notification->device,
1664 			notification->directory, notification->node, notification->name);
1665 
1666 		iterator.Remove();
1667 		delete notification;
1668 	}
1669 }
1670 
1671 
1672 void
1673 ModuleNotificationService::Notify(int32 opcode, dev_t device, ino_t directory,
1674 	ino_t node, const char* name)
1675 {
1676 	module_notification* notification = new(std::nothrow) module_notification;
1677 	if (notification == NULL)
1678 		return;
1679 
1680 	if (name != NULL) {
1681 		notification->name = strdup(name);
1682 		if (notification->name == NULL) {
1683 			delete notification;
1684 			return;
1685 		}
1686 	} else
1687 		notification->name = NULL;
1688 
1689 	notification->opcode = opcode;
1690 	notification->device = device;
1691 	notification->directory = directory;
1692 	notification->node = node;
1693 
1694 	RecursiveLocker _(fLock);
1695 	fNotifications.Add(notification);
1696 }
1697 
1698 
1699 /*static*/ void
1700 ModuleNotificationService::HandleNotifications(void */*data*/,
1701 	int /*iteration*/)
1702 {
1703 	sModuleNotificationService._HandleNotifications();
1704 }
1705 
1706 
1707 //	#pragma mark - Exported Kernel API (private part)
1708 
1709 
1710 /*!	Unloads a module in case it's not in use. This is the counterpart
1711 	to load_module().
1712 */
1713 status_t
1714 unload_module(const char* path)
1715 {
1716 	struct module_image* moduleImage;
1717 
1718 	recursive_lock_lock(&sModulesLock);
1719 	moduleImage = (module_image*)hash_lookup(sModuleImagesHash, path);
1720 	recursive_lock_unlock(&sModulesLock);
1721 
1722 	if (moduleImage == NULL)
1723 		return B_ENTRY_NOT_FOUND;
1724 
1725 	put_module_image(moduleImage);
1726 	return B_OK;
1727 }
1728 
1729 
1730 /*!	Unlike get_module(), this function lets you specify the add-on to
1731 	be loaded by path.
1732 	However, you must not use the exported modules without having called
1733 	get_module() on them. When you're done with the NULL terminated
1734 	\a modules array, you have to call unload_module(), no matter if
1735 	you're actually using any of the modules or not - of course, the
1736 	add-on won't be unloaded until the last put_module().
1737 */
1738 status_t
1739 load_module(const char* path, module_info*** _modules)
1740 {
1741 	module_image* moduleImage;
1742 	status_t status = get_module_image(path, &moduleImage);
1743 	if (status != B_OK)
1744 		return status;
1745 
1746 	*_modules = moduleImage->info;
1747 	return B_OK;
1748 }
1749 
1750 
1751 status_t
1752 start_watching_modules(const char* prefix, NotificationListener& listener)
1753 {
1754 	KMessage specifier;
1755 	status_t status = specifier.AddString("prefix", prefix);
1756 	if (status != B_OK)
1757 		return status;
1758 
1759 	return sModuleNotificationService.AddListener(&specifier, listener);
1760 }
1761 
1762 
1763 status_t
1764 stop_watching_modules(const char* prefix, NotificationListener& listener)
1765 {
1766 	KMessage specifier;
1767 	status_t status = specifier.AddString("prefix", prefix);
1768 	if (status != B_OK)
1769 		return status;
1770 
1771 	return sModuleNotificationService.RemoveListener(&specifier, listener);
1772 }
1773 
1774 
1775 /*! Setup the module structures and data for use - must be called
1776 	before any other module call.
1777 */
1778 status_t
1779 module_init(kernel_args* args)
1780 {
1781 	struct preloaded_image* image;
1782 
1783 	recursive_lock_init(&sModulesLock, "modules rlock");
1784 
1785 	sModulesHash = hash_init(MODULE_HASH_SIZE, 0, module_compare, module_hash);
1786 	if (sModulesHash == NULL)
1787 		return B_NO_MEMORY;
1788 
1789 	sModuleImagesHash = hash_init(MODULE_HASH_SIZE, 0, module_image_compare,
1790 		module_image_hash);
1791 	if (sModuleImagesHash == NULL)
1792 		return B_NO_MEMORY;
1793 
1794 	// register built-in modules
1795 
1796 	register_builtin_modules(sBuiltInModules);
1797 
1798 	// register preloaded images
1799 
1800 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1801 		status_t status = register_preloaded_module_image(image);
1802 		if (status != B_OK && image->is_module) {
1803 			dprintf("Could not register image \"%s\": %s\n", image->name,
1804 				strerror(status));
1805 		}
1806 	}
1807 
1808 	new(&sModuleNotificationService) ModuleNotificationService();
1809 
1810 	sDisableUserAddOns = get_safemode_boolean(B_SAFEMODE_DISABLE_USER_ADD_ONS,
1811 		false);
1812 
1813 	add_debugger_command("modules", &dump_modules,
1814 		"list all known & loaded modules");
1815 
1816 	return B_OK;
1817 }
1818 
1819 
1820 status_t
1821 module_init_post_threads(void)
1822 {
1823 	return register_kernel_daemon(
1824 		&ModuleNotificationService::HandleNotifications, NULL, 10);
1825 		// once every second
1826 
1827 	return B_OK;
1828 }
1829 
1830 
1831 status_t
1832 module_init_post_boot_device(bool bootingFromBootLoaderVolume)
1833 {
1834 	// Remove all unused pre-loaded module images. Now that the boot device is
1835 	// available, we can load an image when we need it.
1836 	// When the boot volume is also where the boot loader pre-loaded the images
1837 	// from, we get the actual paths for those images.
1838 	TRACE(("module_init_post_boot_device(%d)\n", bootingFromBootLoaderVolume));
1839 
1840 	RecursiveLocker _(sModulesLock);
1841 
1842 	// First of all, clear all pre-loaded module's module_image, if the module
1843 	// isn't in use.
1844 	hash_iterator iterator;
1845 	hash_open(sModulesHash, &iterator);
1846 	struct module* module;
1847 	while ((module = (struct module*)hash_next(sModulesHash, &iterator))
1848 			!= NULL) {
1849 		if (module->ref_count == 0
1850 			&& (module->flags & B_BUILT_IN_MODULE) == 0) {
1851 			TRACE(("  module %p, \"%s\" unused, clearing image\n", module,
1852 				module->name));
1853 			module->module_image = NULL;
1854 		}
1855 	}
1856 
1857 	// Now iterate through the images and drop them respectively normalize their
1858 	// paths.
1859 	hash_open(sModuleImagesHash, &iterator);
1860 
1861 	module_image* imagesToReinsert = NULL;
1862 		// When renamed, an image is added to this list to be re-entered in the
1863 		// hash at the end. We can't do that during the iteration.
1864 
1865 	while (true) {
1866 		struct module_image* image
1867 			= (struct module_image*)hash_next(sModuleImagesHash, &iterator);
1868 		if (image == NULL)
1869 			break;
1870 
1871 		if (image->ref_count == 0) {
1872 			// not in use -- unload it
1873 			TRACE(("  module image %p, \"%s\" unused, removing\n", image,
1874 				image->path));
1875 			hash_remove_current(sModuleImagesHash, &iterator);
1876 			unload_module_image(image, false);
1877 		} else if (bootingFromBootLoaderVolume) {
1878 			bool pathNormalized = false;
1879 			KPath pathBuffer;
1880 			if (image->path[0] != '/') {
1881 				// relative path
1882 				for (uint32 i = kNumModulePaths; i-- > 0;) {
1883 					if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
1884 						continue;
1885 
1886 					if (find_directory(kModulePaths[i], gBootDevice, true,
1887 							pathBuffer.LockBuffer(), pathBuffer.BufferSize())
1888 								!= B_OK) {
1889 						pathBuffer.UnlockBuffer();
1890 						continue;
1891 					}
1892 
1893 					pathBuffer.UnlockBuffer();
1894 
1895 					// Append the relative boot module directory and the
1896 					// relative image path, normalize the path, and check
1897 					// whether it exists.
1898 					struct stat st;
1899 					if (pathBuffer.Append("kernel/boot") != B_OK
1900 						|| pathBuffer.Append(image->path) != B_OK
1901 						|| pathBuffer.Normalize(true) != B_OK
1902 						|| lstat(pathBuffer.Path(), &st) != 0) {
1903 						continue;
1904 					}
1905 
1906 					pathNormalized = true;
1907 					break;
1908 				}
1909 			} else {
1910 				// absolute path -- try to normalize it anyway
1911 				struct stat st;
1912 				if (pathBuffer.SetPath(image->path) == B_OK
1913 					&& pathBuffer.Normalize(true) == B_OK
1914 					&& lstat(pathBuffer.Path(), &st) == 0) {
1915 					pathNormalized = true;
1916 				}
1917 			}
1918 
1919 			if (pathNormalized) {
1920 				TRACE(("  normalized path of module image %p, \"%s\" -> "
1921 					"\"%s\"\n", image, image->path, pathBuffer.Path()));
1922 
1923 				// set the new path
1924 				free(image->path);
1925 				size_t pathLen = pathBuffer.Length();
1926 				image->path = (char*)realloc(pathBuffer.DetachBuffer(),
1927 					pathLen + 1);
1928 
1929 				// remove the image -- its hash value has probably changed,
1930 				// so we need to re-insert it later
1931 				hash_remove_current(sModuleImagesHash, &iterator);
1932 				image->next = imagesToReinsert;
1933 				imagesToReinsert = image;
1934 			} else {
1935 				dprintf("module_init_post_boot_device() failed to normalize "
1936 					"path of module image %p, \"%s\"\n", image, image->path);
1937 			}
1938 		}
1939 	}
1940 
1941 	// re-insert the images that have got a new path
1942 	while (module_image* image = imagesToReinsert) {
1943 		imagesToReinsert = image->next;
1944 		hash_insert(sModuleImagesHash, image);
1945 	}
1946 
1947 	TRACE(("module_init_post_boot_device() done\n"));
1948 
1949 	return B_OK;
1950 }
1951 
1952 
1953 //	#pragma mark - Exported Kernel API (public part)
1954 
1955 
1956 /*! This returns a pointer to a structure that can be used to
1957 	iterate through a list of all modules available under
1958 	a given prefix that adhere to the specified suffix.
1959 	All paths will be searched and the returned list will
1960 	contain all modules available under the prefix.
1961 	The structure is then used by read_next_module_name(), and
1962 	must be freed by calling close_module_list().
1963 */
1964 void*
1965 open_module_list_etc(const char* prefix, const char* suffix)
1966 {
1967 	TRACE(("open_module_list(prefix = %s)\n", prefix));
1968 
1969 	if (sModulesHash == NULL) {
1970 		dprintf("open_module_list() called too early!\n");
1971 		return NULL;
1972 	}
1973 
1974 	module_iterator* iterator = (module_iterator*)malloc(
1975 		sizeof(module_iterator));
1976 	if (iterator == NULL)
1977 		return NULL;
1978 
1979 	memset(iterator, 0, sizeof(module_iterator));
1980 
1981 	iterator->prefix = strdup(prefix != NULL ? prefix : "");
1982 	if (iterator->prefix == NULL) {
1983 		free(iterator);
1984 		return NULL;
1985 	}
1986 	iterator->prefix_length = strlen(iterator->prefix);
1987 
1988 	iterator->suffix = suffix;
1989 	if (suffix != NULL)
1990 		iterator->suffix_length = strlen(iterator->suffix);
1991 
1992 	if (gBootDevice > 0) {
1993 		// We do have a boot device to scan
1994 
1995 		// first, we'll traverse over the built-in modules
1996 		iterator->builtin_modules = true;
1997 		iterator->loaded_modules = false;
1998 
1999 		// put all search paths on the stack
2000 		for (uint32 i = 0; i < kNumModulePaths; i++) {
2001 			if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
2002 				break;
2003 
2004 			KPath pathBuffer;
2005 			if (find_directory(kModulePaths[i], gBootDevice, true,
2006 					pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
2007 				continue;
2008 
2009 			pathBuffer.UnlockBuffer();
2010 			pathBuffer.Append("kernel");
2011 
2012 			// Copy base path onto the iterator stack
2013 			char* path = strdup(pathBuffer.Path());
2014 			if (path == NULL)
2015 				continue;
2016 
2017 			size_t length = strlen(path);
2018 
2019 			// TODO: it would currently be nicer to use the commented
2020 			// version below, but the iterator won't work if the prefix
2021 			// is inside a module then.
2022 			// It works this way, but should be done better.
2023 #if 0
2024 			// Build path component: base path + '/' + prefix
2025 			size_t length = strlen(sModulePaths[i]);
2026 			char* path = (char*)malloc(length + iterator->prefix_length + 2);
2027 			if (path == NULL) {
2028 				// ToDo: should we abort the whole operation here?
2029 				//	if we do, don't forget to empty the stack
2030 				continue;
2031 			}
2032 
2033 			memcpy(path, sModulePaths[i], length);
2034 			path[length] = '/';
2035 			memcpy(path + length + 1, iterator->prefix,
2036 				iterator->prefix_length + 1);
2037 #endif
2038 
2039 			iterator_push_path_on_stack(iterator, path, length + 1);
2040 		}
2041 	} else {
2042 		// include loaded modules in case there is no boot device yet
2043 		iterator->builtin_modules = false;
2044 		iterator->loaded_modules = true;
2045 	}
2046 
2047 	return (void*)iterator;
2048 }
2049 
2050 
2051 void*
2052 open_module_list(const char* prefix)
2053 {
2054 	return open_module_list_etc(prefix, NULL);
2055 }
2056 
2057 
2058 /*!	Frees the cookie allocated by open_module_list() */
2059 status_t
2060 close_module_list(void* cookie)
2061 {
2062 	module_iterator* iterator = (module_iterator*)cookie;
2063 	const char* path;
2064 
2065 	TRACE(("close_module_list()\n"));
2066 
2067 	if (iterator == NULL)
2068 		return B_BAD_VALUE;
2069 
2070 	// free stack
2071 	while ((path = iterator_pop_path_from_stack(iterator, NULL)) != NULL)
2072 		free((char*)path);
2073 
2074 	// close what have been left open
2075 	if (iterator->module_image != NULL)
2076 		put_module_image(iterator->module_image);
2077 
2078 	if (iterator->current_dir != NULL)
2079 		closedir(iterator->current_dir);
2080 
2081 	free(iterator->stack);
2082 	free((char*)iterator->current_path);
2083 	free((char*)iterator->current_module_path);
2084 
2085 	free(iterator->prefix);
2086 	free(iterator);
2087 
2088 	return B_OK;
2089 }
2090 
2091 
2092 /*!	Return the next module name from the available list, using
2093 	a structure previously created by a call to open_module_list().
2094 	Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND
2095 	when done.
2096 */
2097 status_t
2098 read_next_module_name(void* cookie, char* buffer, size_t* _bufferSize)
2099 {
2100 	module_iterator* iterator = (module_iterator*)cookie;
2101 	status_t status;
2102 
2103 	TRACE(("read_next_module_name: looking for next module\n"));
2104 
2105 	if (iterator == NULL || buffer == NULL || _bufferSize == NULL)
2106 		return B_BAD_VALUE;
2107 
2108 	if (iterator->status < B_OK)
2109 		return iterator->status;
2110 
2111 	status = iterator->status;
2112 	recursive_lock_lock(&sModulesLock);
2113 
2114 	status = iterator_get_next_module(iterator, buffer, _bufferSize);
2115 
2116 	iterator->status = status;
2117 	recursive_lock_unlock(&sModulesLock);
2118 
2119 	TRACE(("read_next_module_name: finished with status %s\n",
2120 		strerror(status)));
2121 	return status;
2122 }
2123 
2124 
2125 /*!	Iterates through all loaded modules, and stores its path in "buffer".
2126 	TODO: check if the function in BeOS really does that (could also mean:
2127 		iterate through all modules that are currently loaded; have a valid
2128 		module_image pointer)
2129 */
2130 status_t
2131 get_next_loaded_module_name(uint32* _cookie, char* buffer, size_t* _bufferSize)
2132 {
2133 	if (sModulesHash == NULL) {
2134 		dprintf("get_next_loaded_module_name() called too early!\n");
2135 		return B_ERROR;
2136 	}
2137 
2138 	//TRACE(("get_next_loaded_module_name(\"%s\")\n", buffer));
2139 
2140 	if (_cookie == NULL || buffer == NULL || _bufferSize == NULL)
2141 		return B_BAD_VALUE;
2142 
2143 	status_t status = B_ENTRY_NOT_FOUND;
2144 	uint32 offset = *_cookie;
2145 
2146 	RecursiveLocker _(sModulesLock);
2147 
2148 	hash_iterator iterator;
2149 	hash_open(sModulesHash, &iterator);
2150 	struct module* module = (struct module*)hash_next(sModulesHash, &iterator);
2151 
2152 	for (uint32 i = 0; module != NULL; i++) {
2153 		if (i >= offset) {
2154 			*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
2155 			*_cookie = i + 1;
2156 			status = B_OK;
2157 			break;
2158 		}
2159 		module = (struct module*)hash_next(sModulesHash, &iterator);
2160 	}
2161 
2162 	hash_close(sModulesHash, &iterator, false);
2163 
2164 	return status;
2165 }
2166 
2167 
2168 status_t
2169 get_module(const char* path, module_info** _info)
2170 {
2171 	module_image* moduleImage = NULL;
2172 	module* module;
2173 	status_t status;
2174 
2175 	TRACE(("get_module(%s)\n", path));
2176 
2177 	if (path == NULL)
2178 		return B_BAD_VALUE;
2179 
2180 	RecursiveLocker _(sModulesLock);
2181 
2182 	module = (struct module*)hash_lookup(sModulesHash, path);
2183 
2184 	// if we don't have it cached yet, search for it
2185 	if (module == NULL || ((module->flags & B_BUILT_IN_MODULE) == 0
2186 			&& module->module_image == NULL)) {
2187 		module = search_module(path, &moduleImage);
2188 		if (module == NULL) {
2189 			FATAL(("module: Search for %s failed.\n", path));
2190 			return B_ENTRY_NOT_FOUND;
2191 		}
2192 
2193 		module->info = moduleImage->info[module->offset];
2194 		module->module_image = moduleImage;
2195 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0 && gBootDevice < 0
2196 		&& module->ref_count == 0) {
2197 		// The boot volume isn't available yet. I.e. instead of searching the
2198 		// right module image, we already know it and just increment the ref
2199 		// count.
2200 		atomic_add(&module->module_image->ref_count, 1);
2201 	}
2202 
2203 	// The state will be adjusted by the call to init_module
2204 	// if we have just loaded the file
2205 	if (module->ref_count == 0) {
2206 		status = init_module(module);
2207 		// For "keep loaded" modules we increment the ref count here. That will
2208 		// cause them never to get unloaded.
2209 		if (status == B_OK && (module->flags & B_KEEP_LOADED) != 0)
2210 			module->ref_count++;
2211 	} else
2212 		status = B_OK;
2213 
2214 	if (status == B_OK) {
2215 		ASSERT(module->ref_count >= 0);
2216 		module->ref_count++;
2217 		*_info = module->info;
2218 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0
2219 		&& module->ref_count == 0) {
2220 		// initialization failed -- release the image reference
2221 		put_module_image(module->module_image);
2222 		if (gBootDevice >= 0)
2223 			module->module_image = NULL;
2224 	}
2225 
2226 	return status;
2227 }
2228 
2229 
2230 status_t
2231 put_module(const char* path)
2232 {
2233 	module* module;
2234 
2235 	TRACE(("put_module(path = %s)\n", path));
2236 
2237 	RecursiveLocker _(sModulesLock);
2238 
2239 	module = (struct module*)hash_lookup(sModulesHash, path);
2240 	if (module == NULL) {
2241 		FATAL(("module: We don't seem to have a reference to module %s\n",
2242 			path));
2243 		return B_BAD_VALUE;
2244 	}
2245 
2246 	if (module->ref_count == 0) {
2247 		panic("module %s has no references.\n", path);
2248 		return B_BAD_VALUE;
2249 	}
2250 
2251 	if (--module->ref_count == 0) {
2252 		if ((module->flags & B_KEEP_LOADED) != 0) {
2253 			panic("ref count of B_KEEP_LOADED module %s dropped to 0!",
2254 				module->name);
2255 			module->ref_count++;
2256 			return B_BAD_VALUE;
2257 		}
2258 
2259 		uninit_module(module);
2260 
2261 		if ((module->flags & B_BUILT_IN_MODULE) == 0
2262 			&& module->ref_count == 0) {
2263 				// uninit_module() increments the ref count on failure
2264 			put_module_image(module->module_image);
2265 			// Unless we don't have a boot device yet, we clear the module's
2266 			// image pointer if the ref count dropped to 0. get_module() will
2267 			// have to reload the image.
2268 			if (gBootDevice >= 0)
2269 				module->module_image = NULL;
2270 		}
2271 	}
2272 
2273 	return B_OK;
2274 }
2275