1 //---------------------------------------------------------------------- 2 // This software is part of the Haiku distribution and is covered 3 // by the MIT License. 4 //--------------------------------------------------------------------- 5 6 #include <stdio.h> 7 #include <string.h> 8 9 #include <Application.h> 10 #include <DiskDevice.h> 11 #include <DiskDeviceJob.h> 12 //#include <DiskDeviceList.h> 13 #include <DiskDeviceRoster.h> 14 #include <DiskDeviceVisitor.h> 15 #include <DiskSystem.h> 16 #include <KDiskDeviceManager.h> // for userland testing only 17 #include <Message.h> 18 #include <Messenger.h> 19 #include <Partition.h> 20 #include <Path.h> 21 //#include <ObjectList.h> 22 #include <OS.h> 23 24 const char *kTestFileDevice = "/boot/home/tmp/test-file-device"; 25 26 // DumpVisitor 27 class DumpVisitor : public BDiskDeviceVisitor { 28 public: 29 virtual bool Visit(BDiskDevice *device) 30 { 31 BPath path; 32 status_t error = device->GetPath(&path); 33 const char *pathString = NULL; 34 if (error == B_OK) 35 pathString = path.Path(); 36 else 37 pathString = strerror(error); 38 printf("device %ld: `%s'\n", device->ID(), pathString); 39 printf(" has media: %d\n", device->HasMedia()); 40 printf(" removable: %d\n", device->IsRemovableMedia()); 41 printf(" read only: %d\n", device->IsReadOnlyMedia()); 42 printf(" write once: %d\n", device->IsWriteOnceMedia()); 43 printf(" ---\n"); 44 Visit(device, 0); 45 return false; 46 } 47 48 virtual bool Visit(BPartition *partition, int32 level) 49 { 50 char prefix[128]; 51 sprintf(prefix, "%*s", 2 * (int)level, ""); 52 if (level > 0) { 53 BPath path; 54 status_t error = partition->GetPath(&path); 55 const char *pathString = NULL; 56 if (error == B_OK) 57 pathString = path.Path(); 58 else 59 pathString = strerror(error); 60 printf("%spartition %ld: `%s'\n", prefix, partition->ID(), 61 pathString); 62 } 63 printf("%s offset: %lld\n", prefix, partition->Offset()); 64 printf("%s size: %lld\n", prefix, partition->Size()); 65 printf("%s block size: %lu\n", prefix, partition->BlockSize()); 66 printf("%s index: %ld\n", prefix, partition->Index()); 67 printf("%s status: %lu\n", prefix, partition->Status()); 68 printf("%s file system: %d\n", prefix, 69 partition->ContainsFileSystem()); 70 printf("%s part. system: %d\n", prefix, 71 partition->ContainsPartitioningSystem()); 72 printf("%s device: %d\n", prefix, partition->IsDevice()); 73 printf("%s read only: %d\n", prefix, partition->IsReadOnly()); 74 printf("%s mounted: %d\n", prefix, partition->IsMounted()); 75 printf("%s flags: %lx\n", prefix, partition->Flags()); 76 printf("%s name: `%s'\n", prefix, partition->Name()); 77 printf("%s content name: `%s'\n", prefix, partition->ContentName()); 78 printf("%s type: `%s'\n", prefix, partition->Type()); 79 printf("%s content type: `%s'\n", prefix, partition->ContentType()); 80 // volume, icon,... 81 return false; 82 } 83 }; 84 85 /* 86 // print_time 87 void 88 print_time(const char *format, bigtime_t &time) 89 { 90 bigtime_t lastTime = time; 91 time = system_time(); 92 printf("%lld: %s took: %lld us\n", time, format, time - lastTime); 93 } 94 95 // TestApp 96 class TestApp : public BApplication { 97 public: 98 TestApp(const char *signature) 99 : BApplication(signature), 100 fDevices(20, true) 101 { 102 BDiskDeviceRoster roster; 103 bool done = false; 104 do { 105 BDiskDevice *device = new BDiskDevice; 106 done = (roster.GetNextDevice(device) != B_OK); 107 if (done) 108 delete device; 109 else 110 fDevices.AddItem(device); 111 } while (!done); 112 } 113 114 ~TestApp() 115 { 116 for (int32 i = 0; BDiskDevice *device = fDevices.ItemAt(i); i++) { 117 status_t error = device->Eject(true); 118 printf("eject device `%s': %s\n", device->Path(), strerror(error)); 119 } 120 } 121 122 virtual void MessageReceived(BMessage *message) 123 { 124 printf("TestApp::MessageReceived(%.4s)\n", (char*)&message->what); 125 switch (message->what) { 126 case B_DEVICE_UPDATE: 127 { 128 uint32 event; 129 if (message->FindInt32("event", (int32*)&event) == B_OK) { 130 switch (event) { 131 case B_DEVICE_MOUNT_POINT_MOVED: 132 MountPointMoved(message); 133 break; 134 case B_DEVICE_PARTITION_MOUNTED: 135 PartitionMounted(message); 136 break; 137 case B_DEVICE_PARTITION_UNMOUNTED: 138 PartitionUnmounted(message); 139 break; 140 case B_DEVICE_PARTITION_CHANGED: 141 PartitionChanged(message); 142 break; 143 case B_DEVICE_PARTITION_ADDED: 144 PartitionAdded(message); 145 break; 146 case B_DEVICE_PARTITION_REMOVED: 147 PartitionRemoved(message); 148 break; 149 case B_DEVICE_SESSION_ADDED: 150 SessionAdded(message); 151 break; 152 case B_DEVICE_SESSION_REMOVED: 153 SessionRemoved(message); 154 break; 155 case B_DEVICE_MEDIA_CHANGED: 156 MediaChanged(message); 157 break; 158 case B_DEVICE_ADDED: 159 DeviceAdded(message); 160 break; 161 case B_DEVICE_REMOVED: 162 DeviceRemoved(message); 163 break; 164 default: 165 printf("unhandled event\n"); 166 message->PrintToStream(); 167 break; 168 } 169 } 170 break; 171 } 172 default: 173 BApplication::MessageReceived(message); 174 break; 175 } 176 } 177 178 179 void MountPointMoved(BMessage *message) 180 { 181 printf("TestApp::MountPointMoved()\n"); 182 PrintPartitionInfo(message); 183 entry_ref oldRoot, newRoot; 184 BPath oldPath, newPath; 185 if (message->FindRef("old_directory", &oldRoot) == B_OK 186 && message->FindRef("new_directory", &newRoot) == B_OK 187 && oldPath.SetTo(&oldRoot) == B_OK 188 && newPath.SetTo(&newRoot) == B_OK) { 189 printf("old mount point: `%s'\n", oldPath.Path()); 190 printf("new mount point: `%s'\n", newPath.Path()); 191 } 192 193 } 194 195 void PartitionMounted(BMessage *message) 196 { 197 printf("TestApp::PartitionMounted()\n"); 198 PrintPartitionInfo(message); 199 } 200 201 void PartitionUnmounted(BMessage *message) 202 { 203 printf("TestApp::PartitionUnmounted()\n"); 204 PrintPartitionInfo(message); 205 } 206 207 // PartitionChanged 208 void PartitionChanged(BMessage *message) 209 { 210 printf("TestApp::PartitionUnmounted()\n"); 211 PrintPartitionInfo(message); 212 } 213 214 // PartitionAdded 215 void PartitionAdded(BMessage *message) 216 { 217 printf("TestApp::PartitionAdded()\n"); 218 PrintPartitionInfo(message); 219 } 220 221 // PartitionRemoved 222 void PartitionRemoved(BMessage *message) 223 { 224 printf("TestApp::PartitionRemoved()\n"); 225 PrintPartitionInfo(message); 226 } 227 228 // SessionAdded 229 void SessionAdded(BMessage *message) 230 { 231 printf("TestApp::SessionAdded()\n"); 232 PrintSessionInfo(message); 233 } 234 235 // SessionRemoved 236 void SessionRemoved(BMessage *message) 237 { 238 printf("TestApp::SessionRemoved()\n"); 239 PrintSessionInfo(message); 240 } 241 242 // MediaChanged 243 void MediaChanged(BMessage *message) 244 { 245 printf("TestApp::MediaChanged()\n"); 246 PrintDeviceInfo(message); 247 int32 id; 248 if (message->FindInt32("device_id", &id) == B_OK) { 249 for (int32 i = 0; BDiskDevice *device = fDevices.ItemAt(i); i++) { 250 if (device->ID() == id) { 251 bool updated; 252 status_t error = device->Update(&updated); 253 printf("updated: %d\n", updated); 254 if (error == B_OK) { 255 DumpVisitor visitor; 256 device->Traverse(&visitor); 257 } else { 258 printf("device->Update() failed: %s\n", 259 strerror(error)); 260 } 261 break; 262 } 263 } 264 } 265 } 266 267 // DeviceAdded 268 void DeviceAdded(BMessage *message) 269 { 270 printf("TestApp::DeviceAdded()\n"); 271 PrintDeviceInfo(message); 272 } 273 274 // DeviceRemoved 275 void DeviceRemoved(BMessage *message) 276 { 277 printf("TestApp::DeviceRemoved()\n"); 278 PrintDeviceInfo(message); 279 } 280 281 // PrintPartitionInfo 282 void PrintPartitionInfo(BMessage *message) 283 { 284 int32 deviceID; 285 int32 sessionID; 286 int32 partitionID; 287 if (message->FindInt32("device_id", &deviceID) == B_OK 288 && message->FindInt32("session_id", &sessionID) == B_OK 289 && message->FindInt32("partition_id", &partitionID) == B_OK) { 290 BDiskDeviceRoster roster; 291 BDiskDevice device; 292 BPartition *partition; 293 if (roster.GetPartitionWithID(partitionID, &device, &partition) 294 == B_OK) { 295 DumpVisitor().Visit(partition); 296 } 297 } 298 } 299 300 // PrintSessionInfo 301 void PrintSessionInfo(BMessage *message) 302 { 303 int32 deviceID; 304 int32 sessionID; 305 if (message->FindInt32("device_id", &deviceID) == B_OK 306 && message->FindInt32("session_id", &sessionID) == B_OK) { 307 BDiskDeviceRoster roster; 308 BDiskDevice device; 309 BSession *session; 310 if (roster.GetSessionWithID(sessionID, &device, &session) 311 == B_OK) { 312 DumpVisitor().Visit(session); 313 } 314 } 315 } 316 317 // PrintDeviceInfo 318 void PrintDeviceInfo(BMessage *message) 319 { 320 int32 deviceID; 321 if (message->FindInt32("device_id", &deviceID) == B_OK) { 322 BDiskDeviceRoster roster; 323 BDiskDevice device; 324 if (roster.GetDeviceWithID(deviceID, &device) == B_OK) 325 DumpVisitor().Visit(&device); 326 } 327 } 328 329 private: 330 BObjectList<BDiskDevice> fDevices; 331 }; 332 333 class MyDeviceList : public BDiskDeviceList { 334 public: 335 MyDeviceList(bool useOwnLocker) 336 : BDiskDeviceList(useOwnLocker) 337 { 338 } 339 340 virtual void MountPointMoved(BPartition *partition) 341 { 342 printf("MountPointMoved()\n"); 343 DumpVisitor().Visit(partition); 344 } 345 346 virtual void PartitionMounted(BPartition *partition) 347 { 348 printf("PartitionMounted()\n"); 349 DumpVisitor().Visit(partition); 350 } 351 352 virtual void PartitionUnmounted(BPartition *partition) 353 { 354 printf("PartitionUnmounted()\n"); 355 DumpVisitor().Visit(partition); 356 } 357 358 virtual void PartitionChanged(BPartition *partition) 359 { 360 printf("PartitionChanged()\n"); 361 DumpVisitor().Visit(partition); 362 } 363 364 virtual void PartitionAdded(BPartition *partition) 365 { 366 printf("PartitionAdded()\n"); 367 DumpVisitor().Visit(partition); 368 } 369 370 virtual void PartitionRemoved(BPartition *partition) 371 { 372 printf("PartitionRemoved()\n"); 373 DumpVisitor().Visit(partition); 374 } 375 376 virtual void SessionAdded(BSession *session) 377 { 378 printf("SessionAdded()\n"); 379 DumpVisitor().Visit(session); 380 } 381 382 virtual void SessionRemoved(BSession *session) 383 { 384 printf("SessionRemoved()\n"); 385 DumpVisitor().Visit(session); 386 } 387 388 virtual void MediaChanged(BDiskDevice *device) 389 { 390 printf("MediaChanged()\n"); 391 DumpVisitor().Visit(device); 392 } 393 394 virtual void DeviceAdded(BDiskDevice *device) 395 { 396 printf("DeviceAdded()\n"); 397 DumpVisitor().Visit(device); 398 } 399 400 virtual void DeviceRemoved(BDiskDevice *device) 401 { 402 printf("DeviceRemoved()\n"); 403 DumpVisitor().Visit(device); 404 } 405 }; 406 407 408 // TestApp2 409 class TestApp2 : public BApplication { 410 public: 411 TestApp2(const char *signature) 412 : BApplication(signature), 413 fDeviceList(false) 414 { 415 printf("dumping empty list...\n"); 416 DumpVisitor visitor; 417 fDeviceList.Traverse(&visitor); 418 printf("dumping done\n"); 419 printf("fetching\n"); 420 status_t error = fDeviceList.Fetch(); 421 if (error == B_OK) 422 fDeviceList.Traverse(&visitor); 423 else 424 printf("fetching failed: %s\n", strerror(error)); 425 printf("unset\n"); 426 fDeviceList.Unset(); 427 printf("dumping empty list...\n"); 428 fDeviceList.Traverse(&visitor); 429 printf("dumping done\n"); 430 AddHandler(&fDeviceList); 431 error = fDeviceList.Fetch(); 432 if (error != B_OK) 433 printf("fetching failed: %s\n", strerror(error)); 434 } 435 436 ~TestApp2() 437 { 438 Lock(); 439 RemoveHandler(&fDeviceList); 440 Unlock(); 441 } 442 443 virtual void ReadyToRun() 444 { 445 // list the available partition add-ons 446 BDiskDeviceRoster roster; 447 char shortName[B_FILE_NAME_LENGTH]; 448 char longName[B_FILE_NAME_LENGTH]; 449 printf("partition add-ons:\n"); 450 while (roster.GetNextPartitioningSystem(shortName, longName) == B_OK) { 451 printf(" `%s' (`%s')\n", shortName, longName); 452 } 453 fDeviceList.Lock(); 454 for (int32 i = 0; BDiskDevice *device = fDeviceList.DeviceAt(i); i++) { 455 printf("device: `%s'\n", device->Path()); 456 if (!strcmp(device->Path(), "/dev/disk/virtual/0/raw")) { 457 if (BSession *session = device->SessionAt(0)) { 458 BString parameters; 459 bool cancelled = false; 460 status_t error = session->GetPartitioningParameters( 461 "intel", ¶meters, BRect(), &cancelled); 462 if (error == B_OK) { 463 printf("partitioning parameters: `%s'\n", 464 parameters.String()); 465 } else if (error == B_ERROR && cancelled) { 466 printf("partitioning dialog cancelled\n"); 467 } else { 468 printf("error getting partitioning parameters: %s\n", 469 strerror(error)); 470 } 471 } 472 break; 473 } 474 } 475 fDeviceList.Unlock(); 476 } 477 478 private: 479 MyDeviceList fDeviceList; 480 }; 481 */ 482 483 // wait_for_jobs 484 void 485 wait_for_jobs() 486 { 487 BDiskDeviceRoster roster; 488 bool activeJobs = false; 489 do { 490 if (activeJobs) 491 snooze(50000); 492 activeJobs = false; 493 printf("disk device jobs at time %lld\n", system_time()); 494 roster.RewindActiveJobs(); 495 BDiskDeviceJob job; 496 while (roster.GetNextActiveJob(&job) == B_OK) { 497 activeJobs = true; 498 printf(" job %ld:\n", job.ID()); 499 printf(" type: %lu\n", job.Type()); 500 printf(" description: `%s'\n", job.Description()); 501 printf(" partition: %ld\n", job.PartitionID()); 502 printf(" status: %lu\n", job.Status()); 503 printf(" progress: %f\n", job.Progress()); 504 } 505 if (!activeJobs) 506 printf(" none\n"); 507 } while (activeJobs); 508 } 509 510 // main 511 int 512 main() 513 { 514 /* 515 TestApp app("application/x-vnd.obos-disk-device-test"); 516 BDiskDeviceRoster roster; 517 DumpVisitor visitor; 518 roster.Traverse(&visitor); 519 status_t error = B_OK; 520 error = roster.StartWatching(BMessenger(&app)); 521 if (error != B_OK) 522 printf("start watching failed: %s\n", strerror(error)); 523 if (error == B_OK) 524 app.Run(); 525 error = roster.StopWatching(BMessenger(&app)); 526 if (error != B_OK) 527 printf("stop watching failed: %s\n", strerror(error)); 528 */ 529 /* 530 TestApp2 app("application/x-vnd.obos-disk-device-test"); 531 app.Run(); 532 return 0; 533 */ 534 535 // for userland testing only 536 KDiskDeviceManager::CreateDefault(); 537 KDiskDeviceManager::Default()->InitialDeviceScan(); 538 539 // wait till all (scan) jobs are done 540 wait_for_jobs(); 541 // add a file device 542 BDiskDeviceRoster roster; 543 partition_id id = roster.RegisterFileDevice(kTestFileDevice); 544 if (id < B_OK) 545 printf("registering the file device failed: %s\n", strerror(id)); 546 else { 547 // wait till all (scan) jobs are done 548 wait_for_jobs(); 549 } 550 // list all disk devices and partitions 551 DumpVisitor visitor; 552 roster.VisitEachPartition(&visitor); 553 // list disk systems 554 BDiskSystem diskSystem; 555 while (roster.GetNextDiskSystem(&diskSystem) == B_OK) { 556 printf("disk system:\n"); 557 printf(" name: `%s'\n", diskSystem.Name()); 558 printf(" pretty name: `%s'\n", diskSystem.PrettyName()); 559 printf(" file system: %d (!%d)\n", diskSystem.IsFileSystem(), 560 diskSystem.IsPartitioningSystem()); 561 // flags 562 printf(" flags:\n"); 563 bool mounted = false; 564 bool supports = diskSystem.SupportsDefragmenting(&mounted); 565 printf(" defragmenting: %d (%d)\n", supports, mounted); 566 supports = diskSystem.SupportsRepairing(true, &mounted); 567 printf(" checking: %d (%d)\n", supports, mounted); 568 supports = diskSystem.SupportsRepairing(false, &mounted); 569 printf(" repairing: %d (%d)\n", supports, mounted); 570 supports = diskSystem.SupportsResizing(&mounted); 571 printf(" resizing: %d (%d)\n", supports, mounted); 572 supports = diskSystem.SupportsResizingChild(); 573 printf(" resizing child: %d\n", supports); 574 supports = diskSystem.SupportsMoving(&mounted); 575 printf(" moving: %d (%d)\n", supports, mounted); 576 supports = diskSystem.SupportsMovingChild(); 577 printf(" moving child: %d\n", supports); 578 supports = diskSystem.SupportsSettingName(); 579 printf(" setting name: %d\n", supports); 580 supports = diskSystem.SupportsSettingContentName(&mounted); 581 printf(" setting content name: %d (%d)\n", supports, mounted); 582 supports = diskSystem.SupportsSettingType(); 583 printf(" setting type: %d\n", supports); 584 supports = diskSystem.SupportsSettingParameters(); 585 printf(" setting params: %d\n", supports); 586 supports = diskSystem.SupportsSettingContentParameters(&mounted); 587 printf(" setting content params: %d (%d)\n", supports, mounted); 588 supports = diskSystem.SupportsCreatingChild(); 589 printf(" creating child: %d\n", supports); 590 supports = diskSystem.SupportsDeletingChild(); 591 printf(" deleting child: %d\n", supports); 592 supports = diskSystem.SupportsInitializing(); 593 printf(" initializing: %d\n", supports); 594 } 595 // get the file device 596 BDiskDevice device; 597 status_t error = roster.GetDeviceWithID(id, &device); 598 if (error != B_OK) 599 printf("Couldn't get device: %s\n", strerror(error)); 600 // prepare for modifications 601 error = device.PrepareModifications(); 602 if (error != B_OK) 603 printf("Preparing modifications failed: %s\n", strerror(error)); 604 // test resize a partition 605 if (error == B_OK) { 606 if (BPartition *partition = device.ChildAt(1)) { 607 // uninitialize contents 608 status_t status = partition->Uninitialize(); 609 if (status != B_OK) { 610 printf("Uninitializing the partition failed: %s\n", 611 strerror(status)); 612 } 613 // resize 614 status = partition->Resize(1024 * 200); 615 if (status != B_OK) { 616 printf("Resizing the partition failed: %s\n", 617 strerror(status)); 618 } 619 } 620 printf("\nDevice after changing it:\n"); 621 device.VisitEachDescendant(&visitor); 622 } 623 // cancel modifications 624 /* if (error == B_OK) { 625 error = device.CancelModifications(); 626 if (error != B_OK) 627 printf("Cancelling modifications failed: %s\n", strerror(error)); 628 } 629 */ // commit modifications 630 if (error == B_OK) { 631 error = device.CommitModifications(); 632 if (error != B_OK) 633 printf("Committing modifications failed: %s\n", strerror(error)); 634 } 635 wait_for_jobs(); 636 // printf("\nDevice after cancelling the changes:\n"); 637 printf("\nDevice after committing the changes:\n"); 638 device.VisitEachDescendant(&visitor); 639 640 // for userland testing only 641 KDiskDeviceManager::DeleteDefault(); 642 } 643 644