kernel/device_manager: Implement B_GET_DRIVER_FOR_DEVICE
for legacy and new drivers. This is an opcode for ioctl that can be used on almost any device entry found in /dev. When used, ioctl will fill a buffer with the absolute path to the driver file that is being used by the device. This opcode was available in BeOS R5, though remained unimplemented in Haiku since the introduction of the Device Manager almost two decades ago. Original change by Jacob Secunda. Change-Id: Ic49141b677b4158a63918459d4048450c825447c Reviewed-on: https://review.haiku-os.org/c/haiku/+/5078 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
parent
d3e920ba77
commit
8e17b43da6
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -21,8 +21,9 @@
|
||||
#include <device_manager_defs.h>
|
||||
#include <fs/devfs.h>
|
||||
#include <fs/KPath.h>
|
||||
#include <kernel.h>
|
||||
#include <generic_syscall.h>
|
||||
#include <kernel.h>
|
||||
#include <kmodule.h>
|
||||
#include <util/AutoLock.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
#include <util/Stack.h>
|
||||
@ -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<char*>(buffer), path, length);
|
||||
free(path);
|
||||
return status;
|
||||
}
|
||||
default:
|
||||
return AbstractModuleDevice::Control(_cookie, op, buffer, length);;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - device_node
|
||||
|
||||
|
||||
|
@ -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<char*>(buffer), fDriver->path, length);
|
||||
default:
|
||||
return AbstractModuleDevice::Control(_cookie, op, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LegacyDevice::SetHooks(device_hooks* hooks)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user