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