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