1 /* Copyright 1986-1992 Emmet P. Gray.
2 * Copyright 1994,1996-2009 Alain Knaff.
3 * This file is part of mtools.
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.
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.
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/>.
21 #define DONT_NEED_WAIT
23 #include "sysincludes.h"
30 #include "floppyd_io.h"
31 #include "nameclash.h"
39 #include "partition.h"
40 #include "file_name.h"
43 #define abs(x) ((x)>0?(x):-(x))
47 #include "linux/hdreg.h"
49 #define _LINUX_STRING_H_
52 #undef _LINUX_STRING_H_
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)
68 set_word(boot->boot.nsect, dev->sectors);
69 set_word(boot->boot.nheads, dev->heads);
72 assert(*tot_sectors != 0);
75 if (*tot_sectors < 0x10000){
76 set_word(boot->boot.psect, *tot_sectors);
77 set_dword(boot->boot.bigsect, 0);
79 set_word(boot->boot.psect, 0);
80 set_dword(boot->boot.bigsect, *tot_sectors);
83 if (dev->use_2m & 0x7f){
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;
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;
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;
105 set_word(boot->boot.ext.old.InfpX, i);
107 boot->bytes[i++] = 64;
108 boot->bytes[i++] = 3;
110 sector2 = dev->sectors;
114 while ( sector2 < (1 << size2) >> 2 )
116 boot->bytes[i++] = 128 + j;
117 boot->bytes[i++] = j++;
118 boot->bytes[i++] = size2;
119 sector2 -= (1 << size2) >> 2;
121 boot->bytes[nb_renum] = ( i - nb_renum - 1 ) / 3;
123 set_word(boot->boot.ext.old.InfTm, i);
125 sector2 = dev->sectors;
128 while ( sector2 < 1 << ( size2 - 2) )
130 boot->bytes[i++] = size2;
131 sector2 -= 1 << (size2 - 2 );
134 set_word(boot->boot.ext.old.BootP,i);
138 for (sum=0, j=64; j<i; j++)
139 sum += boot->bytes[j];/* checksum */
140 boot->boot.ext.old.CheckSum=-sum;
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. */
158 static int comp_fat_bits(Fs_t *Fs, int estimate,
159 unsigned long tot_sectors, int fat32)
163 needed_fat_bits = 12;
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)
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;
176 if(abs(estimate) && abs(estimate) < needed_fat_bits) {
179 "Contradiction between FAT size on command line and FAT size in conf file\n");
183 "Device too big for a %d bit FAT\n",
189 unsigned int min_fat16_size;
191 if(needed_fat_bits > 12)
192 return needed_fat_bits;
193 min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12,
195 if(tot_sectors < min_fat16_size)
197 else if(Fs->cluster_size == 0 &&
198 tot_sectors >= 2* min_fat16_size)
199 return 16; /* heuristics */
207 * According to Microsoft "Hardware White Paper", "Microsoft
208 * Extensible Formware Initiative", "FAT32 File System Specification",
209 * Version 1.03, December 6, 2000:
210 * If (CountofClusters < 4085) {
212 * } else if (CountofClusters < 65525) {
218 * This document can be found at the following URL
219 * http://www.microsoft.com/hwdev/download/hardware/fatgen103.pdf
220 * The relevant passus is on page 15.
222 * Actually, experimentations with Windows NT 4 show that the
223 * cutoff is 4087 rather than 4085... This is Microsoft after all.
224 * Not sure what the other Microsoft OS'es do though...
226 static void calc_fat_bits2(Fs_t *Fs, unsigned long tot_sectors, int fat_bits,
227 int may_change_cluster_size,
228 int may_change_root_size)
230 unsigned long rem_sect;
233 * the "remaining sectors" after directory and boot
234 * hasve been accounted for.
236 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
237 switch(abs(fat_bits)) {
240 #define MY_DISK_SIZE(bits,clusters) \
241 DISK_SIZE( (bits), Fs->sector_size, (clusters), \
242 Fs->num_fat, Fs->cluster_size)
244 if(rem_sect >= MY_DISK_SIZE(16, FAT12+2))
245 /* big enough for FAT16
246 * We take a margin of 2, because NT4
247 * misbehaves, and starts considering a disk
248 * as FAT16 only if it is larger than 4086
249 * sectors, rather than 4084 as it should
252 else if(rem_sect <= MY_DISK_SIZE(12, FAT12-1))
253 /* small enough for FAT12 */
256 /* "between two chairs",
257 * augment cluster size, and
259 if(may_change_cluster_size &&
260 Fs->cluster_size * Fs->sector_size * 2
261 <= MAX_BYTES_PER_CLUSTER)
262 Fs->cluster_size <<= 1;
263 else if(may_change_root_size) {
265 rem_sect - MY_DISK_SIZE(12, FAT12-1);
284 static __inline__ void format_root(Fs_t *Fs, char *label, union bootsector *boot)
289 struct ClashHandling_t ch;
292 init_clash_handling(&ch);
293 ch.name_converter = label_name_uc;
294 ch.ignore_entry = -2;
296 buf = safe_malloc(Fs->sector_size);
297 RootDir = OpenRoot((Stream_t *)Fs);
299 fprintf(stderr,"Could not open root directory\n");
303 memset(buf, '\0', Fs->sector_size);
305 if(Fs->fat_bits == 32) {
306 /* on a FAT32 system, we only write one sector,
307 * as the directory can be extended at will...*/
308 dirlen = Fs->cluster_size;
309 fatAllocate(Fs, Fs->rootCluster, Fs->end_fat);
311 dirlen = Fs->dir_len;
312 for (i = 0; i < dirlen; i++)
313 WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),
318 mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
321 if(Fs->fat_bits == 32)
322 set_word(boot->boot.dirents, 0);
324 set_word(boot->boot.dirents, Fs->dir_len * (Fs->sector_size / 32));
330 static void xdf_calc_fat_size(Fs_t *Fs, unsigned long tot_sectors,
333 unsigned int rem_sect;
335 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
338 /* an XDF disk, we know the fat_size and have to find
339 * out the rest. We start with a cluster size of 1 and
340 * keep doubling until everything fits into the
341 * FAT. This will occur eventually, as our FAT has a
342 * minimal size of 1 */
343 for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
344 Fs->num_clus = rem_sect / Fs->cluster_size;
345 if(abs(fat_bits) == 16 || Fs->num_clus >= FAT12)
349 if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
353 fprintf(stderr,"Internal error while calculating Xdf fat size\n");
358 static void calc_fat_size(Fs_t *Fs, unsigned long tot_sectors)
360 unsigned long rem_sect;
361 unsigned long real_rem_sect;
362 unsigned long numerator;
363 unsigned long denominator;
366 int printGrowMsg=1; /* Should we print "growing FAT" messages ?*/
369 fprintf(stderr, "Fat start=%d\n", Fs->fat_start);
370 fprintf(stderr, "tot_sectors=%lu\n", tot_sectors);
371 fprintf(stderr, "dir_len=%d\n", Fs->dir_len);
373 real_rem_sect = rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
375 /* Cheat a little bit to address the _really_ common case of
376 odd number of remaining sectors while both nfat and cluster size
378 if(rem_sect %2 == 1 &&
379 Fs->num_fat %2 == 0 &&
380 Fs->cluster_size %2 == 0)
384 fprintf(stderr, "Rem sect=%lu\n", rem_sect);
387 if(Fs->fat_bits == 0) {
388 fprintf(stderr, "Weird, fat bits = 0\n");
393 /* See fat_size_calculation.tex or
394 (http://ftp.gnu.org/software/mtools/manual/fat_size_calculation.pdf)
395 for an explantation about why the stuff below works...
398 fat_nybbles = Fs->fat_bits / 4;
399 numerator = rem_sect+2*Fs->cluster_size;
401 Fs->cluster_size * Fs->sector_size * 2 +
402 Fs->num_fat * fat_nybbles;
405 numerator *= fat_nybbles;
407 /* Avoid numerical overflows, divide the denominator
408 * rather than multiplying the numerator */
409 denominator = denominator / fat_nybbles;
412 fprintf(stderr, "Numerator=%lu denominator=%lu\n",
413 numerator, denominator);
416 Fs->fat_len = (numerator-1)/denominator+1;
417 Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/Fs->cluster_size;
419 /* Apply upper bounds for FAT bits */
420 if(Fs->fat_bits == 16 && Fs->num_clus >= FAT16)
421 Fs->num_clus = FAT16-1;
422 if(Fs->fat_bits == 12 && Fs->num_clus >= FAT12)
423 Fs->num_clus = FAT12-1;
425 /* A safety, if above math is correct, this should not be happen...*/
426 if(Fs->num_clus > (Fs->fat_len * Fs->sector_size * 2 /
429 "Fat size miscalculation, shrinking num_clus from %d ",
431 Fs->num_clus = (Fs->fat_len * Fs->sector_size * 2 /
433 fprintf(stderr, " to %d\n", Fs->num_clus);
436 fprintf(stderr, "Num_clus=%d fat_len=%d nybbles=%d\n",
437 Fs->num_clus, Fs->fat_len, fat_nybbles);
440 if ( Fs->num_clus < FAT16 && Fs->fat_bits > 16 ){
441 fprintf(stderr,"Too few clusters for this fat size."
442 " Please choose a 16-bit fat in your /etc/mtools.conf"
443 " or .mtoolsrc file\n");
447 /* As the number of clusters is specified nowhere in the boot sector,
448 * it will be calculated by removing everything else from total number
449 * of sectors. This means that if we reduced the number of clusters
450 * above, we will have to grow the FAT in order to take up any excess
453 assert(rem_sect >= Fs->num_clus * Fs->cluster_size +
454 Fs->fat_len * Fs->num_fat);
457 Fs->num_clus * Fs->cluster_size -
458 Fs->fat_len * Fs->num_fat;
459 if(slack >= Fs->cluster_size) {
460 /* This can happen under two circumstances:
461 1. We had to reduce num_clus because we reached maximum
462 number of cluster for FAT12 or FAT16
465 fprintf(stderr, "Slack=%d\n", slack);
466 fprintf(stderr, "Growing fat size from %d",
470 (slack - Fs->cluster_size) / Fs->num_fat + 1;
473 " to %d in order to take up excess cluster area\n",
476 Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/
482 /* Fat must be big enough for all clusters */
483 assert( ((Fs->num_clus+2) * fat_nybbles) <=
484 (Fs->fat_len*Fs->sector_size*2));
486 /* num_clus must be big enough to cover rest of disk, or else further
487 * users of the filesystem will assume a bigger num_clus, which might
488 * be too big for fat_len */
489 assert(Fs->num_clus ==
490 (real_rem_sect - Fs->num_fat * Fs->fat_len) / Fs->cluster_size);
495 static unsigned char bootprog[]=
496 {0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
497 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
498 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
499 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
502 static __inline__ void inst_boot_prg(union bootsector *boot, int offset)
504 memcpy((char *) boot->boot.jump + offset,
505 (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
506 if(offset - 2 < 0x80) {
508 boot->boot.jump[0] = 0xeb;
509 boot->boot.jump[1] = offset -2;
510 boot->boot.jump[2] = 0x90;
512 /* long jump, if offset is too large */
513 boot->boot.jump[0] = 0xe9;
514 boot->boot.jump[1] = offset -3;
515 boot->boot.jump[2] = 0x00;
517 set_word(boot->boot.jump + offset + 20, offset + 24);
520 static void calc_cluster_size(struct Fs_t *Fs, unsigned long tot_sectors,
524 unsigned int max_clusters; /* maximal possible number of sectors for
525 * this FAT entry length (12/16/32) */
526 unsigned int max_fat_size; /* maximal size of the FAT for this FAT
527 * entry length (12/16/32) */
528 unsigned int rem_sect; /* remaining sectors after we accounted for
529 * the root directory and boot sector(s) */
531 switch(abs(fat_bits)) {
533 max_clusters = FAT12-1;
534 max_fat_size = Fs->num_fat *
535 FAT_SIZE(12, Fs->sector_size, max_clusters);
538 case 0: /* still hesititating between 12 and 16 */
539 max_clusters = FAT16-1;
540 max_fat_size = Fs->num_fat *
541 FAT_SIZE(16, Fs->sector_size, max_clusters);
544 Fs->cluster_size = 8;
546 * http://support.microsoft.com/support/kb/articles/q154/9/97.asp
547 * Micro$oft does not support FAT32 with less than 4K
551 fprintf(stderr,"Bad fat size\n");
555 if(tot_sectors <= Fs->fat_start + Fs->num_fat + Fs->dir_len) {
556 /* we need at least enough sectors to fit boot, fat and root
558 fprintf(stderr, "Not enough sectors\n");
562 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
564 /* double the cluster size until we can fill up the disk with
565 * the maximal number of sectors of this size */
566 while(Fs->cluster_size * max_clusters + max_fat_size < rem_sect) {
567 if(Fs->cluster_size > 64) {
568 /* bigger than 64. Should fit */
570 "Internal error while calculating cluster size\n");
573 Fs->cluster_size <<= 1;
578 struct OldDos_t old_dos[]={
579 { 40, 9, 1, 4, 1, 2, 0xfc },
580 { 40, 9, 2, 7, 2, 2, 0xfd },
581 { 40, 8, 1, 4, 1, 1, 0xfe },
582 { 40, 8, 2, 7, 2, 1, 0xff },
583 { 80, 9, 2, 7, 2, 3, 0xf9 },
584 { 80, 15, 2,14, 1, 7, 0xf9 },
585 { 80, 18, 2,14, 1, 9, 0xf0 },
586 { 80, 36, 2,15, 2, 9, 0xf0 },
587 { 1, 8, 1, 1, 1, 1, 0xf0 },
590 static int old_dos_size_to_geom(size_t size, int *cyls, int *heads, int *sects)
594 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
595 if (old_dos[i].sectors *
597 old_dos[i].heads == size) {
598 *cyls = old_dos[i].tracks;
599 *heads = old_dos[i].heads;
600 *sects = old_dos[i].sectors;
608 static void calc_fs_parameters(struct device *dev, unsigned long tot_sectors,
609 struct Fs_t *Fs, union bootsector *boot)
613 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
614 if (dev->sectors == old_dos[i].sectors &&
615 dev->tracks == old_dos[i].tracks &&
616 dev->heads == old_dos[i].heads &&
617 (dev->fat_bits == 0 || abs(dev->fat_bits) == 12) &&
618 (Fs->dir_len == 0 || Fs->dir_len == old_dos[i].dir_len) &&
619 (Fs->cluster_size == 0 ||
620 Fs->cluster_size == old_dos[i].cluster_size)) {
621 boot->boot.descr = old_dos[i].media;
622 Fs->cluster_size = old_dos[i].cluster_size;
623 Fs->dir_len = old_dos[i].dir_len;
624 Fs->fat_len = old_dos[i].fat_len;
629 if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
630 int may_change_cluster_size = (Fs->cluster_size == 0);
631 int may_change_root_size = (Fs->dir_len == 0);
633 /* a non-standard format */
634 if(DWORD(nhs) || tot_sectors % (dev->sectors * dev->heads))
635 boot->boot.descr = 0xf8;
637 boot->boot.descr = 0xf0;
640 if(!Fs->cluster_size) {
642 Fs->cluster_size = 1;
644 Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
645 if (dev->use_2m & 0x7f)
646 Fs->cluster_size = 1;
654 Fs->dir_len = (tot_sectors > 2000) ? 32 : 7;
657 calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
660 xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
664 calc_fat_bits2(Fs, tot_sectors, dev->fat_bits,
665 may_change_cluster_size,
666 may_change_root_size);
667 calc_fat_size(Fs, tot_sectors);
671 set_word(boot->boot.fatlen, Fs->fat_len);
676 static void calc_fs_parameters_32(unsigned long tot_sectors,
677 struct Fs_t *Fs, union bootsector *boot)
680 boot->boot.descr = 0xf8;
682 boot->boot.descr = 0xf0;
683 if(!Fs->cluster_size)
685 * http://www.microsoft.com/kb/articles/q154/9/97.htm,
686 * Micro$oft does not support FAT32 with less than 4K
688 Fs->cluster_size = 8;
691 Fs->num_clus = tot_sectors / Fs->cluster_size;
693 calc_fat_size(Fs, tot_sectors);
694 set_word(boot->boot.fatlen, 0);
695 set_dword(boot->boot.ext.fat32.bigFat, Fs->fat_len);
701 static void usage(int ret)
704 "Mtools version %s, dated %s\n", mversion, mdate);
706 "Usage: %s [-V] [-t tracks] [-h heads] [-n sectors] "
707 "[-v label] [-1] [-4] [-8] [-f size] "
709 "[-k] [-B bootsector] [-r root_dir_len] [-L fat_len] "
710 "[-F] [-I fsVersion] [-C] [-c cluster_size] "
711 "[-H hidden_sectors] "
715 "[-S hardsectorsize] [-M softsectorsize] [-3] "
716 "[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
717 "device\n", progname);
722 static int get_block_geom(int fd, struct device *dev, char *errmsg) {
723 struct hd_geometry geom;
725 int heads=dev->heads;
726 int sectors=dev->sectors;
729 if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
730 sprintf(errmsg, "Could not get geometry of device (%s)",
735 if (ioctl(fd, BLKGETSIZE, &size) < 0) {
736 sprintf(errmsg, "Could not get size of device (%s)",
744 sectors = geom.sectors;
746 sect_per_track = heads * sectors;
749 hidden = geom.start % sect_per_track;
750 if(hidden && hidden != sectors) {
752 "Hidden (%d) does not match sectors (%d)\n",
756 dev->hidden = hidden;
759 dev->sectors = sectors;
761 dev->tracks = (size + dev->hidden % sect_per_track) / sect_per_track;
766 void mformat(int argc, char **argv, int dummy)
768 int r; /* generic return value */
772 int sectors0=18; /* number of sectors on track 0 */
774 int rate_0, rate_any;
776 int argssize=0; /* sector size */
779 struct label_blk_t *labelBlock;
785 struct xdf_info info;
787 union bootsector boot;
791 struct device used_dev;
792 int argtracks, argheads, argsectors;
793 unsigned long tot_sectors=0;
796 char drive, name[EXPAND_BUF];
798 char label[VBUFSIZE];
800 dos_name_t shortlabel;
804 unsigned long serial;
811 int Atari = 0; /* should we add an Atari-style serial number ? */
831 if(getenv("MTOOLS_DIR_LEN")) {
832 Fs.dir_len = atoi(getenv("MTOOLS_DIR_LEN"));
838 if(getenv("MTOOLS_NFATS")) {
839 Fs.num_fat = atoi(getenv("MTOOLS_NFATS"));
844 rate_0 = mtools_rate_0;
845 rate_any = mtools_rate_any;
847 /* get command line options */
848 if(helpFlag(argc, argv))
850 while ((c = getopt(argc,argv,
852 "kK:B:r:L:I:FCc:Xh:s:T:l:N:H:M:S:2:30:Aad:m:"))!= EOF) {
856 set_cmd_line_image(optarg);
859 /* standard DOS flags */
872 r=old_dos_size_to_geom(atoi(optarg),
873 &argtracks, &argheads,
877 "Bad size %s\n", optarg);
882 argtracks = atoi(optarg);
886 tot_sectors = atoi(optarg);
889 case 'n': /*non-standard*/
891 argsectors = atoi(optarg);
894 case 'l': /* non-standard */
896 strncpy(label, optarg, VBUFSIZE-1);
897 label[VBUFSIZE-1] = '\0';
900 /* flags supported by Dos but not mtools */
904 /*case 's': leave this for compatibility */
906 "Flag %c not supported by mtools\n",c);
911 /* flags added by mtools */
918 argssize = atoi(optarg) | 0x80;
921 if(argssize >= 0x87) {
922 fprintf(stderr, "argssize must be less than 6\n");
935 sectors0 = atoi(optarg);
941 case '0': /* rate on track 0 */
942 rate_0 = atoi(optarg);
944 case 'A': /* rate on other tracks */
945 rate_any = atoi(optarg);
949 msize = atoi(optarg);
954 fprintf(stderr, "Only sector sizes of 512, 1024, 2048 or 4096 bytes are allowed\n");
960 serial = strtoul(optarg,&endptr,16);
963 case 'a': /* Atari style serial number */
968 create = O_CREAT | O_TRUNC;
977 fsVersion = strtoul(optarg,&endptr,0);
981 Fs.cluster_size = atoi(optarg);
985 Fs.dir_len = strtoul(optarg,&endptr,0);
988 Fs.fat_len = strtoul(optarg,&endptr,0);
999 backupBoot = atoi(optarg);
1000 if(backupBoot < 2 || backupBoot >= 32) {
1001 fprintf(stderr, "Backupboot must be comprised between 2 and 32\n");
1006 argheads = atoi(optarg);
1009 Fs.num_fat = atoi(optarg);
1012 mediaDesc = strtoul(optarg,&endptr,0);
1014 mediaDesc = strtoul(optarg,&endptr,16);
1019 if(endptr && *endptr) {
1020 fprintf(stderr, "Bad number %s\n", optarg);
1025 if (argc - optind > 1)
1027 if(argc - optind == 1) {
1028 if(!argv[optind][0] || argv[optind][1] != ':')
1030 drive = toupper(argv[argc -1][0]);
1032 drive = get_default_drive();
1034 /* Use default drive only if it is ":" (image file), as else
1035 it would be too dangerous... */
1036 fprintf(stderr, "Drive letter missing\n");
1041 if(argtracks && tot_sectors) {
1042 fprintf(stderr, "Only one of -t or -T may be specified\n");
1047 if(create && format_xdf) {
1048 fprintf(stderr,"Create and XDF can't be used together\n");
1053 /* check out a drive whose letter and parameters match */
1054 sprintf(errmsg, "Drive '%c:' not supported", drive);
1057 for(dev=devices;dev->drive;dev++) {
1060 if (dev->drive != drive)
1064 SET_INT(used_dev.tracks, argtracks);
1065 SET_INT(used_dev.heads, argheads);
1066 SET_INT(used_dev.sectors, argsectors);
1067 SET_INT(used_dev.use_2m, arguse_2m);
1068 SET_INT(used_dev.ssize, argssize);
1070 used_dev.hidden = hs;
1072 expand(dev->name, name);
1073 #ifdef USING_NEW_VOLD
1074 strcpy(name, getVoldName(dev, name));
1082 Fs.Direct = FloppydOpen(&used_dev, name,
1087 Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
1094 used_dev.misc_flags |= USE_XDF_FLAG;
1095 Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
1097 if(Fs.Direct && !Fs.fat_len)
1098 Fs.fat_len = info.FatSize;
1099 if(Fs.Direct && !Fs.dir_len)
1100 Fs.dir_len = info.RootDirSize;
1108 if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
1110 int fd= get_fd(Fs.Direct);
1111 struct MT_STAT stbuf;
1113 if (MT_FSTAT(fd, &stbuf) < 0) {
1114 sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
1118 if (S_ISBLK(stbuf.st_mode) &&
1119 get_block_geom(fd, &used_dev, errmsg) < 0)
1124 /* no way to find out geometry */
1125 if ((!used_dev.tracks && !tot_sectors) ||
1126 !used_dev.heads || !used_dev.sectors){
1129 "(You must tell the complete geometry "
1130 "of the disk, \neither in /etc/mtools.conf or "
1131 "on the command line) ");
1136 /* set parameters, if needed */
1137 if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
1138 sprintf(errmsg,"Can't set disk parameters: %s",
1143 Fs.sector_size = 512;
1144 if( !(used_dev.use_2m & 0x7f)) {
1145 Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
1148 SET_INT(Fs.sector_size, msize);
1151 for(j = 0; j < 31; j++) {
1152 if (Fs.sector_size == (unsigned int) (1 << j)) {
1157 Fs.sectorMask = Fs.sector_size - 1;
1160 if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
1161 blocksize = Fs.sector_size;
1163 blocksize = used_dev.blocksize;
1165 if(blocksize > MAX_SECTOR)
1166 blocksize = MAX_SECTOR;
1168 /* do a "test" read */
1170 READS(Fs.Direct, &boot.characters, 0, Fs.sector_size) !=
1171 (signed int) Fs.sector_size) {
1173 "Error reading from '%s', wrong parameters?",
1181 /* print error msg if needed */
1182 if ( dev->drive == 0 ){
1184 fprintf(stderr,"%s: %s\n", argv[0],errmsg);
1188 /* calculate the total number of sectors */
1189 if(tot_sectors == 0) {
1190 unsigned long sect_per_track = used_dev.heads*used_dev.sectors;
1191 tot_sectors = used_dev.tracks*sect_per_track - used_dev.hidden%sect_per_track;
1194 /* create the image file if needed */
1196 WRITES(Fs.Direct, &boot.characters,
1197 sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
1201 /* the boot sector */
1205 fd = open(bootSector, O_RDONLY | O_BINARY | O_LARGEFILE);
1207 perror("open boot sector");
1210 if(read(fd, &boot.bytes, blocksize) < blocksize) {
1211 perror("short read on boot sector");
1217 if(!keepBoot && !(used_dev.use_2m & 0x7f)) {
1218 memset(boot.characters, '\0', Fs.sector_size);
1219 if(Fs.sector_size == 512 && !used_dev.partition) {
1220 /* install fake partition table pointing to itself */
1221 struct partition *partTable=(struct partition *)
1222 (&boot.bytes[0x1ae]);
1223 setBeginEnd(&partTable[1], 0,
1224 used_dev.heads * used_dev.sectors * used_dev.tracks,
1225 used_dev.heads, used_dev.sectors, 1, 0);
1228 set_dword(boot.boot.nhs, used_dev.hidden);
1230 Fs.Next = buf_init(Fs.Direct,
1231 blocksize * used_dev.heads * used_dev.sectors,
1232 blocksize * used_dev.heads * used_dev.sectors,
1236 boot.boot.nfat = Fs.num_fat;
1238 set_word(&boot.bytes[510], 0xaa55);
1240 /* Initialize the remaining parameters */
1241 set_word(boot.boot.nsect, used_dev.sectors);
1242 set_word(boot.boot.nheads, used_dev.heads);
1244 used_dev.fat_bits = comp_fat_bits(&Fs,used_dev.fat_bits, tot_sectors, fat32);
1246 if(used_dev.fat_bits == 32) {
1248 Fs.writeAllFats = 1;
1250 calc_fs_parameters_32(tot_sectors, &Fs, &boot);
1252 Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1254 /* extension flags: mirror fats, and use #0 as primary */
1255 set_word(boot.boot.ext.fat32.extFlags,0);
1257 /* fs version. What should go here? */
1258 set_word(boot.boot.ext.fat32.fsVersion,fsVersion);
1260 /* root directory */
1261 set_dword(boot.boot.ext.fat32.rootCluster, Fs.rootCluster = 2);
1264 set_word(boot.boot.ext.fat32.infoSector, Fs.infoSectorLoc = 1);
1265 Fs.infoSectorLoc = 1;
1267 /* no backup boot sector */
1268 set_word(boot.boot.ext.fat32.backupBoot, backupBoot);
1270 labelBlock = & boot.boot.ext.fat32.labelBlock;
1272 Fs.infoSectorLoc = 0;
1274 calc_fs_parameters(&used_dev, tot_sectors, &Fs, &boot);
1275 Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1276 Fs.clus_start = Fs.dir_start + Fs.dir_len;
1277 labelBlock = & boot.boot.ext.old.labelBlock;
1281 /* Set the codepage */
1282 Fs.cp = cp_open(used_dev.codepage);
1287 /* only zero out physdrive if we don't have a template
1289 labelBlock->physdrive = 0x00;
1290 labelBlock->reserved = 0;
1291 labelBlock->dos4 = 0x29;
1293 if (!serial_set || Atari)
1294 srandom((long)time (0));
1297 set_dword(labelBlock->serial, serial);
1298 label_name_pc(GET_DOSCONVERT((Stream_t *)&Fs),
1299 label[0] ? label : "NO NAME ", 0,
1300 &mangled, &shortlabel);
1301 strncpy(labelBlock->label, shortlabel.base, 11);
1302 sprintf(labelBlock->fat_type, "FAT%2.2d ", Fs.fat_bits);
1303 labelBlock->fat_type[7] = ' ';
1305 set_word(boot.boot.secsiz, Fs.sector_size);
1306 boot.boot.clsiz = (unsigned char) Fs.cluster_size;
1307 set_word(boot.boot.nrsvsect, Fs.fat_start);
1309 bootOffset = init_geometry_boot(&boot, &used_dev, sectors0,
1311 &tot_sectors, keepBoot);
1313 bootOffset = ((unsigned char *) labelBlock) - boot.bytes +
1314 sizeof(struct label_blk_t);
1317 boot.boot.banner[4] = 0;
1318 boot.boot.banner[5] = random();
1319 boot.boot.banner[6] = random();
1320 boot.boot.banner[7] = random();
1324 inst_boot_prg(&boot, bootOffset);
1325 /* Mimic 3.8 behavior, else 2m disk do not work (???)
1326 * luferbu@fluidsignal.com (Luis Bustamante), Fri, 14 Jun 2002
1328 if(used_dev.use_2m & 0x7f) {
1329 boot.boot.jump[0] = 0xeb;
1330 boot.boot.jump[1] = 0x80;
1331 boot.boot.jump[2] = 0x90;
1333 if(used_dev.use_2m & 0x7f)
1336 boot.boot.descr=mediaDesc;
1337 Fs.lastFatSectorNr = 0;
1338 Fs.lastFatSectorData = 0;
1339 zero_fat(&Fs, boot.boot.descr);
1340 Fs.freeSpace = Fs.num_clus;
1346 i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size;
1348 fatEncode(&Fs, i+2, 0xfff7);
1351 format_root(&Fs, label, &boot);
1352 WRITES((Stream_t *)&Fs, boot.characters,
1353 (mt_off_t) 0, Fs.sector_size);
1355 if(used_dev.fat_bits == 32) {
1356 WRITES((Stream_t *)&Fs, boot.characters,
1357 (mt_off_t) backupBoot * Fs.sector_size, Fs.sector_size);
1360 if(Fs.fat_bits == 32 && WORD_S(ext.fat32.backupBoot) != MAX16) {
1361 WRITES((Stream_t *)&Fs, boot.characters,
1362 sectorsToBytes((Stream_t*)&Fs,
1363 WORD_S(ext.fat32.backupBoot)),
1366 FLUSH((Stream_t *)&Fs); /* flushes Fs.
1367 * This triggers the writing of the FAT */
1369 Fs.Class->freeFunc((Stream_t *)&Fs);
1371 if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
1374 "Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
1375 "variable before accessing this disk\n\n"
1376 "Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
1377 " export MTOOLS_USE_XDF=1\n\n"
1378 "C shell syntax (csh and tcsh):\n"
1379 " setenv MTOOLS_USE_XDF 1\n" );