home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / mtools_3.6.src.lzh / MTOOLS_3.6 / mformat.c < prev    next >
Text File  |  1997-11-12  |  20KB  |  851 lines

  1. /*
  2.  * mformat.c
  3.  */
  4.  
  5. #include "sysincludes.h"
  6. #include "msdos.h"
  7. #include "mtools.h"
  8. #include "mainloop.h"
  9. #include "fsP.h"
  10. #include "file.h"
  11. #include "plain_io.h"
  12. #include "nameclash.h"
  13. #include "buffer.h"
  14. #ifdef USE_XDF
  15. #include "xdf_io.h"
  16. #endif
  17.  
  18. #ifdef _OSK
  19. #define srandom(x) srand(x)
  20. #define random() rand()
  21. #endif
  22.  
  23. #include <math.h>
  24.  
  25. #define abs(x) ((x)>0?(x):-(x))
  26.  
  27. extern int errno;
  28.  
  29. static void init_geometry_boot(struct bootsector *boot, struct device *dev,
  30.                    int sectors0, int rate_0, int rate_any,
  31.                    int *tot_sectors)
  32. {
  33.     int i;
  34.     int nb_renum;
  35.     int sector2;
  36.     int size2;
  37.     int j;
  38.     int sum;
  39.  
  40.     set_word(boot->nsect, dev->sectors);
  41.     set_word(boot->nheads, dev->heads);
  42.  
  43.     *tot_sectors = dev->heads * dev->sectors * dev->tracks - DWORD(nhs);
  44.  
  45.     if (*tot_sectors < 0x10000){
  46.         set_word(boot->psect, *tot_sectors);
  47.         set_dword(boot->bigsect, 0);
  48.     } else {
  49.         set_word(boot->psect, 0);
  50.         set_dword(boot->bigsect, *tot_sectors);
  51.     }
  52.  
  53.     if (dev->use_2m & 0x7f){
  54.         strncpy(boot->banner, "2M-STV04", 8);
  55.         boot->ext.old.res_2m = 0;
  56.         boot->ext.old.fmt_2mf = 6;
  57.         if ( dev->sectors % ( ((1 << dev->ssize) + 3) >> 2 ))
  58.             boot->ext.old.wt = 1;
  59.         else
  60.             boot->ext.old.wt = 0;
  61.         boot->ext.old.rate_0= rate_0;
  62.         boot->ext.old.rate_any= rate_any;
  63.         if (boot->ext.old.rate_any== 2 )
  64.             boot->ext.old.rate_any= 1;
  65.         i=76;
  66.  
  67.         /* Infp0 */
  68.         set_word(boot->ext.old.Infp0, i);
  69.         boot->jump[i++] = sectors0;
  70.         boot->jump[i++] = 108;
  71.         for(j=1; j<= sectors0; j++)
  72.             boot->jump[i++] = j;
  73.  
  74.         set_word(boot->ext.old.InfpX, i);
  75.         
  76.         boot->jump[i++] = 64;
  77.         boot->jump[i++] = 3;
  78.         nb_renum = i++;
  79.         sector2 = dev->sectors;
  80.         size2 = dev->ssize;
  81.         j=1;
  82.         while( sector2 ){
  83.             while ( sector2 < (1 << size2) >> 2 )
  84.                 size2--;
  85.             boot->jump[i++] = 128 + j;
  86.             boot->jump[i++] = j++;
  87.             boot->jump[i++] = size2;
  88.             sector2 -= (1 << size2) >> 2;
  89.         }
  90.         boot->jump[nb_renum] = ( i - nb_renum - 1 ) / 3;
  91.  
  92.         set_word(boot->ext.old.InfTm, i);
  93.  
  94.         sector2 = dev->sectors;
  95.         size2= dev->ssize;
  96.         while(sector2){
  97.             while ( sector2 < 1 << ( size2 - 2) )
  98.                 size2--;
  99.             boot->jump[i++] = size2;
  100.             sector2 -= 1 << (size2 - 2 );
  101.         }
  102.         
  103.         set_word(boot->ext.old.BootP,i);
  104.  
  105.         /* checksum */        
  106.         for (sum=0, j=64; j<i; j++) 
  107.             sum += boot->jump[j];/* checksum */
  108.         boot->ext.old.CheckSum=-sum;
  109.     } else {
  110.         boot->jump[0] = 0xeb;
  111.         boot->jump[1] = 0;
  112.         boot->jump[2] = 0x90;
  113.         strncpy(boot->banner, "MTOOLS33", 8);
  114.         /* It looks like some versions of DOS are rather picky
  115.          * about this, and assume default parameters without this,
  116.          * ignoring any indication about cluster size et al. */
  117.         set_word(boot->ext.old.BootP, OFFSET(ext.old.BootP) + 2);
  118.     }
  119.     return;
  120. }
  121.  
  122.  
  123. static int comp_fat_bits(Fs_t *Fs, int estimate, 
  124.              unsigned int tot_sectors, int fat32)
  125. {
  126.     int needed_fat_bits;
  127.  
  128.     needed_fat_bits = 12;
  129.     if(tot_sectors > MAX_FAT12_SIZE(Fs->sector_size))
  130.         needed_fat_bits = 16;           
  131.     if(fat32 || tot_sectors > MAX_FAT16_SIZE(Fs->sector_size))
  132.         needed_fat_bits = 32;        
  133.     if(abs(estimate) && abs(estimate) < needed_fat_bits) {
  134.         if(fat32) {
  135.             fprintf(stderr,
  136.                 "Contradiction between FAT size on command line and FAT size in conf file\n");
  137.             exit(1);
  138.         }        
  139.         fprintf(stderr,
  140.             "Device too big for a %d bit FAT\n",
  141.             estimate);
  142.         exit(1);
  143.     }
  144.  
  145.     if(needed_fat_bits == 32 && !fat32 && abs(estimate) !=32){
  146.         fprintf(stderr,"Warning: Using 32 bit FAT.  Drive will only be accessibly by Win95 OEM\n");        
  147.     }
  148.  
  149.     if(!estimate) {
  150.         if(needed_fat_bits > 12)
  151.             return needed_fat_bits;
  152.         else if(tot_sectors < MIN_FAT16_SIZE(Fs->sector_size))
  153.             return 12;
  154.         else if(tot_sectors >= 2* MIN_FAT16_SIZE(Fs->sector_size))
  155.             return 16; /* heuristics */
  156.     }
  157.  
  158.     return estimate;
  159. }
  160.  
  161. static void calc_fat_bits2(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
  162. {
  163.     unsigned int rem_sect;
  164.  
  165.     /*
  166.      * the "remaining sectors" after directory and boot
  167.      * has been accounted for.
  168.      */
  169.     rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
  170.     switch(abs(fat_bits)) {
  171.         case 0:
  172.             if((rem_sect - 32)/Fs->cluster_size > FAT12)
  173.                 /* big enough for FAT16:
  174.                  * sectors minus 2 fats of 32
  175.                  * bits */
  176.                 set_fat16(Fs);
  177.             else if((rem_sect - 24)/Fs->cluster_size <= FAT12)
  178.                 set_fat12(Fs);
  179.             else {
  180.                 /* "between two chairs",
  181.                  * augment cluster size, and
  182.                  * settle it */
  183.                 Fs->cluster_size <<= 1;
  184.                 set_fat12(Fs);
  185.             }
  186.             break;
  187.         case 12:
  188.             set_fat12(Fs);
  189.             break;
  190.         case 16:
  191.             set_fat16(Fs);
  192.             break;
  193.         case 32:
  194.             set_fat32(Fs);
  195.             break;
  196.     }
  197. }
  198.  
  199. static inline void format_root(Fs_t *Fs, char *label, struct bootsector *boot)
  200. {
  201.     Stream_t *RootDir;
  202.     char *buf;
  203.     int i;
  204.     struct ClashHandling_t ch;
  205.     int dirlen;
  206.  
  207.     init_clash_handling(&ch);
  208.     ch.name_converter = label_name;
  209.     ch.ignore_entry = -2;
  210.  
  211.     buf = safe_malloc(Fs->sector_size);
  212.     RootDir = open_root((Stream_t *)Fs);
  213.     if(!RootDir){
  214.         fprintf(stderr,"Could not open root directory\n");
  215.         exit(1);
  216.     }
  217.  
  218.     memset(buf, '\0', Fs->sector_size);
  219.  
  220.     if(Fs->fat_bits == 32)
  221.         /* on a FAT32 system, we only write one sector,
  222.          * as the directory can be extended at will...*/
  223.         dirlen = 1;
  224.     else
  225.         dirlen = Fs->dir_len; 
  226.     for (i = 0; i < dirlen; i++)
  227.         WRITES(RootDir, buf, i * Fs->sector_size,  Fs->sector_size);
  228.  
  229.     ch.ignore_entry = 1;
  230.     if(label[0])
  231.         mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
  232.  
  233.     FREE(&RootDir);
  234.     if(Fs->fat_bits == 32)
  235.         set_word(boot->dirents, 0);
  236.     else
  237.         set_word(boot->dirents, Fs->dir_len * (Fs->sector_size / 32));
  238. }
  239.  
  240.  
  241. static void xdf_calc_fat_size(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
  242. {
  243.     unsigned int rem_sect;
  244.  
  245.     rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
  246.  
  247.     if(Fs->fat_len) {
  248.         /* an XDF disk, we know the fat_size and have to find
  249.          * out the rest. We start with a cluster size of 1 and
  250.          * keep doubling until everything fits into the
  251.          * FAT. This will occur eventually, as our FAT has a
  252.          * minimal size of 1 */
  253.         for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
  254.             Fs->num_clus = rem_sect / Fs->cluster_size;
  255.             if(abs(fat_bits) == 16 || Fs->num_clus > FAT12)
  256.                 set_fat16(Fs);
  257.             else
  258.                 set_fat12(Fs);
  259.             if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
  260.                 return;
  261.         }
  262.     }
  263.     fprintf(stderr,"Internal error while calculating Xdf fat size\n");
  264.     exit(1);
  265. }
  266.  
  267.  
  268. static void calc_fat_size(Fs_t *Fs, unsigned int tot_sectors)
  269. {
  270.     unsigned int rem_sect;
  271.     int tries;
  272.     int occupied;
  273.     
  274.     tries=0;
  275.     /* rough estimate of fat size */
  276.     Fs->fat_len = 1;
  277.     rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
  278.     while(1){
  279.         Fs->num_clus = (rem_sect - 2 * Fs->fat_len ) /Fs->cluster_size;
  280.         Fs->fat_len = NEEDED_FAT_SIZE(Fs);
  281.         occupied = 2 * Fs->fat_len + Fs->cluster_size * Fs->num_clus;
  282.         
  283.         /* if we have used up more than we have,
  284.          * we'll have to reloop */
  285.         
  286.         if ( occupied > rem_sect )
  287.             continue;
  288.  
  289.  
  290.         /* if we have exactly used up all
  291.          * sectors, fine */
  292.         if ( rem_sect - occupied < Fs->cluster_size )
  293.             break;
  294.  
  295.         /* if we have not used up all our
  296.          * sectors, try again.  After the second
  297.          * try, decrease the amount of available
  298.          * space. This is to deal with the case of
  299.          * 344 or 345, ..., 1705, ... available
  300.          * sectors.  */
  301.         
  302.         switch(tries++){
  303.             default:
  304.                 /* this should never happen */
  305.                 fprintf(stderr,
  306.                     "Internal error in cluster/fat repartition"
  307.                     " calculation.\n");
  308.                 exit(1);
  309.             case 2:
  310.                 /* FALLTHROUGH */
  311.             case 1:
  312.                 rem_sect-= Fs->cluster_size;
  313.                 Fs->dir_len += Fs->cluster_size;
  314.             case 0:
  315.                 continue;
  316.         }
  317.     }
  318.  
  319.     if ( Fs->num_clus > FAT12 && Fs->fat_bits == 12 ){
  320.         fprintf(stderr,"Too many clusters for this fat size."
  321.             " Please choose a 16-bit fat in your /etc/mtools"
  322.             " or .mtoolsrc file\n");
  323.         exit(1);
  324.     }
  325. }
  326.  
  327.  
  328. static unsigned char bootprog[]=
  329. {0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
  330.  0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
  331.  0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
  332.  0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
  333.  0x00, 0xcd, 0x19};
  334.  
  335. static inline void inst_boot_prg(struct bootsector *boot)
  336. {
  337.     int offset = WORD(ext.old.BootP);
  338.     memcpy((char *) boot->jump + offset, 
  339.            (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
  340.     boot->jump[0] = 0xeb;
  341.     boot->jump[1] = offset + 1;
  342.     boot->jump[2] = 0x90;
  343.     set_word(boot->jump + offset + 20, offset + 24);
  344. }
  345.  
  346. static void calc_cluster_size(struct Fs_t *Fs, unsigned int tot_sectors,
  347.                   int fat_bits)
  348.                   
  349. {
  350.     unsigned int term, mult, rem_sect;
  351.  
  352.     switch(abs(fat_bits)) {
  353.         case 12:            
  354.             mult = FAT12;
  355.             term = MAX_FAT12_FATLEN(Fs->sector_size);
  356.             break;
  357.         case 16:
  358.         case 0: /* still hesititating between 12 and 16 */
  359.             mult = FAT16;
  360.             term = MAX_FAT16_FATLEN(Fs->sector_size);
  361.             break;
  362.         case 32:
  363.             Fs->cluster_size = 1;
  364.             return;
  365.         default:
  366.             fprintf(stderr,"Bad fat size\n");
  367.             exit(1);
  368.     }
  369.  
  370.     rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
  371.     while(Fs->cluster_size * mult  + term < rem_sect) {
  372.         if(Fs->cluster_size > 64) {
  373.             /* bigger than 64. Should fit */
  374.             fprintf(stderr,
  375.                 "Internal error while calculating cluster size\n");
  376.             exit(1);
  377.         }
  378.         Fs->cluster_size <<= 1;
  379.     }
  380. }
  381.  
  382.  
  383. struct OldDos_t old_dos[]={
  384. {   40,  9,  1, 4, 1, 2, 0xfc },
  385. {   40,  9,  2, 7, 2, 2, 0xfd },
  386. {   40,  8,  1, 4, 1, 1, 0xfe },
  387. {   40,  8,  2, 7, 2, 1, 0xff },
  388. {   80,  9,  2, 7, 2, 3, 0xf9 },
  389. {   80, 15,  2,14, 1, 7, 0xf9 },
  390. {   80, 18,  2,14, 1, 9, 0xf0 },
  391. {   80, 36,  2,15, 2, 9, 0xf0 },
  392. {    1,  8,  1, 1, 1, 1, 0xf0 },
  393. };
  394.  
  395. static void calc_fs_parameters(struct device *dev, unsigned int tot_sectors,
  396.                    struct Fs_t *Fs, struct bootsector *boot)
  397. {
  398.     int i;
  399.  
  400.     for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
  401.         if (dev->sectors == old_dos[i].sectors &&
  402.             dev->tracks == old_dos[i].tracks &&
  403.             dev->heads == old_dos[i].heads &&
  404.             (dev->fat_bits == 0 || abs(dev->fat_bits) == 12)){
  405.             boot->descr = old_dos[i].media;
  406.             Fs->cluster_size = old_dos[i].cluster_size;
  407.             Fs->dir_len = old_dos[i].dir_len;
  408.             Fs->fat_len = old_dos[i].fat_len;
  409.             Fs->fat_bits = 12;
  410.             break;
  411.         }
  412.     }
  413.     if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
  414.         /* a non-standard format */
  415.         if(DWORD(nhs))
  416.             boot->descr = 0xf8;
  417.           else
  418.             boot->descr = 0xf0;
  419.  
  420.  
  421.         if(!Fs->cluster_size) {
  422.             if (dev->heads == 1)
  423.                 Fs->cluster_size = 1;
  424.             else {
  425.                 Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
  426.                 if (dev->use_2m & 0x7f)
  427.                     Fs->cluster_size = 1;
  428.             }
  429.         }
  430.         
  431.         if(!Fs->dir_len) {
  432.             if (dev->heads == 1)
  433.                 Fs->dir_len = 4;
  434.             else
  435.                 Fs->dir_len = (tot_sectors > 2000) ? 11 : 7;
  436.         }            
  437.  
  438.         calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
  439.         if(Fs->fat_len)
  440.             xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
  441.         else {
  442.             calc_fat_bits2(Fs, tot_sectors, dev->fat_bits);
  443.             calc_fat_size(Fs, tot_sectors);
  444.         }
  445.     }
  446.  
  447.     set_word(boot->fatlen, Fs->fat_len);
  448. }
  449.  
  450.  
  451.  
  452. static void calc_fs_parameters_32(unsigned int tot_sectors,
  453.                   struct Fs_t *Fs, struct bootsector *boot)
  454. {
  455.     if(DWORD(nhs))
  456.         boot->descr = 0xf8;
  457.     else
  458.         boot->descr = 0xf0;
  459.     if(!Fs->cluster_size)
  460.         /* FAT32 disks have a cluster size of 1 by default.
  461.          * After all, we can afford it, can't we? */        
  462.         Fs->cluster_size = 1;
  463.     
  464.     Fs->dir_len = 0;
  465.     Fs->num_clus = tot_sectors / Fs->cluster_size;
  466.     set_fat32(Fs);
  467.     calc_fat_size(Fs, tot_sectors);
  468.     set_word(boot->fatlen, 0);
  469.     set_dword(boot->ext.fat32.bigFat, Fs->fat_len);
  470. }
  471.  
  472.  
  473.  
  474.  
  475. static void usage(void)
  476. {
  477.     fprintf(stderr, 
  478.         "Mtools version %s, dated %s\n", mversion, mdate);
  479.     fprintf(stderr, 
  480.         "Usage: %s [-V] [-t tracks] [-h heads] [-s sectors] "
  481.         "[-l label] [-n serialnumber] "
  482.         "[-S hardsectorsize] [-M softsectorsize] [-1]"
  483.         "[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
  484.         "device\n", progname);
  485.     exit(1);
  486. }
  487.  
  488. void mformat(int argc, char **argv, int dummy)
  489. {
  490.     Fs_t Fs;
  491.     int hs, hs_set;
  492.     int arguse_2m = 0;
  493.     int sectors0=18; /* number of sectors on track 0 */
  494.     int create = 0;
  495.     int rate_0, rate_any;
  496.     int mangled;
  497.     int argssize=0; /* sector size */
  498.     int msize=0;
  499.     int fat32 = 0;
  500.  
  501. #ifdef USE_XDF
  502.     int i;
  503.     int format_xdf = 0;
  504.     struct xdf_info info;
  505. #endif
  506.     struct bootsector *boot;
  507.     int c;
  508.     struct device used_dev;
  509.     int argtracks, argheads, argsectors;
  510.     int tot_sectors;
  511.  
  512.     char drive, name[EXPAND_BUF];
  513.  
  514.     char label[VBUFSIZE], buf[MAX_SECTOR], shortlabel[13];
  515.     struct device *dev;
  516.     char errmsg[200];
  517.  
  518.     unsigned long serial;
  519.      int serial_set;
  520.     int fsVersion;
  521.  
  522.     int Atari = 0; /* should we add an Atari-style serial number ? */
  523.  
  524.     hs = hs_set = 0;
  525.     argtracks = 0;
  526.     argheads = 0;
  527.     argsectors = 0;
  528.     arguse_2m = 0;
  529.     argssize = 0x2;
  530.     label[0] = '\0';
  531.     serial_set = 0;
  532.     serial = 0;
  533.     fsVersion = 0;
  534.     
  535.     Fs.cluster_size = 0;
  536.     Fs.refs = 1;
  537.     Fs.dir_len = 0;
  538.     Fs.fat_len = 0;
  539.     Fs.Class = &FsClass;    
  540.     rate_0 = mtools_rate_0;
  541.     rate_any = mtools_rate_any;
  542.  
  543.     /* get command line options */
  544.     while ((c = getopt(argc,argv,"r:IFCc:Xt:h:s:l:n:H:M:S:12:0Aaf:"))!= EOF) {
  545.         switch (c) {
  546.             case 'r': 
  547.                 Fs.dir_len = strtoul(optarg,0,0);
  548.                 break;
  549.             case 'f':
  550.                 Fs.fat_len = strtoul(optarg,0,0);
  551.                 break;
  552.             case 'F':
  553.                 fat32 = 1;
  554.                 break;
  555.             case 'I':
  556.                 fsVersion = strtoul(optarg,0,0);
  557.                 break;
  558.             case 'C':
  559.                 create = O_CREAT;
  560.                 break;
  561.             case 'c':
  562.                 Fs.cluster_size = atoi(optarg);
  563.                 break;
  564.             case 'H':
  565.                 hs = atoi(optarg);
  566.                 hs_set = 1;
  567.                 break;
  568. #ifdef USE_XDF
  569.             case 'X':
  570.                 format_xdf = 1;
  571.                 break;
  572. #endif
  573.             case 't':
  574.                 argtracks = atoi(optarg);
  575.                 break;
  576.             case 'h':
  577.                 argheads = atoi(optarg);
  578.                 break;
  579.             case 's':
  580.                 argsectors = atoi(optarg);
  581.                 break;
  582.             case 'l':
  583.                 strncpy(label, optarg, VBUFSIZE-1);
  584.                 label[VBUFSIZE-1] = '\0';
  585.                 break;
  586.              case 'n':
  587.                  serial = strtoul(optarg,0,0);
  588.                  serial_set = 1;
  589.                  break;
  590.             case 'S':
  591.                 argssize = atoi(optarg) | 0x80;
  592.                 if(argssize < 0x81)
  593.                     usage();
  594.                 break;
  595.             case 'M':
  596.                 msize = atoi(optarg);
  597.                 if (msize % 256 || msize > 8192 )
  598.                     usage();
  599.                 break;
  600.             case '1':
  601.                 arguse_2m = 0x80;
  602.                 break;
  603.             case '2':
  604.                 arguse_2m = 0xff;
  605.                 sectors0 = atoi(optarg);
  606.                 break;
  607.             case '0': /* rate on track 0 */
  608.                 rate_0 = atoi(optarg);
  609.                 break;
  610.             case 'A': /* rate on other tracks */
  611.                 rate_any = atoi(optarg);
  612.                 break;
  613.             case 'a': /* Atari style serial number */
  614.                 Atari = 1;
  615.                 break;
  616.             default:
  617.                 usage();
  618.         }
  619.     }
  620.  
  621.     if (argc - optind != 1 ||
  622.         !argv[optind][0] || argv[optind][1] != ':')
  623.         usage();
  624.  
  625. #ifdef USE_XDF
  626.     if(create && format_xdf) {
  627.         fprintf(stderr,"Create and XDF can't be used together\n");
  628.         exit(1);
  629.     }
  630. #endif
  631.     
  632.     drive = toupper(argv[argc -1][0]);
  633.  
  634.     /* check out a drive whose letter and parameters match */    
  635.     sprintf(errmsg, "Drive '%c:' not supported", drive);    
  636.     Fs.Direct = NULL;
  637.     for(dev=devices;dev->drive;dev++) {
  638.         FREE(&(Fs.Direct));
  639.         /* drive letter */
  640.         if (dev->drive != drive)
  641.             continue;
  642.         used_dev = *dev;
  643.  
  644.         SET_INT(used_dev.tracks, argtracks);
  645.         SET_INT(used_dev.heads, argheads);
  646.         SET_INT(used_dev.sectors, argsectors);
  647.         SET_INT(used_dev.use_2m, arguse_2m);
  648.         SET_INT(used_dev.ssize, argssize);
  649.         if(hs_set)
  650.             used_dev.hidden = hs;
  651.         
  652.         expand(dev->name, name);
  653. #ifdef USE_XDF
  654.         if(!format_xdf)
  655. #endif
  656.             Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
  657.                            O_RDWR | create,
  658.                            errmsg, 0);
  659. #ifdef USE_XDF
  660.         else {
  661.             used_dev.use_xdf = 1;
  662.             Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
  663.                         errmsg, &info);
  664.             if(Fs.Direct && !Fs.fat_len)
  665.                 Fs.fat_len = info.FatSize;
  666.             if(Fs.Direct && !Fs.dir_len)
  667.                 Fs.dir_len = info.RootDirSize;
  668.         }
  669. #endif
  670.  
  671.         if (!Fs.Direct)
  672.             continue;
  673.  
  674.         /* non removable media */
  675.         if (!used_dev.tracks || !used_dev.heads || !used_dev.sectors){
  676.             sprintf(errmsg, 
  677.                 "Non-removable media is not supported "
  678.                 "(You must tell the complete geometry "
  679.                 "of the disk, either in /etc/mtools or "
  680.                 "on the command line) ");
  681.             continue;
  682.         }
  683.  
  684. #if 0
  685.         /* set parameters, if needed */
  686.         if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
  687.             sprintf(errmsg,"Can't set disk parameters: %s", 
  688.                 strerror(errno));
  689.             continue;
  690.         }
  691. #endif
  692.         Fs.sector_size = 512;
  693.         if( !(used_dev.use_2m & 0x7f))
  694.             Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
  695.         SET_INT(Fs.sector_size, msize);
  696.  
  697.         /* do a "test" read */
  698.         if (!create &&
  699.             READS(Fs.Direct, (char *) buf, 0, Fs.sector_size) != 
  700.             Fs.sector_size) {
  701.             sprintf(errmsg, 
  702.                 "Error reading from '%s', wrong parameters?",
  703.                 name);
  704.             continue;
  705.         }
  706.         break;
  707.     }
  708.  
  709.  
  710.     /* print error msg if needed */    
  711.     if ( dev->drive == 0 ){
  712.         FREE(&Fs.Direct);
  713.         fprintf(stderr,"%s: %s\n", argv[0],errmsg);
  714.         exit(1);
  715.     }
  716.  
  717.     /* the boot sector */
  718.     boot = (struct bootsector *) buf;
  719.     memset((char *)boot, '\0', Fs.sector_size);
  720.     set_dword(boot->nhs, used_dev.hidden);
  721.  
  722.     Fs.Next = buf_init(Fs.Direct,
  723.                Fs.sector_size * used_dev.heads * used_dev.sectors,
  724.                Fs.sector_size,
  725.                Fs.sector_size * used_dev.heads * used_dev.sectors);
  726.  
  727.     boot->nfat = Fs.num_fat = 2;
  728.     set_word(boot->jump + 510, 0xaa55);
  729.     
  730.     /* get the parameters */
  731.     tot_sectors = used_dev.tracks * used_dev.heads * used_dev.sectors - 
  732.         DWORD(nhs);
  733.  
  734.     set_word(boot->nsect, dev->sectors);
  735.     set_word(boot->nheads, dev->heads);
  736.  
  737.     dev->fat_bits = comp_fat_bits(&Fs,dev->fat_bits, tot_sectors, fat32);
  738.  
  739.     if(dev->fat_bits == 32) {
  740.         Fs.primaryFat = 0;
  741.         Fs.writeAllFats = 1;
  742.         Fs.fat_start = 3;
  743.         calc_fs_parameters_32(tot_sectors, &Fs, boot);
  744.  
  745.         Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
  746.  
  747.         /* extension flags: mirror fats, and use #0 as primary */
  748.         set_word(boot->ext.fat32.extFlags,0);
  749.  
  750.         /* fs version.  What should go here? */
  751.         set_word(boot->ext.fat32.fsVersion,fsVersion);
  752.  
  753.         /* root directory */
  754.         set_dword(boot->ext.fat32.rootCluster, Fs.rootCluster = 2);
  755.  
  756.         /* info sector */
  757.         set_word(boot->ext.fat32.infoSector, Fs.infoSectorLoc = 2);
  758.  
  759.         /* no backup boot sector */
  760.         set_word(boot->ext.fat32.backupBoot, 1);
  761.     } else {
  762.         Fs.fat_start = 1;
  763.         calc_fs_parameters(&used_dev, tot_sectors, &Fs, boot);
  764.         boot->ext.old.physdrive = 0x00;
  765.         boot->ext.old.reserved = 0;
  766.         boot->ext.old.dos4 = 0x29;
  767.         Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
  768.         Fs.clus_start = Fs.dir_start + Fs.dir_len;
  769.  
  770.         if (!serial_set || Atari)
  771.             srandom(time (0));
  772.         if (!serial_set)
  773.             serial=random();
  774.         set_dword(boot->ext.old.serial, serial);    
  775.         if(!label[0])
  776.             strncpy(shortlabel, "NO NAME    ",11);
  777.         else
  778.             label_name(label, 0, &mangled, shortlabel);
  779.         strncpy(boot->ext.old.label, shortlabel, 11);
  780.         sprintf(boot->ext.old.fat_type, "FAT%2.2d   ", Fs.fat_bits);
  781.     }
  782.  
  783.     set_word(boot->secsiz, Fs.sector_size);
  784.     boot->clsiz = (unsigned char) Fs.cluster_size;
  785.     set_word(boot->nrsvsect, Fs.fat_start);
  786.  
  787.     init_geometry_boot(boot, &used_dev, sectors0, rate_0, rate_any,
  788.                &tot_sectors);
  789.     if(Atari) {
  790.         boot->banner[4] = 0;
  791.         boot->banner[5] = random();
  792.         boot->banner[6] = random();
  793.         boot->banner[7] = random();
  794.     }        
  795.  
  796.     if (create) {
  797.         WRITES(Fs.Direct, (char *) buf,
  798.                Fs.sector_size * (tot_sectors-1),
  799.                Fs.sector_size);
  800.     }
  801.  
  802.     inst_boot_prg(boot);
  803.     if(dev->use_2m & 0x7f)
  804.         Fs.num_fat = 1;
  805.     zero_fat(&Fs, boot->descr);
  806.     if(Fs.fat_bits == 32) {
  807.         /* initialize info sector */
  808.         Fs.infoSector = (InfoSector_t *) safe_malloc(Fs.sector_size);
  809.         set_dword(Fs.infoSector->signature, INFOSECT_SIGNATURE);
  810.         set_dword(Fs.infoSector->count, Fs.num_clus);
  811.         set_dword(Fs.infoSector->pos, 2);
  812.  
  813.         /* this will trigger writing it */
  814.         Fs.fat_dirty = 1;
  815.  
  816.         /* root directory: allocate one sector */
  817.         Fs.fat_encode(&Fs, Fs.rootCluster, Fs.end_fat);
  818.     } else
  819.         Fs.infoSector = 0;
  820.  
  821. #ifdef USE_XDF
  822.     if(format_xdf)
  823.         for(i=0; 
  824.             i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size; 
  825.             i++)
  826.             Fs.fat_encode(&Fs, i+2, 0xfff7);
  827. #endif
  828.  
  829.     format_root(&Fs, label, boot);
  830.     WRITES((Stream_t *)&Fs, (char *) boot, 0, Fs.sector_size);
  831.     if(Fs.fat_bits == 32 && WORD(ext.fat32.backupBoot) != MAX32) {
  832.         WRITES((Stream_t *)&Fs, (char *) boot, 
  833.                WORD(ext.fat32.backupBoot) * Fs.sector_size,
  834.                Fs.sector_size);
  835.     }
  836.     FLUSH((Stream_t *)&Fs); /* flushes Fs. 
  837.                  * This triggers the writing of the FAT */
  838. #ifdef USE_XDF
  839.     if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
  840.         fprintf(stderr,
  841.             "Note:\n"
  842.             "Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
  843.             "variable before accessing this disk\n\n"
  844.             "Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
  845.             " export MTOOLS_USE_XDF=1\n\n"
  846.             "C shell syntax (csh and tcsh):\n"
  847.             " setenv MTOOLS_USE_XDF 1\n" );    
  848. #endif
  849.     exit(0);
  850. }
  851.