d6aa167171c8ee142da11e14e8e58d7bca6cd53b
[platform/upstream/mtools.git] / mformat.c
1 /*  Copyright 1986-1992 Emmet P. Gray.
2  *  Copyright 1994,1996-2009 Alain Knaff.
3  *  This file is part of mtools.
4  *
5  *  Mtools is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  Mtools is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * mformat.c
19  */
20
21 #define DONT_NEED_WAIT
22
23 #include "sysincludes.h"
24 #include "msdos.h"
25 #include "mtools.h"
26 #include "mainloop.h"
27 #include "fsP.h"
28 #include "file.h"
29 #include "plain_io.h"
30 #include "floppyd_io.h"
31 #include "nameclash.h"
32 #include "buffer.h"
33 #ifdef HAVE_ASSERT_H
34 #include <assert.h>
35 #endif
36 #ifdef USE_XDF
37 #include "xdf_io.h"
38 #endif
39 #include "partition.h"
40 #include "file_name.h"
41
42 #ifndef abs
43 #define abs(x) ((x)>0?(x):-(x))
44 #endif
45
46 #ifdef OS_linux
47 #include "linux/hdreg.h"
48
49 #define _LINUX_STRING_H_
50 #define kdev_t int
51 #include "linux/fs.h"
52 #undef _LINUX_STRING_H_
53
54 #endif
55
56
57 static int init_geometry_boot(union bootsector *boot, struct device *dev,
58                                int sectors0, int rate_0, int rate_any,
59                                unsigned long *tot_sectors, int keepBoot)
60 {
61         int i;
62         int nb_renum;
63         int sector2;
64         int size2;
65         int j;
66         int sum;
67
68         set_word(boot->boot.nsect, dev->sectors);
69         set_word(boot->boot.nheads, dev->heads);
70
71 #ifdef HAVE_ASSERT_H
72         assert(*tot_sectors != 0);
73 #endif
74
75         if (*tot_sectors < 0x10000){
76                 set_word(boot->boot.psect, *tot_sectors);
77                 set_dword(boot->boot.bigsect, 0);
78         } else {
79                 set_word(boot->boot.psect, 0);
80                 set_dword(boot->boot.bigsect, *tot_sectors);
81         }
82
83         if (dev->use_2m & 0x7f){
84                 int bootOffset;
85                 strncpy(boot->boot.banner, "2M-STV04", 8);
86                 boot->boot.ext.old.res_2m = 0;
87                 boot->boot.ext.old.fmt_2mf = 6;
88                 if ( dev->sectors % ( ((1 << dev->ssize) + 3) >> 2 ))
89                         boot->boot.ext.old.wt = 1;
90                 else
91                         boot->boot.ext.old.wt = 0;
92                 boot->boot.ext.old.rate_0= rate_0;
93                 boot->boot.ext.old.rate_any= rate_any;
94                 if (boot->boot.ext.old.rate_any== 2 )
95                         boot->boot.ext.old.rate_any= 1;
96                 i=76;
97
98                 /* Infp0 */
99                 set_word(boot->boot.ext.old.Infp0, i);
100                 boot->bytes[i++] = sectors0;
101                 boot->bytes[i++] = 108;
102                 for(j=1; j<= sectors0; j++)
103                         boot->bytes[i++] = j;
104
105                 set_word(boot->boot.ext.old.InfpX, i);
106                 
107                 boot->bytes[i++] = 64;
108                 boot->bytes[i++] = 3;
109                 nb_renum = i++;
110                 sector2 = dev->sectors;
111                 size2 = dev->ssize;
112                 j=1;
113                 while( sector2 ){
114                         while ( sector2 < (1 << size2) >> 2 )
115                                 size2--;
116                         boot->bytes[i++] = 128 + j;
117                         boot->bytes[i++] = j++;
118                         boot->bytes[i++] = size2;
119                         sector2 -= (1 << size2) >> 2;
120                 }
121                 boot->bytes[nb_renum] = ( i - nb_renum - 1 ) / 3;
122
123                 set_word(boot->boot.ext.old.InfTm, i);
124
125                 sector2 = dev->sectors;
126                 size2= dev->ssize;
127                 while(sector2){
128                         while ( sector2 < 1 << ( size2 - 2) )
129                                 size2--;
130                         boot->bytes[i++] = size2;
131                         sector2 -= 1 << (size2 - 2 );
132                 }
133                 
134                 set_word(boot->boot.ext.old.BootP,i);
135                 bootOffset = i;
136
137                 /* checksum */          
138                 for (sum=0, j=64; j<i; j++) 
139                         sum += boot->bytes[j];/* checksum */
140                 boot->boot.ext.old.CheckSum=-sum;
141                 return bootOffset;
142         } else {
143                 if(!keepBoot) {
144                         boot->boot.jump[0] = 0xeb;
145                         boot->boot.jump[1] = 0;
146                         boot->boot.jump[2] = 0x90;
147                         strncpy(boot->boot.banner, mformat_banner, 8);
148                         /* It looks like some versions of DOS are
149                          * rather picky about this, and assume default
150                          * parameters without this, ignoring any
151                          * indication about cluster size et al. */
152                 }
153                 return 0;
154         }
155 }
156
157
158 static int comp_fat_bits(Fs_t *Fs, int estimate, 
159                          unsigned long tot_sectors, int fat32)
160 {
161         int needed_fat_bits;
162
163         needed_fat_bits = 12;
164
165 #define MAX_DISK_SIZE(bits,clusters) \
166         TOTAL_DISK_SIZE((bits), Fs->sector_size, (clusters), \
167                         Fs->num_fat, MAX_BYTES_PER_CLUSTER/Fs->sector_size)
168
169         if(tot_sectors > MAX_DISK_SIZE(12, FAT12-1))
170                 needed_fat_bits = 16;
171         if(fat32 || tot_sectors > MAX_DISK_SIZE(16, FAT16-1))
172                 needed_fat_bits = 32;
173
174 #undef MAX_DISK_SIZE
175
176         if(abs(estimate) && abs(estimate) < needed_fat_bits) {
177                 if(fat32) {
178                         fprintf(stderr,
179                                 "Contradiction between FAT size on command line and FAT size in conf file\n");
180                         exit(1);
181                 }
182                 fprintf(stderr,
183                         "Device too big for a %d bit FAT\n",
184                         estimate);
185                 exit(1);
186         }
187
188         if(!estimate) {
189                 unsigned int min_fat16_size;
190
191                 if(needed_fat_bits > 12)
192                         return needed_fat_bits;
193                 min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12,
194                                            Fs->num_fat, 1);
195                 if(tot_sectors < min_fat16_size)
196                         return 12;
197                 else if(tot_sectors >= 2* min_fat16_size)
198                         return 16; /* heuristics */
199         }
200
201         return estimate;
202 }
203
204
205 /*
206  * According to Microsoft "Hardware White Paper", "Microsoft
207  * Extensible Formware Initiative", "FAT32 File System Specification",
208  * Version 1.03, December 6, 2000:
209  * If (CountofClusters < 4085) { 
210  *  // Volume is FAT12  
211  * } else if (CountofClusters < 65525) { 
212  *  // Volume is FAT16
213  * } else { 
214  *  //Volume is FAT32
215  * }
216  *
217  * This document can be found at the following URL
218  * http://www.microsoft.com/hwdev/download/hardware/fatgen103.pdf
219  * The relevant passus is on page 15.
220  *
221  * Actually, experimentations with Windows NT 4 show that the
222  * cutoff is 4087 rather than 4085... This is Microsoft after all.
223  * Not sure what the other Microsoft OS'es do though...
224  */
225 static void calc_fat_bits2(Fs_t *Fs, unsigned long tot_sectors, int fat_bits,
226                            int may_change_cluster_size, 
227                            int may_change_root_size)
228 {
229         unsigned long rem_sect;
230
231         /*
232          * the "remaining sectors" after directory and boot
233          * hasve been accounted for.
234          */
235         rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
236         switch(abs(fat_bits)) {
237                 case 0:
238
239 #define MY_DISK_SIZE(bits,clusters) \
240                         DISK_SIZE( (bits), Fs->sector_size, (clusters), \
241                                    Fs->num_fat, Fs->cluster_size)
242
243                         if(rem_sect >= MY_DISK_SIZE(16, FAT12+2))
244                                 /* big enough for FAT16 
245                                  * We take a margin of 2, because NT4 
246                                  * misbehaves, and starts considering a disk
247                                  * as FAT16 only if it is larger than 4086
248                                  * sectors, rather than 4084 as it should
249                                  */
250                                 set_fat16(Fs);
251                         else if(rem_sect <= MY_DISK_SIZE(12, FAT12-1))
252                                  /* small enough for FAT12 */
253                                  set_fat12(Fs);
254                         else {
255                                 /* "between two chairs",
256                                  * augment cluster size, and
257                                  * settle it */
258                                 if(may_change_cluster_size && 
259                                    Fs->cluster_size * Fs->sector_size * 2 
260                                    <= MAX_BYTES_PER_CLUSTER)
261                                         Fs->cluster_size <<= 1;
262                                 else if(may_change_root_size) {
263                                         Fs->dir_len +=
264                                                 rem_sect - MY_DISK_SIZE(12, FAT12-1);
265                                 }
266                                 set_fat12(Fs);
267                         }
268                         break;
269 #undef MY_DISK_SIZE
270
271                 case 12:
272                         set_fat12(Fs);
273                         break;
274                 case 16:
275                         set_fat16(Fs);
276                         break;
277                 case 32:
278                         set_fat32(Fs);
279                         break;
280         }
281 }
282
283 static __inline__ void format_root(Fs_t *Fs, char *label, union bootsector *boot)
284 {
285         Stream_t *RootDir;
286         char *buf;
287         int i;
288         struct ClashHandling_t ch;
289         int dirlen;
290
291         init_clash_handling(&ch);
292         ch.name_converter = label_name;
293         ch.ignore_entry = -2;
294
295         buf = safe_malloc(Fs->sector_size);
296         RootDir = OpenRoot((Stream_t *)Fs);
297         if(!RootDir){
298                 fprintf(stderr,"Could not open root directory\n");
299                 exit(1);
300         }
301
302         memset(buf, '\0', Fs->sector_size);
303
304         if(Fs->fat_bits == 32) {
305                 /* on a FAT32 system, we only write one sector,
306                  * as the directory can be extended at will...*/
307                 dirlen = Fs->cluster_size;
308                 fatAllocate(Fs, Fs->rootCluster, Fs->end_fat);
309         } else
310                 dirlen = Fs->dir_len;
311         for (i = 0; i < dirlen; i++)
312                 WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),
313                            Fs->sector_size);
314
315         ch.ignore_entry = 1;
316         if(label[0])
317                 mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
318
319         FREE(&RootDir);
320         if(Fs->fat_bits == 32)
321                 set_word(boot->boot.dirents, 0);
322         else
323                 set_word(boot->boot.dirents, Fs->dir_len * (Fs->sector_size / 32));
324         free(buf);
325 }
326
327
328 static void xdf_calc_fat_size(Fs_t *Fs, unsigned long tot_sectors,
329                               int fat_bits)
330 {
331         unsigned int rem_sect;
332
333         rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
334
335         if(Fs->fat_len) {
336                 /* an XDF disk, we know the fat_size and have to find
337                  * out the rest. We start with a cluster size of 1 and
338                  * keep doubling until everything fits into the
339                  * FAT. This will occur eventually, as our FAT has a
340                  * minimal size of 1 */
341                 for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
342                         Fs->num_clus = rem_sect / Fs->cluster_size;
343                         if(abs(fat_bits) == 16 || Fs->num_clus >= FAT12)
344                                 set_fat16(Fs);
345                         else
346                                 set_fat12(Fs);
347                         if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
348                                 return;
349                 }
350         }
351         fprintf(stderr,"Internal error while calculating Xdf fat size\n");
352         exit(1);
353 }
354
355
356 static void calc_fat_size(Fs_t *Fs, unsigned long tot_sectors)
357 {
358         unsigned long rem_sect;
359         unsigned long real_rem_sect;
360         unsigned long numerator;
361         unsigned long denominator;
362         int fat_nybbles;
363         unsigned int slack;
364         int printGrowMsg=1; /* Should we print "growing FAT" messages ?*/
365         
366 #ifdef DEBUG
367         fprintf(stderr, "Fat start=%d\n", Fs->fat_start);
368         fprintf(stderr, "tot_sectors=%lu\n", tot_sectors);
369         fprintf(stderr, "dir_len=%d\n", Fs->dir_len);
370 #endif
371         real_rem_sect = rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
372
373         /* Cheat a little bit to address the _really_ common case of
374            odd number of remaining sectors while both nfat and cluster size
375            are even... */
376         if(rem_sect         %2 == 1 &&
377            Fs->num_fat      %2 == 0 &&
378            Fs->cluster_size %2 == 0)
379                 rem_sect--;
380
381 #ifdef DEBUG
382         fprintf(stderr, "Rem sect=%lu\n", rem_sect);
383 #endif
384
385         if(Fs->fat_bits == 0) {
386                 fprintf(stderr, "Weird, fat bits = 0\n");
387                 exit(1);                
388         }
389
390
391         /* See fat_size_calculation.tex or
392            (http://ftp.gnu.org/software/mtools/manual/fat_size_calculation.pdf)
393            for an explantation about why the stuff below works...
394         */
395
396         fat_nybbles = Fs->fat_bits / 4;
397         numerator   = rem_sect+2*Fs->cluster_size;
398         denominator =
399           Fs->cluster_size * Fs->sector_size * 2 +
400           Fs->num_fat * fat_nybbles;
401
402         if(fat_nybbles == 3)
403                 numerator *= fat_nybbles;
404         else
405                 /* Avoid numerical overflows, divide the denominator
406                  * rather than multiplying the numerator */
407                 denominator = denominator / fat_nybbles;
408
409 #ifdef DEBUG
410         fprintf(stderr, "Numerator=%lu denominator=%lu\n",
411                 numerator, denominator);
412 #endif
413
414         Fs->fat_len = (numerator-1)/denominator+1;
415         Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/Fs->cluster_size;
416
417         /* Apply upper bounds for FAT bits */
418         if(Fs->fat_bits == 16 && Fs->num_clus >= FAT16)
419                 Fs->num_clus = FAT16-1;
420         if(Fs->fat_bits == 12 && Fs->num_clus >= FAT12)
421                 Fs->num_clus = FAT12-1;
422         
423         /* A safety, if above math is correct, this should not be happen...*/
424         if(Fs->num_clus > (Fs->fat_len * Fs->sector_size * 2 /
425                            fat_nybbles - 2)) {
426                 fprintf(stderr,
427                         "Fat size miscalculation, shrinking num_clus from %d ",
428                         Fs->num_clus);
429                 Fs->num_clus = (Fs->fat_len * Fs->sector_size * 2 /
430                                 fat_nybbles - 2);
431                 fprintf(stderr, " to %d\n", Fs->num_clus);
432         }
433 #ifdef DEBUG
434         fprintf(stderr, "Num_clus=%d fat_len=%d nybbles=%d\n",
435                 Fs->num_clus, Fs->fat_len, fat_nybbles);
436 #endif
437
438         if ( Fs->num_clus < FAT16 && Fs->fat_bits > 16 ){
439                 fprintf(stderr,"Too few clusters for this fat size."
440                         " Please choose a 16-bit fat in your /etc/mtools.conf"
441                         " or .mtoolsrc file\n");
442                 exit(1);
443         }
444
445         /* As the number of clusters is specified nowhere in the boot sector,
446          * it will be calculated by removing everything else from total number
447          * of sectors. This means that if we reduced the number of clusters
448          * above, we will have to grow the FAT in order to take up any excess
449          * sectors... */
450 #ifdef HAVE_ASSERT_H
451         assert(rem_sect >= Fs->num_clus * Fs->cluster_size +
452                Fs->fat_len * Fs->num_fat);
453 #endif
454         slack = rem_sect -
455                 Fs->num_clus * Fs->cluster_size -
456                 Fs->fat_len * Fs->num_fat;
457         if(slack >= Fs->cluster_size) {
458                 /* This can happen under two circumstances:
459                    1. We had to reduce num_clus because we reached maximum
460                    number of cluster for FAT12 or FAT16
461                 */
462                 if(printGrowMsg) {
463                         fprintf(stderr, "Slack=%d\n", slack);
464                         fprintf(stderr, "Growing fat size from %d",
465                                 Fs->fat_len);
466                 }
467                 Fs->fat_len +=
468                         (slack - Fs->cluster_size) / Fs->num_fat + 1;
469                 if(printGrowMsg) {
470                         fprintf(stderr,
471                                 " to %d in order to take up excess cluster area\n",
472                                 Fs->fat_len);
473                 }
474                 Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/
475                         Fs->cluster_size;
476
477         }
478
479 #ifdef HAVE_ASSERT_H
480         /* Fat must be big enough for all clusters */
481         assert( ((Fs->num_clus+2) * fat_nybbles) <=
482                 (Fs->fat_len*Fs->sector_size*2));
483
484         /* num_clus must be big enough to cover rest of disk, or else further
485          * users of the filesystem will assume a bigger num_clus, which might
486          * be too big for fat_len */
487         assert(Fs->num_clus ==
488                (real_rem_sect - Fs->num_fat * Fs->fat_len) / Fs->cluster_size);
489 #endif
490 }
491
492
493 static unsigned char bootprog[]=
494 {0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
495  0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
496  0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
497  0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
498  0x00, 0xcd, 0x19};
499
500 static __inline__ void inst_boot_prg(union bootsector *boot, int offset)
501 {
502         memcpy((char *) boot->boot.jump + offset,
503                (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
504         if(offset - 2 < 0x80) {
505           /* short jump */
506           boot->boot.jump[0] = 0xeb;
507           boot->boot.jump[1] = offset -2;
508           boot->boot.jump[2] = 0x90;
509         } else {
510           /* long jump, if offset is too large */
511           boot->boot.jump[0] = 0xe9;
512           boot->boot.jump[1] = offset -3;
513           boot->boot.jump[2] = 0x00;
514         }
515         set_word(boot->boot.jump + offset + 20, offset + 24);
516 }
517
518 static void calc_cluster_size(struct Fs_t *Fs, unsigned long tot_sectors,
519                               int fat_bits)
520                         
521 {
522         unsigned int max_clusters; /* maximal possible number of sectors for
523                                    * this FAT entry length (12/16/32) */
524         unsigned int max_fat_size; /* maximal size of the FAT for this FAT
525                                     * entry length (12/16/32) */
526         unsigned int rem_sect; /* remaining sectors after we accounted for
527                                 * the root directory and boot sector(s) */
528
529         switch(abs(fat_bits)) {
530                 case 12:                        
531                         max_clusters = FAT12-1;
532                         max_fat_size = Fs->num_fat *
533                                 FAT_SIZE(12, Fs->sector_size, max_clusters);
534                         break;
535                 case 16:
536                 case 0: /* still hesititating between 12 and 16 */
537                         max_clusters = FAT16-1;
538                         max_fat_size = Fs->num_fat *
539                                 FAT_SIZE(16, Fs->sector_size, max_clusters);
540                         break;
541                 case 32:                
542                         Fs->cluster_size = 8;
543                         /* According to
544                          * http://support.microsoft.com/support/kb/articles/q154/9/97.asp
545                          * Micro$oft does not support FAT32 with less than 4K
546                          */
547                         return;
548                 default:
549                         fprintf(stderr,"Bad fat size\n");
550                         exit(1);
551         }
552
553         if(tot_sectors <= Fs->fat_start + Fs->num_fat + Fs->dir_len) {
554                 /* we need at least enough sectors to fit boot, fat and root
555                  * dir */
556                 fprintf(stderr, "Not enough sectors\n");
557                 exit(1);
558         }
559
560         rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
561
562         /* double the cluster size until we can fill up the disk with
563          * the maximal number of sectors of this size */
564         while(Fs->cluster_size * max_clusters  + max_fat_size < rem_sect) {
565                 if(Fs->cluster_size > 64) {
566                         /* bigger than 64. Should fit */
567                         fprintf(stderr,
568                                 "Internal error while calculating cluster size\n");
569                         exit(1);
570                 }
571                 Fs->cluster_size <<= 1;
572         }
573 }
574
575
576 struct OldDos_t old_dos[]={
577 {   40,  9,  1, 4, 1, 2, 0xfc },
578 {   40,  9,  2, 7, 2, 2, 0xfd },
579 {   40,  8,  1, 4, 1, 1, 0xfe },
580 {   40,  8,  2, 7, 2, 1, 0xff },
581 {   80,  9,  2, 7, 2, 3, 0xf9 },
582 {   80, 15,  2,14, 1, 7, 0xf9 },
583 {   80, 18,  2,14, 1, 9, 0xf0 },
584 {   80, 36,  2,15, 2, 9, 0xf0 },
585 {    1,  8,  1, 1, 1, 1, 0xf0 },
586 };
587
588 static int old_dos_size_to_geom(size_t size, int *cyls, int *heads, int *sects)
589 {
590         unsigned int i;
591         size = size * 2;
592         for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
593                 if (old_dos[i].sectors *
594                     old_dos[i].tracks *
595                     old_dos[i].heads == size) {
596                         *cyls = old_dos[i].tracks;
597                         *heads = old_dos[i].heads;
598                         *sects = old_dos[i].sectors;
599                         return 0;
600                 }
601         }
602         return 1;
603 }
604
605
606 static void calc_fs_parameters(struct device *dev, unsigned long tot_sectors,
607                                struct Fs_t *Fs, union bootsector *boot)
608 {
609         unsigned int i;
610
611         for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
612                 if (dev->sectors == old_dos[i].sectors &&
613                     dev->tracks == old_dos[i].tracks &&
614                     dev->heads == old_dos[i].heads &&
615                     (dev->fat_bits == 0 || abs(dev->fat_bits) == 12) &&
616                     (Fs->dir_len == 0 || Fs->dir_len == old_dos[i].dir_len) &&
617                     (Fs->cluster_size == 0 ||
618                      Fs->cluster_size == old_dos[i].cluster_size)) {
619                         boot->boot.descr = old_dos[i].media;
620                         Fs->cluster_size = old_dos[i].cluster_size;
621                         Fs->dir_len = old_dos[i].dir_len;
622                         Fs->fat_len = old_dos[i].fat_len;
623                         Fs->fat_bits = 12;
624                         break;
625                 }
626         }
627         if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
628                 int may_change_cluster_size = (Fs->cluster_size == 0);
629                 int may_change_root_size = (Fs->dir_len == 0);
630
631                 /* a non-standard format */
632                 if(DWORD(nhs) || tot_sectors % (dev->sectors * dev->heads))
633                         boot->boot.descr = 0xf8;
634                   else
635                         boot->boot.descr = 0xf0;
636
637
638                 if(!Fs->cluster_size) {
639                         if (dev->heads == 1)
640                                 Fs->cluster_size = 1;
641                         else {
642                                 Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
643                                 if (dev->use_2m & 0x7f)
644                                         Fs->cluster_size = 1;
645                         }
646                 }
647                 
648                 if(!Fs->dir_len) {
649                         if (dev->heads == 1)
650                                 Fs->dir_len = 4;
651                         else
652                                 Fs->dir_len = (tot_sectors > 2000) ? 32 : 7;
653                 }                       
654
655                 calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
656                 if(Fs->fat_len)
657                         xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
658                 else {
659                         calc_fat_bits2(Fs, tot_sectors, dev->fat_bits,
660                                        may_change_cluster_size,
661                                        may_change_root_size);
662                         calc_fat_size(Fs, tot_sectors);
663                 }
664         }
665
666         set_word(boot->boot.fatlen, Fs->fat_len);
667 }
668
669
670
671 static void calc_fs_parameters_32(unsigned long tot_sectors,
672                                   struct Fs_t *Fs, union bootsector *boot)
673 {
674         if(DWORD(nhs))
675                 boot->boot.descr = 0xf8;
676         else
677                 boot->boot.descr = 0xf0;
678         if(!Fs->cluster_size)
679                 /* According to
680                  * http://www.microsoft.com/kb/articles/q154/9/97.htm,
681                  * Micro$oft does not support FAT32 with less than 4K
682                  */
683                 Fs->cluster_size = 8;
684         
685         Fs->dir_len = 0;
686         Fs->num_clus = tot_sectors / Fs->cluster_size;
687         set_fat32(Fs);
688         calc_fat_size(Fs, tot_sectors);
689         set_word(boot->boot.fatlen, 0);
690         set_dword(boot->boot.ext.fat32.bigFat, Fs->fat_len);
691 }
692
693
694
695
696 static void usage(int ret)
697 {
698         fprintf(stderr,
699                 "Mtools version %s, dated %s\n", mversion, mdate);
700         fprintf(stderr,
701                 "Usage: %s [-V] [-t tracks] [-h heads] [-n sectors] "
702                 "[-v label] [-1] [-4] [-8] [-f size] "
703                 "[-N serialnumber] "
704                 "[-k] [-B bootsector] [-r root_dir_len] [-L fat_len] "
705                 "[-F] [-I fsVersion] [-C] [-c cluster_size] "
706                 "[-H hidden_sectors] "
707 #ifdef USE_XDF
708                 "[-X] "
709 #endif
710                 "[-S hardsectorsize] [-M softsectorsize] [-3] "
711                 "[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
712                 "device\n", progname);
713         exit(ret);
714 }
715
716 #ifdef OS_linux
717 static int get_block_geom(int fd, struct MT_STAT *buf, struct device *dev,
718                           char *errmsg) {
719         struct hd_geometry geom;
720         long size;
721         int heads=dev->heads;
722         int sectors=dev->sectors;
723         int sect_per_track;
724
725         if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
726                 sprintf(errmsg, "Could not get geometry of device (%s)",
727                         strerror(errno));
728                 return -1;
729         }
730         
731         if (ioctl(fd, BLKGETSIZE, &size) < 0) {
732                 sprintf(errmsg, "Could not get size of device (%s)",
733                         strerror(errno));
734                 return -1;
735         }
736
737         if(!heads)
738                 heads = geom.heads;
739         if(!sectors)
740                 sectors = geom.sectors;
741
742         sect_per_track = heads * sectors;
743         if(!dev->hidden) {
744                 int hidden;
745                 hidden = geom.start % sect_per_track;
746                 if(hidden && hidden != sectors) {
747                         sprintf(errmsg,
748                                 "Hidden (%d) does not match sectors (%d)\n",
749                                 hidden, sectors);
750                         return -1;
751                 }
752                 dev->hidden = hidden;
753         }
754         dev->heads = heads;
755         dev->sectors = sectors;
756         if(!dev->tracks)
757                 dev->tracks = (size + dev->hidden % sect_per_track) / sect_per_track;
758         return 0;
759 }
760 #endif
761
762 void mformat(int argc, char **argv, int dummy)
763 {
764         int r; /* generic return value */
765         Fs_t Fs;
766         int hs, hs_set;
767         int arguse_2m = 0;
768         int sectors0=18; /* number of sectors on track 0 */
769         int create = 0;
770         int rate_0, rate_any;
771         int mangled;
772         int argssize=0; /* sector size */
773         int msize=0;
774         int fat32 = 0;
775         struct label_blk_t *labelBlock;
776         int bootOffset;
777
778 #ifdef USE_XDF
779         unsigned int i;
780         int format_xdf = 0;
781         struct xdf_info info;
782 #endif
783         union bootsector boot;
784         char *bootSector=0;
785         int c;
786         int keepBoot = 0;
787         struct device used_dev;
788         int argtracks, argheads, argsectors;
789         unsigned long tot_sectors=0;
790         int blocksize;
791
792         char drive, name[EXPAND_BUF];
793
794         char label[VBUFSIZE];
795
796         dos_name_t shortlabel;
797         struct device *dev;
798         char errmsg[200];
799
800         unsigned long serial;
801         int serial_set;
802         int fsVersion;
803         int mediaDesc=-1;
804
805         mt_size_t maxSize;
806
807         int Atari = 0; /* should we add an Atari-style serial number ? */
808
809         int backupBoot = 6;
810
811         hs = hs_set = 0;
812         argtracks = 0;
813         argheads = 0;
814         argsectors = 0;
815         arguse_2m = 0;
816         argssize = 0x2;
817         label[0] = '\0';
818         serial_set = 0;
819         serial = 0;
820         fsVersion = 0;
821         
822         Fs.cluster_size = 0;
823         Fs.refs = 1;
824         Fs.dir_len = 0;
825         if(getenv("MTOOLS_DIR_LEN")) {
826           Fs.dir_len = atoi(getenv("MTOOLS_DIR_LEN"));
827           if(Fs.dir_len <= 0)
828             Fs.dir_len=0;
829         }
830         Fs.fat_len = 0;
831         Fs.num_fat = 2;
832         if(getenv("MTOOLS_NFATS")) {
833           Fs.num_fat = atoi(getenv("MTOOLS_NFATS"));
834           if(Fs.num_fat <= 0)
835             Fs.num_fat=2;
836         }
837         Fs.Class = &FsClass;    
838         rate_0 = mtools_rate_0;
839         rate_any = mtools_rate_any;
840
841         /* get command line options */
842         if(helpFlag(argc, argv))
843                 usage(0);
844         while ((c = getopt(argc,argv,
845                            "i:148f:t:n:v:qub"
846                            "kK:B:r:L:I:FCc:Xh:s:T:l:N:H:M:S:2:30:Aad:m:"))!= EOF) {
847                 switch (c) {
848                         case 'i':
849                                 set_cmd_line_image(optarg, 0);
850                                 break;
851
852                         /* standard DOS flags */
853                         case '1':
854                                 argheads = 1;
855                                 break;
856                         case '4':
857                                 argsectors = 9;
858                                 argtracks = 40;
859                                 break;
860                         case '8':
861                                 argsectors = 8;
862                                 argtracks = 40;
863                                 break;
864                         case 'f':
865                                 r=old_dos_size_to_geom(atoi(optarg),
866                                                        &argtracks, &argheads,
867                                                        &argsectors);
868                                 if(r) {
869                                         fprintf(stderr,
870                                                 "Bad size %s\n", optarg);
871                                         exit(1);
872                                 }
873                                 break;
874                         case 't':
875                                 argtracks = atoi(optarg);
876                                 break;
877
878                         case 'T':
879                                 tot_sectors = atoi(optarg);
880                                 break;
881
882                         case 'n': /*non-standard*/
883                         case 's':
884                                 argsectors = atoi(optarg);
885                                 break;
886
887                         case 'l': /* non-standard */
888                         case 'v':
889                                 strncpy(label, optarg, VBUFSIZE-1);
890                                 label[VBUFSIZE-1] = '\0';
891                                 break;
892
893                         /* flags supported by Dos but not mtools */
894                         case 'q':
895                         case 'u':
896                         case 'b':
897                         /*case 's': leave this for compatibility */
898                                 fprintf(stderr,
899                                         "Flag %c not supported by mtools\n",c);
900                                 exit(1);
901                                 
902
903
904                         /* flags added by mtools */
905                         case 'F':
906                                 fat32 = 1;
907                                 break;
908
909
910                         case 'S':
911                                 argssize = atoi(optarg) | 0x80;
912                                 if(argssize < 0x81)
913                                         usage(1);
914                                 if(argssize >= 0x87) {
915                                         fprintf(stderr, "argssize must be less than 6\n");
916                                         usage(1);
917                                 }
918                                 break;
919
920 #ifdef USE_XDF
921                         case 'X':
922                                 format_xdf = 1;
923                                 break;
924 #endif
925
926                         case '2':
927                                 arguse_2m = 0xff;
928                                 sectors0 = atoi(optarg);
929                                 break;
930                         case '3':
931                                 arguse_2m = 0x80;
932                                 break;
933
934                         case '0': /* rate on track 0 */
935                                 rate_0 = atoi(optarg);
936                                 break;
937                         case 'A': /* rate on other tracks */
938                                 rate_any = atoi(optarg);
939                                 break;
940
941                         case 'M':
942                                 msize = atoi(optarg);
943                                 if(msize != 512 &&
944                                    msize != 1024 &&
945                                    msize != 2048 &&
946                                    msize != 4096) {
947                                   fprintf(stderr, "Only sector sizes of 512, 1024, 2048 or 4096 bytes are allowed\n");
948                                   usage(1);
949                                 }
950                                 break;
951
952                         case 'N':
953                                 serial = strtoul(optarg,0,16);
954                                 serial_set = 1;
955                                 break;
956                         case 'a': /* Atari style serial number */
957                                 Atari = 1;
958                                 break;
959
960                         case 'C':
961                                 create = O_CREAT | O_TRUNC;
962                                 break;
963
964                         case 'H':
965                                 hs = atoi(optarg);
966                                 hs_set = 1;
967                                 break;
968
969                         case 'I':
970                                 fsVersion = strtoul(optarg,0,0);
971                                 break;
972
973                         case 'c':
974                                 Fs.cluster_size = atoi(optarg);
975                                 break;
976
977                         case 'r':
978                                 Fs.dir_len = strtoul(optarg,0,0);
979                                 break;
980                         case 'L':
981                                 Fs.fat_len = strtoul(optarg,0,0);
982                                 break;
983
984
985                         case 'B':
986                                 bootSector = optarg;
987                                 break;
988                         case 'k':
989                                 keepBoot = 1;
990                                 break;
991                         case 'K':
992                                 backupBoot = atoi(optarg);
993                                 if(backupBoot < 2 || backupBoot >= 32) {
994                                   fprintf(stderr, "Backupboot must be comprised between 2 and 32\n");
995                                   exit(1);
996                                 }
997                                 break;
998                         case 'h':
999                                 argheads = atoi(optarg);
1000                                 break;
1001                         case 'd':
1002                                 Fs.num_fat = atoi(optarg);
1003                                 break;
1004                         case 'm':
1005                                 mediaDesc = strtoul(optarg,0,0);
1006                                 break;
1007                         default:
1008                                 usage(1);
1009                 }
1010         }
1011
1012         if (argc - optind != 1 ||
1013             !argv[optind][0] || argv[optind][1] != ':')
1014                 usage(1);
1015
1016         if(argtracks && tot_sectors) {
1017                 fprintf(stderr, "Only one of -t or -T may be specified\n");
1018                 usage(1);
1019         }
1020
1021 #ifdef USE_XDF
1022         if(create && format_xdf) {
1023                 fprintf(stderr,"Create and XDF can't be used together\n");
1024                 exit(1);
1025         }
1026 #endif
1027         
1028         drive = toupper(argv[argc -1][0]);
1029
1030         /* check out a drive whose letter and parameters match */       
1031         sprintf(errmsg, "Drive '%c:' not supported", drive);    
1032         Fs.Direct = NULL;
1033         blocksize = 0;
1034         for(dev=devices;dev->drive;dev++) {
1035                 FREE(&(Fs.Direct));
1036                 /* drive letter */
1037                 if (dev->drive != drive)
1038                         continue;
1039                 used_dev = *dev;
1040
1041                 SET_INT(used_dev.tracks, argtracks);
1042                 SET_INT(used_dev.heads, argheads);
1043                 SET_INT(used_dev.sectors, argsectors);
1044                 SET_INT(used_dev.use_2m, arguse_2m);
1045                 SET_INT(used_dev.ssize, argssize);
1046                 if(hs_set)
1047                         used_dev.hidden = hs;
1048                 
1049                 expand(dev->name, name);
1050 #ifdef USING_NEW_VOLD
1051                 strcpy(name, getVoldName(dev, name));
1052 #endif
1053
1054 #ifdef USE_XDF
1055                 if(!format_xdf) {
1056 #endif
1057                         Fs.Direct = 0;
1058 #ifdef USE_FLOPPYD
1059                         Fs.Direct = FloppydOpen(&used_dev, dev, name,
1060                                                 O_RDWR | create,
1061                                                 errmsg, 0, 1, &maxSize);
1062 #endif
1063                         if(!Fs.Direct) {                        
1064                                 Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
1065                                                            O_RDWR | create,
1066                                                            errmsg, 0, 1,
1067                                                            &maxSize);
1068                         }
1069 #ifdef USE_XDF
1070                 } else {
1071                         used_dev.misc_flags |= USE_XDF_FLAG;
1072                         Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
1073                                             errmsg, &info);
1074                         if(Fs.Direct && !Fs.fat_len)
1075                                 Fs.fat_len = info.FatSize;
1076                         if(Fs.Direct && !Fs.dir_len)
1077                                 Fs.dir_len = info.RootDirSize;
1078                 }
1079 #endif
1080
1081                 if (!Fs.Direct)
1082                         continue;
1083
1084 #ifdef OS_linux
1085                 if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
1086                         (!IS_SCSI(dev))) {
1087                         int fd= get_fd(Fs.Direct);
1088                         struct MT_STAT stbuf;
1089
1090                         if (MT_FSTAT(fd, &stbuf) < 0) {
1091                                 sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
1092                                 continue;                                               
1093                         }
1094
1095                         if (S_ISBLK(stbuf.st_mode) &&
1096                             get_block_geom(fd, &stbuf, &used_dev, errmsg) < 0)
1097                                 continue;
1098                 }
1099 #endif
1100
1101                 /* no way to find out geometry */
1102                 if ((!used_dev.tracks && !tot_sectors) ||
1103                      !used_dev.heads || !used_dev.sectors){
1104                         sprintf(errmsg,
1105                                 "Unknown geometry "
1106                                 "(You must tell the complete geometry "
1107                                 "of the disk, \neither in /etc/mtools.conf or "
1108                                 "on the command line) ");
1109                         continue;
1110                 }
1111
1112 #if 0
1113                 /* set parameters, if needed */
1114                 if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
1115                         sprintf(errmsg,"Can't set disk parameters: %s",
1116                                 strerror(errno));
1117                         continue;
1118                 }
1119 #endif
1120                 Fs.sector_size = 512;
1121                 if( !(used_dev.use_2m & 0x7f)) {
1122                         Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
1123                 }
1124
1125                 SET_INT(Fs.sector_size, msize);
1126                 {
1127                     unsigned int j;
1128                     for(j = 0; j < 31; j++) {
1129                         if (Fs.sector_size == (unsigned int) (1 << j)) {
1130                             Fs.sectorShift = j;
1131                             break;
1132                         }
1133                     }
1134                     Fs.sectorMask = Fs.sector_size - 1;
1135                 }
1136
1137                 if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
1138                         blocksize = Fs.sector_size;
1139                 else
1140                         blocksize = used_dev.blocksize;
1141                 
1142                 if(blocksize > MAX_SECTOR)
1143                         blocksize = MAX_SECTOR;
1144
1145                 /* do a "test" read */
1146                 if (!create &&
1147                     READS(Fs.Direct, &boot.characters, 0, Fs.sector_size) !=
1148                     (signed int) Fs.sector_size) {
1149                         sprintf(errmsg,
1150                                 "Error reading from '%s', wrong parameters?",
1151                                 name);
1152                         continue;
1153                 }
1154                 break;
1155         }
1156
1157
1158         /* print error msg if needed */ 
1159         if ( dev->drive == 0 ){
1160                 FREE(&Fs.Direct);
1161                 fprintf(stderr,"%s: %s\n", argv[0],errmsg);
1162                 exit(1);
1163         }
1164
1165         /* calculate the total number of sectors */
1166         if(tot_sectors == 0) {
1167                 unsigned long sect_per_track = used_dev.heads*used_dev.sectors; 
1168                 tot_sectors = used_dev.tracks*sect_per_track - used_dev.hidden%sect_per_track;
1169         }
1170
1171         /* create the image file if needed */
1172         if (create) {
1173                 WRITES(Fs.Direct, &boot.characters,
1174                        sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
1175                        Fs.sector_size);
1176         }
1177
1178         /* the boot sector */
1179         if(bootSector) {
1180                 int fd;
1181
1182                 fd = open(bootSector, O_RDONLY | O_BINARY | O_LARGEFILE);
1183                 if(fd < 0) {
1184                         perror("open boot sector");
1185                         exit(1);
1186                 }
1187                 if(read(fd, &boot.bytes, blocksize) < blocksize) {
1188                         perror("short read on boot sector");
1189                         exit(1);
1190                 }
1191                 keepBoot = 1;
1192                 close(fd);
1193         }
1194         if(!keepBoot && !(used_dev.use_2m & 0x7f)) {
1195                 memset(boot.characters, '\0', Fs.sector_size);
1196                 if(Fs.sector_size == 512 && !used_dev.partition) {
1197                         /* install fake partition table pointing to itself */
1198                         struct partition *partTable=(struct partition *)
1199                                 (&boot.bytes[0x1ae]);
1200                         setBeginEnd(&partTable[1], 0,
1201                                                 used_dev.heads * used_dev.sectors * used_dev.tracks,
1202                                                 used_dev.heads, used_dev.sectors, 1, 0);
1203                 }
1204         }
1205         set_dword(boot.boot.nhs, used_dev.hidden);
1206
1207         Fs.Next = buf_init(Fs.Direct,
1208                            blocksize * used_dev.heads * used_dev.sectors,
1209                            blocksize * used_dev.heads * used_dev.sectors,
1210                            blocksize);
1211         Fs.Buffer = 0;
1212
1213         boot.boot.nfat = Fs.num_fat;
1214         if(!keepBoot)
1215                 set_word(&boot.bytes[510], 0xaa55);
1216         
1217         /* Initialize the remaining parameters */
1218         set_word(boot.boot.nsect, used_dev.sectors);
1219         set_word(boot.boot.nheads, used_dev.heads);
1220
1221         used_dev.fat_bits = comp_fat_bits(&Fs,used_dev.fat_bits, tot_sectors, fat32);
1222
1223         if(used_dev.fat_bits == 32) {
1224                 Fs.primaryFat = 0;
1225                 Fs.writeAllFats = 1;
1226                 Fs.fat_start = 32;
1227                 calc_fs_parameters_32(tot_sectors, &Fs, &boot);
1228
1229                 Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1230
1231                 /* extension flags: mirror fats, and use #0 as primary */
1232                 set_word(boot.boot.ext.fat32.extFlags,0);
1233
1234                 /* fs version.  What should go here? */
1235                 set_word(boot.boot.ext.fat32.fsVersion,fsVersion);
1236
1237                 /* root directory */
1238                 set_dword(boot.boot.ext.fat32.rootCluster, Fs.rootCluster = 2);
1239
1240                 /* info sector */
1241                 set_word(boot.boot.ext.fat32.infoSector, Fs.infoSectorLoc = 1);
1242                 Fs.infoSectorLoc = 1;
1243
1244                 /* no backup boot sector */
1245                 set_word(boot.boot.ext.fat32.backupBoot, backupBoot);
1246                 
1247                 labelBlock = & boot.boot.ext.fat32.labelBlock;
1248         } else {
1249                 Fs.infoSectorLoc = 0;
1250                 Fs.fat_start = 1;
1251                 calc_fs_parameters(&used_dev, tot_sectors, &Fs, &boot);
1252                 Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1253                 Fs.clus_start = Fs.dir_start + Fs.dir_len;
1254                 labelBlock = & boot.boot.ext.old.labelBlock;
1255
1256         }
1257
1258         /* Set the codepage */
1259         Fs.cp = cp_open(used_dev.codepage);
1260         if(Fs.cp == NULL)
1261                 exit(1);
1262
1263         if (!keepBoot)
1264                 /* only zero out physdrive if we don't have a template
1265                  * bootsector */
1266                 labelBlock->physdrive = 0x00;
1267         labelBlock->reserved = 0;
1268         labelBlock->dos4 = 0x29;
1269
1270         if (!serial_set || Atari)
1271                 srandom((long)time (0));
1272         if (!serial_set)
1273                 serial=random();
1274         set_dword(labelBlock->serial, serial);  
1275         label_name(GET_DOSCONVERT((Stream_t *)&Fs),
1276                    label[0] ? label : "NO NAME    ", 0, &mangled, &shortlabel);
1277         strncpy(labelBlock->label, shortlabel.base, 11);
1278         sprintf(labelBlock->fat_type, "FAT%2.2d  ", Fs.fat_bits);
1279         labelBlock->fat_type[7] = ' ';
1280
1281         set_word(boot.boot.secsiz, Fs.sector_size);
1282         boot.boot.clsiz = (unsigned char) Fs.cluster_size;
1283         set_word(boot.boot.nrsvsect, Fs.fat_start);
1284
1285         bootOffset = init_geometry_boot(&boot, &used_dev, sectors0,
1286                                         rate_0, rate_any,
1287                                         &tot_sectors, keepBoot);
1288         if(!bootOffset) {
1289                 bootOffset = ((unsigned char *) labelBlock) - boot.bytes +
1290                         sizeof(struct label_blk_t);
1291         }
1292         if(Atari) {
1293                 boot.boot.banner[4] = 0;
1294                 boot.boot.banner[5] = random();
1295                 boot.boot.banner[6] = random();
1296                 boot.boot.banner[7] = random();
1297         }               
1298
1299         if(!keepBoot)
1300                 inst_boot_prg(&boot, bootOffset);
1301         /* Mimic 3.8 behavior, else 2m disk do not work (???)
1302          * luferbu@fluidsignal.com (Luis Bustamante), Fri, 14 Jun 2002
1303          */
1304         if(used_dev.use_2m & 0x7f) {
1305           boot.boot.jump[0] = 0xeb;
1306           boot.boot.jump[1] = 0x80;
1307           boot.boot.jump[2] = 0x90;
1308         }
1309         if(used_dev.use_2m & 0x7f)
1310                 Fs.num_fat = 1;
1311         if(mediaDesc != -1)
1312                 boot.boot.descr=mediaDesc;
1313         Fs.lastFatSectorNr = 0;
1314         Fs.lastFatSectorData = 0;
1315         zero_fat(&Fs, boot.boot.descr);
1316         Fs.freeSpace = Fs.num_clus;
1317         Fs.last = 2;
1318
1319 #ifdef USE_XDF
1320         if(format_xdf)
1321                 for(i=0;
1322                     i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size;
1323                     i++)
1324                         fatEncode(&Fs, i+2, 0xfff7);
1325 #endif
1326
1327         format_root(&Fs, label, &boot);
1328         WRITES((Stream_t *)&Fs, boot.characters,
1329                (mt_off_t) 0, Fs.sector_size);
1330
1331         if(used_dev.fat_bits == 32) {
1332           WRITES((Stream_t *)&Fs, boot.characters,
1333                  (mt_off_t) backupBoot * Fs.sector_size, Fs.sector_size);
1334         }
1335
1336         if(Fs.fat_bits == 32 && WORD_S(ext.fat32.backupBoot) != MAX16) {
1337                 WRITES((Stream_t *)&Fs, boot.characters,
1338                        sectorsToBytes((Stream_t*)&Fs,
1339                                       WORD_S(ext.fat32.backupBoot)),
1340                        Fs.sector_size);
1341         }
1342         FLUSH((Stream_t *)&Fs); /* flushes Fs.
1343                                  * This triggers the writing of the FAT */
1344         FREE(&Fs.Next);
1345         Fs.Class->freeFunc((Stream_t *)&Fs);
1346 #ifdef USE_XDF
1347         if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
1348                 fprintf(stderr,
1349                         "Note:\n"
1350                         "Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
1351                         "variable before accessing this disk\n\n"
1352                         "Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
1353                         " export MTOOLS_USE_XDF=1\n\n"
1354                         "C shell syntax (csh and tcsh):\n"
1355                         " setenv MTOOLS_USE_XDF 1\n" ); 
1356 #endif
1357         exit(0);
1358 }