source: trunk/minix/commands/i386/mtools-3.9.7/mformat.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 25.8 KB
Line 
1/*
2 * mformat.c
3 */
4
5#define DONT_NEED_WAIT
6
7#include "sysincludes.h"
8#include "msdos.h"
9#include "mtools.h"
10#include "mainloop.h"
11#include "fsP.h"
12#include "file.h"
13#include "plain_io.h"
14#include "floppyd_io.h"
15#include "nameclash.h"
16#include "buffer.h"
17#ifdef USE_XDF
18#include "xdf_io.h"
19#endif
20#include "partition.h"
21
22#ifndef abs
23#define abs(x) ((x)>0?(x):-(x))
24#endif
25
26#ifdef OS_linux
27#include "linux/hdreg.h"
28
29#define _LINUX_STRING_H_
30#define kdev_t int
31#include "linux/fs.h"
32#undef _LINUX_STRING_H_
33
34#endif
35
36
37extern int errno;
38
39static int init_geometry_boot(struct bootsector *boot, struct device *dev,
40 int sectors0, int rate_0, int rate_any,
41 int *tot_sectors, int keepBoot)
42{
43 int i;
44 int nb_renum;
45 int sector2;
46 int size2;
47 int j;
48 int sum;
49
50 set_word(boot->nsect, dev->sectors);
51 set_word(boot->nheads, dev->heads);
52
53 *tot_sectors = dev->heads * dev->sectors * dev->tracks - DWORD(nhs);
54
55 if (*tot_sectors < 0x10000){
56 set_word(boot->psect, *tot_sectors);
57 set_dword(boot->bigsect, 0);
58 } else {
59 set_word(boot->psect, 0);
60 set_dword(boot->bigsect, *tot_sectors);
61 }
62
63 if (dev->use_2m & 0x7f){
64 int bootOffset;
65 strncpy(boot->banner, "2M-STV04", 8);
66 boot->ext.old.res_2m = 0;
67 boot->ext.old.fmt_2mf = 6;
68 if ( dev->sectors % ( ((1 << dev->ssize) + 3) >> 2 ))
69 boot->ext.old.wt = 1;
70 else
71 boot->ext.old.wt = 0;
72 boot->ext.old.rate_0= rate_0;
73 boot->ext.old.rate_any= rate_any;
74 if (boot->ext.old.rate_any== 2 )
75 boot->ext.old.rate_any= 1;
76 i=76;
77
78 /* Infp0 */
79 set_word(boot->ext.old.Infp0, i);
80 boot->jump[i++] = sectors0;
81 boot->jump[i++] = 108;
82 for(j=1; j<= sectors0; j++)
83 boot->jump[i++] = j;
84
85 set_word(boot->ext.old.InfpX, i);
86
87 boot->jump[i++] = 64;
88 boot->jump[i++] = 3;
89 nb_renum = i++;
90 sector2 = dev->sectors;
91 size2 = dev->ssize;
92 j=1;
93 while( sector2 ){
94 while ( sector2 < (1 << size2) >> 2 )
95 size2--;
96 boot->jump[i++] = 128 + j;
97 boot->jump[i++] = j++;
98 boot->jump[i++] = size2;
99 sector2 -= (1 << size2) >> 2;
100 }
101 boot->jump[nb_renum] = ( i - nb_renum - 1 ) / 3;
102
103 set_word(boot->ext.old.InfTm, i);
104
105 sector2 = dev->sectors;
106 size2= dev->ssize;
107 while(sector2){
108 while ( sector2 < 1 << ( size2 - 2) )
109 size2--;
110 boot->jump[i++] = size2;
111 sector2 -= 1 << (size2 - 2 );
112 }
113
114 set_word(boot->ext.old.BootP,i);
115 bootOffset = i;
116
117 /* checksum */
118 for (sum=0, j=64; j<i; j++)
119 sum += boot->jump[j];/* checksum */
120 boot->ext.old.CheckSum=-sum;
121 return bootOffset;
122 } else {
123 if(!keepBoot) {
124 boot->jump[0] = 0xeb;
125 boot->jump[1] = 0;
126 boot->jump[2] = 0x90;
127 strncpy(boot->banner, "MTOOL397", 8);
128 /* It looks like some versions of DOS are
129 * rather picky about this, and assume default
130 * parameters without this, ignoring any
131 * indication about cluster size et al. */
132 }
133 return 0;
134 }
135}
136
137
138static int comp_fat_bits(Fs_t *Fs, int estimate,
139 unsigned int tot_sectors, int fat32)
140{
141 int needed_fat_bits;
142
143 needed_fat_bits = 12;
144
145#define MAX_DISK_SIZE(bits,clusters) \
146 TOTAL_DISK_SIZE((bits), Fs->sector_size, (clusters), \
147 Fs->num_fat, MAX_SECT_PER_CLUSTER)
148
149 if(tot_sectors > MAX_DISK_SIZE(12, FAT12))
150 needed_fat_bits = 16;
151 if(fat32 || tot_sectors > MAX_DISK_SIZE(16, FAT16))
152 needed_fat_bits = 32;
153
154#undef MAX_DISK_SIZE
155
156 if(abs(estimate) && abs(estimate) < needed_fat_bits) {
157 if(fat32) {
158 fprintf(stderr,
159 "Contradiction between FAT size on command line and FAT size in conf file\n");
160 exit(1);
161 }
162 fprintf(stderr,
163 "Device too big for a %d bit FAT\n",
164 estimate);
165 exit(1);
166 }
167
168 if(needed_fat_bits == 32 && !fat32 && abs(estimate) !=32){
169 fprintf(stderr,"Warning: Using 32 bit FAT. Drive will only be accessibly by Win95 OEM / Win98\n");
170 }
171
172 if(!estimate) {
173 int min_fat16_size;
174
175 if(needed_fat_bits > 12)
176 return needed_fat_bits;
177 min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12+1,
178 Fs->num_fat, 1);
179 if(tot_sectors < min_fat16_size)
180 return 12;
181 else if(tot_sectors >= 2* min_fat16_size)
182 return 16; /* heuristics */
183 }
184
185 return estimate;
186}
187
188static void calc_fat_bits2(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
189{
190 unsigned int rem_sect;
191
192 /*
193 * the "remaining sectors" after directory and boot
194 * hasve been accounted for.
195 */
196 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
197 switch(abs(fat_bits)) {
198 case 0:
199
200#define MY_DISK_SIZE(bits,clusters) \
201 DISK_SIZE( (bits), Fs->sector_size, (clusters), \
202 Fs->num_fat, Fs->cluster_size)
203
204 if(rem_sect >= MY_DISK_SIZE(16, FAT12 + 1))
205 /* big enough for FAT16 */
206 set_fat16(Fs);
207 else if(rem_sect <= MY_DISK_SIZE(12, FAT12))
208 /* small enough for FAT12 */
209 set_fat12(Fs);
210 else {
211 /* "between two chairs",
212 * augment cluster size, and
213 * settle it */
214 if(Fs->cluster_size < MAX_SECT_PER_CLUSTER)
215 Fs->cluster_size <<= 1;
216 set_fat12(Fs);
217 }
218 break;
219#undef MY_DISK_SIZE
220
221 case 12:
222 set_fat12(Fs);
223 break;
224 case 16:
225 set_fat16(Fs);
226 break;
227 case 32:
228 set_fat32(Fs);
229 break;
230 }
231}
232
233static inline void format_root(Fs_t *Fs, char *label, struct bootsector *boot)
234{
235 Stream_t *RootDir;
236 char *buf;
237 int i;
238 struct ClashHandling_t ch;
239 int dirlen;
240
241 init_clash_handling(&ch);
242 ch.name_converter = label_name;
243 ch.ignore_entry = -2;
244
245 buf = safe_malloc(Fs->sector_size);
246 RootDir = OpenRoot((Stream_t *)Fs);
247 if(!RootDir){
248 fprintf(stderr,"Could not open root directory\n");
249 exit(1);
250 }
251
252 memset(buf, '\0', Fs->sector_size);
253
254 if(Fs->fat_bits == 32) {
255 /* on a FAT32 system, we only write one sector,
256 * as the directory can be extended at will...*/
257 dirlen = 1;
258 fatAllocate(Fs, Fs->rootCluster, Fs->end_fat);
259 } else
260 dirlen = Fs->dir_len;
261 for (i = 0; i < dirlen; i++)
262 WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),
263 Fs->sector_size);
264
265 ch.ignore_entry = 1;
266 if(label[0])
267 mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
268
269 FREE(&RootDir);
270 if(Fs->fat_bits == 32)
271 set_word(boot->dirents, 0);
272 else
273 set_word(boot->dirents, Fs->dir_len * (Fs->sector_size / 32));
274 free(buf);
275}
276
277
278static void xdf_calc_fat_size(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
279{
280 unsigned int rem_sect;
281
282 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
283
284 if(Fs->fat_len) {
285 /* an XDF disk, we know the fat_size and have to find
286 * out the rest. We start with a cluster size of 1 and
287 * keep doubling until everything fits into the
288 * FAT. This will occur eventually, as our FAT has a
289 * minimal size of 1 */
290 for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
291 Fs->num_clus = rem_sect / Fs->cluster_size;
292 if(abs(fat_bits) == 16 || Fs->num_clus > FAT12)
293 set_fat16(Fs);
294 else
295 set_fat12(Fs);
296 if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
297 return;
298 }
299 }
300 fprintf(stderr,"Internal error while calculating Xdf fat size\n");
301 exit(1);
302}
303
304
305static void calc_fat_size(Fs_t *Fs, unsigned int tot_sectors)
306{
307 unsigned int rem_sect;
308 int tries;
309 int occupied;
310
311 tries=0;
312 /* rough estimate of fat size */
313 Fs->fat_len = 1;
314 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
315 while(1){
316 Fs->num_clus = (rem_sect - 2 * Fs->fat_len ) /Fs->cluster_size;
317 Fs->fat_len = NEEDED_FAT_SIZE(Fs);
318 occupied = 2 * Fs->fat_len + Fs->cluster_size * Fs->num_clus;
319
320 /* if we have used up more than we have,
321 * we'll have to reloop */
322
323 if ( occupied > rem_sect )
324 continue;
325
326
327 /* if we have exactly used up all
328 * sectors, fine */
329 if ( rem_sect - occupied < Fs->cluster_size )
330 break;
331
332 /* if we have not used up all our
333 * sectors, try again. After the second
334 * try, decrease the amount of available
335 * space. This is to deal with the case of
336 * 344 or 345, ..., 1705, ... available
337 * sectors. */
338
339 switch(tries++){
340 default:
341 /* this should never happen */
342 fprintf(stderr,
343 "Internal error in cluster/fat repartition"
344 " calculation.\n");
345 exit(1);
346 case 2:
347 /* FALLTHROUGH */
348 case 1:
349 rem_sect-= Fs->cluster_size;
350 Fs->dir_len += Fs->cluster_size;
351 case 0:
352 continue;
353 }
354 }
355
356 if ( Fs->num_clus > FAT12 && Fs->fat_bits == 12 ){
357 fprintf(stderr,"Too many clusters for this fat size."
358 " Please choose a 16-bit fat in your /etc/mtools"
359 " or .mtoolsrc file\n");
360 exit(1);
361 }
362 if ( Fs->num_clus <= FAT12 && Fs->fat_bits > 12 ){
363 fprintf(stderr,"Too few clusters for this fat size."
364 " Please choose a 12-bit fat in your /etc/mtools"
365 " or .mtoolsrc file\n");
366 exit(1);
367 }
368}
369
370
371static unsigned char bootprog[]=
372{0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
373 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
374 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
375 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
376 0x00, 0xcd, 0x19};
377
378static inline void inst_boot_prg(struct bootsector *boot, int offset)
379{
380 memcpy((char *) boot->jump + offset,
381 (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
382 boot->jump[0] = 0xeb;
383 boot->jump[1] = offset - 1;
384 boot->jump[2] = 0x90;
385 set_word(boot->jump + offset + 20, offset + 24);
386}
387
388static void calc_cluster_size(struct Fs_t *Fs, unsigned int tot_sectors,
389 int fat_bits)
390
391{
392 unsigned int max_clusters; /* maximal possible number of sectors for
393 * this FAT entry length (12/16/32) */
394 unsigned int max_fat_size; /* maximal size of the FAT for this FAT
395 * entry length (12/16/32) */
396 unsigned int rem_sect; /* remaining sectors after we accounted for
397 * the root directory and boot sector(s) */
398
399 switch(abs(fat_bits)) {
400 case 12:
401 max_clusters = FAT12;
402 max_fat_size = Fs->num_fat *
403 FAT_SIZE(12, Fs->sector_size, max_clusters);
404 break;
405 case 16:
406 case 0: /* still hesititating between 12 and 16 */
407 max_clusters = FAT16;
408 max_fat_size = Fs->num_fat *
409 FAT_SIZE(16, Fs->sector_size, max_clusters);
410 break;
411 case 32:
412 Fs->cluster_size = 8;
413 /* According to
414 * http://www.microsoft.com/kb/articles/q154/9/97.htm,
415 * Micro$oft does not support FAT32 with less than 4K
416 */
417 return;
418 default:
419 fprintf(stderr,"Bad fat size\n");
420 exit(1);
421 }
422
423 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
424
425 /* double the cluster size until we can fill up the disk with
426 * the maximal number of sectors of this size */
427 while(Fs->cluster_size * max_clusters + max_fat_size < rem_sect) {
428 if(Fs->cluster_size > 64) {
429 /* bigger than 64. Should fit */
430 fprintf(stderr,
431 "Internal error while calculating cluster size\n");
432 exit(1);
433 }
434 Fs->cluster_size <<= 1;
435 }
436}
437
438
439struct OldDos_t old_dos[]={
440{ 40, 9, 1, 4, 1, 2, 0xfc },
441{ 40, 9, 2, 7, 2, 2, 0xfd },
442{ 40, 8, 1, 4, 1, 1, 0xfe },
443{ 40, 8, 2, 7, 2, 1, 0xff },
444{ 80, 9, 2, 7, 2, 3, 0xf9 },
445{ 80, 15, 2,14, 1, 7, 0xf9 },
446{ 80, 18, 2,14, 1, 9, 0xf0 },
447{ 80, 36, 2,15, 2, 9, 0xf0 },
448{ 1, 8, 1, 1, 1, 1, 0xf0 },
449};
450
451static int old_dos_size_to_geom(int size, int *cyls, int *heads, int *sects)
452{
453 int i;
454 size = size * 2;
455 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
456 if (old_dos[i].sectors *
457 old_dos[i].tracks *
458 old_dos[i].heads == size) {
459 *cyls = old_dos[i].tracks;
460 *heads = old_dos[i].heads;
461 *sects = old_dos[i].sectors;
462 return 0;
463 }
464 }
465 return 1;
466}
467
468
469static void calc_fs_parameters(struct device *dev, unsigned int tot_sectors,
470 struct Fs_t *Fs, struct bootsector *boot)
471{
472 int i;
473
474 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
475 if (dev->sectors == old_dos[i].sectors &&
476 dev->tracks == old_dos[i].tracks &&
477 dev->heads == old_dos[i].heads &&
478 (dev->fat_bits == 0 || abs(dev->fat_bits) == 12)){
479 boot->descr = old_dos[i].media;
480 Fs->cluster_size = old_dos[i].cluster_size;
481 Fs->dir_len = old_dos[i].dir_len;
482 Fs->fat_len = old_dos[i].fat_len;
483 Fs->fat_bits = 12;
484 break;
485 }
486 }
487 if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
488 /* a non-standard format */
489 if(DWORD(nhs))
490 boot->descr = 0xf8;
491 else
492 boot->descr = 0xf0;
493
494
495 if(!Fs->cluster_size) {
496 if (dev->heads == 1)
497 Fs->cluster_size = 1;
498 else {
499 Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
500 if (dev->use_2m & 0x7f)
501 Fs->cluster_size = 1;
502 }
503 }
504
505 if(!Fs->dir_len) {
506 if (dev->heads == 1)
507 Fs->dir_len = 4;
508 else
509 Fs->dir_len = (tot_sectors > 2000) ? 11 : 7;
510 }
511
512 calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
513 if(Fs->fat_len)
514 xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
515 else {
516 calc_fat_bits2(Fs, tot_sectors, dev->fat_bits);
517 calc_fat_size(Fs, tot_sectors);
518 }
519 }
520
521 set_word(boot->fatlen, Fs->fat_len);
522}
523
524
525
526static void calc_fs_parameters_32(unsigned int tot_sectors,
527 struct Fs_t *Fs, struct bootsector *boot)
528{
529 if(DWORD(nhs))
530 boot->descr = 0xf8;
531 else
532 boot->descr = 0xf0;
533 if(!Fs->cluster_size)
534 /* According to
535 * http://www.microsoft.com/kb/articles/q154/9/97.htm,
536 * Micro$oft does not support FAT32 with less than 4K
537 */
538 Fs->cluster_size = 8;
539
540 Fs->dir_len = 0;
541 Fs->num_clus = tot_sectors / Fs->cluster_size;
542 set_fat32(Fs);
543 calc_fat_size(Fs, tot_sectors);
544 set_word(boot->fatlen, 0);
545 set_dword(boot->ext.fat32.bigFat, Fs->fat_len);
546}
547
548
549
550
551static void usage(void)
552{
553 fprintf(stderr,
554 "Mtools version %s, dated %s\n", mversion, mdate);
555 fprintf(stderr,
556 "Usage: %s [-t tracks] [-h heads] [-n sectors] "
557 "[-v label] [-1] [-4] [-8] [-f size] "
558 "[-N serialnumber] "
559 "[-k] [-B bootsector] [-r root_dir_len] [-L fat_len] "
560 "[-F] [-I fsVersion] [-C] [-c cluster_size] "
561 "[-H hidden_sectors] "
562#ifdef USE_XDF
563 "[-X] "
564#endif
565 "[-S hardsectorsize] [-M softsectorsize] [-3] "
566 "[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
567 "device\n", progname);
568 exit(1);
569}
570
571void mformat(int argc, char **argv, int dummy)
572{
573 int r; /* generic return value */
574 Fs_t Fs;
575 int hs, hs_set;
576 int arguse_2m = 0;
577 int sectors0=18; /* number of sectors on track 0 */
578 int create = 0;
579 int rate_0, rate_any;
580 int mangled;
581 int argssize=0; /* sector size */
582 int msize=0;
583 int fat32 = 0;
584 struct label_blk_t *labelBlock;
585 int bootOffset;
586
587#ifdef USE_XDF
588 int i;
589 int format_xdf = 0;
590 struct xdf_info info;
591#endif
592 struct bootsector *boot;
593 char *bootSector=0;
594 int c;
595 int keepBoot = 0;
596 struct device used_dev;
597 int argtracks, argheads, argsectors;
598 int tot_sectors;
599 int blocksize;
600
601 char *drive, name[EXPAND_BUF];
602
603 char label[VBUFSIZE], buf[MAX_SECTOR], shortlabel[13];
604 struct device *dev;
605 char errmsg[200];
606
607 unsigned long serial;
608 int serial_set;
609 int fsVersion;
610
611 mt_off_t maxSize;
612
613 int Atari = 0; /* should we add an Atari-style serial number ? */
614#ifdef OS_Minix
615 char *devname;
616 struct device onedevice[2];
617 struct stat stbuf;
618#endif
619
620 hs = hs_set = 0;
621 argtracks = 0;
622 argheads = 0;
623 argsectors = 0;
624 arguse_2m = 0;
625 argssize = 0x2;
626 label[0] = '\0';
627 serial_set = 0;
628 serial = 0;
629 fsVersion = 0;
630
631 Fs.cluster_size = 0;
632 Fs.refs = 1;
633 Fs.dir_len = 0;
634 Fs.fat_len = 0;
635 Fs.Class = &FsClass;
636 rate_0 = mtools_rate_0;
637 rate_any = mtools_rate_any;
638
639 /* get command line options */
640 while ((c = getopt(argc,argv,
641 "148f:t:n:v:qub"
642 "kB:r:L:IFCc:Xh:s:l:N:H:M:S:230:Aa"))!= EOF) {
643 switch (c) {
644 /* standard DOS flags */
645 case '1':
646 argheads = 1;
647 break;
648 case '4':
649 argsectors = 9;
650 argtracks = 40;
651 break;
652 case '8':
653 argsectors = 8;
654 argtracks = 40;
655 break;
656 case 'f':
657 r=old_dos_size_to_geom(atoi(optarg),
658 &argtracks, &argheads,
659 &argsectors);
660 if(r) {
661 fprintf(stderr,
662 "Bad size %s\n", optarg);
663 exit(1);
664 }
665 break;
666 case 't':
667 argtracks = atoi(optarg);
668 break;
669
670 case 'n': /*non-standard*/
671 case 's':
672 argsectors = atoi(optarg);
673 break;
674
675 case 'l': /* non-standard */
676 case 'v':
677 strncpy(label, optarg, VBUFSIZE-1);
678 label[VBUFSIZE-1] = '\0';
679 break;
680
681 /* flags supported by Dos but not mtools */
682 case 'q':
683 case 'u':
684 case 'b':
685 /*case 's': leave this for compatibility */
686 fprintf(stderr,
687 "Flag %c not supported by mtools\n",c);
688 exit(1);
689
690
691
692 /* flags added by mtools */
693 case 'F':
694 fat32 = 1;
695 break;
696
697
698 case 'S':
699 argssize = atoi(optarg) | 0x80;
700 if(argssize < 0x81)
701 usage();
702 break;
703
704#ifdef USE_XDF
705 case 'X':
706 format_xdf = 1;
707 break;
708#endif
709
710 case '2':
711 arguse_2m = 0xff;
712 sectors0 = atoi(optarg);
713 break;
714 case '3':
715 arguse_2m = 0x80;
716 break;
717
718 case '0': /* rate on track 0 */
719 rate_0 = atoi(optarg);
720 break;
721 case 'A': /* rate on other tracks */
722 rate_any = atoi(optarg);
723 break;
724
725 case 'M':
726 msize = atoi(optarg);
727 if (msize % 256 || msize > 8192 )
728 usage();
729 break;
730
731 case 'N':
732 serial = strtoul(optarg,0,16);
733 serial_set = 1;
734 break;
735 case 'a': /* Atari style serial number */
736 Atari = 1;
737 break;
738
739 case 'C':
740 create = O_CREAT;
741 break;
742
743 case 'H':
744 hs = atoi(optarg);
745 hs_set = 1;
746 break;
747
748 case 'I':
749 fsVersion = strtoul(optarg,0,0);
750 break;
751
752 case 'c':
753 Fs.cluster_size = atoi(optarg);
754 break;
755
756 case 'r':
757 Fs.dir_len = strtoul(optarg,0,0);
758 break;
759 case 'L':
760 Fs.fat_len = strtoul(optarg,0,0);
761 break;
762
763
764 case 'B':
765 bootSector = optarg;
766 break;
767 case 'k':
768 keepBoot = 1;
769 break;
770 case 'h':
771 argheads = atoi(optarg);
772 break;
773
774 default:
775 usage();
776 }
777 }
778
779 if (argc - optind != 1 ||
780 skip_drive(argv[optind]) == argv[optind])
781 usage();
782
783#ifdef USE_XDF
784 if(create && format_xdf) {
785 fprintf(stderr,"Create and XDF can't be used together\n");
786 exit(1);
787 }
788#endif
789
790 drive = get_drive(argv[argc -1], NULL);
791
792#ifdef OS_Minix
793 devname = safe_malloc((9 + strlen(drive)) * sizeof(devname[0]));
794 strcpy(devname, "/dev/dosX");
795 if (isupper(drive[0]) && drive[1] == 0) {
796 /* single letter device name, use /dev/dos$drive */
797 devname[8]= drive[0];
798 } else
799 if (strchr(drive, '/') == NULL) {
800 /* a simple name, use /dev/$drive */
801 strcpy(devname+5, drive);
802 } else {
803 /* a pathname, use as is. */
804 strcpy(devname, drive);
805 }
806 if (stat(devname, &stbuf) != -1) {
807 memset(onedevice, 0, sizeof(onedevice));
808 onedevice[0].name = devname;
809 onedevice[0].drive = drive;
810 onedevice[1].name = NULL;
811 onedevice[1].drive = NULL;
812 dev = onedevice;
813 } else {
814 dev = devices;
815 }
816#else
817 dev = devices;
818#endif
819
820 /* check out a drive whose letter and parameters match */
821 sprintf(errmsg, "Drive '%s:' not supported", drive);
822 Fs.Direct = NULL;
823 blocksize = 0;
824 for(;dev->drive;dev++) {
825 FREE(&(Fs.Direct));
826 /* drive name */
827 if (strcmp(dev->drive, drive) != 0)
828 continue;
829 used_dev = *dev;
830
831 SET_INT(used_dev.tracks, argtracks);
832 SET_INT(used_dev.heads, argheads);
833 SET_INT(used_dev.sectors, argsectors);
834 SET_INT(used_dev.use_2m, arguse_2m);
835 SET_INT(used_dev.ssize, argssize);
836 if(hs_set)
837 used_dev.hidden = hs;
838
839 expand(dev->name, name);
840#ifdef USING_NEW_VOLD
841 strcpy(name, getVoldName(dev, name));
842#endif
843
844#ifdef USE_XDF
845 if(!format_xdf) {
846#endif
847 Fs.Direct = 0;
848#ifdef USE_FLOPPYD
849 Fs.Direct = FloppydOpen(&used_dev, dev, name, O_RDWR | create,
850 errmsg, 0, 1);
851 if(Fs.Direct) {
852 maxSize = max_off_t_31;
853 }
854#endif
855 if(!Fs.Direct) {
856 Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
857 O_RDWR | create,
858 errmsg, 0, 1, &maxSize);
859 }
860#ifdef USE_XDF
861 } else {
862 used_dev.misc_flags |= USE_XDF_FLAG;
863 Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
864 errmsg, &info);
865 if(Fs.Direct && !Fs.fat_len)
866 Fs.fat_len = info.FatSize;
867 if(Fs.Direct && !Fs.dir_len)
868 Fs.dir_len = info.RootDirSize;
869 }
870#endif
871
872 if (!Fs.Direct)
873 continue;
874
875#ifdef OS_linux
876 if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
877 (!IS_SCSI(dev))) {
878 int fd= get_fd(Fs.Direct);
879 struct stat buf;
880
881 if (fstat(fd, &buf) < 0) {
882 sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
883 continue;
884 }
885
886 if (S_ISBLK(buf.st_mode)) {
887 struct hd_geometry geom;
888 long size;
889 int sect_per_track;
890
891 if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
892 sprintf(errmsg, "Could not get geometry of device (%s)",
893 strerror(errno));
894 continue;
895 }
896
897 if (ioctl(fd, BLKGETSIZE, &size) < 0) {
898 sprintf(errmsg, "Could not get size of device (%s)",
899 strerror(errno));
900 continue;
901 }
902
903 sect_per_track = geom.heads * geom.sectors;
904 used_dev.heads = geom.heads;
905 used_dev.sectors = geom.sectors;
906 used_dev.hidden = geom.start % sect_per_track;
907 used_dev.tracks = (size + used_dev.hidden) / sect_per_track;
908 }
909 }
910#endif
911
912 /* no way to find out geometry */
913 if (!used_dev.tracks || !used_dev.heads || !used_dev.sectors){
914 sprintf(errmsg,
915 "Unknown geometry "
916 "(You must tell the complete geometry "
917 "of the disk, \neither in /etc/mtools.conf or "
918 "on the command line) ");
919 continue;
920 }
921
922#if 0
923 /* set parameters, if needed */
924 if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
925 sprintf(errmsg,"Can't set disk parameters: %s",
926 strerror(errno));
927 continue;
928 }
929#endif
930 Fs.sector_size = 512;
931 if( !(used_dev.use_2m & 0x7f)) {
932 Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
933 }
934
935 SET_INT(Fs.sector_size, msize);
936 {
937 int i;
938 for(i = 0; i < 31; i++) {
939 if (Fs.sector_size == 1 << i) {
940 Fs.sectorShift = i;
941 break;
942 }
943 }
944 Fs.sectorMask = Fs.sector_size - 1;
945 }
946
947 if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
948 blocksize = Fs.sector_size;
949 else
950 blocksize = used_dev.blocksize;
951
952 if(blocksize > MAX_SECTOR)
953 blocksize = MAX_SECTOR;
954
955 /* do a "test" read */
956 if (!create &&
957 READS(Fs.Direct, (char *) buf, 0, Fs.sector_size) !=
958 Fs.sector_size) {
959 sprintf(errmsg,
960 "Error reading from '%s', wrong parameters?",
961 name);
962 continue;
963 }
964 break;
965 }
966
967
968 /* print error msg if needed */
969 if ( dev->drive == 0 ){
970 FREE(&Fs.Direct);
971 fprintf(stderr,"%s: %s\n", argv[0],errmsg);
972 exit(1);
973 }
974
975 /* the boot sector */
976 boot = (struct bootsector *) buf;
977 if(bootSector) {
978 int fd;
979
980 fd = open(bootSector, O_RDONLY);
981 if(fd < 0) {
982 perror("open boot sector");
983 exit(1);
984 }
985 read(fd, buf, blocksize);
986 keepBoot = 1;
987 }
988 if(!keepBoot) {
989 memset((char *)boot, '\0', Fs.sector_size);
990 if(Fs.sector_size == 512 && !used_dev.partition) {
991 /* install fake partition table pointing to itself */
992 struct partition *partTable=(struct partition *)
993 (((char*) boot) + 0x1ae);
994 setBeginEnd(&partTable[1], 0,
995 used_dev.heads * used_dev.sectors * used_dev.tracks,
996 used_dev.heads, used_dev.sectors, 1, 0);
997 }
998 }
999 set_dword(boot->nhs, used_dev.hidden);
1000
1001 Fs.Next = buf_init(Fs.Direct,
1002 blocksize * used_dev.heads * used_dev.sectors,
1003 blocksize * used_dev.heads * used_dev.sectors,
1004 blocksize);
1005 Fs.Buffer = 0;
1006
1007 boot->nfat = Fs.num_fat = 2;
1008 if(!keepBoot)
1009 set_word(boot->jump + 510, 0xaa55);
1010
1011 /* get the parameters */
1012 tot_sectors = used_dev.tracks * used_dev.heads * used_dev.sectors -
1013 DWORD(nhs);
1014
1015 set_word(boot->nsect, dev->sectors);
1016 set_word(boot->nheads, dev->heads);
1017
1018 dev->fat_bits = comp_fat_bits(&Fs,dev->fat_bits, tot_sectors, fat32);
1019
1020 if(dev->fat_bits == 32) {
1021 Fs.primaryFat = 0;
1022 Fs.writeAllFats = 1;
1023 Fs.fat_start = 32;
1024 calc_fs_parameters_32(tot_sectors, &Fs, boot);
1025
1026 Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1027
1028 /* extension flags: mirror fats, and use #0 as primary */
1029 set_word(boot->ext.fat32.extFlags,0);
1030
1031 /* fs version. What should go here? */
1032 set_word(boot->ext.fat32.fsVersion,fsVersion);
1033
1034 /* root directory */
1035 set_dword(boot->ext.fat32.rootCluster, Fs.rootCluster = 2);
1036
1037 /* info sector */
1038 set_word(boot->ext.fat32.infoSector, Fs.infoSectorLoc = 1);
1039 Fs.infoSectorLoc = 1;
1040
1041 /* no backup boot sector */
1042 set_word(boot->ext.fat32.backupBoot, 6);
1043
1044 labelBlock = & boot->ext.fat32.labelBlock;
1045 } else {
1046 Fs.infoSectorLoc = 0;
1047 Fs.fat_start = 1;
1048 calc_fs_parameters(&used_dev, tot_sectors, &Fs, boot);
1049 Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1050 Fs.clus_start = Fs.dir_start + Fs.dir_len;
1051 labelBlock = & boot->ext.old.labelBlock;
1052
1053 }
1054
1055 if (!keepBoot)
1056 /* only zero out physdrive if we don't have a template
1057 * bootsector */
1058 labelBlock->physdrive = 0x00;
1059 labelBlock->reserved = 0;
1060 labelBlock->dos4 = 0x29;
1061
1062 if (!serial_set || Atari)
1063 srandom((long)time (0));
1064 if (!serial_set)
1065 serial=random();
1066 set_dword(labelBlock->serial, serial);
1067 if(!label[0])
1068 strncpy(shortlabel, "NO NAME ",11);
1069 else
1070 label_name(label, 0, &mangled, shortlabel);
1071 strncpy(labelBlock->label, shortlabel, 11);
1072 sprintf(labelBlock->fat_type, "FAT%2.2d ", Fs.fat_bits);
1073 labelBlock->fat_type[7] = ' ';
1074
1075 set_word(boot->secsiz, Fs.sector_size);
1076 boot->clsiz = (unsigned char) Fs.cluster_size;
1077 set_word(boot->nrsvsect, Fs.fat_start);
1078
1079 bootOffset = init_geometry_boot(boot, &used_dev, sectors0,
1080 rate_0, rate_any,
1081 &tot_sectors, keepBoot);
1082 if(!bootOffset) {
1083 bootOffset = ((char *) labelBlock) - ((char *) boot) +
1084 sizeof(struct label_blk_t);
1085 }
1086 if(Atari) {
1087 boot->banner[4] = 0;
1088 boot->banner[5] = random();
1089 boot->banner[6] = random();
1090 boot->banner[7] = random();
1091 }
1092
1093 if (create) {
1094 WRITES(Fs.Direct, (char *) buf,
1095 sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
1096 Fs.sector_size);
1097 }
1098
1099 if(!keepBoot)
1100 inst_boot_prg(boot, bootOffset);
1101 if(dev->use_2m & 0x7f)
1102 Fs.num_fat = 1;
1103 Fs.lastFatSectorNr = 0;
1104 Fs.lastFatSectorData = 0;
1105 zero_fat(&Fs, boot->descr);
1106 Fs.freeSpace = Fs.num_clus;
1107 Fs.last = 2;
1108
1109#ifdef USE_XDF
1110 if(format_xdf)
1111 for(i=0;
1112 i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size;
1113 i++)
1114 fatEncode(&Fs, i+2, 0xfff7);
1115#endif
1116
1117 format_root(&Fs, label, boot);
1118 WRITES((Stream_t *)&Fs, (char *) boot, (mt_off_t) 0, Fs.sector_size);
1119 if(Fs.fat_bits == 32 && WORD(ext.fat32.backupBoot) != MAX32) {
1120 WRITES((Stream_t *)&Fs, (char *) boot,
1121 sectorsToBytes((Stream_t*)&Fs, WORD(ext.fat32.backupBoot)),
1122 Fs.sector_size);
1123 }
1124 FLUSH((Stream_t *)&Fs); /* flushes Fs.
1125 * This triggers the writing of the FAT */
1126 FREE(&Fs.Next);
1127 Fs.Class->freeFunc((Stream_t *)&Fs);
1128#ifdef USE_XDF
1129 if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
1130 fprintf(stderr,
1131 "Note:\n"
1132 "Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
1133 "variable before accessing this disk\n\n"
1134 "Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
1135 " export MTOOLS_USE_XDF=1\n\n"
1136 "C shell syntax (csh and tcsh):\n"
1137 " setenv MTOOLS_USE_XDF 1\n" );
1138#endif
1139 exit(0);
1140}
Note: See TracBrowser for help on using the repository browser.