diff --git a/headers/os/storage/DiskDeviceDefs.h b/headers/os/storage/DiskDeviceDefs.h index d79a253194..9a1475dd48 100644 --- a/headers/os/storage/DiskDeviceDefs.h +++ b/headers/os/storage/DiskDeviceDefs.h @@ -62,6 +62,7 @@ enum { B_DISK_DEVICE_HAS_MEDIA = 0x02, B_DISK_DEVICE_READ_ONLY = 0x04, B_DISK_DEVICE_WRITE_ONCE = 0x08, + B_DISK_DEVICE_IS_FILE = 0x10, }; // disk system flags diff --git a/headers/private/kernel/disk_device_manager/ddm_userland_interface.h b/headers/private/kernel/disk_device_manager/ddm_userland_interface.h index 69e03b4562..93233e3b23 100644 --- a/headers/private/kernel/disk_device_manager/ddm_userland_interface.h +++ b/headers/private/kernel/disk_device_manager/ddm_userland_interface.h @@ -26,21 +26,25 @@ extern "C" { partition_id _user_get_next_disk_device_id(int32 *cookie, size_t *neededSize); partition_id _user_find_disk_device(const char *filename, size_t *neededSize); partition_id _user_find_partition(const char *filename, size_t *neededSize); +partition_id _user_find_file_disk_device(const char *filename, + size_t *neededSize); status_t _user_get_disk_device_data(partition_id deviceID, bool deviceOnly, user_disk_device_data *buffer, size_t bufferSize, size_t *neededSize); partition_id _user_register_file_device(const char *filename); status_t _user_unregister_file_device(partition_id deviceID, - const char *filename); + const char *filename); // Only a valid deviceID or filename need to be passed. The other one // is -1/NULL. If both is given only filename is ignored. +status_t _user_get_file_disk_device_path(partition_id id, char* buffer, + size_t bufferSize); // disk systems status_t _user_get_disk_system_info(disk_system_id id, - user_disk_system_info *info); + user_disk_system_info *info); status_t _user_get_next_disk_system_info(int32 *cookie, - user_disk_system_info *info); + user_disk_system_info *info); status_t _user_find_disk_system(const char *name, user_disk_system_info *info); // disk device modification diff --git a/headers/private/storage/DiskDevice.h b/headers/private/storage/DiskDevice.h index a9cf2b975c..90994462a5 100644 --- a/headers/private/storage/DiskDevice.h +++ b/headers/private/storage/DiskDevice.h @@ -37,6 +37,9 @@ public: bool receiveCompleteProgressUpdates = true); status_t CancelModifications(); + bool IsFile() const; + status_t GetFilePath(BPath* path) const; + private: friend class BDiskDeviceList; friend class BDiskDeviceRoster; diff --git a/headers/private/storage/DiskDeviceRoster.h b/headers/private/storage/DiskDeviceRoster.h index 2fce72e5c9..17236ae1a1 100644 --- a/headers/private/storage/DiskDeviceRoster.h +++ b/headers/private/storage/DiskDeviceRoster.h @@ -28,7 +28,7 @@ enum { // Basic masks B_DEVICE_REQUEST_MOUNT_POINT = 0x0001, // mount point changes B_DEVICE_REQUEST_MOUNTING = 0x0002, // mounting/unmounting - B_DEVICE_REQUEST_PARTITION = 0x0004, // partition changes + B_DEVICE_REQUEST_PARTITION = 0x0004, // partition changes B_DEVICE_REQUEST_DEVICE = 0x0008, // device changes (media changes) B_DEVICE_REQUEST_DEVICE_LIST = 0x0010, // device additions/removals B_DEVICE_REQUEST_JOB_LIST = 0x0020, // job addition/initiation/cancellation/completion @@ -125,6 +125,8 @@ public: BDiskDevice* device); status_t GetPartitionForPath(const char* filename, BDiskDevice* device, BPartition** _partition); + status_t GetFileDeviceForPath(const char* filename, + BDiskDevice* device); status_t StartWatching(BMessenger target, uint32 eventMask = B_DEVICE_REQUEST_ALL); diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index cf8b3de8f4..4944b9eaab 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -441,9 +441,14 @@ extern status_t _kern_get_cpuid(cpuid_info *info, uint32 eax, uint32 cpu); /* Disk Device Manager syscalls */ // iterating, retrieving device/partition data -extern partition_id _kern_get_next_disk_device_id(int32 *cookie, size_t *neededSize); -extern partition_id _kern_find_disk_device(const char *filename, size_t *neededSize); -extern partition_id _kern_find_partition(const char *filename, size_t *neededSize); +extern partition_id _kern_get_next_disk_device_id(int32 *cookie, + size_t *neededSize); +extern partition_id _kern_find_disk_device(const char *filename, + size_t *neededSize); +extern partition_id _kern_find_partition(const char *filename, + size_t *neededSize); +extern partition_id _kern_find_file_disk_device(const char *filename, + size_t *neededSize); extern status_t _kern_get_disk_device_data(partition_id deviceID, bool deviceOnly, struct user_disk_device_data *buffer, size_t bufferSize, size_t *neededSize); @@ -452,6 +457,8 @@ extern status_t _kern_unregister_file_device(partition_id deviceID, const char *filename); // Only a valid deviceID or filename need to be passed. The other one // is -1/NULL. If both is given only filename is ignored. +extern status_t _kern_get_file_disk_device_path(partition_id id, + char* buffer, size_t bufferSize); // disk systems extern status_t _kern_get_disk_system_info(disk_system_id id, diff --git a/src/kits/storage/disk_device/DiskDevice.cpp b/src/kits/storage/disk_device/DiskDevice.cpp index f5714c66c9..9cf19f6fab 100644 --- a/src/kits/storage/disk_device/DiskDevice.cpp +++ b/src/kits/storage/disk_device/DiskDevice.cpp @@ -59,8 +59,8 @@ BDiskDevice::~BDiskDevice() bool BDiskDevice::HasMedia() const { - return (fDeviceData - && fDeviceData->device_flags & B_DISK_DEVICE_HAS_MEDIA); + return fDeviceData + && (fDeviceData->device_flags & B_DISK_DEVICE_HAS_MEDIA) != 0; } @@ -71,8 +71,8 @@ BDiskDevice::HasMedia() const bool BDiskDevice::IsRemovableMedia() const { - return (fDeviceData - && fDeviceData->device_flags & B_DISK_DEVICE_REMOVABLE); + return fDeviceData + && (fDeviceData->device_flags & B_DISK_DEVICE_REMOVABLE) != 0; } @@ -80,8 +80,8 @@ BDiskDevice::IsRemovableMedia() const bool BDiskDevice::IsReadOnlyMedia() const { - return (fDeviceData - && fDeviceData->device_flags & B_DISK_DEVICE_READ_ONLY); + return fDeviceData + && (fDeviceData->device_flags & B_DISK_DEVICE_READ_ONLY) != 0; } @@ -89,8 +89,8 @@ BDiskDevice::IsReadOnlyMedia() const bool BDiskDevice::IsWriteOnceMedia() const { - return (fDeviceData - && fDeviceData->device_flags & B_DISK_DEVICE_WRITE_ONCE); + return fDeviceData + && (fDeviceData->device_flags & B_DISK_DEVICE_WRITE_ONCE) != 0; } @@ -190,7 +190,7 @@ BDiskDevice::Unset() status_t BDiskDevice::InitCheck() const { - return (fDeviceData ? B_OK : B_NO_INIT); + return fDeviceData ? B_OK : B_NO_INIT; } @@ -216,7 +216,7 @@ BDiskDevice::IsModified() const { return Visit(device, 0); } - + virtual bool Visit(BPartition *partition, int32 level) { return partition->_IsModified(); @@ -229,7 +229,7 @@ BDiskDevice::IsModified() const // PrepareModifications /*! \brief Initializes the partition hierarchy for modifications. - * + * * Subsequent modifications are performed on so-called \a shadow structure * and not written to device until \ref CommitModifications is called. * @@ -333,6 +333,36 @@ BDiskDevice::CancelModifications() } +/*! \brief Returns whether or not this device is a virtual device backed + up by a file. +*/ +bool +BDiskDevice::IsFile() const +{ + return fDeviceData + && (fDeviceData->device_flags & B_DISK_DEVICE_IS_FILE) != 0; +} + + +/*! \brief Retrieves the path of the file backing up the disk device.*/ +status_t +BDiskDevice::GetFilePath(BPath* path) const +{ + if (path == NULL) + return B_BAD_VALUE; + if (!IsFile()) + return B_BAD_TYPE; + + char pathBuffer[B_PATH_NAME_LENGTH]; + status_t status = _kern_get_file_disk_device_path( + fDeviceData->device_partition_data.id, pathBuffer, sizeof(pathBuffer)); + if (status != B_OK) + return status; + + return path->SetTo(pathBuffer); +} + + // copy constructor /*! \brief Privatized copy constructor to avoid usage. */ diff --git a/src/kits/storage/disk_device/DiskDeviceRoster.cpp b/src/kits/storage/disk_device/DiskDeviceRoster.cpp index 242d119bad..54aba98ca9 100644 --- a/src/kits/storage/disk_device/DiskDeviceRoster.cpp +++ b/src/kits/storage/disk_device/DiskDeviceRoster.cpp @@ -377,7 +377,7 @@ BDiskDeviceRoster::GetPartitionWithID(int32 id, BDiskDevice *device, return B_OK; } -// GetDeviceForPath + status_t BDiskDeviceRoster::GetDeviceForPath(const char *filename, BDiskDevice *device) { @@ -392,11 +392,10 @@ BDiskDeviceRoster::GetDeviceForPath(const char *filename, BDiskDevice *device) return device->_SetTo(id, true, neededSize); } -// GetPartitionForPath + status_t BDiskDeviceRoster::GetPartitionForPath(const char *filename, - BDiskDevice *device, - BPartition **partition) + BDiskDevice *device, BPartition **partition) { if (!filename || !device || !partition) return B_BAD_VALUE; @@ -416,6 +415,25 @@ BDiskDeviceRoster::GetPartitionForPath(const char *filename, return B_OK; } + +status_t +BDiskDeviceRoster::GetFileDeviceForPath(const char *filename, + BDiskDevice *device) +{ + if (!filename || !device) + return B_BAD_VALUE; + + // get the device ID + size_t neededSize = 0; + partition_id id = _kern_find_file_disk_device(filename, &neededSize); + if (id < 0) + return id; + + // download the device data + return device->_SetTo(id, true, neededSize); +} + + // StartWatching /*! \brief Adds a target to the list of targets to be notified on disk device events. diff --git a/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp b/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp index 8b428abde7..68f246f57c 100644 --- a/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp +++ b/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp @@ -27,6 +27,7 @@ KFileDiskDevice::KFileDiskDevice(partition_id id) : KDiskDevice(id), fFilePath(NULL) { + SetDeviceFlags(DeviceFlags() | B_DISK_DEVICE_IS_FILE); } // destructor diff --git a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp index 18b9b10f93..f3c0c27978 100644 --- a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp +++ b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp @@ -4,6 +4,7 @@ * * Authors: * Ingo Weinhold, bonefish@cs.tu-berlin.de + * Axel Dörfler, axeld@pinc-software.de */ /*! \file ddm_userland_interface.cpp @@ -15,6 +16,7 @@ #include #include +#include #include #include #include @@ -328,6 +330,38 @@ _user_find_partition(const char *_filename, size_t *neededSize) } +partition_id +_user_find_file_disk_device(const char *_filename, size_t *neededSize) +{ + UserStringParameter filename; + status_t error = filename.Init(_filename, B_PATH_NAME_LENGTH); + if (error != B_OK) + return error; + + KPath path(filename, true); + + partition_id id = B_ENTRY_NOT_FOUND; + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // find the device + if (KFileDiskDevice* device = manager->RegisterFileDevice(path.Path())) { + PartitionRegistrar _(device, true); + id = device->ID(); + if (neededSize) { + if (DeviceReadLocker locker = device) { + // get the needed size + UserDataWriter writer; + device->WriteUserData(writer); + error = copy_to_user_value(neededSize, writer.AllocatedSize()); + if (error != B_OK) + return error; + } else + return B_ERROR; + } + } + return id; +} + + // _user_get_disk_device_data /*! \brief Writes data describing the disk device identified by ID and all its partitions into the supplied buffer. @@ -459,6 +493,31 @@ _user_unregister_file_device(partition_id deviceID, const char *_filename) } +status_t +_user_get_file_disk_device_path(partition_id id, char* buffer, + size_t bufferSize) +{ + if (id < 0 || buffer == NULL || bufferSize == 0) + return B_BAD_VALUE; + + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + + if (KDiskDevice *device = manager->RegisterDevice(id, true)) { + PartitionRegistrar _(device, true); + if (DeviceReadLocker locker = device) { + KFileDiskDevice* fileDevice + = dynamic_cast(device); + if (fileDevice == NULL) + return B_BAD_VALUE; + + return user_strlcpy(buffer, fileDevice->FilePath(), bufferSize); + } + } + + return B_ERROR; +} + + // _user_get_disk_system_info status_t _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)