1/* 2 * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "disk_device_manager.h" 8 9#include <stdio.h> 10 11#include <KernelExport.h> 12 13#include "KDiskDevice.h" 14#include "KDiskDeviceManager.h" 15#include "KDiskDeviceUtils.h" 16#include "KDiskSystem.h" 17#include "KPartition.h" 18 19 20// debugging 21//#define DBG(x) 22#define DBG(x) x 23#define OUT dprintf 24 25 26disk_device_data* 27write_lock_disk_device(partition_id partitionID) 28{ 29 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 30 if (KDiskDevice* device = manager->RegisterDevice(partitionID, false)) { 31 if (device->WriteLock()) 32 return device->DeviceData(); 33 // Only unregister, when the locking fails. The guarantees, that the 34 // lock owner also has a reference. 35 device->Unregister(); 36 } 37 return NULL; 38} 39 40 41void 42write_unlock_disk_device(partition_id partitionID) 43{ 44 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 45 if (KDiskDevice* device = manager->RegisterDevice(partitionID, false)) { 46 device->WriteUnlock(); 47 device->Unregister(); 48 49 device->Unregister(); 50 } 51} 52 53 54disk_device_data* 55read_lock_disk_device(partition_id partitionID) 56{ 57 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 58 if (KDiskDevice* device = manager->RegisterDevice(partitionID, false)) { 59 if (device->ReadLock()) 60 return device->DeviceData(); 61 // Only unregister, when the locking fails. The guarantees, that the 62 // lock owner also has a reference. 63 device->Unregister(); 64 } 65 return NULL; 66} 67 68 69void 70read_unlock_disk_device(partition_id partitionID) 71{ 72 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 73 if (KDiskDevice* device = manager->RegisterDevice(partitionID, false)) { 74 device->ReadUnlock(); 75 device->Unregister(); 76 77 device->Unregister(); 78 } 79} 80 81 82int32 83find_disk_device(const char* path) 84{ 85 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 86 partition_id id = -1; 87 if (KDiskDevice* device = manager->RegisterDevice(path)) { 88 id = device->ID(); 89 device->Unregister(); 90 } 91 return id; 92} 93 94 95int32 96find_partition(const char* path) 97{ 98 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 99 partition_id id = -1; 100 if (KPartition* partition = manager->RegisterPartition(path)) { 101 id = partition->ID(); 102 partition->Unregister(); 103 } 104 return id; 105} 106 107 108disk_device_data* 109get_disk_device(partition_id partitionID) 110{ 111 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 112 KDiskDevice* device = manager->FindDevice(partitionID, false); 113 return (device ? device->DeviceData() : NULL); 114} 115 116 117partition_data* 118get_partition(partition_id partitionID) 119{ 120 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 121 KPartition* partition = manager->FindPartition(partitionID); 122 return (partition ? partition->PartitionData() : NULL); 123} 124 125 126partition_data* 127get_parent_partition(partition_id partitionID) 128{ 129 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 130 KPartition* partition = manager->FindPartition(partitionID); 131 if (partition && partition->Parent()) 132 return partition->Parent()->PartitionData(); 133 return NULL; 134} 135 136 137partition_data* 138get_child_partition(partition_id partitionID, int32 index) 139{ 140 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 141 if (KPartition* partition = manager->FindPartition(partitionID)) { 142 if (KPartition* child = partition->ChildAt(index)) 143 return child->PartitionData(); 144 } 145 return NULL; 146} 147 148 149int 150open_partition(partition_id partitionID, int openMode) 151{ 152 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 153 KPartition* partition = manager->FindPartition(partitionID); 154 if (partition == NULL) 155 return B_BAD_VALUE; 156 157 int fd = -1; 158 status_t result = partition->Open(openMode, &fd); 159 if (result != B_OK) 160 return -1; 161 162 return fd; 163} 164 165 166partition_data* 167create_child_partition(partition_id partitionID, int32 index, off_t offset, 168 off_t size, partition_id childID) 169{ 170 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 171 if (KPartition* partition = manager->FindPartition(partitionID)) { 172 KPartition* child = NULL; 173 if (partition->CreateChild(childID, index, offset, size, &child) 174 == B_OK) { 175 return child->PartitionData(); 176 } else { 177 DBG(OUT(" creating child (%" B_PRId32 ", %" B_PRId32 ") failed\n", 178 partitionID, index)); 179 } 180 } else 181 DBG(OUT(" partition %" B_PRId32 " not found\n", partitionID)); 182 183 return NULL; 184} 185 186 187bool 188delete_partition(partition_id partitionID) 189{ 190 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 191 if (KPartition* partition = manager->FindPartition(partitionID)) { 192 if (KPartition* parent = partition->Parent()) 193 return parent->RemoveChild(partition); 194 } 195 return false; 196} 197 198 199void 200partition_modified(partition_id partitionID) 201{ 202 // TODO: implemented 203} 204 205 206status_t 207scan_partition(partition_id partitionID) 208{ 209 // get the partition 210 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 211 KPartition* partition = manager->RegisterPartition(partitionID); 212 if (partition == NULL) 213 return B_ENTRY_NOT_FOUND; 214 PartitionRegistrar _(partition, true); 215 216 // scan it 217 return manager->ScanPartition(partition); 218} 219 220 221status_t 222get_default_partition_content_name(partition_id partitionID, 223 const char* fileSystemName, char* buffer, size_t bufferSize) 224{ 225 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 226 KPartition* partition = manager->RegisterPartition(partitionID); 227 if (partition == NULL) 228 return B_ENTRY_NOT_FOUND; 229 230 double size = partition->ContentSize(); 231 partition->Unregister(); 232 233 const char* const suffixes[] = { 234 "", "K", "M", "G", "T", "P", "E", NULL 235 }; 236 237 int index = 0; 238 while (size >= 1024 && suffixes[index + 1]) { 239 size /= 1024; 240 index++; 241 } 242 243 // Our kernel snprintf() ignores the precision argument, so we manually 244 // do one digit precision. 245 uint64 result = uint64(size * 10 + 0.5); 246 247 snprintf(buffer, bufferSize, "%s Volume (%" B_PRId32 ".%" B_PRId32 " %sB)", 248 fileSystemName, int32(result / 10), int32(result % 10), suffixes[index]); 249 250 return B_OK; 251} 252 253 254disk_system_id 255find_disk_system(const char* name) 256{ 257 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 258 if (ManagerLocker locker = manager) { 259 if (KDiskSystem* diskSystem = manager->FindDiskSystem(name)) 260 return diskSystem->ID(); 261 } 262 return -1; 263} 264 265 266bool 267update_disk_device_job_progress(disk_job_id jobID, float progress) 268{ 269#if 0 270 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 271 if (ManagerLocker locker = manager) { 272 if (KDiskDeviceJob* job = manager->FindJob(jobID)) { 273 job->UpdateProgress(progress); 274 return true; 275 } 276 } 277#endif 278 return false; 279} 280 281 282bool 283update_disk_device_job_extra_progress(disk_job_id jobID, const char* info) 284{ 285#if 0 286 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 287 if (ManagerLocker locker = manager) { 288 if (KDiskDeviceJob* job = manager->FindJob(jobID)) { 289 job->UpdateExtraProgress(info); 290 return true; 291 } 292 } 293#endif 294 return false; 295} 296 297 298bool 299set_disk_device_job_error_message(disk_job_id jobID, const char* message) 300{ 301#if 0 302 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 303 if (ManagerLocker locker = manager) { 304 if (KDiskDeviceJob* job = manager->FindJob(jobID)) { 305 job->SetErrorMessage(message); 306 return true; 307 } 308 } 309#endif 310 return false; 311} 312 313 314uint32 315update_disk_device_job_interrupt_properties(disk_job_id jobID, 316 uint32 interruptProperties) 317{ 318#if 0 319 bool paused = false; 320 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 321 do { 322 sem_id pauseSemaphore = -1; 323 if (ManagerLocker locker = manager) { 324 // get the job and the respective job queue 325 if (KDiskDeviceJob* job = manager->FindJob(jobID)) { 326 if (KDiskDeviceJobQueue* jobQueue = job->JobQueue()) { 327 // terminate if canceled. 328 if (jobQueue->IsCanceled()) { 329 if (jobQueue->ShallReverse()) 330 return B_DISK_DEVICE_JOB_REVERSE; 331 return B_DISK_DEVICE_JOB_CANCEL; 332 } 333 // set the new interrupt properties only when not 334 // requested to pause 335 if (jobQueue->IsPauseRequested()) 336 pauseSemaphore = jobQueue->ReadyToPause(); 337 else 338 job->SetInterruptProperties(interruptProperties); 339 } 340 } 341 } 342 // pause, if requested; redo the loop then 343 paused = (pauseSemaphore >= 0); 344 if (paused) { 345 acquire_sem(pauseSemaphore); 346 pauseSemaphore = -1; 347 } 348 } while (paused); 349#endif 350 return B_DISK_DEVICE_JOB_CONTINUE; 351} 352 353