source: trunk/src/ufat32/format.c@ 186

Last change on this file since 186 was 186, checked in by Valery V. Sedletski, 8 years ago

UFAT32.DLL: Support for CHKDSK/FORMAT /P command line switch.

File size: 23.1 KB
RevLine 
[97]1// Fat32 formatter version 1.05
2// (c) Tom Thornhill 2007,2008,2009
3// This software is covered by the GPL.
4// By using this tool, you agree to absolve Ridgecrop of an liabilities for lost data.
5// Please backup any data you value before using this tool.
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <signal.h>
[101]11#include <math.h>
[97]12
13#include "fat32c.h"
14
15/*
1628.2 CALCULATING THE VOLUME SERIAL NUMBER
17
18For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94
19seconds. DOS takes the date and time just before it writes it to the
20disk.
21
22Low order word is calculated: Volume Serial Number is:
23 Month & Day 12/26 0c1ah
24 Sec & Hundrenths 41:94 295eh 3578:1d02
25 -----
26 3578h
27
28High order word is calculated:
29 Hours & Minutes 21:55 1537h
30 Year 1995 07cbh
31 -----
32 1d02h
33*/
34
35
36/*
37This is the Microsoft calculation from FATGEN
38
39 DWORD RootDirSectors = 0;
40 DWORD TmpVal1, TmpVal2, FATSz;
41
42 TmpVal1 = DskSize - ( ReservedSecCnt + RootDirSectors);
43 TmpVal2 = (256 * SecPerClus) + NumFATs;
44 TmpVal2 = TmpVal2 / 2;
45 FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
46
47 return( FatSz );
48*/
49
50// disk file open handle
51HANDLE hDev = 0;
[186]52extern char msg;
[97]53
54DWORD get_fat_size_sectors ( DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPerClus, DWORD NumFATs, DWORD BytesPerSect )
55{
56 ULONGLONG Numerator, Denominator;
57 ULONGLONG FatElementSize = 4;
58 ULONGLONG FatSz;
59
60 // This is based on
61 // http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html
62 // I've made the obvious changes for FAT32
63 Numerator = FatElementSize * ( DskSize - ReservedSecCnt );
64 Denominator = ( SecPerClus * BytesPerSect ) + ( FatElementSize * NumFATs );
65 FatSz = Numerator / Denominator;
66 // round up
67 FatSz += 1;
68
69 return( (DWORD) FatSz );
70}
71
72
73BYTE get_spc ( DWORD ClusterSizeKB, DWORD BytesPerSect )
74{
75 DWORD spc = ( ClusterSizeKB * 1024 ) / BytesPerSect;
76 return( (BYTE) spc );
77}
78
79BYTE get_sectors_per_cluster ( LONGLONG DiskSizeBytes, DWORD BytesPerSect )
80{
81 BYTE ret = 0x01; // 1 sector per cluster
82 LONGLONG DiskSizeMB = DiskSizeBytes / ( 1024*1024 );
83
84 // 512 MB to 8,191 MB 4 KB
85 if ( DiskSizeMB > 512 )
86 ret = get_spc( 4, BytesPerSect ); // ret = 0x8;
87
88 // 8,192 MB to 16,383 MB 8 KB
89 if ( DiskSizeMB > 8192 )
90 ret = get_spc( 8, BytesPerSect ); // ret = 0x10;
91
92 // 16,384 MB to 32,767 MB 16 KB
93 if ( DiskSizeMB > 16384 )
94 ret = get_spc( 16, BytesPerSect ); // ret = 0x20;
95
96 // Larger than 32,768 MB 32 KB
97 if ( DiskSizeMB > 32768 )
98 ret = get_spc( 32, BytesPerSect ); // ret = 0x40;
99
100 return( ret );
101
102}
103
104void zero_sectors ( HANDLE hDevice, DWORD Sector, DWORD BytesPerSect, DWORD NumSects) //, DISK_GEOMETRY* pdgDrive )
105{
106 BYTE *pZeroSect;
107 DWORD BurstSize;
108 DWORD WriteSize;
109 BOOL ret;
110 DWORD dwWritten;
111 //LARGE_INTEGER Start, End, Ticks, Frequency;
112 ULONGLONG Start, End, Ticks, Frequency;
113 double fTime;
114 double fBytesTotal;
[101]115 ULONGLONG qBytesTotal, qBytesWritten;
[98]116 float fPercentWritten, fPrevPercentWritten = 0;
117 //char Str[12];
[97]118
119 //BurstSize = pdgDrive->SectorsPerTrack * pdgDrive->TracksPerCylinder;
[100]120 BurstSize = 64; // 32K
121 //BurstSize = 128; // 64K
[97]122 //BurstSize = 8; // 4k
123 //BurstSize = 1; // one sector
124
[100]125 //printf("zero_sectors: \nhDevice=0x%lx, Sector=%lu, \nBytesPerSect=%lu, NumSects=%lu\n",
126 // hDevice, Sector, BytesPerSect, NumSects);
127
[97]128 mem_alloc((void **)&pZeroSect, BytesPerSect * BurstSize);
129
130 seek_to_sect( hDevice, Sector, BytesPerSect );
131
132 query_freq( &Frequency );
133 query_time( &Start );
134
135 qBytesTotal = NumSects * BytesPerSect;
136 qBytesWritten = 0;
137 fPercentWritten = 0;
138
139 //printf("Percent written: ");
140
141 while ( NumSects )
142 {
143 if ( NumSects > BurstSize )
144 WriteSize = BurstSize;
145 else
146 WriteSize = NumSects;
147
148 //ret = WriteFile ( hDevice, pZeroSect, WriteSize*BytesPerSect, &dwWritten, NULL );
149 ret = write_file ( hDevice, pZeroSect, WriteSize * BytesPerSect, &dwWritten );
150
[133]151 if ( !ret )
152 die ( "Failed to write", ret );
[97]153
154 qBytesWritten += dwWritten;
[98]155
[101]156 fPercentWritten = ( 100 * qBytesWritten ) / qBytesTotal;
[98]157 //sprintf(Str, "%.2f%%...", fPercentWritten);
[97]158
[137]159 if ( fPercentWritten - fPrevPercentWritten >= 1 )
[98]160 {
161 // update progress indicator if it has grown by >= 5%
162 fPrevPercentWritten = fPercentWritten;
163 // percent written indication
164 show_progress(fPercentWritten);
165 }
[97]166
167 NumSects -= WriteSize;
168 }
169
170 query_time( &End );
171
172 //Ticks.QuadPart = End.QuadPart - Start.QuadPart;
173 //fTime = (double) ( Ticks.QuadPart ) / Frequency.QuadPart;
174
175 Ticks = End - Start;
176 fTime = (double) ( Ticks ) / Frequency;
177
178 mem_free(pZeroSect, BytesPerSect * BurstSize);
179
180 fBytesTotal = (double) qBytesTotal;
[186]181 show_message ( "\nWrote %I64d bytes in %.2f seconds, %.2f Megabytes/sec\n", 0, 3,
[97]182 qBytesTotal, fTime, fBytesTotal/(fTime*1024.0*1024.0) );
183}
184
185int format_volume (char *path, format_params *params)
186{
187 // First open the device
[129]188 char *p;
[97]189 DWORD i;
190 HANDLE hDevice;
191 UCHAR PartitionType = 0x0c;
192
193 int cbRet;
194 BOOL bRet;
[186]195 BYTE szString[12];
[97]196
[100]197 // extended BPB
198 struct extbpb dp = {0, 0, 32, 2, 0, 0, 0xf8, 0, 0, 0, 0, 0, {0}};
[97]199
200 // Recommended values
[100]201 //DWORD ReservedSectCount = 32; !!! create cmd line parameter !!!
[97]202 //DWORD NumFATs = 2;
203 DWORD BackupBootSect = 6;
204 DWORD VolumeId=0; // calculated before format
205
206 // // Calculated later
207 //DWORD FatSize=0;
208 //DWORD BytesPerSect=0;
209 //DWORD SectorsPerCluster=0;
210 //DWORD TotalSectors=0;
211 DWORD SystemAreaSize=0;
212 DWORD UserAreaSize=0;
213 ULONGLONG qTotalSectors=0;
214
215 // structures to be written to the disk
216 FAT_BOOTSECTOR32 *pFAT32BootSect;
217 FAT_FSINFO *pFAT32FsInfo;
218
219 DWORD *pFirstSectOfFat;
220
221 // Debug temp vars
222 ULONGLONG FatNeeded, ClusterCount;
223 char c;
224
225 static char volId[12] = {0};
226 char *vol = volId;
227
[137]228 if (params->reserved_sectors)
229 dp.ReservedSectCount = params->reserved_sectors;
230
[97]231 VolumeId = get_vol_id( );
232
233 strncpy(vol, params->volume_label, 11);
234 check_vol_label(path, (char **)&vol);
235
236 // Open drive
237 open_drive (path, &hDevice);
[129]238 get_drive_params(hDevice, &dp);
[97]239 lock_drive(hDevice);
240 begin_format(hDevice);
[130]241 sectorio(hDevice);
[97]242
243 // Checks on Disk Size
[100]244 // qTotalSectors = dp.PartitionLength / dp.BytesPerSect;
245 qTotalSectors = dp.TotalSectors;
[97]246 // low end limit - 65536 sectors
247 if ( qTotalSectors < 65536 )
248 {
249 // I suspect that most FAT32 implementations would mount this volume just fine, but the
250 // spec says that we shouldn't do this, so we won't
251 die ( "This drive is too small for FAT32 - there must be at least 64K clusters\n", -1);
252 }
253
254 if ( qTotalSectors >= 0xffffffff )
255 {
256 // This is a more fundamental limitation on FAT32 - the total sector count in the root dir
257 // ís 32bit. With a bit of creativity, FAT32 could be extended to handle at least 2^28 clusters
258 // There would need to be an extra field in the FSInfo sector, and the old sector count could
259 // be set to 0xffffffff. This is non standard though, the Windows FAT driver FASTFAT.SYS won't
260 // understand this. Perhaps a future version of FAT32 and FASTFAT will handle this.
261 die ( "This drive is too big for FAT32 - max 2TB supported\n", -1);
262 }
263
264 mem_alloc ( (void **)&pFAT32BootSect, dp.BytesPerSect );
265 mem_alloc ( (void **)&pFAT32FsInfo, dp.BytesPerSect );
266 mem_alloc ( (void **)&pFirstSectOfFat, dp.BytesPerSect );
267
268 if ( !pFAT32BootSect || !pFAT32FsInfo || !pFirstSectOfFat )
269 die ( "Failed to allocate memory", -2 );
270
271 // fill out the boot sector and fs info
272 pFAT32BootSect->sJmpBoot[0]=0xEB;
273 pFAT32BootSect->sJmpBoot[1]=0x5A;
274 pFAT32BootSect->sJmpBoot[2]=0x90;
275 strcpy( pFAT32BootSect->sOEMName, "MSWIN4.1" );
276 pFAT32BootSect->wBytsPerSec = (WORD) dp.BytesPerSect;
[156]277
[97]278 if ( params->sectors_per_cluster )
279 dp.SectorsPerCluster = params->sectors_per_cluster;
280 else
[100]281 dp.SectorsPerCluster = get_sectors_per_cluster( ((LONGLONG)dp.TotalSectors) * dp.BytesPerSect, dp.BytesPerSect );
[97]282
283 pFAT32BootSect->bSecPerClus = (BYTE) dp.SectorsPerCluster ;
284 pFAT32BootSect->wRsvdSecCnt = (WORD) dp.ReservedSectCount;
285 pFAT32BootSect->bNumFATs = (BYTE) dp.NumFATs;
286 pFAT32BootSect->wRootEntCnt = 0;
287 pFAT32BootSect->wTotSec16 = 0;
288 pFAT32BootSect->bMedia = 0xF8;
289 pFAT32BootSect->wFATSz16 = 0;
290 pFAT32BootSect->wSecPerTrk = (WORD) dp.SectorsPerTrack;
291 pFAT32BootSect->wNumHeads = (WORD) dp.TracksPerCylinder;
292 pFAT32BootSect->dHiddSec = (DWORD) dp.HiddenSectors;
[100]293 //dp.TotalSectors = (DWORD) (dp.PartitionLength / dp.BytesPerSect);
[97]294 pFAT32BootSect->dTotSec32 = dp.TotalSectors;
295
296 dp.FatSize = get_fat_size_sectors ( pFAT32BootSect->dTotSec32, pFAT32BootSect->wRsvdSecCnt, pFAT32BootSect->bSecPerClus, pFAT32BootSect->bNumFATs, dp.BytesPerSect );
297
298 pFAT32BootSect->dFATSz32 = dp.FatSize;
299 pFAT32BootSect->wExtFlags = 0;
300 pFAT32BootSect->wFSVer = 0;
301 pFAT32BootSect->dRootClus = 2;
302 pFAT32BootSect->wFSInfo = 1;
303 pFAT32BootSect->wBkBootSec = (WORD) BackupBootSect;
304 pFAT32BootSect->bDrvNum = 0x80;
305 pFAT32BootSect->Reserved1 = 0;
306 pFAT32BootSect->bBootSig = 0x29;
307
308 // Specify volume label
309 if (!*vol)
[129]310 vol = get_vol_label(path, vol);
[97]311
[129]312 vol = strupr(vol);
313
[97]314 pFAT32BootSect->dBS_VolID = VolumeId;
[129]315 strncpy ( pFAT32BootSect->sVolLab, vol, 11 );
316 strncpy ( pFAT32BootSect->sBS_FilSysType, "FAT32 ", 8 );
[97]317 ((BYTE*)pFAT32BootSect)[510] = 0x55;
318 ((BYTE*)pFAT32BootSect)[511] = 0xaa;
319
320 /* FATGEN103.DOC says "NOTE: Many FAT documents mistakenly say that this 0xAA55 signature occupies the "last 2 bytes of
321 the boot sector". This statement is correct if - and only if - BPB_BytsPerSec is 512. If BPB_BytsPerSec is greater than
322 512, the offsets of these signature bytes do not change (although it is perfectly OK for the last two bytes at the end
323 of the boot sector to also contain this signature)."
324
325 Windows seems to only check the bytes at offsets 510 and 511. Other OSs might check the ones at the end of the sector,
326 so we'll put them there too.
327 */
328 if ( dp.BytesPerSect != 512 )
329 {
330 ((BYTE*)pFAT32BootSect)[dp.BytesPerSect-2] = 0x55;
331 ((BYTE*)pFAT32BootSect)[dp.BytesPerSect-1] = 0xaa;
332 }
333
334 // FSInfo sect
335 pFAT32FsInfo->dLeadSig = 0x41615252;
336 pFAT32FsInfo->dStrucSig = 0x61417272;
337 pFAT32FsInfo->dFree_Count = (DWORD) -1;
338 pFAT32FsInfo->dNxt_Free = (DWORD) -1;
339 pFAT32FsInfo->dTrailSig = 0xaa550000;
340
341 // First FAT Sector
342 pFirstSectOfFat[0] = 0x0ffffff8; // Reserved cluster 1 media id in low byte
343 pFirstSectOfFat[1] = 0x0fffffff; // Reserved cluster 2 EOC
344 pFirstSectOfFat[2] = 0x0fffffff; // end of cluster chain for root dir
345
346 // Write boot sector, fats
347 // Sector 0 Boot Sector
348 // Sector 1 FSInfo
349 // Sector 2 More boot code - we write zeros here
350 // Sector 3 unused
351 // Sector 4 unused
352 // Sector 5 unused
353 // Sector 6 Backup boot sector
354 // Sector 7 Backup FSInfo sector
355 // Sector 8 Backup 'more boot code'
356 // zero'd sectors upto ReservedSectCount
357 // FAT1 ReservedSectCount to ReservedSectCount + FatSize
358 // ...
359 // FATn ReservedSectCount to ReservedSectCount + FatSize
360 // RootDir - allocated to cluster2
361
362 UserAreaSize = dp.TotalSectors - dp.ReservedSectCount - (dp.NumFATs*dp.FatSize);
363 ClusterCount = UserAreaSize / dp.SectorsPerCluster;
364
365 // Sanity check for a cluster count of >2^28, since the upper 4 bits of the cluster values in
366 // the FAT are reserved.
367 if ( ClusterCount > 0x0FFFFFFF )
368 {
[98]369 die ( "This drive has more than 2^28 clusters, \n"
370 "try to specify a larger cluster size or use \n"
371 "the default (i.e. don't use -cXX)\n", -3 );
[97]372 }
373
374 // Sanity check - < 64K clusters means that the volume will be misdetected as FAT16
375 if ( ClusterCount < 65536 )
376 {
[98]377 die ( "FAT32 must have at least 65536 clusters, \n"
378 "try to specify a smaller cluster size or \n"
379 "use the default (i.e. don't use -cXX)\n", -4 );
[97]380 }
381
382 // Sanity check, make sure the fat is big enough
383 // Convert the cluster count into a Fat sector count, and check the fat size value we calculated
384 // earlier is OK.
385 FatNeeded = ClusterCount * 4;
386 FatNeeded += (dp.BytesPerSect-1);
387 FatNeeded /= dp.BytesPerSect;
[100]388
389 //printf("dp.BytesPerSect=%lu\n", dp.BytesPerSect);
390 //printf("ClusterCount=%llu, FatNeeded=%llu, FatSize=%lu\n", ClusterCount, FatNeeded, dp.FatSize);
[97]391 if ( FatNeeded > dp.FatSize )
392 {
[98]393 die ( "This drive is too big for this version \n"
394 "of fat32format, check for an upgrade\n", -5 );
[97]395 }
396
397 // Now we're commited - print some info first
[186]398 show_message ( "Size: %g MB %u sectors\n", 0, 0, (double) ((dp.TotalSectors / (1024*1024)) * dp.BytesPerSect), dp.TotalSectors );
399 show_message ( "%d Bytes Per Sector, Cluster size %d bytes\n", 0, 0, dp.BytesPerSect, dp.SectorsPerCluster * dp.BytesPerSect );
[97]400
[186]401 //show_message ( "Volume Serial No. is %x:%x", 1243, 1, TYPE_LONG, VolumeId );
402 sprintf(szString, "%4.4X-%4.4X", HIUSHORT(VolumeId), LOUSHORT(VolumeId));
403 show_message ( "The Volume Serial Number is %s.", 1243, 1, TYPE_STRING, szString);
404 show_message ( "Volume label is %s", 1375, 1, TYPE_STRING, vol );
405
406 show_message ( "%d Reserved Sectors, %d Sectors per FAT, %d fats\n", 0, 0, dp.ReservedSectCount, dp.FatSize, dp.NumFATs );
407
408 show_message ( "%d Total clusters\n", 0, 0, ClusterCount );
[97]409
410 // fix up the FSInfo sector
411 pFAT32FsInfo->dFree_Count = (UserAreaSize/dp.SectorsPerCluster)-1;
412 pFAT32FsInfo->dNxt_Free = 3; // clusters 0-1 resered, we used cluster 2 for the root dir
413
[186]414 show_message ( "%d Free Clusters\n", 0, 0, pFAT32FsInfo->dFree_Count );
[97]415 // Work out the Cluster count
416
[186]417 show_message( "Formatting drive %s\n", 534, 0, path );
[97]418
419 // Once zero_sectors has run, any data on the drive is basically lost....
420
421 // First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster
422 SystemAreaSize = (dp.ReservedSectCount+(dp.NumFATs*dp.FatSize) + dp.SectorsPerCluster);
423 zero_sectors( hDevice, 0, dp.BytesPerSect, SystemAreaSize); // &dgDrive);
424
[186]425 show_message ( "Clearing out %d sectors for \nReserved sectors, fats and root cluster...\n", 0, 0, SystemAreaSize );
426 show_message ( "Initialising reserved sectors and FATs...\n", 0, 0 );
[97]427 // Now we should write the boot sector and fsinfo twice, once at 0 and once at the backup boot sect position
428 for ( i=0; i<2; i++ )
429 {
430 int SectorStart = (i==0) ? 0 : BackupBootSect;
431 write_sect ( hDevice, SectorStart, dp.BytesPerSect, pFAT32BootSect, 1 );
432 write_sect ( hDevice, SectorStart+1, dp.BytesPerSect, pFAT32FsInfo, 1 );
433 }
434 // Write the first fat sector in the right places
435 for ( i=0; i<dp.NumFATs; i++ )
436 {
437 int SectorStart = dp.ReservedSectCount + (i * dp.FatSize );
438 write_sect ( hDevice, SectorStart, dp.BytesPerSect, pFirstSectOfFat, 1 );
439 }
440
441 // The filesystem recogniser in Windows XP doesn't use the partition type - in can be
442 // set to pretty much anything other Os's like Dos (still useful for Norton Ghost!) and Windows ME might,
443 // so we could fix it here
444 // On the other hand, I'm not sure that exposing big partitions to Windows ME/98 is a very good idea
445 // There are a couple of issues here -
446 // 1) WinME/98 doesn't know about 48bit LBA, so IDE drives bigger than 137GB will cause it
447 // problems. Rather than refuse to mount them, it uses 28bit LBA which wraps
448 // around, so writing to files above the 137GB boundary will erase the FAT and root dirs.
449 // 2) Win98 and WinME have 16 bit scandisk tools, which you need to disable, assuming you
450 // can get third party support for 48bit LBA, or use a USB external case, most of which
451 // will let you use a 48bit LBA drive.
452 // see http://www.48bitlba.com/win98.htm for instructions
453
[129]454 set_part_type (hDevice, &dp, 0xc);
[97]455 remount_media ( hDevice );
456 unlock_drive ( hDevice );
457 close_drive ( hDevice );
458 fflush(stdout);
459
[129]460 set_vol_label (path, vol);
461
[115]462 // free memory
463 mem_free ( (void *)pFirstSectOfFat, dp.BytesPerSect );
464 mem_free ( (void *)pFAT32FsInfo, dp.BytesPerSect );
465 mem_free ( (void *)pFAT32BootSect, dp.BytesPerSect );
466
[97]467 return( TRUE );
468}
469
470void usage( char *s )
471{
[98]472 printf ( "\nFat32format, ver. 1.07, \n"
473 "see http://www.ridgecrop.demon.co.uk/fat32format.htm\n"
474 "Modified and ported to OS/2 by osFree project \n"
475 "(http://osfree.org) for ufat32.dll.\n"
476 "This software is covered by the GPL.\n"
477 "Use with care - Ridgecrop are not liable\n"
[100]478 "for data lost using this tool.\n\n"
[98]479 "Usage:[c:\\] %s <d>: [options]\n\n"
[97]480 "/C:<N> with different cluster sizes:\n"
481 " N: sectors per cluster:\n"
482 " 1 ( max size 137GB ) \n"
483 " 2 ( max size 274GB )\n"
484 " 4 ( max size 549GB )\n"
[100]485 " 8 ( max size 1TB. )\n"
[98]486 " ... \n"
487 " 128 - use 128 sectors per cluster (64K clusters)\n"
[97]488 "/V:<volume label>\n"
[137]489 "/R:<reserved sectors>\n"
[97]490 "/? this help message\n\n", s );
491
492 exit(1);
493}
494
495void sig_handler (int sig);
496
497int setup_signals (void)
498{
499 if (SIG_ERR == signal(SIGABRT, sig_handler)) {
500 perror("Could not set SIGABRT");
501 return EXIT_FAILURE;
502 }
503
504 if (SIG_ERR == signal(SIGBREAK, sig_handler)) {
505 perror("Could not set SIGBREAK");
506 return EXIT_FAILURE;
507 }
508
509 if (SIG_ERR == signal(SIGINT, sig_handler)) {
510 perror("Could not set SIGINT");
511 return EXIT_FAILURE;
512 }
513
514 if (SIG_ERR == signal(SIGFPE, sig_handler)) {
515 perror("Could not set SIGFPE");
516 return EXIT_FAILURE;
517 }
518 if (SIG_ERR == signal(SIGSEGV, sig_handler)) {
519 perror("Could not set SIGSEGV");
520 return EXIT_FAILURE;
521 }
522 if (SIG_ERR == signal(SIGILL, sig_handler)) {
523 perror("Could not set SIGILL");
524 return EXIT_FAILURE;
525 }
526
527 return 0;
528}
529
530int format(int argc, char *argv[], char *envp[])
531{
532 format_params p;
533 char cVolume;
[98]534 int i=1;
[97]535 char path[] = "Z:";
536 char *s, *t;
[98]537 char key[12], val[12];
[97]538
539 // set up signal handlers
540 if (setup_signals())
541 {
542 printf("Error setting the signal handler!\n");
543 quit (1);
544 }
545
546 memset( &p, 0, sizeof(p) );
547
548 if ( argc < 2 )
549 {
550 usage( argv[0] );
551 }
552
553 cVolume = argv[1][0];
554
555 if (!isalpha(cVolume) || argv[1][1] != ':')
556 usage( argv[0] );
557
558#if 0
559 if ( cVolume != 'f' )
560 die( "Debug - only F: can be formatted\n", -9 );
561#endif
562
563 path[0] = cVolume;
564 path[1] = ':';
565 path[2] = '\0';
566
567 for ( i = 2; i < argc; i++ )
568 {
569 if ( !((strlen(argv[i])>=2) && ((argv[i][0] == '-')||(argv[i][0] == '/'))) )
570 usage( argv[0] );
571
572 memset(key, 0, 12);
573 memset(val, 0, 12);
574
575 if ( strlen(argv[i]) > 3 )
576 {
577 // move to ':'
578 s = argv[i] + 1;
579 t = strchr(s, ':');
580
581 if (t >= s)
582 {
583 strncpy(key, s, t - s); key[t - s] = '\0';
584 strncpy(val, t + 1, strlen(t + 1)); val[strlen(t + 1)] = '\0';
585 }
586 else
587 {
588 strncpy(key, s, 12);
589 val[0] = '\0';
590 }
591 }
592
593 // skip /fs:... parameter
594 if (!stricmp(key, "FS"))
595 continue;
596
597 switch ( toupper(argv[i][1]) )
598 {
599 case 'C':
600 p.sectors_per_cluster = atol(val);
601 if ( (p.sectors_per_cluster != 1) && // 512 bytes, 0.5k
602 (p.sectors_per_cluster != 2) && // 1K
603 (p.sectors_per_cluster != 4) && // 2K
604 (p.sectors_per_cluster != 8) && // 4K
605 (p.sectors_per_cluster != 16) && // 8K
606 (p.sectors_per_cluster != 32) && // 16K
607 (p.sectors_per_cluster != 64) && // 32K
608 (p.sectors_per_cluster != 128) // 64K ( Microsoft say don't use 64K or bigger);
609 )
610 {
611 printf ( "Ignoring bad cluster size %d\n", p.sectors_per_cluster );
612 p.sectors_per_cluster = 0;
613 usage( argv[0] );
614 }
615 continue;
[137]616 case 'R':
617 p.reserved_sectors = atol(val);
618 if (! p.reserved_sectors)
619 {
620 printf( "Ignoring bad reserved sectors %d\n", p.reserved_sectors );
621 p.reserved_sectors = 32;
622 usage( argv[0] );
623 }
624 continue;
[97]625 case 'H':
626 case '?':
627 usage( argv[0] );
628 case 'V':
629 memcpy(p.volume_label, val, 12);
630 continue;
[186]631 case 'P':
632 msg = TRUE;
633 continue;
[97]634 default:
[100]635 // printf ( "Ignoring bad flag '-%c'\n", argv[i][1] );
[97]636 usage( argv[0] );
637 }
638 //i++;
639 }
640
[98]641 if ( format_volume( path, &p ) )
642 show_message( "Done.", 1294, 0 );
[97]643
644 return 0;
645}
646
647#ifndef __DLL__
648int main(int argc, char *argv[])
649{
650 return format(argc, argv, NULL);
651}
652#endif
653
654void cleanup ( void )
655{
656 if (hDev == 0)
657 return;
658
659 remount_media ( hDev );
660 unlock_drive ( hDev );
661 close_drive ( hDev);
[99]662 hDev = 0;
[97]663}
664
665void quit (int rc)
666{
667 cleanup ();
668 exit (rc);
669}
670
671void show_sig_string(int s)
672{
673 char *str = "";
674 switch (s)
675 {
676 case SIGABRT:
677 str="SIGABRT";
678 break;
679 case SIGBREAK:
680 str="SIGBREAK";
681 break;
682 case SIGINT:
683 str="SIGINT";
684 break;
685 case SIGFPE:
686 str="SIGFPE";
687 break;
688 case SIGSEGV:
689 str="SIGSEGV";
690 break;
691 case SIGILL:
692 str="SIGILL";
693 break;
694 default:
695 ;
696 }
697 printf("Signal: %d = %s\n", s, str);
698}
699
700void sig_handler (int sig)
701{
702 show_sig_string(sig);
703 cleanup();
704}
Note: See TracBrowser for help on using the repository browser.