Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

fmtexp.c

Go to the documentation of this file.
00001 #include "precomp.h" 00002 #pragma hdrstop 00003 00004 #define READ_SIZE 65536 00005 00006 typedef struct { 00007 UCHAR IntelNearJumpCommand[1]; // Intel Jump command 00008 UCHAR BootStrapJumpOffset[2]; // offset of boot strap code 00009 UCHAR OemData[8]; // OEM data 00010 UCHAR BytesPerSector[2]; // BPB 00011 UCHAR SectorsPerCluster[1]; // 00012 UCHAR ReservedSectors[2]; // 00013 UCHAR Fats[1]; // 00014 UCHAR RootEntries[2]; // 00015 UCHAR Sectors[2]; // 00016 UCHAR Media[1]; // 00017 UCHAR SectorsPerFat[2]; // 00018 UCHAR SectorsPerTrack[2]; // 00019 UCHAR Heads[2]; // 00020 UCHAR HiddenSectors[4]; // 00021 UCHAR LargeSectors[4]; // 00022 UCHAR PhysicalDrive[1]; // 0 = removable, 80h = fixed 00023 UCHAR CurrentHead[1]; // not used by fs utils 00024 UCHAR Signature[1]; // boot signature 00025 UCHAR SerialNumber[4]; // serial number 00026 UCHAR Label[11]; // volume label, aligned padded 00027 UCHAR SystemIdText[8]; // system ID, FAT for example 00028 } UNALIGNED_SECTOR_ZERO, *PUNALIGNED_SECTOR_ZERO; 00029 00030 00031 #define CSEC_FAT32MEG 65536 00032 #define CSEC_FAT16BIT 32680 00033 #define SYSID_FAT12BIT 1 00034 #define SYSID_FAT16BIT 4 00035 #define SYSID_FAT32MEG 6 00036 #define MIN_CLUS_BIG 4085 // Minimum clusters for a big FAT. 00037 #define MAX_CLUS_BIG 65525 // Maximum + 1 clusters for big FAT. 00038 00039 00040 00041 ARC_STATUS 00042 FmtIsFatPartition( 00043 IN ULONG PartitionId, 00044 IN ULONG SectorSize, 00045 OUT PBOOLEAN IsFatPartition 00046 ) 00047 /*++ 00048 00049 Routine Description: 00050 00051 This routine computes whether or not the given partition is a FAT 00052 partition. 00053 00054 Arguments: 00055 00056 VolumeId - Supplies the volume to check. 00057 SectorSize - Supplies the number of bytes per sector. 00058 IsFatPartition - Returns whether or not the partition is FAT. 00059 00060 Return Value: 00061 00062 LowReadSectors, ENOMEM, ESUCCESS 00063 00064 --*/ 00065 { 00066 PUCHAR Buffer; 00067 ARC_STATUS r; 00068 00069 if (!(Buffer = AllocateMemory(SectorSize*2))) { 00070 return ENOMEM; 00071 } 00072 00073 r = LowReadSectors(PartitionId, SectorSize, 0, 2, Buffer); 00074 00075 if (r != ESUCCESS) { 00076 FreeMemory(Buffer); 00077 return r; 00078 } 00079 00080 *IsFatPartition = Buffer[510] == 0x55 && 00081 Buffer[511] == 0xAA && 00082 Buffer[0x10] != 0 && 00083 Buffer[0x15] == Buffer[SectorSize] && 00084 Buffer[SectorSize + 1] == 0xFF && 00085 Buffer[SectorSize + 2] == 0xFF; 00086 00087 FreeMemory(Buffer); 00088 return ESUCCESS; 00089 } 00090 00091 00092 ARC_STATUS 00093 FmtIsFat( 00094 IN PCHAR PartitionPath, 00095 OUT PBOOLEAN IsFatPartition 00096 ) 00097 /*++ 00098 00099 Routine Description: 00100 00101 This routine computes whether or not the given partition is a FAT 00102 partition. 00103 00104 Arguments: 00105 00106 PartitionPath - Supplies a path to the partition. 00107 IsFatPartition - Returns whether or not the partition is FAT. 00108 00109 Return Value: 00110 00111 ArcOpen, ArcClose, LowGetPartitionGeometry, FmtIsFatPartition 00112 00113 --*/ 00114 { 00115 ULONG partition_id; 00116 ARC_STATUS r; 00117 ULONG total_sectors, sector_size, sec_per_track, heads; 00118 00119 r = LowGetPartitionGeometry(PartitionPath, &total_sectors, &sector_size, 00120 &sec_per_track, &heads); 00121 00122 if (r != ESUCCESS) { 00123 return r; 00124 } 00125 00126 r = ArcOpen(PartitionPath, ArcOpenReadOnly, &partition_id); 00127 00128 if (r != ESUCCESS) { 00129 return r; 00130 } 00131 00132 r = FmtIsFatPartition(partition_id, sector_size, IsFatPartition); 00133 00134 if (r != ESUCCESS) { 00135 ArcClose(partition_id); 00136 return r; 00137 } 00138 00139 return ArcClose(partition_id); 00140 } 00141 00142 00143 00144 00145 USHORT 00146 ComputeSecPerCluster( 00147 IN ULONG NumSectors, 00148 IN BOOLEAN SmallFat 00149 ) 00150 /*++ 00151 00152 Routine Description: 00153 00154 This routine computes the number of sectors per cluster. 00155 00156 Arguments: 00157 00158 NumSectors - Supplies the number of sectors on the disk. 00159 SmallFat - Supplies whether or not the FAT should be small. 00160 00161 Return Value: 00162 00163 The number of sectors per cluster necessary. 00164 00165 --*/ 00166 { 00167 ULONG threshold; 00168 USHORT sec_per_clus; 00169 USHORT min_sec_per_clus; 00170 00171 threshold = SmallFat ? MIN_CLUS_BIG : MAX_CLUS_BIG; 00172 sec_per_clus = 1; 00173 00174 while (NumSectors >= threshold) { 00175 sec_per_clus *= 2; 00176 threshold *= 2; 00177 } 00178 00179 if (SmallFat) { 00180 min_sec_per_clus = 8; 00181 } else { 00182 min_sec_per_clus = 4; 00183 } 00184 00185 return max(sec_per_clus, min_sec_per_clus); 00186 } 00187 00188 00189 ULONG 00190 ComputeNewSerialNumber( 00191 IN ULONG Seed 00192 ) 00193 /*++ 00194 00195 Routine Description: 00196 00197 This routine computes a new serial number for a volume. 00198 00199 Arguments: 00200 00201 Seed - Supplies a seed for the serial number. 00202 00203 Return Value: 00204 00205 A new volume serial number. 00206 00207 --*/ 00208 { 00209 PUCHAR p; 00210 ULONG i; 00211 00212 p = (PUCHAR) &Seed; 00213 00214 for (i = 0; i < sizeof(ULONG); i++) { 00215 00216 Seed += p[i]; 00217 Seed = (Seed >> 2) + (Seed << 30); 00218 } 00219 00220 return Seed; 00221 } 00222 00223 00224 VOID 00225 EditFat( 00226 IN USHORT ClusterNumber, 00227 IN USHORT ClusterEntry, 00228 IN OUT PUCHAR Fat, 00229 IN BOOLEAN SmallFat 00230 ) 00231 /*++ 00232 00233 Routine Description: 00234 00235 This routine edits the FAT entry 'ClusterNumber' with 'ClusterEntry'. 00236 00237 Arguments: 00238 00239 ClusterNumber - Supplies the number of the cluster to edit. 00240 ClusterEntry - Supplies the new value for that cluster number. 00241 Fat - Supplies the FAT to edit. 00242 SmallFat - Supplies whether or not the FAT is small. 00243 00244 Return Value: 00245 00246 None. 00247 00248 --*/ 00249 { 00250 ULONG n; 00251 00252 if (SmallFat) { 00253 00254 n = ClusterNumber*3; 00255 if (n%2) { 00256 Fat[n/2] = (UCHAR) ((Fat[n/2]&0x0F) | ((ClusterEntry&0x000F)<<4)); 00257 Fat[n/2 + 1] = (UCHAR) ((ClusterEntry&0x0FF0)>>4); 00258 } else { 00259 Fat[n/2] = (UCHAR) (ClusterEntry&0x00FF); 00260 Fat[n/2 + 1] = (UCHAR) ((Fat[n/2 + 1]&0xF0) | 00261 ((ClusterEntry&0x0F00)>>8)); 00262 } 00263 00264 } else { 00265 00266 ((PUSHORT) Fat)[ClusterNumber] = ClusterEntry; 00267 00268 } 00269 } 00270 00271 00272 ARC_STATUS 00273 FmtFillFormatBuffer( 00274 IN ULONG NumberOfSectors, 00275 IN ULONG SectorSize, 00276 IN ULONG SectorsPerTrack, 00277 IN ULONG NumberOfHeads, 00278 IN ULONG NumberOfHiddenSectors, 00279 OUT PVOID FormatBuffer, 00280 IN ULONG FormatBufferSize, 00281 OUT PULONG SuperAreaSize, 00282 IN ULONG TimeSeed, 00283 IN PULONG BadSectorsList, 00284 IN ULONG NumberOfBadSectors 00285 ) 00286 /*++ 00287 00288 Routine Description: 00289 00290 This routine computes a FAT super area based on the disk size, 00291 disk geometry, and bad sectors of the volume. 00292 00293 Arguments: 00294 00295 NumberOfSectors - Supplies the number of sectors on the volume. 00296 SectorSize - Supplies the number of bytes per sector. 00297 SectorsPerTrack - Supplies the number of sectors per track. 00298 NumberOfHeads - Supplies the number of heads. 00299 NumberOfHiddenSectors - Supplies the number of hidden sectors. 00300 FormatBuffer - Returns the super area for the volume. 00301 FormatBufferSize - Supplies the number of bytes in the supplied 00302 buffer. 00303 SuperAreaSize - Returns the number of bytes in the super area. 00304 TimeSeed - Supplies a time seed for serial number. 00305 BadSectorsList - Supplies the list of bad sectors on the volume. 00306 NumberOfBadSectors - Supplies the number of bad sectors in the list. 00307 00308 Return Value: 00309 00310 ENOMEM - The buffer wasn't big enough. 00311 E2BIG - The disk is too large to be formatted. 00312 EIO - There is a bad sector in the super area. 00313 EINVAL - There is a bad sector off the end of the disk. 00314 ESUCCESS 00315 00316 --*/ 00317 { 00318 PUNALIGNED_SECTOR_ZERO psecz; 00319 PUCHAR puchar; 00320 USHORT tmp_ushort; 00321 ULONG tmp_ulong; 00322 BOOLEAN small_fat; 00323 ULONG num_sectors; 00324 ULONG partition_id; 00325 ULONG sec_per_fat; 00326 ULONG sec_per_root; 00327 ULONG sec_per_clus; 00328 ULONG i; 00329 ULONG sec_per_sa; 00330 00331 00332 // First memset the buffer to all zeros; 00333 memset(FormatBuffer, 0, (unsigned int) FormatBufferSize); 00334 00335 00336 // Make sure that there's enough room for the BPB. 00337 00338 if (!FormatBuffer || FormatBufferSize < SectorSize) { 00339 return ENOMEM; 00340 } 00341 00342 // Compute the number of sectors on disk. 00343 num_sectors = NumberOfSectors; 00344 00345 // Compute the partition identifier. 00346 partition_id = num_sectors < CSEC_FAT16BIT ? SYSID_FAT12BIT : 00347 num_sectors < CSEC_FAT32MEG ? SYSID_FAT16BIT : 00348 SYSID_FAT32MEG; 00349 00350 // Compute whether or not to have a big or small FAT. 00351 small_fat = (BOOLEAN) (partition_id == SYSID_FAT12BIT); 00352 00353 00354 psecz = (PUNALIGNED_SECTOR_ZERO) FormatBuffer; 00355 puchar = (PUCHAR) FormatBuffer; 00356 00357 // Set up the jump instruction. 00358 psecz->IntelNearJumpCommand[0] = 0xEB; 00359 tmp_ushort = 0x903C; 00360 memcpy(psecz->BootStrapJumpOffset, &tmp_ushort, sizeof(USHORT)); 00361 00362 // Set up the OEM data. 00363 memcpy(psecz->OemData, "WINNT1.0", 8); // BUGBUG norbertk 00364 00365 // Set up the bytes per sector. 00366 tmp_ushort = (USHORT) SectorSize; 00367 memcpy(psecz->BytesPerSector, &tmp_ushort, sizeof(USHORT)); 00368 00369 // Set up the number of sectors per cluster. 00370 sec_per_clus = ComputeSecPerCluster(num_sectors, small_fat); 00371 if (sec_per_clus > 128) { 00372 00373 // The disk is too large to be formatted. 00374 return E2BIG; 00375 } 00376 psecz->SectorsPerCluster[0] = (UCHAR) sec_per_clus; 00377 00378 // Set up the number of reserved sectors. 00379 tmp_ushort = 1; 00380 memcpy(psecz->ReservedSectors, &tmp_ushort, sizeof(USHORT)); 00381 00382 // Set up the number of FATs. 00383 psecz->Fats[0] = 2; 00384 00385 // Set up the number of root entries and number of sectors for the root. 00386 tmp_ushort = 512; 00387 memcpy(psecz->RootEntries, &tmp_ushort, sizeof(USHORT)); 00388 sec_per_root = (512*32 - 1)/SectorSize + 1; 00389 00390 // Set up the number of sectors. 00391 if (num_sectors >= 1<<16) { 00392 tmp_ushort = 0; 00393 tmp_ulong = num_sectors; 00394 } else { 00395 tmp_ushort = (USHORT) num_sectors; 00396 tmp_ulong = 0; 00397 } 00398 memcpy(psecz->Sectors, &tmp_ushort, sizeof(USHORT)); 00399 memcpy(psecz->LargeSectors, &tmp_ulong, sizeof(ULONG)); 00400 00401 // Set up the media byte. 00402 psecz->Media[0] = 0xF8; 00403 00404 // Set up the number of sectors per FAT. 00405 if (small_fat) { 00406 sec_per_fat = num_sectors/(2 + SectorSize*sec_per_clus*2/3); 00407 } else { 00408 sec_per_fat = num_sectors/(2 + SectorSize*sec_per_clus/2); 00409 } 00410 sec_per_fat++; 00411 tmp_ushort = (USHORT) sec_per_fat; 00412 memcpy(psecz->SectorsPerFat, &tmp_ushort, sizeof(USHORT)); 00413 00414 // Set up the number of sectors per track. 00415 tmp_ushort = (USHORT) SectorsPerTrack; 00416 memcpy(psecz->SectorsPerTrack, &tmp_ushort, sizeof(USHORT)); 00417 00418 // Set up the number of heads. 00419 tmp_ushort = (USHORT) NumberOfHeads; 00420 memcpy(psecz->Heads, &tmp_ushort, sizeof(USHORT)); 00421 00422 // Set up the number of hidden sectors. 00423 memcpy(psecz->HiddenSectors, &NumberOfHiddenSectors, sizeof(ULONG)); 00424 00425 // Set up the physical drive number. 00426 psecz->PhysicalDrive[0] = 0x80; 00427 00428 // Set up the BPB signature. 00429 psecz->Signature[0] = 0x29; 00430 00431 // Set up the serial number. 00432 tmp_ulong = ComputeNewSerialNumber(TimeSeed); 00433 memcpy(psecz->SerialNumber, &tmp_ulong, sizeof(ULONG)); 00434 00435 // Set up the system id. 00436 memcpy(psecz->SystemIdText, "FAT ", 8); 00437 00438 // Set up the boot signature. 00439 puchar[510] = 0x55; 00440 puchar[511] = 0xAA; 00441 00442 00443 // Now make sure that the buffer has enough room for both of the 00444 // FATs and the root directory. 00445 00446 sec_per_sa = 1 + 2*sec_per_fat + sec_per_root; 00447 *SuperAreaSize = SectorSize*sec_per_sa; 00448 if (*SuperAreaSize > FormatBufferSize) { 00449 return ENOMEM; 00450 } 00451 00452 00453 // Set up the first FAT. 00454 00455 puchar[SectorSize] = 0xF8; 00456 puchar[SectorSize + 1] = 0xFF; 00457 puchar[SectorSize + 2] = 0xFF; 00458 00459 if (!small_fat) { 00460 puchar[SectorSize + 3] = 0xFF; 00461 } 00462 00463 00464 for (i = 0; i < NumberOfBadSectors; i++) { 00465 00466 if (BadSectorsList[i] < sec_per_sa) { 00467 // There's a bad sector in the super area. 00468 return EIO; 00469 } 00470 00471 if (BadSectorsList[i] >= num_sectors) { 00472 // Bad sector out of range. 00473 return EINVAL; 00474 } 00475 00476 // Compute the bad cluster number; 00477 tmp_ushort = (USHORT) 00478 ((BadSectorsList[i] - sec_per_sa)/sec_per_clus + 2); 00479 00480 EditFat(tmp_ushort, (USHORT) 0xFFF7, &puchar[SectorSize], small_fat); 00481 } 00482 00483 00484 // Copy the first FAT onto the second. 00485 00486 memcpy(&puchar[SectorSize*(1 + sec_per_fat)], 00487 &puchar[SectorSize], 00488 (unsigned int) SectorSize*sec_per_fat); 00489 00490 return ESUCCESS; 00491 } 00492 00493 00494 ARC_STATUS 00495 FmtVerifySectors( 00496 IN ULONG PartitionId, 00497 IN ULONG NumberOfSectors, 00498 IN ULONG SectorSize, 00499 OUT PULONG* BadSectorsList, 00500 OUT PULONG NumberOfBadSectors 00501 ) 00502 /*++ 00503 00504 Routine Description: 00505 00506 This routine verifies all of the sectors on the volume. 00507 It returns a pointer to a list of bad sectors. The pointer 00508 will be NULL if there was an error detected. 00509 00510 Arguments: 00511 00512 PartitionId - Supplies a handle to the partition for reading. 00513 NumberOfSectors - Supplies the number of partition sectors. 00514 SectorSize - Supplies the number of bytes per sector. 00515 BadSectorsList - Returns the list of bad sectors. 00516 NumberOfBadSectors - Returns the number of bad sectors in the list. 00517 00518 Return Value: 00519 00520 ENOMEM, ESUCCESS 00521 00522 --*/ 00523 { 00524 ULONG num_read_sec; 00525 PVOID read_buffer; 00526 ULONG i, j; 00527 PULONG bad_sec_buf; 00528 ULONG max_num_bad; 00529 ARC_STATUS r; 00530 ULONG percent; 00531 00532 if (!(read_buffer = AllocateMemory(READ_SIZE))) { 00533 return ENOMEM; 00534 } 00535 00536 max_num_bad = 100; 00537 if (!(bad_sec_buf = (PULONG) AllocateMemory(max_num_bad*sizeof(ULONG)))) { 00538 FreeMemory(read_buffer); 00539 return ENOMEM; 00540 } 00541 00542 *NumberOfBadSectors = 0; 00543 00544 num_read_sec = READ_SIZE/SectorSize; 00545 00546 00547 percent = 1; 00548 for (i = 0; i < NumberOfSectors; i += num_read_sec) { 00549 00550 if (percent != i*100/NumberOfSectors) { 00551 percent = i*100/NumberOfSectors; 00552 AlPrint("%s%d percent formatted.\r", MSGMARGIN, percent); 00553 } 00554 00555 if (i + num_read_sec > NumberOfSectors) { 00556 num_read_sec = NumberOfSectors - i; 00557 } 00558 00559 r = LowReadSectors(PartitionId, SectorSize, i, 00560 num_read_sec, read_buffer); 00561 00562 if (r != ESUCCESS) { 00563 00564 for (j = 0; j < num_read_sec; j++) { 00565 00566 r = LowReadSectors(PartitionId, SectorSize, i+j, 1, 00567 read_buffer); 00568 00569 if (r != ESUCCESS) { 00570 00571 if (*NumberOfBadSectors == max_num_bad) { 00572 00573 max_num_bad += 100; 00574 if (!(bad_sec_buf = (PULONG) 00575 ReallocateMemory(bad_sec_buf, 00576 max_num_bad*sizeof(ULONG)))) { 00577 00578 FreeMemory(read_buffer); 00579 FreeMemory(bad_sec_buf); 00580 return ENOMEM; 00581 } 00582 } 00583 00584 bad_sec_buf[(*NumberOfBadSectors)++] = i + j; 00585 } 00586 } 00587 } 00588 } 00589 00590 AlPrint("%s100 percent formatted.\r\n",MSGMARGIN); 00591 00592 *BadSectorsList = bad_sec_buf; 00593 00594 FreeMemory(read_buffer); 00595 00596 return ESUCCESS; 00597 } 00598 00599 00600 ARC_STATUS 00601 FmtFatFormat( 00602 IN PCHAR PartitionPath, 00603 IN ULONG HiddenSectorCount 00604 ) 00605 /*++ 00606 00607 Routine Description: 00608 00609 This routine does a FAT format on the given partition. 00610 00611 Arguments: 00612 00613 PartitionPath - Supplies a path to the partition to format. 00614 00615 Return Value: 00616 00617 LowGetPartitionGeometry, ArcOpen, 00618 FmtVerifySectors, FmtFillFormatBuffer, LowWriteSectors, 00619 ArcClose, ENOMEM 00620 00621 --*/ 00622 { 00623 ULONG num_sectors; 00624 ULONG sector_size; 00625 ULONG sec_per_track; 00626 ULONG heads; 00627 ULONG hidden_sectors; 00628 PULONG bad_sectors; 00629 ULONG num_bad_sectors; 00630 PVOID format_buffer; 00631 ULONG max_sec_per_sa; 00632 ULONG super_area_size; 00633 ARC_STATUS r; 00634 ULONG partition_id; 00635 ULONG time_seed; 00636 PTIME_FIELDS ptime_fields; 00637 00638 00639 r = LowGetPartitionGeometry(PartitionPath, &num_sectors, 00640 &sector_size, &sec_per_track, &heads); 00641 00642 if (r != ESUCCESS) { 00643 return r; 00644 } 00645 00646 hidden_sectors = HiddenSectorCount; 00647 00648 r = ArcOpen(PartitionPath, ArcOpenReadWrite, &partition_id); 00649 00650 if (r != ESUCCESS) { 00651 return r; 00652 } 00653 00654 bad_sectors = NULL; 00655 00656 r = FmtVerifySectors(partition_id, num_sectors, sector_size, 00657 &bad_sectors, &num_bad_sectors); 00658 00659 if (r != ESUCCESS) { 00660 ArcClose(partition_id); 00661 return r; 00662 } 00663 00664 max_sec_per_sa = 1 + 00665 2*((2*65536 - 1)/sector_size + 1) + 00666 ((512*32 - 1)/sector_size + 1); 00667 00668 ptime_fields = ArcGetTime(); 00669 00670 time_seed = (ptime_fields->Year - 1970)*366*24*60*60 + 00671 (ptime_fields->Month)*31*24*60*60 + 00672 (ptime_fields->Day)*24*60*60 + 00673 (ptime_fields->Hour)*60*60 + 00674 (ptime_fields->Minute)*60 + 00675 (ptime_fields->Second); 00676 00677 if (!(format_buffer = AllocateMemory(max_sec_per_sa*sector_size))) { 00678 00679 if (bad_sectors) { 00680 FreeMemory(bad_sectors); 00681 } 00682 ArcClose(partition_id); 00683 return ENOMEM; 00684 } 00685 00686 r = FmtFillFormatBuffer(num_sectors, 00687 sector_size, 00688 sec_per_track, 00689 heads, 00690 hidden_sectors, 00691 format_buffer, 00692 max_sec_per_sa*sector_size, 00693 &super_area_size, 00694 time_seed, 00695 bad_sectors, 00696 num_bad_sectors); 00697 00698 00699 if (bad_sectors) { 00700 FreeMemory(bad_sectors); 00701 } 00702 00703 if (r != ESUCCESS) { 00704 ArcClose(partition_id); 00705 FreeMemory(format_buffer); 00706 return r; 00707 } 00708 00709 r = LowWriteSectors(partition_id, sector_size, 0, 00710 super_area_size/sector_size, format_buffer); 00711 00712 FreeMemory(format_buffer); 00713 00714 if (r != ESUCCESS) { 00715 ArcClose(partition_id); 00716 return r; 00717 } 00718 00719 return ArcClose(partition_id); 00720 } 00721 00722 00723 ARC_STATUS 00724 FmtQueryFatPartitionList( 00725 OUT PCHAR** FatPartitionList, 00726 OUT PULONG ListLength 00727 ) 00728 /*++ 00729 00730 Routine Description: 00731 00732 This routine browses the component tree for all disk peripherals 00733 and the attempts to open partitions on all of them. It add all 00734 FAT partitions to the list and returns it. 00735 00736 Arguments: 00737 00738 FatPartitionList - Returns a list of FAT partitions. 00739 ListLength - Returns the length of the list. 00740 00741 Return Value: 00742 00743 LowQueryPathList, ArcOpen, ArcClose, FmtIsFat, EIO, ENOMEM, ESUCCESS 00744 00745 --*/ 00746 { 00747 CONFIGURATION_TYPE config_type; 00748 ARC_STATUS r; 00749 PCHAR* peripheral_list; 00750 ULONG peripheral_list_length; 00751 ULONG i, j; 00752 ULONG num_partitions; 00753 CHAR partition_buf[21]; 00754 ULONG partition_id; 00755 PCHAR* fat_partition_list; 00756 ULONG fat_partition_list_length; 00757 BOOLEAN is_fat; 00758 PCHAR partition_name; 00759 00760 00761 // First get a list of the all of the disk peripheral paths. 00762 00763 config_type = DiskPeripheral; 00764 r = LowQueryPathList(NULL, &config_type, &peripheral_list, 00765 &peripheral_list_length); 00766 00767 if (r != ESUCCESS) { 00768 return r; 00769 } 00770 00771 // Now we have a list of disk peripheral paths. 00772 00773 00774 00775 // Next, count how many partitions there are. 00776 00777 num_partitions = 0; 00778 for (i = 0; i < peripheral_list_length; i++) { 00779 00780 partition_name = AllocateMemory(strlen(peripheral_list[i]) + 21); 00781 00782 if (!partition_name) { 00783 LowFreePathList(peripheral_list, peripheral_list_length); 00784 return ENOMEM; 00785 } 00786 00787 for (j = 1; ; j++) { 00788 00789 strcpy(partition_name, peripheral_list[i]); 00790 sprintf(partition_buf, "partition(%d)", j); 00791 strcat(partition_name, partition_buf); 00792 00793 r = ArcOpen(partition_name, ArcOpenReadOnly, &partition_id); 00794 00795 if (r != ESUCCESS) { 00796 break; 00797 } 00798 00799 num_partitions++; 00800 00801 r = ArcClose(partition_id); 00802 00803 if (r != ESUCCESS) { 00804 LowFreePathList(peripheral_list, peripheral_list_length); 00805 FreeMemory(partition_name); 00806 return r; 00807 } 00808 } 00809 00810 FreeMemory(partition_name); 00811 } 00812 00813 // 'num_partitions' indicates the number of partitions on the disk. 00814 00815 00816 // Allocate a buffer for the FAT partitions list. There can be 00817 // no more FAT partitions then there are partitions. 00818 00819 fat_partition_list = (PCHAR*) AllocateMemory(num_partitions*sizeof(PCHAR)); 00820 00821 if (!fat_partition_list) { 00822 LowFreePathList(peripheral_list, peripheral_list_length); 00823 return ENOMEM; 00824 } 00825 00826 for (i = 0; i < num_partitions; i++) { 00827 fat_partition_list[i] = NULL; 00828 } 00829 00830 fat_partition_list_length = 0; 00831 00832 // 'fat_partition_list_length' indicates the number of FAT partitions. 00833 00834 00835 00836 // Now go through all of the peripherals trying all possible 00837 // partitions on each. Test these to see if they are FAT and 00838 // put the FAT ones in 'fat_partitions_list'. 00839 00840 for (i = 0; i < peripheral_list_length; i++) { 00841 00842 partition_name = AllocateMemory(strlen(peripheral_list[i]) + 21); 00843 00844 if (!partition_name) { 00845 LowFreePathList(peripheral_list, peripheral_list_length); 00846 LowFreePathList(fat_partition_list, fat_partition_list_length); 00847 return ENOMEM; 00848 } 00849 00850 for (j = 1; ; j++) { 00851 00852 strcpy(partition_name, peripheral_list[i]); 00853 sprintf(partition_buf, "partition(%d)", j); 00854 strcat(partition_name, partition_buf); 00855 00856 r = ArcOpen(partition_name, ArcOpenReadOnly, &partition_id); 00857 00858 if (r != ESUCCESS) { 00859 break; 00860 } 00861 00862 r = ArcClose(partition_id); 00863 00864 if (r != ESUCCESS) { 00865 LowFreePathList(peripheral_list, peripheral_list_length); 00866 LowFreePathList(fat_partition_list, fat_partition_list_length); 00867 FreeMemory(partition_name); 00868 return r; 00869 } 00870 00871 r = FmtIsFat(partition_name, &is_fat); 00872 00873 if (r != ESUCCESS) { 00874 LowFreePathList(peripheral_list, peripheral_list_length); 00875 LowFreePathList(fat_partition_list, fat_partition_list_length); 00876 FreeMemory(partition_name); 00877 return r; 00878 } 00879 00880 if (is_fat) { 00881 00882 if (fat_partition_list_length == num_partitions) { 00883 // This can't happen. 00884 LowFreePathList(peripheral_list, peripheral_list_length); 00885 LowFreePathList(fat_partition_list, fat_partition_list_length); 00886 FreeMemory(partition_name); 00887 return EIO; 00888 } 00889 00890 fat_partition_list[fat_partition_list_length] = 00891 AllocateMemory(strlen(partition_name) + 1); 00892 00893 if (!fat_partition_list[fat_partition_list_length]) { 00894 LowFreePathList(peripheral_list, peripheral_list_length); 00895 LowFreePathList(fat_partition_list, fat_partition_list_length); 00896 FreeMemory(partition_name); 00897 return ENOMEM; 00898 } 00899 00900 strcpy(fat_partition_list[fat_partition_list_length], partition_name); 00901 00902 fat_partition_list_length++; 00903 } 00904 } 00905 00906 FreeMemory(partition_name); 00907 } 00908 00909 LowFreePathList(peripheral_list, peripheral_list_length); 00910 00911 *FatPartitionList = fat_partition_list; 00912 *ListLength = fat_partition_list_length; 00913 00914 return ESUCCESS; 00915 } 00916 00917 00918 ARC_STATUS 00919 FmtFreeFatPartitionList( 00920 IN OUT PCHAR* FatPartitionList, 00921 IN ULONG ListLength 00922 ) 00923 /*++ 00924 00925 Routine Description: 00926 00927 This routine frees up the heap space taken by the FAT partition 00928 list. 00929 00930 Arguments: 00931 00932 FatPartitionList - Supplies the buffer to free. 00933 ListLength - Supplies the buffer length. 00934 00935 Return Value: 00936 00937 LowFreePathList 00938 00939 --*/ 00940 { 00941 return LowFreePathList(FatPartitionList, ListLength); 00942 }

Generated on Sat May 15 19:40:02 2004 for test by doxygen 1.3.7