00001
00002
00003
00004
00005 #define DONT_NEED_WAIT
00006
00007 #include "sysincludes.h"
00008 #include "msdos.h"
00009 #include "mtools.h"
00010 #include "mainloop.h"
00011 #include "fsP.h"
00012 #include "file.h"
00013 #include "plain_io.h"
00014 #include "floppyd_io.h"
00015 #include "nameclash.h"
00016 #include "buffer.h"
00017 #ifdef USE_XDF
00018 #include "xdf_io.h"
00019 #endif
00020 #include "partition.h"
00021
00022 #ifndef abs
00023 #define abs(x) ((x)>0?(x):-(x))
00024 #endif
00025
00026 #ifdef OS_linux
00027 #include "linux/hdreg.h"
00028
00029 #define _LINUX_STRING_H_
00030 #define kdev_t int
00031 #include "linux/fs.h"
00032 #undef _LINUX_STRING_H_
00033
00034 #endif
00035
00036
00037 extern int errno;
00038
00039 static int init_geometry_boot(struct bootsector *boot, struct device *dev,
00040 int sectors0, int rate_0, int rate_any,
00041 int *tot_sectors, int keepBoot)
00042 {
00043 int i;
00044 int nb_renum;
00045 int sector2;
00046 int size2;
00047 int j;
00048 int sum;
00049
00050 set_word(boot->nsect, dev->sectors);
00051 set_word(boot->nheads, dev->heads);
00052
00053 *tot_sectors = dev->heads * dev->sectors * dev->tracks - DWORD(nhs);
00054
00055 if (*tot_sectors < 0x10000){
00056 set_word(boot->psect, *tot_sectors);
00057 set_dword(boot->bigsect, 0);
00058 } else {
00059 set_word(boot->psect, 0);
00060 set_dword(boot->bigsect, *tot_sectors);
00061 }
00062
00063 if (dev->use_2m & 0x7f){
00064 int bootOffset;
00065 strncpy(boot->banner, "2M-STV04", 8);
00066 boot->ext.old.res_2m = 0;
00067 boot->ext.old.fmt_2mf = 6;
00068 if ( dev->sectors % ( ((1 << dev->ssize) + 3) >> 2 ))
00069 boot->ext.old.wt = 1;
00070 else
00071 boot->ext.old.wt = 0;
00072 boot->ext.old.rate_0= rate_0;
00073 boot->ext.old.rate_any= rate_any;
00074 if (boot->ext.old.rate_any== 2 )
00075 boot->ext.old.rate_any= 1;
00076 i=76;
00077
00078
00079 set_word(boot->ext.old.Infp0, i);
00080 boot->jump[i++] = sectors0;
00081 boot->jump[i++] = 108;
00082 for(j=1; j<= sectors0; j++)
00083 boot->jump[i++] = j;
00084
00085 set_word(boot->ext.old.InfpX, i);
00086
00087 boot->jump[i++] = 64;
00088 boot->jump[i++] = 3;
00089 nb_renum = i++;
00090 sector2 = dev->sectors;
00091 size2 = dev->ssize;
00092 j=1;
00093 while( sector2 ){
00094 while ( sector2 < (1 << size2) >> 2 )
00095 size2--;
00096 boot->jump[i++] = 128 + j;
00097 boot->jump[i++] = j++;
00098 boot->jump[i++] = size2;
00099 sector2 -= (1 << size2) >> 2;
00100 }
00101 boot->jump[nb_renum] = ( i - nb_renum - 1 ) / 3;
00102
00103 set_word(boot->ext.old.InfTm, i);
00104
00105 sector2 = dev->sectors;
00106 size2= dev->ssize;
00107 while(sector2){
00108 while ( sector2 < 1 << ( size2 - 2) )
00109 size2--;
00110 boot->jump[i++] = size2;
00111 sector2 -= 1 << (size2 - 2 );
00112 }
00113
00114 set_word(boot->ext.old.BootP,i);
00115 bootOffset = i;
00116
00117
00118 for (sum=0, j=64; j<i; j++)
00119 sum += boot->jump[j];
00120 boot->ext.old.CheckSum=-sum;
00121 return bootOffset;
00122 } else {
00123 if(!keepBoot) {
00124 boot->jump[0] = 0xeb;
00125 boot->jump[1] = 0;
00126 boot->jump[2] = 0x90;
00127 strncpy(boot->banner, "MTOOL397", 8);
00128
00129
00130
00131
00132 }
00133 return 0;
00134 }
00135 }
00136
00137
00138 static int comp_fat_bits(Fs_t *Fs, int estimate,
00139 unsigned int tot_sectors, int fat32)
00140 {
00141 int needed_fat_bits;
00142
00143 needed_fat_bits = 12;
00144
00145 #define MAX_DISK_SIZE(bits,clusters) \
00146 TOTAL_DISK_SIZE((bits), Fs->sector_size, (clusters), \
00147 Fs->num_fat, MAX_SECT_PER_CLUSTER)
00148
00149 if(tot_sectors > MAX_DISK_SIZE(12, FAT12))
00150 needed_fat_bits = 16;
00151 if(fat32 || tot_sectors > MAX_DISK_SIZE(16, FAT16))
00152 needed_fat_bits = 32;
00153
00154 #undef MAX_DISK_SIZE
00155
00156 if(abs(estimate) && abs(estimate) < needed_fat_bits) {
00157 if(fat32) {
00158 fprintf(stderr,
00159 "Contradiction between FAT size on command line and FAT size in conf file\n");
00160 exit(1);
00161 }
00162 fprintf(stderr,
00163 "Device too big for a %d bit FAT\n",
00164 estimate);
00165 exit(1);
00166 }
00167
00168 if(needed_fat_bits == 32 && !fat32 && abs(estimate) !=32){
00169 fprintf(stderr,"Warning: Using 32 bit FAT. Drive will only be accessibly by Win95 OEM / Win98\n");
00170 }
00171
00172 if(!estimate) {
00173 int min_fat16_size;
00174
00175 if(needed_fat_bits > 12)
00176 return needed_fat_bits;
00177 min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12+1,
00178 Fs->num_fat, 1);
00179 if(tot_sectors < min_fat16_size)
00180 return 12;
00181 else if(tot_sectors >= 2* min_fat16_size)
00182 return 16;
00183 }
00184
00185 return estimate;
00186 }
00187
00188 static void calc_fat_bits2(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
00189 {
00190 unsigned int rem_sect;
00191
00192
00193
00194
00195
00196 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
00197 switch(abs(fat_bits)) {
00198 case 0:
00199
00200 #define MY_DISK_SIZE(bits,clusters) \
00201 DISK_SIZE( (bits), Fs->sector_size, (clusters), \
00202 Fs->num_fat, Fs->cluster_size)
00203
00204 if(rem_sect >= MY_DISK_SIZE(16, FAT12 + 1))
00205
00206 set_fat16(Fs);
00207 else if(rem_sect <= MY_DISK_SIZE(12, FAT12))
00208
00209 set_fat12(Fs);
00210 else {
00211
00212
00213
00214 if(Fs->cluster_size < MAX_SECT_PER_CLUSTER)
00215 Fs->cluster_size <<= 1;
00216 set_fat12(Fs);
00217 }
00218 break;
00219 #undef MY_DISK_SIZE
00220
00221 case 12:
00222 set_fat12(Fs);
00223 break;
00224 case 16:
00225 set_fat16(Fs);
00226 break;
00227 case 32:
00228 set_fat32(Fs);
00229 break;
00230 }
00231 }
00232
00233 static inline void format_root(Fs_t *Fs, char *label, struct bootsector *boot)
00234 {
00235 Stream_t *RootDir;
00236 char *buf;
00237 int i;
00238 struct ClashHandling_t ch;
00239 int dirlen;
00240
00241 init_clash_handling(&ch);
00242 ch.name_converter = label_name;
00243 ch.ignore_entry = -2;
00244
00245 buf = safe_malloc(Fs->sector_size);
00246 RootDir = OpenRoot((Stream_t *)Fs);
00247 if(!RootDir){
00248 fprintf(stderr,"Could not open root directory\n");
00249 exit(1);
00250 }
00251
00252 memset(buf, '\0', Fs->sector_size);
00253
00254 if(Fs->fat_bits == 32) {
00255
00256
00257 dirlen = 1;
00258 fatAllocate(Fs, Fs->rootCluster, Fs->end_fat);
00259 } else
00260 dirlen = Fs->dir_len;
00261 for (i = 0; i < dirlen; i++)
00262 WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),
00263 Fs->sector_size);
00264
00265 ch.ignore_entry = 1;
00266 if(label[0])
00267 mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
00268
00269 FREE(&RootDir);
00270 if(Fs->fat_bits == 32)
00271 set_word(boot->dirents, 0);
00272 else
00273 set_word(boot->dirents, Fs->dir_len * (Fs->sector_size / 32));
00274 free(buf);
00275 }
00276
00277
00278 static void xdf_calc_fat_size(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
00279 {
00280 unsigned int rem_sect;
00281
00282 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
00283
00284 if(Fs->fat_len) {
00285
00286
00287
00288
00289
00290 for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
00291 Fs->num_clus = rem_sect / Fs->cluster_size;
00292 if(abs(fat_bits) == 16 || Fs->num_clus > FAT12)
00293 set_fat16(Fs);
00294 else
00295 set_fat12(Fs);
00296 if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
00297 return;
00298 }
00299 }
00300 fprintf(stderr,"Internal error while calculating Xdf fat size\n");
00301 exit(1);
00302 }
00303
00304
00305 static void calc_fat_size(Fs_t *Fs, unsigned int tot_sectors)
00306 {
00307 unsigned int rem_sect;
00308 int tries;
00309 int occupied;
00310
00311 tries=0;
00312
00313 Fs->fat_len = 1;
00314 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
00315 while(1){
00316 Fs->num_clus = (rem_sect - 2 * Fs->fat_len ) /Fs->cluster_size;
00317 Fs->fat_len = NEEDED_FAT_SIZE(Fs);
00318 occupied = 2 * Fs->fat_len + Fs->cluster_size * Fs->num_clus;
00319
00320
00321
00322
00323 if ( occupied > rem_sect )
00324 continue;
00325
00326
00327
00328
00329 if ( rem_sect - occupied < Fs->cluster_size )
00330 break;
00331
00332
00333
00334
00335
00336
00337
00338
00339 switch(tries++){
00340 default:
00341
00342 fprintf(stderr,
00343 "Internal error in cluster/fat repartition"
00344 " calculation.\n");
00345 exit(1);
00346 case 2:
00347
00348 case 1:
00349 rem_sect-= Fs->cluster_size;
00350 Fs->dir_len += Fs->cluster_size;
00351 case 0:
00352 continue;
00353 }
00354 }
00355
00356 if ( Fs->num_clus > FAT12 && Fs->fat_bits == 12 ){
00357 fprintf(stderr,"Too many clusters for this fat size."
00358 " Please choose a 16-bit fat in your /etc/mtools"
00359 " or .mtoolsrc file\n");
00360 exit(1);
00361 }
00362 if ( Fs->num_clus <= FAT12 && Fs->fat_bits > 12 ){
00363 fprintf(stderr,"Too few clusters for this fat size."
00364 " Please choose a 12-bit fat in your /etc/mtools"
00365 " or .mtoolsrc file\n");
00366 exit(1);
00367 }
00368 }
00369
00370
00371 static unsigned char bootprog[]=
00372 {0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
00373 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
00374 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
00375 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
00376 0x00, 0xcd, 0x19};
00377
00378 static inline void inst_boot_prg(struct bootsector *boot, int offset)
00379 {
00380 memcpy((char *) boot->jump + offset,
00381 (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
00382 boot->jump[0] = 0xeb;
00383 boot->jump[1] = offset - 1;
00384 boot->jump[2] = 0x90;
00385 set_word(boot->jump + offset + 20, offset + 24);
00386 }
00387
00388 static void calc_cluster_size(struct Fs_t *Fs, unsigned int tot_sectors,
00389 int fat_bits)
00390
00391 {
00392 unsigned int max_clusters;
00393
00394 unsigned int max_fat_size;
00395
00396 unsigned int rem_sect;
00397
00398
00399 switch(abs(fat_bits)) {
00400 case 12:
00401 max_clusters = FAT12;
00402 max_fat_size = Fs->num_fat *
00403 FAT_SIZE(12, Fs->sector_size, max_clusters);
00404 break;
00405 case 16:
00406 case 0:
00407 max_clusters = FAT16;
00408 max_fat_size = Fs->num_fat *
00409 FAT_SIZE(16, Fs->sector_size, max_clusters);
00410 break;
00411 case 32:
00412 Fs->cluster_size = 8;
00413
00414
00415
00416
00417 return;
00418 default:
00419 fprintf(stderr,"Bad fat size\n");
00420 exit(1);
00421 }
00422
00423 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
00424
00425
00426
00427 while(Fs->cluster_size * max_clusters + max_fat_size < rem_sect) {
00428 if(Fs->cluster_size > 64) {
00429
00430 fprintf(stderr,
00431 "Internal error while calculating cluster size\n");
00432 exit(1);
00433 }
00434 Fs->cluster_size <<= 1;
00435 }
00436 }
00437
00438
00439 struct OldDos_t old_dos[]={
00440 { 40, 9, 1, 4, 1, 2, 0xfc },
00441 { 40, 9, 2, 7, 2, 2, 0xfd },
00442 { 40, 8, 1, 4, 1, 1, 0xfe },
00443 { 40, 8, 2, 7, 2, 1, 0xff },
00444 { 80, 9, 2, 7, 2, 3, 0xf9 },
00445 { 80, 15, 2,14, 1, 7, 0xf9 },
00446 { 80, 18, 2,14, 1, 9, 0xf0 },
00447 { 80, 36, 2,15, 2, 9, 0xf0 },
00448 { 1, 8, 1, 1, 1, 1, 0xf0 },
00449 };
00450
00451 static int old_dos_size_to_geom(int size, int *cyls, int *heads, int *sects)
00452 {
00453 int i;
00454 size = size * 2;
00455 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
00456 if (old_dos[i].sectors *
00457 old_dos[i].tracks *
00458 old_dos[i].heads == size) {
00459 *cyls = old_dos[i].tracks;
00460 *heads = old_dos[i].heads;
00461 *sects = old_dos[i].sectors;
00462 return 0;
00463 }
00464 }
00465 return 1;
00466 }
00467
00468
00469 static void calc_fs_parameters(struct device *dev, unsigned int tot_sectors,
00470 struct Fs_t *Fs, struct bootsector *boot)
00471 {
00472 int i;
00473
00474 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
00475 if (dev->sectors == old_dos[i].sectors &&
00476 dev->tracks == old_dos[i].tracks &&
00477 dev->heads == old_dos[i].heads &&
00478 (dev->fat_bits == 0 || abs(dev->fat_bits) == 12)){
00479 boot->descr = old_dos[i].media;
00480 Fs->cluster_size = old_dos[i].cluster_size;
00481 Fs->dir_len = old_dos[i].dir_len;
00482 Fs->fat_len = old_dos[i].fat_len;
00483 Fs->fat_bits = 12;
00484 break;
00485 }
00486 }
00487 if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
00488
00489 if(DWORD(nhs))
00490 boot->descr = 0xf8;
00491 else
00492 boot->descr = 0xf0;
00493
00494
00495 if(!Fs->cluster_size) {
00496 if (dev->heads == 1)
00497 Fs->cluster_size = 1;
00498 else {
00499 Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
00500 if (dev->use_2m & 0x7f)
00501 Fs->cluster_size = 1;
00502 }
00503 }
00504
00505 if(!Fs->dir_len) {
00506 if (dev->heads == 1)
00507 Fs->dir_len = 4;
00508 else
00509 Fs->dir_len = (tot_sectors > 2000) ? 11 : 7;
00510 }
00511
00512 calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
00513 if(Fs->fat_len)
00514 xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
00515 else {
00516 calc_fat_bits2(Fs, tot_sectors, dev->fat_bits);
00517 calc_fat_size(Fs, tot_sectors);
00518 }
00519 }
00520
00521 set_word(boot->fatlen, Fs->fat_len);
00522 }
00523
00524
00525
00526 static void calc_fs_parameters_32(unsigned int tot_sectors,
00527 struct Fs_t *Fs, struct bootsector *boot)
00528 {
00529 if(DWORD(nhs))
00530 boot->descr = 0xf8;
00531 else
00532 boot->descr = 0xf0;
00533 if(!Fs->cluster_size)
00534
00535
00536
00537
00538 Fs->cluster_size = 8;
00539
00540 Fs->dir_len = 0;
00541 Fs->num_clus = tot_sectors / Fs->cluster_size;
00542 set_fat32(Fs);
00543 calc_fat_size(Fs, tot_sectors);
00544 set_word(boot->fatlen, 0);
00545 set_dword(boot->ext.fat32.bigFat, Fs->fat_len);
00546 }
00547
00548
00549
00550
00551 static void usage(void)
00552 {
00553 fprintf(stderr,
00554 "Mtools version %s, dated %s\n", mversion, mdate);
00555 fprintf(stderr,
00556 "Usage: %s [-t tracks] [-h heads] [-n sectors] "
00557 "[-v label] [-1] [-4] [-8] [-f size] "
00558 "[-N serialnumber] "
00559 "[-k] [-B bootsector] [-r root_dir_len] [-L fat_len] "
00560 "[-F] [-I fsVersion] [-C] [-c cluster_size] "
00561 "[-H hidden_sectors] "
00562 #ifdef USE_XDF
00563 "[-X] "
00564 #endif
00565 "[-S hardsectorsize] [-M softsectorsize] [-3] "
00566 "[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
00567 "device\n", progname);
00568 exit(1);
00569 }
00570
00571 void mformat(int argc, char **argv, int dummy)
00572 {
00573 int r;
00574 Fs_t Fs;
00575 int hs, hs_set;
00576 int arguse_2m = 0;
00577 int sectors0=18;
00578 int create = 0;
00579 int rate_0, rate_any;
00580 int mangled;
00581 int argssize=0;
00582 int msize=0;
00583 int fat32 = 0;
00584 struct label_blk_t *labelBlock;
00585 int bootOffset;
00586
00587 #ifdef USE_XDF
00588 int i;
00589 int format_xdf = 0;
00590 struct xdf_info info;
00591 #endif
00592 struct bootsector *boot;
00593 char *bootSector=0;
00594 int c;
00595 int keepBoot = 0;
00596 struct device used_dev;
00597 int argtracks, argheads, argsectors;
00598 int tot_sectors;
00599 int blocksize;
00600
00601 char *drive, name[EXPAND_BUF];
00602
00603 char label[VBUFSIZE], buf[MAX_SECTOR], shortlabel[13];
00604 struct device *dev;
00605 char errmsg[200];
00606
00607 unsigned long serial;
00608 int serial_set;
00609 int fsVersion;
00610
00611 mt_off_t maxSize;
00612
00613 int Atari = 0;
00614 #ifdef OS_Minix
00615 char *devname;
00616 struct device onedevice[2];
00617 struct stat stbuf;
00618 #endif
00619
00620 hs = hs_set = 0;
00621 argtracks = 0;
00622 argheads = 0;
00623 argsectors = 0;
00624 arguse_2m = 0;
00625 argssize = 0x2;
00626 label[0] = '\0';
00627 serial_set = 0;
00628 serial = 0;
00629 fsVersion = 0;
00630
00631 Fs.cluster_size = 0;
00632 Fs.refs = 1;
00633 Fs.dir_len = 0;
00634 Fs.fat_len = 0;
00635 Fs.Class = &FsClass;
00636 rate_0 = mtools_rate_0;
00637 rate_any = mtools_rate_any;
00638
00639
00640 while ((c = getopt(argc,argv,
00641 "148f:t:n:v:qub"
00642 "kB:r:L:IFCc:Xh:s:l:N:H:M:S:230:Aa"))!= EOF) {
00643 switch (c) {
00644
00645 case '1':
00646 argheads = 1;
00647 break;
00648 case '4':
00649 argsectors = 9;
00650 argtracks = 40;
00651 break;
00652 case '8':
00653 argsectors = 8;
00654 argtracks = 40;
00655 break;
00656 case 'f':
00657 r=old_dos_size_to_geom(atoi(optarg),
00658 &argtracks, &argheads,
00659 &argsectors);
00660 if(r) {
00661 fprintf(stderr,
00662 "Bad size %s\n", optarg);
00663 exit(1);
00664 }
00665 break;
00666 case 't':
00667 argtracks = atoi(optarg);
00668 break;
00669
00670 case 'n':
00671 case 's':
00672 argsectors = atoi(optarg);
00673 break;
00674
00675 case 'l':
00676 case 'v':
00677 strncpy(label, optarg, VBUFSIZE-1);
00678 label[VBUFSIZE-1] = '\0';
00679 break;
00680
00681
00682 case 'q':
00683 case 'u':
00684 case 'b':
00685
00686 fprintf(stderr,
00687 "Flag %c not supported by mtools\n",c);
00688 exit(1);
00689
00690
00691
00692
00693 case 'F':
00694 fat32 = 1;
00695 break;
00696
00697
00698 case 'S':
00699 argssize = atoi(optarg) | 0x80;
00700 if(argssize < 0x81)
00701 usage();
00702 break;
00703
00704 #ifdef USE_XDF
00705 case 'X':
00706 format_xdf = 1;
00707 break;
00708 #endif
00709
00710 case '2':
00711 arguse_2m = 0xff;
00712 sectors0 = atoi(optarg);
00713 break;
00714 case '3':
00715 arguse_2m = 0x80;
00716 break;
00717
00718 case '0':
00719 rate_0 = atoi(optarg);
00720 break;
00721 case 'A':
00722 rate_any = atoi(optarg);
00723 break;
00724
00725 case 'M':
00726 msize = atoi(optarg);
00727 if (msize % 256 || msize > 8192 )
00728 usage();
00729 break;
00730
00731 case 'N':
00732 serial = strtoul(optarg,0,16);
00733 serial_set = 1;
00734 break;
00735 case 'a':
00736 Atari = 1;
00737 break;
00738
00739 case 'C':
00740 create = O_CREAT;
00741 break;
00742
00743 case 'H':
00744 hs = atoi(optarg);
00745 hs_set = 1;
00746 break;
00747
00748 case 'I':
00749 fsVersion = strtoul(optarg,0,0);
00750 break;
00751
00752 case 'c':
00753 Fs.cluster_size = atoi(optarg);
00754 break;
00755
00756 case 'r':
00757 Fs.dir_len = strtoul(optarg,0,0);
00758 break;
00759 case 'L':
00760 Fs.fat_len = strtoul(optarg,0,0);
00761 break;
00762
00763
00764 case 'B':
00765 bootSector = optarg;
00766 break;
00767 case 'k':
00768 keepBoot = 1;
00769 break;
00770 case 'h':
00771 argheads = atoi(optarg);
00772 break;
00773
00774 default:
00775 usage();
00776 }
00777 }
00778
00779 if (argc - optind != 1 ||
00780 skip_drive(argv[optind]) == argv[optind])
00781 usage();
00782
00783 #ifdef USE_XDF
00784 if(create && format_xdf) {
00785 fprintf(stderr,"Create and XDF can't be used together\n");
00786 exit(1);
00787 }
00788 #endif
00789
00790 drive = get_drive(argv[argc -1], NULL);
00791
00792 #ifdef OS_Minix
00793 devname = safe_malloc((9 + strlen(drive)) * sizeof(devname[0]));
00794 strcpy(devname, "/dev/dosX");
00795 if (isupper(drive[0]) && drive[1] == 0) {
00796
00797 devname[8]= drive[0];
00798 } else
00799 if (strchr(drive, '/') == NULL) {
00800
00801 strcpy(devname+5, drive);
00802 } else {
00803
00804 strcpy(devname, drive);
00805 }
00806 if (stat(devname, &stbuf) != -1) {
00807 memset(onedevice, 0, sizeof(onedevice));
00808 onedevice[0].name = devname;
00809 onedevice[0].drive = drive;
00810 onedevice[1].name = NULL;
00811 onedevice[1].drive = NULL;
00812 dev = onedevice;
00813 } else {
00814 dev = devices;
00815 }
00816 #else
00817 dev = devices;
00818 #endif
00819
00820
00821 sprintf(errmsg, "Drive '%s:' not supported", drive);
00822 Fs.Direct = NULL;
00823 blocksize = 0;
00824 for(;dev->drive;dev++) {
00825 FREE(&(Fs.Direct));
00826
00827 if (strcmp(dev->drive, drive) != 0)
00828 continue;
00829 used_dev = *dev;
00830
00831 SET_INT(used_dev.tracks, argtracks);
00832 SET_INT(used_dev.heads, argheads);
00833 SET_INT(used_dev.sectors, argsectors);
00834 SET_INT(used_dev.use_2m, arguse_2m);
00835 SET_INT(used_dev.ssize, argssize);
00836 if(hs_set)
00837 used_dev.hidden = hs;
00838
00839 expand(dev->name, name);
00840 #ifdef USING_NEW_VOLD
00841 strcpy(name, getVoldName(dev, name));
00842 #endif
00843
00844 #ifdef USE_XDF
00845 if(!format_xdf) {
00846 #endif
00847 Fs.Direct = 0;
00848 #ifdef USE_FLOPPYD
00849 Fs.Direct = FloppydOpen(&used_dev, dev, name, O_RDWR | create,
00850 errmsg, 0, 1);
00851 if(Fs.Direct) {
00852 maxSize = max_off_t_31;
00853 }
00854 #endif
00855 if(!Fs.Direct) {
00856 Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
00857 O_RDWR | create,
00858 errmsg, 0, 1, &maxSize);
00859 }
00860 #ifdef USE_XDF
00861 } else {
00862 used_dev.misc_flags |= USE_XDF_FLAG;
00863 Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
00864 errmsg, &info);
00865 if(Fs.Direct && !Fs.fat_len)
00866 Fs.fat_len = info.FatSize;
00867 if(Fs.Direct && !Fs.dir_len)
00868 Fs.dir_len = info.RootDirSize;
00869 }
00870 #endif
00871
00872 if (!Fs.Direct)
00873 continue;
00874
00875 #ifdef OS_linux
00876 if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
00877 (!IS_SCSI(dev))) {
00878 int fd= get_fd(Fs.Direct);
00879 struct stat buf;
00880
00881 if (fstat(fd, &buf) < 0) {
00882 sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
00883 continue;
00884 }
00885
00886 if (S_ISBLK(buf.st_mode)) {
00887 struct hd_geometry geom;
00888 long size;
00889 int sect_per_track;
00890
00891 if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
00892 sprintf(errmsg, "Could not get geometry of device (%s)",
00893 strerror(errno));
00894 continue;
00895 }
00896
00897 if (ioctl(fd, BLKGETSIZE, &size) < 0) {
00898 sprintf(errmsg, "Could not get size of device (%s)",
00899 strerror(errno));
00900 continue;
00901 }
00902
00903 sect_per_track = geom.heads * geom.sectors;
00904 used_dev.heads = geom.heads;
00905 used_dev.sectors = geom.sectors;
00906 used_dev.hidden = geom.start % sect_per_track;
00907 used_dev.tracks = (size + used_dev.hidden) / sect_per_track;
00908 }
00909 }
00910 #endif
00911
00912
00913 if (!used_dev.tracks || !used_dev.heads || !used_dev.sectors){
00914 sprintf(errmsg,
00915 "Unknown geometry "
00916 "(You must tell the complete geometry "
00917 "of the disk, \neither in /etc/mtools.conf or "
00918 "on the command line) ");
00919 continue;
00920 }
00921
00922 #if 0
00923
00924 if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
00925 sprintf(errmsg,"Can't set disk parameters: %s",
00926 strerror(errno));
00927 continue;
00928 }
00929 #endif
00930 Fs.sector_size = 512;
00931 if( !(used_dev.use_2m & 0x7f)) {
00932 Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
00933 }
00934
00935 SET_INT(Fs.sector_size, msize);
00936 {
00937 int i;
00938 for(i = 0; i < 31; i++) {
00939 if (Fs.sector_size == 1 << i) {
00940 Fs.sectorShift = i;
00941 break;
00942 }
00943 }
00944 Fs.sectorMask = Fs.sector_size - 1;
00945 }
00946
00947 if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
00948 blocksize = Fs.sector_size;
00949 else
00950 blocksize = used_dev.blocksize;
00951
00952 if(blocksize > MAX_SECTOR)
00953 blocksize = MAX_SECTOR;
00954
00955
00956 if (!create &&
00957 READS(Fs.Direct, (char *) buf, 0, Fs.sector_size) !=
00958 Fs.sector_size) {
00959 sprintf(errmsg,
00960 "Error reading from '%s', wrong parameters?",
00961 name);
00962 continue;
00963 }
00964 break;
00965 }
00966
00967
00968
00969 if ( dev->drive == 0 ){
00970 FREE(&Fs.Direct);
00971 fprintf(stderr,"%s: %s\n", argv[0],errmsg);
00972 exit(1);
00973 }
00974
00975
00976 boot = (struct bootsector *) buf;
00977 if(bootSector) {
00978 int fd;
00979
00980 fd = open(bootSector, O_RDONLY);
00981 if(fd < 0) {
00982 perror("open boot sector");
00983 exit(1);
00984 }
00985 read(fd, buf, blocksize);
00986 keepBoot = 1;
00987 }
00988 if(!keepBoot) {
00989 memset((char *)boot, '\0', Fs.sector_size);
00990 if(Fs.sector_size == 512 && !used_dev.partition) {
00991
00992 struct partition *partTable=(struct partition *)
00993 (((char*) boot) + 0x1ae);
00994 setBeginEnd(&partTable[1], 0,
00995 used_dev.heads * used_dev.sectors * used_dev.tracks,
00996 used_dev.heads, used_dev.sectors, 1, 0);
00997 }
00998 }
00999 set_dword(boot->nhs, used_dev.hidden);
01000
01001 Fs.Next = buf_init(Fs.Direct,
01002 blocksize * used_dev.heads * used_dev.sectors,
01003 blocksize * used_dev.heads * used_dev.sectors,
01004 blocksize);
01005 Fs.Buffer = 0;
01006
01007 boot->nfat = Fs.num_fat = 2;
01008 if(!keepBoot)
01009 set_word(boot->jump + 510, 0xaa55);
01010
01011
01012 tot_sectors = used_dev.tracks * used_dev.heads * used_dev.sectors -
01013 DWORD(nhs);
01014
01015 set_word(boot->nsect, dev->sectors);
01016 set_word(boot->nheads, dev->heads);
01017
01018 dev->fat_bits = comp_fat_bits(&Fs,dev->fat_bits, tot_sectors, fat32);
01019
01020 if(dev->fat_bits == 32) {
01021 Fs.primaryFat = 0;
01022 Fs.writeAllFats = 1;
01023 Fs.fat_start = 32;
01024 calc_fs_parameters_32(tot_sectors, &Fs, boot);
01025
01026 Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
01027
01028
01029 set_word(boot->ext.fat32.extFlags,0);
01030
01031
01032 set_word(boot->ext.fat32.fsVersion,fsVersion);
01033
01034
01035 set_dword(boot->ext.fat32.rootCluster, Fs.rootCluster = 2);
01036
01037
01038 set_word(boot->ext.fat32.infoSector, Fs.infoSectorLoc = 1);
01039 Fs.infoSectorLoc = 1;
01040
01041
01042 set_word(boot->ext.fat32.backupBoot, 6);
01043
01044 labelBlock = & boot->ext.fat32.labelBlock;
01045 } else {
01046 Fs.infoSectorLoc = 0;
01047 Fs.fat_start = 1;
01048 calc_fs_parameters(&used_dev, tot_sectors, &Fs, boot);
01049 Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
01050 Fs.clus_start = Fs.dir_start + Fs.dir_len;
01051 labelBlock = & boot->ext.old.labelBlock;
01052
01053 }
01054
01055 if (!keepBoot)
01056
01057
01058 labelBlock->physdrive = 0x00;
01059 labelBlock->reserved = 0;
01060 labelBlock->dos4 = 0x29;
01061
01062 if (!serial_set || Atari)
01063 srandom((long)time (0));
01064 if (!serial_set)
01065 serial=random();
01066 set_dword(labelBlock->serial, serial);
01067 if(!label[0])
01068 strncpy(shortlabel, "NO NAME ",11);
01069 else
01070 label_name(label, 0, &mangled, shortlabel);
01071 strncpy(labelBlock->label, shortlabel, 11);
01072 sprintf(labelBlock->fat_type, "FAT%2.2d ", Fs.fat_bits);
01073 labelBlock->fat_type[7] = ' ';
01074
01075 set_word(boot->secsiz, Fs.sector_size);
01076 boot->clsiz = (unsigned char) Fs.cluster_size;
01077 set_word(boot->nrsvsect, Fs.fat_start);
01078
01079 bootOffset = init_geometry_boot(boot, &used_dev, sectors0,
01080 rate_0, rate_any,
01081 &tot_sectors, keepBoot);
01082 if(!bootOffset) {
01083 bootOffset = ((char *) labelBlock) - ((char *) boot) +
01084 sizeof(struct label_blk_t);
01085 }
01086 if(Atari) {
01087 boot->banner[4] = 0;
01088 boot->banner[5] = random();
01089 boot->banner[6] = random();
01090 boot->banner[7] = random();
01091 }
01092
01093 if (create) {
01094 WRITES(Fs.Direct, (char *) buf,
01095 sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
01096 Fs.sector_size);
01097 }
01098
01099 if(!keepBoot)
01100 inst_boot_prg(boot, bootOffset);
01101 if(dev->use_2m & 0x7f)
01102 Fs.num_fat = 1;
01103 Fs.lastFatSectorNr = 0;
01104 Fs.lastFatSectorData = 0;
01105 zero_fat(&Fs, boot->descr);
01106 Fs.freeSpace = Fs.num_clus;
01107 Fs.last = 2;
01108
01109 #ifdef USE_XDF
01110 if(format_xdf)
01111 for(i=0;
01112 i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size;
01113 i++)
01114 fatEncode(&Fs, i+2, 0xfff7);
01115 #endif
01116
01117 format_root(&Fs, label, boot);
01118 WRITES((Stream_t *)&Fs, (char *) boot, (mt_off_t) 0, Fs.sector_size);
01119 if(Fs.fat_bits == 32 && WORD(ext.fat32.backupBoot) != MAX32) {
01120 WRITES((Stream_t *)&Fs, (char *) boot,
01121 sectorsToBytes((Stream_t*)&Fs, WORD(ext.fat32.backupBoot)),
01122 Fs.sector_size);
01123 }
01124 FLUSH((Stream_t *)&Fs);
01125
01126 FREE(&Fs.Next);
01127 Fs.Class->freeFunc((Stream_t *)&Fs);
01128 #ifdef USE_XDF
01129 if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
01130 fprintf(stderr,
01131 "Note:\n"
01132 "Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
01133 "variable before accessing this disk\n\n"
01134 "Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
01135 " export MTOOLS_USE_XDF=1\n\n"
01136 "C shell syntax (csh and tcsh):\n"
01137 " setenv MTOOLS_USE_XDF 1\n" );
01138 #endif
01139 exit(0);
01140 }