diff --git a/headers/private/kernel/kmodule.h b/headers/private/kernel/kmodule.h index d93e6cf512..08d1d0b5bb 100644 --- a/headers/private/kernel/kmodule.h +++ b/headers/private/kernel/kmodule.h @@ -32,6 +32,7 @@ extern status_t load_module(const char *path, module_info ***_modules); extern status_t module_init(struct kernel_args *args); extern status_t module_init_post_threads(void); extern status_t module_init_post_boot_device(bool bootingFromBootLoaderVolume); +extern status_t module_get_path(const char* moduleName, char** path); #ifdef __cplusplus } diff --git a/src/system/kernel/device_manager/devfs.cpp b/src/system/kernel/device_manager/devfs.cpp index 61d8d04a62..d0659f9ba1 100644 --- a/src/system/kernel/device_manager/devfs.cpp +++ b/src/system/kernel/device_manager/devfs.cpp @@ -1534,21 +1534,6 @@ devfs_ioctl(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, uint32 op, return status; } - case B_GET_DRIVER_FOR_DEVICE: - { -#if 0 - const char* path; - if (!vnode->stream.u.dev.driver) - return B_ENTRY_NOT_FOUND; - path = vnode->stream.u.dev.driver->path; - if (path == NULL) - return B_ENTRY_NOT_FOUND; - - return user_strlcpy((char*)buffer, path, B_FILE_NAME_LENGTH); -#endif - return B_ERROR; - } - case B_GET_PARTITION_INFO: { struct devfs_partition* partition diff --git a/src/system/kernel/device_manager/device_manager.cpp b/src/system/kernel/device_manager/device_manager.cpp index b929971dd2..22365e1d45 100644 --- a/src/system/kernel/device_manager/device_manager.cpp +++ b/src/system/kernel/device_manager/device_manager.cpp @@ -21,8 +21,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -91,6 +92,8 @@ public: virtual void Removed(); + virtual status_t Control(void* cookie, int32 op, void* buffer, size_t length); + void SetRemovedFromParent(bool removed) { fRemovedFromParent = removed; } @@ -1251,6 +1254,28 @@ Device::Removed() } +status_t +Device::Control(void* _cookie, int32 op, void* buffer, size_t length) +{ + switch (op) { + case B_GET_DRIVER_FOR_DEVICE: + { + char* path = NULL; + status_t status = module_get_path(ModuleName(), &path); + if (status != B_OK) + return status; + if (length != 0 && length <= strlen(path)) + return ERANGE; + status = user_strlcpy(static_cast(buffer), path, length); + free(path); + return status; + } + default: + return AbstractModuleDevice::Control(_cookie, op, buffer, length);; + } +} + + // #pragma mark - device_node diff --git a/src/system/kernel/device_manager/legacy_drivers.cpp b/src/system/kernel/device_manager/legacy_drivers.cpp index 50b5430df8..2e0ca6e932 100644 --- a/src/system/kernel/device_manager/legacy_drivers.cpp +++ b/src/system/kernel/device_manager/legacy_drivers.cpp @@ -71,6 +71,8 @@ public: void** _cookie); virtual status_t Select(void* cookie, uint8 event, selectsync* sync); + virtual status_t Control(void* cookie, int32 op, void* buffer, size_t length); + bool Republished() const { return fRepublished; } void SetRepublished(bool republished) { fRepublished = republished; } @@ -1323,6 +1325,20 @@ LegacyDevice::Removed() } +status_t +LegacyDevice::Control(void* _cookie, int32 op, void* buffer, size_t length) +{ + switch (op) { + case B_GET_DRIVER_FOR_DEVICE: + if (length != 0 && length <= strlen(fDriver->path)) + return ERANGE; + return user_strlcpy(static_cast(buffer), fDriver->path, length); + default: + return AbstractModuleDevice::Control(_cookie, op, buffer, length); + } +} + + void LegacyDevice::SetHooks(device_hooks* hooks) { diff --git a/src/system/kernel/module.cpp b/src/system/kernel/module.cpp index c4e869fc4f..1f02be10f6 100644 --- a/src/system/kernel/module.cpp +++ b/src/system/kernel/module.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008, Haiku Inc. All rights reserved. + * Copyright 2002-2022, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Copyright 2001, Thomas Kurschel. All rights reserved. @@ -1742,6 +1742,28 @@ load_module(const char* path, module_info*** _modules) } +status_t +module_get_path(const char* moduleName, char** filePath) +{ + if (moduleName == NULL || filePath == NULL) + return B_BAD_VALUE; + + RecursiveLocker _(sModulesLock); + + // Check if the module and its image are already cached in the module system. + module* foundModule = sModulesHash->Lookup(moduleName); + if (foundModule != NULL) { + if (foundModule->module_image == NULL) + return ENOTSUP; + // The module is built-in and has no associated image. + *filePath = strdup(foundModule->module_image->path); + return *filePath != NULL ? B_OK : B_NO_MEMORY; + } + + return B_NAME_NOT_FOUND; +} + + status_t start_watching_modules(const char* prefix, NotificationListener& listener) {