1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 //--------------------------------------------------------------------- 5 /*! 6 \file intel.cpp 7 \brief disk_scanner partition module for "intel" style partitions. 8 */ 9 10 // TODO: The implementation is very strict right now. It rejects a partition 11 // completely, if it finds an error in its partition tables. We should see, 12 // what error can be handled gracefully, e.g. by ignoring the partition 13 // descriptor or the whole partition table sector. 14 15 #include <errno.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <unistd.h> 20 21 #include <util/kernel_cpp.h> 22 #include <ddm_modules.h> 23 #ifndef _BOOT_MODE 24 # include <DiskDeviceTypes.h> 25 #else 26 # include <boot/partitions.h> 27 #endif 28 #include <KernelExport.h> 29 30 #include "PartitionMap.h" 31 32 #define TRACE(x) ; 33 //#define TRACE(x) dprintf x 34 35 // module names 36 static const char *kPartitionMapModuleName 37 = "partitioning_systems/intel/map/v1"; 38 static const char *kExtendedPartitionModuleName 39 = "partitioning_systems/intel/extended/v1"; 40 41 // Maximal number of logical partitions per extended partition we allow. 42 static const int32 kMaxLogicalPartitionCount = 128; 43 44 45 // AutoDeleter 46 47 template<typename C> 48 class AutoDeleter { 49 public: 50 AutoDeleter(C *object) : fObject(object) {} 51 ~AutoDeleter() { delete fObject; } 52 void SetObject(C *object) { fObject = object; } 53 54 private: 55 C *fObject; 56 }; 57 58 59 // PartitionMapParser 60 61 class PartitionMapParser { 62 public: 63 PartitionMapParser(int deviceFD, off_t sessionOffset, off_t sessionSize, 64 int32 blockSize); 65 ~PartitionMapParser(); 66 67 status_t Parse(const uint8 *block, PartitionMap *map); 68 69 int32 CountPartitions() const; 70 const Partition *PartitionAt(int32 index) const; 71 72 private: 73 status_t _ParsePrimary(const partition_table_sector *pts); 74 status_t _ParseExtended(PrimaryPartition *primary, off_t offset); 75 status_t _ReadPTS(off_t offset, partition_table_sector *pts = NULL); 76 77 private: 78 int fDeviceFD; 79 off_t fSessionOffset; 80 off_t fSessionSize; 81 int32 fBlockSize; 82 partition_table_sector *fPTS; // while parsing 83 PartitionMap *fMap; // 84 }; 85 86 // constructor 87 PartitionMapParser::PartitionMapParser(int deviceFD, off_t sessionOffset, 88 off_t sessionSize, int32 blockSize) 89 : fDeviceFD(deviceFD), 90 fSessionOffset(sessionOffset), 91 fSessionSize(sessionSize), 92 fBlockSize(blockSize), 93 fPTS(NULL), 94 fMap(NULL) 95 { 96 } 97 98 // destructor 99 PartitionMapParser::~PartitionMapParser() 100 { 101 } 102 103 // Parse 104 status_t 105 PartitionMapParser::Parse(const uint8 *block, PartitionMap *map) 106 { 107 status_t error = (map ? B_OK : B_BAD_VALUE); 108 if (error == B_OK) { 109 fMap = map; 110 fMap->Unset(); 111 if (block) { 112 const partition_table_sector *pts 113 = (const partition_table_sector*)block; 114 error = _ParsePrimary(pts); 115 } else { 116 partition_table_sector pts; 117 error = _ReadPTS(0, &pts); 118 if (error == B_OK) 119 error = _ParsePrimary(&pts); 120 } 121 if (error == B_OK && !fMap->Check(fSessionSize, fBlockSize)) 122 error = B_BAD_DATA; 123 fMap = NULL; 124 } 125 return error; 126 } 127 128 // _ParsePrimary 129 status_t 130 PartitionMapParser::_ParsePrimary(const partition_table_sector *pts) 131 { 132 status_t error = (pts ? B_OK : B_BAD_VALUE); 133 // check the signature 134 if (error == B_OK && pts->signature != kPartitionTableSectorSignature) { 135 TRACE(("intel: _ParsePrimary(): invalid PTS signature\n")); 136 error = B_BAD_DATA; 137 } 138 // examine the table 139 if (error == B_OK) { 140 for (int32 i = 0; i < 4; i++) { 141 const partition_descriptor *descriptor = &pts->table[i]; 142 PrimaryPartition *partition = fMap->PrimaryPartitionAt(i); 143 partition->SetTo(descriptor, 0, fBlockSize); 144 // fail, if location is bad 145 if (!partition->CheckLocation(fSessionSize, fBlockSize)) { 146 error = B_BAD_DATA; 147 break; 148 } 149 } 150 } 151 // allocate a PTS buffer 152 if (error == B_OK) { 153 fPTS = new(nothrow) partition_table_sector; 154 if (!fPTS) 155 error = B_NO_MEMORY; 156 } 157 // parse extended partitions 158 if (error == B_OK) { 159 for (int32 i = 0; error == B_OK && i < 4; i++) { 160 PrimaryPartition *primary = fMap->PrimaryPartitionAt(i); 161 if (primary->IsExtended()) 162 error = _ParseExtended(primary, primary->Offset()); 163 } 164 } 165 // cleanup 166 if (fPTS) { 167 delete fPTS; 168 fPTS = NULL; 169 } 170 return error; 171 } 172 173 // _ParseExtended 174 status_t 175 PartitionMapParser::_ParseExtended(PrimaryPartition *primary, off_t offset) 176 { 177 status_t error = B_OK; 178 int32 partitionCount = 0; 179 while (error == B_OK) { 180 // check for cycles 181 if (++partitionCount > kMaxLogicalPartitionCount) { 182 TRACE(("intel: _ParseExtended(): Maximal number of logical " 183 "partitions for extended partition reached. Cycle?\n")); 184 error = B_BAD_DATA; 185 } 186 // read the PTS 187 if (error == B_OK) 188 error = _ReadPTS(offset); 189 // check the signature 190 if (error == B_OK 191 && fPTS->signature != kPartitionTableSectorSignature) { 192 TRACE(("intel: _ParseExtended(): invalid PTS signature\n")); 193 error = B_BAD_DATA; 194 } 195 // ignore the PTS, if any error occured till now 196 if (error != B_OK) { 197 TRACE(("intel: _ParseExtended(): ignoring this PTS\n")); 198 error = B_OK; 199 break; 200 } 201 // examine the table 202 LogicalPartition extended; 203 LogicalPartition nonExtended; 204 if (error == B_OK) { 205 for (int32 i = 0; error == B_OK && i < 4; i++) { 206 const partition_descriptor *descriptor = &fPTS->table[i]; 207 LogicalPartition *partition = NULL; 208 if (!descriptor->is_empty()) { 209 if (descriptor->is_extended()) { 210 if (extended.IsEmpty()) { 211 extended.SetTo(descriptor, offset, fBlockSize, 212 primary); 213 partition = &extended; 214 } else { 215 // only one extended partition allowed 216 error = B_BAD_DATA; 217 TRACE(("intel: _ParseExtended(): " 218 "only one extended partition allowed\n")); 219 } 220 } else { 221 if (nonExtended.IsEmpty()) { 222 nonExtended.SetTo(descriptor, offset, fBlockSize, 223 primary); 224 partition = &nonExtended; 225 } else { 226 // only one non-extended partition allowed 227 error = B_BAD_DATA; 228 TRACE(("intel: _ParseExtended(): only one " 229 "non-extended partition allowed\n")); 230 } 231 } 232 // check the partition's location 233 if (partition && !partition->CheckLocation(fSessionSize, 234 fBlockSize)) { 235 error = B_BAD_DATA; 236 } 237 } 238 } 239 } 240 // add non-extended partition to list 241 if (error == B_OK && !nonExtended.IsEmpty()) { 242 LogicalPartition *partition 243 = new(nothrow) LogicalPartition(nonExtended); 244 if (partition) 245 primary->AddLogicalPartition(partition); 246 else 247 error = B_NO_MEMORY; 248 } 249 // prepare to parse next extended partition 250 if (error == B_OK && !extended.IsEmpty()) 251 offset = extended.Offset(); 252 else 253 break; 254 } 255 return error; 256 } 257 258 // _ReadPTS 259 status_t 260 PartitionMapParser::_ReadPTS(off_t offset, partition_table_sector *pts) 261 { 262 status_t error = B_OK; 263 if (!pts) 264 pts = fPTS; 265 int32 toRead = sizeof(partition_table_sector); 266 // check the offset 267 if (offset < 0 || offset + toRead > fSessionSize) { 268 error = B_BAD_VALUE; 269 TRACE(("intel: _ReadPTS(): bad offset: %Ld\n", offset)); 270 // read 271 } else if (read_pos(fDeviceFD, fSessionOffset + offset, pts, toRead) 272 != toRead) { 273 #ifndef _BOOT_MODE 274 error = errno; 275 if (error == B_OK) 276 error = B_IO_ERROR; 277 #else 278 error = B_IO_ERROR; 279 #endif 280 TRACE(("intel: _ReadPTS(): reading the PTS failed: %s\n", 281 strerror(error))); 282 } 283 return error; 284 } 285 286 287 // intel partition map module 288 289 // module 290 static status_t pm_std_ops(int32 op, ...); 291 292 // scanning 293 static float pm_identify_partition(int fd, partition_data *partition, 294 void **cookie); 295 static status_t pm_scan_partition(int fd, partition_data *partition, 296 void *cookie); 297 static void pm_free_identify_partition_cookie(partition_data *partition, 298 void *cookie); 299 static void pm_free_partition_cookie(partition_data *partition); 300 static void pm_free_partition_content_cookie(partition_data *partition); 301 302 #ifndef _BOOT_MODE 303 // querying 304 static bool pm_supports_resizing_child(partition_data *partition, 305 partition_data *child); 306 307 static bool pm_validate_resize_child(partition_data *partition, 308 partition_data *child, off_t *size); 309 #endif 310 311 #ifdef _BOOT_MODE 312 partition_module_info gIntelPartitionMapModule = { 313 #else 314 static partition_module_info intel_partition_map_module = { 315 #endif 316 { 317 kPartitionMapModuleName, 318 0, 319 pm_std_ops 320 }, 321 kPartitionTypeIntel, // pretty_name 322 0, // flags 323 324 // scanning 325 pm_identify_partition, // identify_partition 326 pm_scan_partition, // scan_partition 327 pm_free_identify_partition_cookie, // free_identify_partition_cookie 328 pm_free_partition_cookie, // free_partition_cookie 329 pm_free_partition_content_cookie, // free_partition_content_cookie 330 331 #ifndef _BOOT_MODE 332 // querying 333 NULL, // supports_repairing 334 NULL, // supports_resizing 335 pm_supports_resizing_child, // supports_resizing_child 336 NULL, // supports_moving 337 NULL, // supports_moving_child 338 NULL, // supports_setting_name 339 NULL, // supports_setting_content_name 340 NULL, // supports_setting_type 341 NULL, // supports_setting_parameters 342 NULL, // supports_setting_content_parameters 343 NULL, // supports_initializing 344 NULL, // supports_initializing_child 345 NULL, // supports_creating_child 346 NULL, // supports_deleting_child 347 NULL, // is_sub_system_for 348 349 NULL, // validate_resize 350 pm_validate_resize_child, // validate_resize_child 351 NULL, // validate_move 352 NULL, // validate_move_child 353 NULL, // validate_set_name 354 NULL, // validate_set_content_name 355 NULL, // validate_set_type 356 NULL, // validate_set_parameters 357 NULL, // validate_set_content_parameters 358 NULL, // validate_initialize 359 NULL, // validate_create_child 360 NULL, // get_partitionable_spaces 361 NULL, // get_next_supported_type 362 NULL, // get_type_for_content_type 363 364 // shadow partition modification 365 NULL, // shadow_changed 366 367 // writing 368 NULL, // repair 369 NULL, // resize 370 NULL, // resize_child 371 NULL, // move 372 NULL, // move_child 373 NULL, // set_name 374 NULL, // set_content_name 375 NULL, // set_type 376 NULL, // set_parameters 377 NULL, // set_content_parameters 378 NULL, // initialize 379 NULL, // create_child 380 NULL, // delete_child 381 #else 382 NULL 383 #endif // _BOOT_MODE 384 }; 385 386 387 // intel extended partition module 388 389 // module 390 static status_t ep_std_ops(int32 op, ...); 391 392 // scanning 393 static float ep_identify_partition(int fd, partition_data *partition, 394 void **cookie); 395 static status_t ep_scan_partition(int fd, partition_data *partition, 396 void *cookie); 397 static void ep_free_identify_partition_cookie(partition_data *partition, 398 void *cookie); 399 static void ep_free_partition_cookie(partition_data *partition); 400 static void ep_free_partition_content_cookie(partition_data *partition); 401 402 #ifdef _BOOT_MODE 403 partition_module_info gIntelExtendedPartitionModule = { 404 #else 405 static partition_module_info intel_extended_partition_module = { 406 #endif 407 { 408 kExtendedPartitionModuleName, 409 0, 410 ep_std_ops 411 }, 412 kPartitionTypeIntelExtended, // pretty_name 413 0, // flags 414 415 // scanning 416 ep_identify_partition, // identify_partition 417 ep_scan_partition, // scan_partition 418 ep_free_identify_partition_cookie, // free_identify_partition_cookie 419 ep_free_partition_cookie, // free_partition_cookie 420 ep_free_partition_content_cookie, // free_partition_content_cookie 421 422 #ifndef _BOOT_MODE 423 // querying 424 NULL, // supports_repairing 425 NULL, // supports_resizing 426 NULL, // supports_resizing_child 427 NULL, // supports_moving 428 NULL, // supports_moving_child 429 NULL, // supports_setting_name 430 NULL, // supports_setting_content_name 431 NULL, // supports_setting_type 432 NULL, // supports_setting_parameters 433 NULL, // supports_setting_content_parameters 434 NULL, // supports_initializing 435 NULL, // supports_initializing_child 436 NULL, // supports_creating_child 437 NULL, // supports_deleting_child 438 NULL, // is_sub_system_for 439 440 NULL, // validate_resize 441 NULL, // validate_resize_child 442 NULL, // validate_move 443 NULL, // validate_move_child 444 NULL, // validate_set_name 445 NULL, // validate_set_content_name 446 NULL, // validate_set_type 447 NULL, // validate_set_parameters 448 NULL, // validate_set_content_parameters 449 NULL, // validate_initialize 450 NULL, // validate_create_child 451 NULL, // get_partitionable_spaces 452 NULL, // get_next_supported_type 453 NULL, // get_type_for_content_type 454 455 // shadow partition modification 456 NULL, // shadow_changed 457 458 // writing 459 NULL, // repair 460 NULL, // resize 461 NULL, // resize_child 462 NULL, // move 463 NULL, // move_child 464 NULL, // set_name 465 NULL, // set_content_name 466 NULL, // set_type 467 NULL, // set_parameters 468 NULL, // set_content_parameters 469 NULL, // initialize 470 NULL, // create_child 471 NULL, // delete_child 472 #else 473 NULL 474 #endif // _BOOT_MODE 475 }; 476 477 478 #ifndef _BOOT_MODE 479 extern "C" partition_module_info *modules[]; 480 _EXPORT partition_module_info *modules[] = 481 { 482 &intel_partition_map_module, 483 &intel_extended_partition_module, 484 NULL 485 }; 486 #endif 487 488 489 // intel partition map module 490 491 // pm_std_ops 492 static 493 status_t 494 pm_std_ops(int32 op, ...) 495 { 496 TRACE(("intel: pm_std_ops(0x%lx)\n", op)); 497 switch(op) { 498 case B_MODULE_INIT: 499 case B_MODULE_UNINIT: 500 return B_OK; 501 } 502 return B_ERROR; 503 } 504 505 // pm_identify_partition 506 static 507 float 508 pm_identify_partition(int fd, partition_data *partition, void **cookie) 509 { 510 // check parameters 511 if (fd < 0 || !partition || !cookie) 512 return -1; 513 TRACE(("intel: pm_identify_partition(%d, %ld: %lld, %lld, %ld)\n", fd, 514 partition->id, partition->offset, partition->size, 515 partition->block_size)); 516 // reject extended partitions 517 if (partition->type 518 && !strcmp(partition->type, kPartitionTypeIntelExtended)) { 519 return -1; 520 } 521 // check block size 522 uint32 blockSize = partition->block_size; 523 if (blockSize < sizeof(partition_table_sector)) { 524 TRACE(("intel: read_partition_map: bad block size: %ld, should be " 525 ">= %ld\n", blockSize, sizeof(partition_table_sector))); 526 return -1; 527 } 528 // allocate a PartitionMap 529 PartitionMap *map = new(nothrow) PartitionMap; 530 if (!map) 531 return -1; 532 // read the partition structure 533 PartitionMapParser parser(fd, 0, partition->size, blockSize); 534 status_t error = parser.Parse(NULL, map); 535 if (error == B_OK) { 536 *cookie = map; 537 return 0.5; 538 } 539 // cleanup, if not detected 540 delete map; 541 return -1; 542 } 543 544 // pm_scan_partition 545 static 546 status_t 547 pm_scan_partition(int fd, partition_data *partition, void *cookie) 548 { 549 AutoDeleter<PartitionMap> deleter((PartitionMap*)cookie); 550 // check parameters 551 if (fd < 0 || !partition || !cookie) 552 return B_ERROR; 553 TRACE(("intel: pm_scan_partition(%d, %ld: %lld, %lld, %ld)\n", fd, 554 partition->id, partition->offset, partition->size, 555 partition->block_size)); 556 PartitionMap *map = (PartitionMap*)cookie; 557 // fill in the partition_data structure 558 partition->status = B_PARTITION_VALID; 559 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM 560 | B_PARTITION_READ_ONLY 561 | B_DISK_SYSTEM_SUPPORTS_RESIZING_CHILD; 562 // TODO: Update when write functionality is implemented. 563 partition->content_size = partition->size; 564 // (no content_name and content_parameters) 565 // (content_type is set by the system) 566 partition->content_cookie = map; 567 // children 568 status_t error = B_OK; 569 int32 index = 0; 570 for (int32 i = 0; i < 4; i++) { 571 PrimaryPartition *primary = map->PrimaryPartitionAt(i); 572 if (!primary->IsEmpty()) { 573 partition_data *child = create_child_partition(partition->id, 574 index, -1); 575 index++; 576 if (!child) { 577 TRACE(("Creating child at index %ld failed\n", index - 1)); 578 // something went wrong 579 error = B_ERROR; 580 break; 581 } 582 child->offset = partition->offset + primary->Offset(); 583 child->size = primary->Size(); 584 child->block_size = partition->block_size; 585 // (no name) 586 char type[B_FILE_NAME_LENGTH]; 587 primary->GetTypeString(type); 588 child->type = strdup(type); 589 // parameters 590 char buffer[128]; 591 sprintf(buffer, "type = %u ; active = %d", primary->Type(), 592 primary->Active()); 593 child->parameters = strdup(buffer); 594 child->cookie = primary; 595 // check for allocation problems 596 if (!child->type || !child->parameters) { 597 error = B_NO_MEMORY; 598 break; 599 } 600 } 601 } 602 // keep map on success or cleanup on error 603 if (error == B_OK) { 604 deleter.SetObject(NULL); 605 } else { 606 partition->content_cookie = NULL; 607 for (int32 i = 0; i < partition->child_count; i++) { 608 if (partition_data *child = get_child_partition(partition->id, i)) 609 child->cookie = NULL; 610 } 611 } 612 return error; 613 } 614 615 // pm_free_identify_partition_cookie 616 static 617 void 618 pm_free_identify_partition_cookie(partition_data */*partition*/, void *cookie) 619 { 620 if (cookie) 621 delete (PartitionMap*)cookie; 622 } 623 624 // pm_free_partition_cookie 625 static 626 void 627 pm_free_partition_cookie(partition_data *partition) 628 { 629 // called for the primary partitions: the PrimaryPartition is allocated 630 // by the partition containing the partition map 631 if (partition) 632 partition->cookie = NULL; 633 } 634 635 // pm_free_partition_content_cookie 636 static 637 void 638 pm_free_partition_content_cookie(partition_data *partition) 639 { 640 if (partition && partition->content_cookie) { 641 delete (PartitionMap*)partition->content_cookie; 642 partition->content_cookie = NULL; 643 } 644 } 645 646 #ifndef _BOOT_MODE 647 // pm_supports_resizing_child 648 static 649 bool 650 pm_supports_resizing_child(partition_data *partition, partition_data *child) 651 { 652 return (partition && child && partition->content_type 653 && !strcmp(partition->content_type, kPartitionTypeIntel)); 654 } 655 656 // pm_validate_resize_child 657 static 658 bool 659 pm_validate_resize_child(partition_data *partition, partition_data *child, 660 off_t *size) 661 { 662 if (!partition || !child || !partition->content_type 663 || strcmp(partition->content_type, kPartitionTypeIntel) 664 || !size) { 665 return false; 666 } 667 // size remains the same? 668 if (*size == child->size) 669 return true; 670 // shrink partition? 671 if (*size < child->size) { 672 if (*size < 0) 673 *size = 0; 674 // make the size a multiple of the block size 675 *size = *size / partition->block_size * partition->block_size; 676 return true; 677 } 678 // grow partition 679 // child must completely lie within the parent partition 680 if (child->offset + *size > partition->offset + partition->size) 681 *size = partition->offset + partition->size - child->offset; 682 // child must not intersect with sibling partitions 683 for (int32 i = 0; i < partition->child_count; i++) { 684 partition_data *sibling = get_child_partition(partition->id, i); 685 if (sibling && sibling != child && sibling->offset > child->offset) { 686 if (child->offset + *size > sibling->offset) 687 *size = sibling->offset - child->offset; 688 } 689 } 690 // make the size a multiple of the block size 691 *size = *size / partition->block_size * partition->block_size; 692 return true; 693 } 694 #endif // _BOOT_MODE 695 696 697 // intel extended partition module 698 699 // ep_std_ops 700 static 701 status_t 702 ep_std_ops(int32 op, ...) 703 { 704 TRACE(("intel: ep_std_ops(0x%lx)\n", op)); 705 switch(op) { 706 case B_MODULE_INIT: 707 case B_MODULE_UNINIT: 708 return B_OK; 709 } 710 return B_ERROR; 711 } 712 713 // ep_identify_partition 714 static 715 float 716 ep_identify_partition(int fd, partition_data *partition, void **cookie) 717 { 718 // check parameters 719 if (fd < 0 || !partition || !cookie || !partition->cookie) 720 return -1; 721 TRACE(("intel: ep_identify_partition(%d, %lld, %lld, %ld)\n", fd, 722 partition->offset, partition->size, partition->block_size)); 723 // our parent must be a intel partition map partition and we must have 724 // extended partition type 725 if (!partition->type 726 || strcmp(partition->type, kPartitionTypeIntelExtended)) { 727 return -1; 728 } 729 partition_data *parent = get_parent_partition(partition->id); 730 if (!parent || !parent->content_type 731 || strcmp(parent->content_type, kPartitionTypeIntel)) { 732 return -1; 733 } 734 // things seem to be in order 735 return 0.5; 736 } 737 738 // ep_scan_partition 739 static 740 status_t 741 ep_scan_partition(int fd, partition_data *partition, void *cookie) 742 { 743 // check parameters 744 if (fd < 0 || !partition || !partition->cookie) 745 return B_ERROR; 746 partition_data *parent = get_parent_partition(partition->id); 747 if (!parent) 748 return B_ERROR; 749 PrimaryPartition *primary = (PrimaryPartition*)partition->cookie; 750 // fill in the partition_data structure 751 partition->status = B_PARTITION_VALID; 752 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM 753 | B_PARTITION_READ_ONLY; 754 // TODO: Update when write functionality is implemented. 755 partition->content_size = partition->size; 756 // (no content_name and content_parameters) 757 // (content_type is set by the system) 758 partition->content_cookie = primary; 759 // children 760 status_t error = B_OK; 761 int32 index = 0; 762 for (int32 i = 0; i < primary->CountLogicalPartitions(); i++) { 763 LogicalPartition *logical = primary->LogicalPartitionAt(i); 764 partition_data *child = create_child_partition(partition->id, 765 index, -1); 766 index++; 767 if (!child) { 768 // something went wrong 769 error = B_ERROR; 770 break; 771 } 772 child->offset = parent->offset + logical->Offset(); 773 child->size = logical->Size(); 774 child->block_size = partition->block_size; 775 // (no name) 776 char type[B_FILE_NAME_LENGTH]; 777 logical->GetTypeString(type); 778 child->type = strdup(type); 779 // parameters 780 char buffer[128]; 781 sprintf(buffer, "type = %u ; active = %d", logical->Type(), 782 logical->Active()); 783 child->parameters = strdup(buffer); 784 child->cookie = logical; 785 // check for allocation problems 786 if (!child->type || !child->parameters) { 787 error = B_NO_MEMORY; 788 break; 789 } 790 } 791 // cleanup on error 792 if (error != B_OK) { 793 partition->content_cookie = NULL; 794 for (int32 i = 0; i < partition->child_count; i++) { 795 if (partition_data *child = get_child_partition(partition->id, i)) 796 child->cookie = NULL; 797 } 798 } 799 return error; 800 } 801 802 // ep_free_identify_partition_cookie 803 static 804 void 805 ep_free_identify_partition_cookie(partition_data *partition, void *cookie) 806 { 807 // nothing to do 808 } 809 810 // ep_free_partition_cookie 811 static 812 void 813 ep_free_partition_cookie(partition_data *partition) 814 { 815 // the logical partition's cookie belongs to the partition map partition 816 if (partition) 817 partition->cookie = NULL; 818 } 819 820 // ep_free_partition_content_cookie 821 static 822 void 823 ep_free_partition_content_cookie(partition_data *partition) 824 { 825 // the extended partition's cookie belongs to the partition map partition 826 if (partition) 827 partition->content_cookie = NULL; 828 } 829 830