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