3 Version: 0.3b (Yggdrasil)
5 Started: 24th August 1994
6 Last Updated: 7th May 1998
7 Updated by: Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
8 Target O/S: Linux (2.x)
10 Description: Utility to allow an MS-DOS filesystem to be created
11 under Linux. A lot of the basic structure of this program has been
12 borrowed from Remy Card's "mke2fs" code.
14 As far as possible the aim here is to make the "mkdosfs" command
15 look almost identical to the other Linux filesystem make utilties,
16 eg bad blocks are still specified as blocks, not sectors, but when
17 it comes down to it, DOS is tied to the idea of a sector (512 bytes
18 as a rule), and not the block. For example the boot block does not
19 occupy a full cluster.
21 Fixes/additions May 1998 by Roman Hodek
22 <Roman.Hodek@informatik.uni-erlangen.de>:
23 - Atari format support
24 - New options -A, -S, -C
25 - Support for filesystems > 2GB
28 Port to work under Windows NT/2K/XP Dec 2002 by
29 Jens-Uwe Mager <jum@anubis.han.de>
31 Copying: Copyright 1993, 1994 David Hudson (dave@humbug.demon.co.uk)
33 Portions copyright 1992, 1993 Remy Card (card@masi.ibp.fr)
34 and 1991 Linus Torvalds (torvalds@klaava.helsinki.fi)
36 This program is free software; you can redistribute it and/or modify
37 it under the terms of the GNU General Public License as published by
38 the Free Software Foundation; either version 2, or (at your option)
41 This program is distributed in the hope that it will be useful,
42 but WITHOUT ANY WARRANTY; without even the implied warranty of
43 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 GNU General Public License for more details.
46 You should have received a copy of the GNU General Public License
47 along with this program; if not, write to the Free Software
48 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
51 /* Include the header files */
53 #include "../version.h"
56 #define _WIN32_WINNT 0x0400
59 #define __LITTLE_ENDIAN 1234
60 #define __BIG_ENDIAN 4321
61 #define __BYTE_ORDER __LITTLE_ENDIAN
63 #define __attribute__(x)
64 #define BLOCK_SIZE 512
66 #include <linux/hdreg.h>
72 #include <sys/ioctl.h>
80 #include <sys/types.h>
83 #if __BYTE_ORDER == __BIG_ENDIAN
85 #include <asm/byteorder.h>
87 /* ++roman: 2.1 kernel headers define these function, they're probably more
88 * efficient then coding the swaps machine-independently. */
89 #define CF_LE_W __le16_to_cpu
90 #define CF_LE_L __le32_to_cpu
91 #define CT_LE_W __cpu_to_le16
92 #define CT_LE_L __cpu_to_le32
94 #define CF_LE_W(v) ((((v) & 0xff) << 8) | (((v) >> 8) & 0xff))
95 #define CF_LE_L(v) (((unsigned)(v)>>24) | (((unsigned)(v)>>8)&0xff00) | \
96 (((unsigned)(v)<<8)&0xff0000) | ((unsigned)(v)<<24))
97 #define CT_LE_W(v) CF_LE_W(v)
98 #define CT_LE_L(v) CF_LE_L(v)
99 #endif /* defined(__le16_to_cpu) */
103 #define CF_LE_W(v) (v)
104 #define CF_LE_L(v) (v)
105 #define CT_LE_W(v) (v)
106 #define CT_LE_L(v) (v)
108 #endif /* __BIG_ENDIAN */
112 typedef unsigned char __u8
;
113 typedef unsigned short __u16
;
114 typedef unsigned int __u32
;
115 typedef unsigned __int64 __u64
;
116 typedef __int64 loff_t
;
117 typedef __int64 ll_t
;
123 int getopt(int argc
, char *const argv
[], const char * optstring
);
125 static int is_device
= 0;
127 #define open WIN32open
128 #define close WIN32close
129 #define read WIN32read
130 #define write WIN32write
131 #define llseek WIN32llseek
133 #define O_SHORT_LIVED _O_SHORT_LIVED
136 #define O_BACKUP 0x10000
137 #define O_SHARED 0x20000
139 static int WIN32open(const char *path
, int oflag
, ...)
144 DWORD creationDisposition
;
145 DWORD flagsAttributes
= FILE_ATTRIBUTE_NORMAL
;
146 SECURITY_ATTRIBUTES securityAttributes
;
151 securityAttributes
.nLength
= sizeof(securityAttributes
);
152 securityAttributes
.lpSecurityDescriptor
= NULL
;
153 securityAttributes
.bInheritHandle
= oflag
& O_NOINHERIT
? FALSE
: TRUE
;
154 switch (oflag
& O_ACCMODE
) {
156 desiredAccess
= GENERIC_READ
;
157 shareMode
= FILE_SHARE_READ
;
160 desiredAccess
= GENERIC_WRITE
;
164 desiredAccess
= GENERIC_READ
|GENERIC_WRITE
;
169 shareMode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
171 if (oflag
& O_APPEND
) {
172 desiredAccess
|= FILE_APPEND_DATA
|SYNCHRONIZE
;
173 shareMode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
175 if (oflag
& O_SHARED
)
176 shareMode
|= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
177 switch (oflag
& (O_CREAT
|O_EXCL
|O_TRUNC
)) {
180 creationDisposition
= OPEN_EXISTING
;
183 creationDisposition
= OPEN_ALWAYS
;
186 case O_CREAT
|O_TRUNC
|O_EXCL
:
187 creationDisposition
= CREATE_NEW
;
191 creationDisposition
= TRUNCATE_EXISTING
;
193 case O_CREAT
|O_TRUNC
:
194 creationDisposition
= OPEN_ALWAYS
;
198 if (oflag
& O_CREAT
) {
200 pmode
= va_arg(ap
, int);
202 if ((pmode
& 0222) == 0)
203 flagsAttributes
|= FILE_ATTRIBUTE_READONLY
;
205 if (oflag
& O_TEMPORARY
) {
206 flagsAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
207 desiredAccess
|= DELETE
;
209 if (oflag
& O_SHORT_LIVED
)
210 flagsAttributes
|= FILE_ATTRIBUTE_TEMPORARY
;
211 if (oflag
& O_SEQUENTIAL
)
212 flagsAttributes
|= FILE_FLAG_SEQUENTIAL_SCAN
;
213 else if (oflag
& O_RANDOM
)
214 flagsAttributes
|= FILE_FLAG_RANDOM_ACCESS
;
215 if (oflag
& O_BACKUP
)
216 flagsAttributes
|= FILE_FLAG_BACKUP_SEMANTICS
;
217 if ((fh
= CreateFile(path
, desiredAccess
, shareMode
, &securityAttributes
,
218 creationDisposition
, flagsAttributes
, NULL
)) == INVALID_HANDLE_VALUE
) {
219 errno
= GetLastError();
223 if (!SetEndOfFile(fh
)) {
224 errno
= GetLastError();
233 static int WIN32close(int fd
)
235 if (!CloseHandle((HANDLE
)fd
)) {
236 errno
= GetLastError();
242 static int WIN32read(int fd
, void *buf
, unsigned int len
)
246 if (!ReadFile((HANDLE
)fd
, buf
, (DWORD
)len
, &actualLen
, NULL
)) {
247 errno
= GetLastError();
248 if (errno
== ERROR_BROKEN_PIPE
)
253 return (int)actualLen
;
256 static int WIN32write(int fd
, void *buf
, unsigned int len
)
260 if (!WriteFile((HANDLE
)fd
, buf
, (DWORD
)len
, &actualLen
, NULL
)) {
261 errno
= GetLastError();
264 return (int)actualLen
;
267 static loff_t
WIN32llseek(int fd
, loff_t offset
, int whence
)
272 lo
= offset
& 0xffffffff;
274 lo
= SetFilePointer((HANDLE
)fd
, lo
, &hi
, whence
);
275 if (lo
== 0xFFFFFFFF && (err
= GetLastError()) != NO_ERROR
) {
279 return ((loff_t
)hi
<< 32) | (off_t
)lo
;
282 int fsctl(int fd
, int code
)
285 if (!DeviceIoControl((HANDLE
)fd
, code
, NULL
, 0, NULL
, 0, &ret
, NULL
)) {
286 errno
= GetLastError();
294 #define O_NOINHERIT 0
295 #define O_TEMPORARY 0
296 #define O_SHORT_LIVED 0
297 #define O_SEQUENTIAL 0
305 typedef long long ll_t
;
306 /* Use the _llseek system call directly, because there (once?) was a bug in
307 * the glibc implementation of it. */
308 #include <linux/unistd.h>
309 #if defined(__alpha) || defined(__ia64__)
310 /* On alpha, the syscall is simply lseek, because it's a 64 bit system. */
311 static loff_t
llseek( int fd
, loff_t offset
, int whence
)
313 return lseek(fd
, offset
, whence
);
316 # ifndef __NR__llseek
317 # error _llseek system call not present
319 static _syscall5( int, _llseek
, uint
, fd
, ulong
, hi
, ulong
, lo
,
320 loff_t
*, res
, uint
, wh
);
321 static loff_t
llseek( int fd
, loff_t offset
, int whence
)
325 if (_llseek(fd
, offset
>>32, offset
&0xffffffff, &actual
, whence
) != 0)
333 /* Constant definitions */
335 #define TRUE 1 /* Boolean constants */
338 #define TEST_BUFFER_BLOCKS 16
339 #define HARD_SECTOR_SIZE 512
340 #define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE )
343 /* Macro definitions */
345 /* Report a failure message and return a failure error code */
347 #define die( str ) fatal_error( "%s: " str "\n" )
350 /* Mark a cluster in the FAT as bad */
352 #define mark_sector_bad( sector ) mark_FAT_sector( sector, FAT_BAD )
354 /* Compute ceil(a/b) */
359 return (a
+ b
- 1) / b
;
362 /* MS-DOS filesystem structures -- I included them here instead of
363 including linux/msdos_fs.h since that doesn't include some fields we
366 #define ATTR_RO 1 /* read-only */
367 #define ATTR_HIDDEN 2 /* hidden */
368 #define ATTR_SYS 4 /* system */
369 #define ATTR_VOLUME 8 /* volume label */
370 #define ATTR_DIR 16 /* directory */
371 #define ATTR_ARCH 32 /* archived */
373 #define ATTR_NONE 0 /* no attribute bits */
374 #define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
375 /* attribute bits that are copied "as is" */
378 #define FAT_EOF (atari_format ? 0x0fffffff : 0x0ffffff8)
379 #define FAT_BAD 0x0ffffff7
381 #define MSDOS_EXT_SIGN 0x29 /* extended boot sector signature */
382 #define MSDOS_FAT12_SIGN "FAT12 " /* FAT12 filesystem signature */
383 #define MSDOS_FAT16_SIGN "FAT16 " /* FAT16 filesystem signature */
384 #define MSDOS_FAT32_SIGN "FAT32 " /* FAT32 filesystem signature */
386 #define BOOT_SIGN 0xAA55 /* Boot sector magic number */
388 #define MAX_CLUST_12 ((1 << 12) - 16)
389 #define MAX_CLUST_16 ((1 << 16) - 16)
390 /* M$ says the high 4 bits of a FAT32 FAT entry are reserved and don't belong
391 * to the cluster number. So the max. cluster# is based on 2^28 */
392 #define MAX_CLUST_32 ((1 << 28) - 16)
394 #define FAT12_THRESHOLD 4078
396 #define OLDGEMDOS_MAX_SECTORS 32765
397 #define GEMDOS_MAX_SECTORS 65531
398 #define GEMDOS_MAX_SECTOR_SIZE (16*1024)
400 #define BOOTCODE_SIZE 448
401 #define BOOTCODE_FAT32_SIZE 420
403 /* __attribute__ ((packed)) is used on all structures to make gcc ignore any
407 #pragma pack(push, 1)
409 struct msdos_volume_info
{
410 __u8 drive_number
; /* BIOS drive number */
411 __u8 RESERVED
; /* Unused */
412 __u8 ext_boot_sign
; /* 0x29 if fields below exist (DOS 3.3+) */
413 __u8 volume_id
[4]; /* Volume ID number */
414 __u8 volume_label
[11];/* Volume label */
415 __u8 fs_type
[8]; /* Typically FAT12 or FAT16 */
416 } __attribute__ ((packed
));
418 struct msdos_boot_sector
420 __u8 boot_jump
[3]; /* Boot strap short or near jump */
421 __u8 system_id
[8]; /* Name - can be used to special case
422 partition manager volumes */
423 __u8 sector_size
[2]; /* bytes per logical sector */
424 __u8 cluster_size
; /* sectors/cluster */
425 __u16 reserved
; /* reserved sectors */
426 __u8 fats
; /* number of FATs */
427 __u8 dir_entries
[2]; /* root directory entries */
428 __u8 sectors
[2]; /* number of sectors */
429 __u8 media
; /* media code (unused) */
430 __u16 fat_length
; /* sectors/FAT */
431 __u16 secs_track
; /* sectors per track */
432 __u16 heads
; /* number of heads */
433 __u32 hidden
; /* hidden sectors (unused) */
434 __u32 total_sect
; /* number of sectors (if sectors == 0) */
437 struct msdos_volume_info vi
;
438 __u8 boot_code
[BOOTCODE_SIZE
];
439 } __attribute__ ((packed
)) _oldfat
;
441 __u32 fat32_length
; /* sectors/FAT */
442 __u16 flags
; /* bit 8: fat mirroring, low 4: active fat */
443 __u8 version
[2]; /* major, minor filesystem version */
444 __u32 root_cluster
; /* first cluster in root directory */
445 __u16 info_sector
; /* filesystem info sector */
446 __u16 backup_boot
; /* backup boot sector */
447 __u16 reserved2
[6]; /* Unused */
448 struct msdos_volume_info vi
;
449 __u8 boot_code
[BOOTCODE_FAT32_SIZE
];
450 } __attribute__ ((packed
)) _fat32
;
451 } __attribute__ ((packed
)) fstype
;
453 } __attribute__ ((packed
));
454 #define fat32 fstype._fat32
455 #define oldfat fstype._oldfat
457 struct fat32_fsinfo
{
458 __u32 reserved1
; /* Nothing as far as I can tell */
459 __u32 signature
; /* 0x61417272L */
460 __u32 free_clusters
; /* Free cluster count. -1 if unknown */
461 __u32 next_cluster
; /* Most recently allocated cluster.
462 * Unused under Linux. */
466 struct msdos_dir_entry
468 char name
[8], ext
[3]; /* name and extension */
469 __u8 attr
; /* attribute bits */
470 __u8 lcase
; /* Case for base and extension */
471 __u8 ctime_ms
; /* Creation time, milliseconds */
472 __u16 ctime
; /* Creation time */
473 __u16 cdate
; /* Creation date */
474 __u16 adate
; /* Last access date */
475 __u16 starthi
; /* high 16 bits of first cl. (FAT32) */
476 __u16 time
, date
, start
; /* time, date and first cluster */
477 __u32 size
; /* file size (in bytes) */
478 } __attribute__ ((packed
));
484 /* The "boot code" we put into the filesystem... it writes a message and
485 tells the user to try again */
487 char dummy_boot_jump
[3] = { 0xeb, 0x3c, 0x90 };
489 char dummy_boot_jump_m68k
[2] = { 0x60, 0x1c };
491 char dummy_boot_code
[BOOTCODE_SIZE
] =
494 "\xbe\x5b\x7c" /* mov si, offset message_txt */
497 "\x22\xc0" /* and al, al */
498 "\x74\x0b" /* jz key_press */
500 "\xb4\x0e" /* mov ah, 0eh */
501 "\xbb\x07\x00" /* mov bx, 0007h */
502 "\xcd\x10" /* int 10h */
504 "\xeb\xf0" /* jmp write_msg */
506 "\x32\xe4" /* xor ah, ah */
507 "\xcd\x16" /* int 16h */
508 "\xcd\x19" /* int 19h */
509 "\xeb\xfe" /* foo: jmp foo */
512 "This is not a bootable disk. Please insert a bootable floppy and\r\n"
513 "press any key to try again ... \r\n";
515 #define MESSAGE_OFFSET 29 /* Offset of message in above code */
517 /* Global variables - the root of all evil :-) - see these and weep! */
519 static char *program_name
= "mkdosfs"; /* Name of the program */
520 static char *device_name
= NULL
; /* Name of the device on which to create the filesystem */
521 static int atari_format
= 0; /* Use Atari variation of MS-DOS FS format */
522 static int check
= FALSE
; /* Default to no readablity checking */
523 static int verbose
= 0; /* Default to verbose mode off */
524 static long volume_id
; /* Volume ID number */
525 static time_t create_time
; /* Creation time */
526 static char volume_name
[] = " "; /* Volume name */
527 static int blocks
; /* Number of blocks in filesystem */
528 static int sector_size
= 512; /* Size of a logical sector */
529 static int sector_size_set
= 0; /* User selected sector size */
530 static int backup_boot
= 0; /* Sector# of backup boot sector */
531 static int reserved_sectors
= 0;/* Number of reserved sectors */
532 static int badblocks
= 0; /* Number of bad blocks in the filesystem */
533 static int nr_fats
= 2; /* Default number of FATs to produce */
534 static int size_fat
= 0; /* Size in bits of FAT entries */
535 static int size_fat_by_user
= 0; /* 1 if FAT size user selected */
536 static int dev
= -1; /* FS block device file handle */
537 static int ignore_full_disk
= 0; /* Ignore warning about 'full' disk devices */
538 static unsigned int currently_testing
= 0; /* Block currently being tested (if autodetect bad blocks) */
539 static struct msdos_boot_sector bs
; /* Boot sector data */
540 static int start_data_sector
; /* Sector number for the start of the data area */
541 static int start_data_block
; /* Block number for the start of the data area */
542 static unsigned char *fat
; /* File allocation table */
543 static unsigned char *info_sector
; /* FAT32 info sector */
544 static struct msdos_dir_entry
*root_dir
; /* Root directory */
545 static int size_root_dir
; /* Size of the root directory in bytes */
546 static int sectors_per_cluster
= 0; /* Number of sectors per disk cluster */
547 static int root_dir_entries
= 0; /* Number of root directory entries */
548 static char *blank_sector
; /* Blank sector - all zeros */
551 /* Function prototype definitions */
553 static void fatal_error (const char *fmt_string
) __attribute__((noreturn
));
554 static void mark_FAT_cluster (int cluster
, unsigned int value
);
555 static void mark_FAT_sector (int sector
, unsigned int value
);
556 static long do_check (char *buffer
, int try, unsigned int current_block
);
557 static void alarm_intr (int alnum
);
558 static void check_blocks (void);
559 static void get_list_blocks (char *filename
);
560 static int valid_offset (int fd
, loff_t offset
);
561 static int count_blocks (char *filename
);
562 static void check_mount (char *device_name
);
564 static void establish_params (void);
566 static void establish_params (int device_num
, int size
);
568 static void setup_tables (void);
569 static void write_tables (void);
572 /* The function implementations */
574 /* Handle the reporting of fatal errors. Volatile to let gcc know that this doesn't return */
577 fatal_error (const char *fmt_string
)
579 fprintf (stderr
, fmt_string
, program_name
, device_name
);
580 exit (1); /* The error exit code is 1! */
584 /* Mark the specified cluster as having a particular value */
587 mark_FAT_cluster (int cluster
, unsigned int value
)
592 if (((cluster
* 3) & 0x1) == 0)
594 fat
[3 * cluster
/ 2] = (unsigned char) (value
& 0x00ff);
595 fat
[(3 * cluster
/ 2) + 1] = (unsigned char) ((fat
[(3 * cluster
/ 2) + 1] & 0x00f0)
596 | ((value
& 0x0f00) >> 8));
600 fat
[3 * cluster
/ 2] = (unsigned char) ((fat
[3 * cluster
/ 2] & 0x000f) | ((value
& 0x000f) << 4));
601 fat
[(3 * cluster
/ 2) + 1] = (unsigned char) ((value
& 0x0ff0) >> 4);
607 fat
[2 * cluster
] = (unsigned char) (value
& 0x00ff);
608 fat
[(2 * cluster
) + 1] = (unsigned char) (value
>> 8);
613 fat
[4 * cluster
] = (unsigned char) (value
& 0x000000ff);
614 fat
[(4 * cluster
) + 1] = (unsigned char) ((value
& 0x0000ff00) >> 8);
615 fat
[(4 * cluster
) + 2] = (unsigned char) ((value
& 0x00ff0000) >> 16);
616 fat
[(4 * cluster
) + 3] = (unsigned char) ((value
& 0xff000000) >> 24);
620 die("Bad FAT size (not 12, 16, or 32)");
625 /* Mark a specified sector as having a particular value in it's FAT entry */
628 mark_FAT_sector (int sector
, unsigned int value
)
632 cluster
= (sector
- start_data_sector
) / (int) (bs
.cluster_size
) /
633 (sector_size
/HARD_SECTOR_SIZE
);
635 die ("Invalid cluster number in mark_FAT_sector: probably bug!");
637 mark_FAT_cluster (cluster
, value
);
641 /* Perform a test on a block. Return the number of blocks that could be read successfully */
644 do_check (char *buffer
, int try, unsigned int current_block
)
648 if (llseek (dev
, (loff_t
)current_block
* BLOCK_SIZE
, SEEK_SET
) /* Seek to the correct location */
649 != (loff_t
)current_block
* BLOCK_SIZE
)
650 die ("seek failed during testing for blocks");
652 got
= read (dev
, buffer
, try * BLOCK_SIZE
); /* Try reading! */
656 if (got
& (BLOCK_SIZE
- 1))
657 printf ("Unexpected values in do_check: probably bugs\n");
664 /* Alarm clock handler - display the status of the quest for bad blocks! Then retrigger the alarm for five senconds
665 later (so we can come here again) */
668 alarm_intr (int alnum
)
670 if (currently_testing
>= blocks
)
673 signal (SIGALRM
, alarm_intr
);
675 if (!currently_testing
)
678 printf ("%d... ", currently_testing
);
688 static char blkbuf
[BLOCK_SIZE
* TEST_BUFFER_BLOCKS
];
692 printf ("Searching for bad blocks ");
695 currently_testing
= 0;
699 signal (SIGALRM
, alarm_intr
);
703 try = TEST_BUFFER_BLOCKS
;
704 while (currently_testing
< blocks
)
706 if (currently_testing
+ try > blocks
)
707 try = blocks
- currently_testing
;
708 got
= do_check (blkbuf
, try, currently_testing
);
709 currently_testing
+= got
;
712 try = TEST_BUFFER_BLOCKS
;
717 if (currently_testing
< start_data_block
)
718 die ("bad blocks before data-area: cannot make fs");
720 for (i
= 0; i
< SECTORS_PER_BLOCK
; i
++) /* Mark all of the sectors in the block as bad */
721 mark_sector_bad (currently_testing
* SECTORS_PER_BLOCK
+ i
);
730 printf ("%d bad block%s\n", badblocks
,
731 (badblocks
> 1) ? "s" : "");
736 get_list_blocks (char *filename
)
740 unsigned long blockno
;
742 listfile
= fopen (filename
, "r");
743 if (listfile
== (FILE *) NULL
)
744 die ("Can't open file of bad blocks");
746 while (!feof (listfile
))
748 fscanf (listfile
, "%ld\n", &blockno
);
749 for (i
= 0; i
< SECTORS_PER_BLOCK
; i
++) /* Mark all of the sectors in the block as bad */
750 mark_sector_bad (blockno
* SECTORS_PER_BLOCK
+ i
);
756 printf ("%d bad block%s\n", badblocks
,
757 (badblocks
> 1) ? "s" : "");
762 /* Given a file descriptor and an offset, check whether the offset is a valid offset for the file - return FALSE if it
763 isn't valid or TRUE if it is */
766 valid_offset (int fd
, loff_t offset
)
770 if (llseek (fd
, offset
, SEEK_SET
) < 0)
772 if (read (fd
, &ch
, 1) < 1)
779 /* Given a filename, look to see how many blocks of BLOCK_SIZE are present, returning the answer */
782 count_blocks (char *filename
)
787 BY_HANDLE_FILE_INFORMATION hinfo
;
791 if ((fd
= open(filename
, O_RDONLY
)) < 0) {
796 * This should probably use IOCTL_DISK_GET_LENGTH_INFO here, but
797 * this ioctl is only available in XP and up.
800 if (!DeviceIoControl((HANDLE
)fd
, IOCTL_DISK_GET_DRIVE_GEOMETRY
, NULL
, 0, &geom
, sizeof(geom
), &ret
, NULL
)) {
801 errno
= GetLastError();
802 die("unable to get length for '%s'");
804 len
= geom
.Cylinders
.QuadPart
*geom
.TracksPerCylinder
*geom
.SectorsPerTrack
*BLOCK_SIZE
;
806 if (!GetFileInformationByHandle((HANDLE
)fd
, &hinfo
)) {
807 errno
= GetLastError();
808 die("unable to get length for '%s'");
810 len
= ((loff_t
)hinfo
.nFileSizeHigh
<< 32) | (loff_t
)hinfo
.nFileSizeLow
;
813 return len
/BLOCK_SIZE
;
818 if ((fd
= open (filename
, O_RDONLY
)) < 0)
825 for (high
= 1; valid_offset (fd
, high
); high
*= 2)
827 while (low
< high
- 1)
829 const loff_t mid
= (low
+ high
) / 2;
831 if (valid_offset (fd
, mid
))
836 valid_offset (fd
, 0);
839 return (low
+ 1) / BLOCK_SIZE
;
844 /* Check to see if the specified device is currently mounted - abort if it is */
847 check_mount (char *device_name
)
853 if ((f
= setmntent (MOUNTED
, "r")) == NULL
)
855 while ((mnt
= getmntent (f
)) != NULL
)
856 if (strcmp (device_name
, mnt
->mnt_fsname
) == 0)
857 die ("%s contains a mounted file system.");
863 /* Establish the geometry and media parameters for the device */
866 establish_params (void)
868 DISK_GEOMETRY geometry
;
872 bs
.media
= (char) 0xf8; /* Set up the media descriptor for a hard drive */
873 bs
.dir_entries
[0] = (char) 0;
874 bs
.dir_entries
[1] = (char) 2;
875 /* For FAT32, use 4k clusters on sufficiently large file systems,
876 * otherwise 1 sector per cluster. This is also what M$'s format
877 * command does for FAT32. */
878 bs
.cluster_size
= (char)
880 ((ll_t
)blocks
*SECTORS_PER_BLOCK
>= 512*1024 ? 8 : 1) :
881 4); /* FAT12 and FAT16: start at 4 sectors per cluster */
884 if (!DeviceIoControl((HANDLE
)dev
, IOCTL_DISK_GET_DRIVE_GEOMETRY
, NULL
, 0, &geometry
, sizeof(geometry
), &ret
, NULL
)) {
885 errno
= GetLastError();
886 die ("unable to get geometry for '%s'");
888 bs
.secs_track
= geometry
.SectorsPerTrack
;
889 bs
.heads
= geometry
.TracksPerCylinder
;
890 switch (geometry
.MediaType
) {
892 bs
.media
= (char) 0xf9;
893 bs
.cluster_size
= (char) 2;
894 bs
.dir_entries
[0] = (char) 112;
895 bs
.dir_entries
[1] = (char) 0;
898 bs
.media
= (char) 0xf0;
899 bs
.cluster_size
= (char)(atari_format
? 2 : 1);
900 bs
.dir_entries
[0] = (char) 224;
901 bs
.dir_entries
[1] = (char) 0;
904 bs
.media
= (char) 0xfd;
905 bs
.cluster_size
= (char) 2;
906 bs
.dir_entries
[0] = (char) 112;
907 bs
.dir_entries
[1] = (char) 0;
910 bs
.media
= (char) 0xf8; /* Set up the media descriptor for a hard drive */
911 bs
.dir_entries
[0] = (char) 0;
912 bs
.dir_entries
[1] = (char) 2;
913 /* For FAT32, use 4k clusters on sufficiently large file systems,
914 * otherwise 1 sector per cluster. This is also what M$'s format
915 * command does for FAT32. */
916 bs
.cluster_size
= (char)
918 ((ll_t
)blocks
*SECTORS_PER_BLOCK
>= 512*1024 ? 8 : 1) :
919 4); /* FAT12 and FAT16: start at 4 sectors per cluster */
924 establish_params (int device_num
,int size
)
927 struct hd_geometry geometry
;
928 struct floppy_struct param
;
930 if ((0 == device_num
) || ((device_num
& 0xff00) == 0x0200))
931 /* file image or floppy disk */
935 param
.size
= size
/512;
966 else /* is a floppy diskette */
968 if (ioctl (dev
, FDGETPRM
, ¶m
)) /* Can we get the diskette geometry? */
969 die ("unable to get diskette geometry for '%s'");
971 bs
.secs_track
= CT_LE_W(param
.sect
); /* Set up the geometry information */
972 bs
.heads
= CT_LE_W(param
.head
);
973 switch (param
.size
) /* Set up the media descriptor byte */
975 case 720: /* 5.25", 2, 9, 40 - 360K */
976 bs
.media
= (char) 0xfd;
977 bs
.cluster_size
= (char) 2;
978 bs
.dir_entries
[0] = (char) 112;
979 bs
.dir_entries
[1] = (char) 0;
982 case 1440: /* 3.5", 2, 9, 80 - 720K */
983 bs
.media
= (char) 0xf9;
984 bs
.cluster_size
= (char) 2;
985 bs
.dir_entries
[0] = (char) 112;
986 bs
.dir_entries
[1] = (char) 0;
989 case 2400: /* 5.25", 2, 15, 80 - 1200K */
990 bs
.media
= (char) 0xf9;
991 bs
.cluster_size
= (char)(atari_format
? 2 : 1);
992 bs
.dir_entries
[0] = (char) 224;
993 bs
.dir_entries
[1] = (char) 0;
996 case 5760: /* 3.5", 2, 36, 80 - 2880K */
997 bs
.media
= (char) 0xf0;
998 bs
.cluster_size
= (char) 2;
999 bs
.dir_entries
[0] = (char) 224;
1000 bs
.dir_entries
[1] = (char) 0;
1003 case 2880: /* 3.5", 2, 18, 80 - 1440K */
1005 bs
.media
= (char) 0xf0;
1006 bs
.cluster_size
= (char)(atari_format
? 2 : 1);
1007 bs
.dir_entries
[0] = (char) 224;
1008 bs
.dir_entries
[1] = (char) 0;
1011 default: /* Anything else */
1012 if (0 == device_num
)
1015 goto floppy_default
;
1018 else if ((device_num
& 0xff00) == 0x0700) /* This is a loop device */
1020 /* Can we get the loop geometry? This is in 512 byte blocks, always? */
1021 if (ioctl (dev
, BLKGETSIZE
, &loop_size
))
1022 die ("unable to get loop geometry for '%s'");
1023 loop_size
= loop_size
>> 1;
1025 switch (loop_size
) /* Assuming the loop device -> floppy later */
1027 case 720: /* 5.25", 2, 9, 40 - 360K */
1028 bs
.secs_track
= CF_LE_W(9);
1029 bs
.heads
= CF_LE_W(2);
1030 bs
.media
= (char) 0xfd;
1031 bs
.cluster_size
= (char) 2;
1032 bs
.dir_entries
[0] = (char) 112;
1033 bs
.dir_entries
[1] = (char) 0;
1036 case 1440: /* 3.5", 2, 9, 80 - 720K */
1037 bs
.secs_track
= CF_LE_W(9);
1038 bs
.heads
= CF_LE_W(2);
1039 bs
.media
= (char) 0xf9;
1040 bs
.cluster_size
= (char) 2;
1041 bs
.dir_entries
[0] = (char) 112;
1042 bs
.dir_entries
[1] = (char) 0;
1045 case 2400: /* 5.25", 2, 15, 80 - 1200K */
1046 bs
.secs_track
= CF_LE_W(15);
1047 bs
.heads
= CF_LE_W(2);
1048 bs
.media
= (char) 0xf9;
1049 bs
.cluster_size
= (char)(atari_format
? 2 : 1);
1050 bs
.dir_entries
[0] = (char) 224;
1051 bs
.dir_entries
[1] = (char) 0;
1054 case 5760: /* 3.5", 2, 36, 80 - 2880K */
1055 bs
.secs_track
= CF_LE_W(36);
1056 bs
.heads
= CF_LE_W(2);
1057 bs
.media
= (char) 0xf0;
1058 bs
.cluster_size
= (char) 2;
1059 bs
.dir_entries
[0] = (char) 224;
1060 bs
.dir_entries
[1] = (char) 0;
1063 case 2880: /* 3.5", 2, 18, 80 - 1440K */
1064 bs
.secs_track
= CF_LE_W(18);
1065 bs
.heads
= CF_LE_W(2);
1066 bs
.media
= (char) 0xf0;
1067 bs
.cluster_size
= (char)(atari_format
? 2 : 1);
1068 bs
.dir_entries
[0] = (char) 224;
1069 bs
.dir_entries
[1] = (char) 0;
1072 default: /* Anything else: default hd setup */
1073 printf("Loop device does not match a floppy size, using "
1074 "default hd params\n");
1075 bs
.secs_track
= CT_LE_W(32); /* these are fake values... */
1076 bs
.heads
= CT_LE_W(64);
1081 /* Must be a hard disk then! */
1083 /* Can we get the drive geometry? (Note I'm not too sure about */
1084 /* whether to use HDIO_GETGEO or HDIO_REQ) */
1085 if (ioctl (dev
, HDIO_GETGEO
, &geometry
))
1086 die ("unable to get drive geometry for '%s'");
1087 bs
.secs_track
= CT_LE_W(geometry
.sectors
); /* Set up the geometry information */
1088 bs
.heads
= CT_LE_W(geometry
.heads
);
1090 bs
.media
= (char) 0xf8; /* Set up the media descriptor for a hard drive */
1091 bs
.dir_entries
[0] = (char) 0; /* Default to 512 entries */
1092 bs
.dir_entries
[1] = (char) 2;
1093 /* For FAT32, use 4k clusters on sufficiently large file systems,
1094 * otherwise 1 sector per cluster. This is also what M$'s format
1095 * command does for FAT32. */
1096 bs
.cluster_size
= (char)
1098 ((ll_t
)blocks
*SECTORS_PER_BLOCK
>= 512*1024 ? 8 : 1) :
1099 4); /* FAT12 and FAT16: start at 4 sectors per cluster */
1105 /* Create the filesystem data tables */
1110 unsigned num_sectors
;
1111 unsigned cluster_count
= 0, fat_length
;
1112 unsigned fatdata
; /* Sectors for FATs + data area */
1114 struct msdos_volume_info
*vi
= (size_fat
== 32 ? &bs
.fat32
.vi
: &bs
.oldfat
.vi
);
1117 /* On Atari, the first few bytes of the boot sector are assigned
1118 * differently: The jump code is only 2 bytes (and m68k machine code
1119 * :-), then 6 bytes filler (ignored), then 3 byte serial number. */
1120 strncpy( bs
.system_id
-1, "mkdosf", 6 );
1122 strcpy (bs
.system_id
, "mkdosfs");
1123 if (sectors_per_cluster
)
1124 bs
.cluster_size
= (char) sectors_per_cluster
;
1127 /* Under FAT32, the root dir is in a cluster chain, and this is
1128 * signalled by bs.dir_entries being 0. */
1129 bs
.dir_entries
[0] = bs
.dir_entries
[1] = (char) 0;
1130 root_dir_entries
= 0;
1132 else if (root_dir_entries
)
1134 /* Override default from establish_params() */
1135 bs
.dir_entries
[0] = (char) (root_dir_entries
& 0x00ff);
1136 bs
.dir_entries
[1] = (char) ((root_dir_entries
& 0xff00) >> 8);
1139 root_dir_entries
= bs
.dir_entries
[0] + (bs
.dir_entries
[1] << 8);
1142 bs
.system_id
[5] = (unsigned char) (volume_id
& 0x000000ff);
1143 bs
.system_id
[6] = (unsigned char) ((volume_id
& 0x0000ff00) >> 8);
1144 bs
.system_id
[7] = (unsigned char) ((volume_id
& 0x00ff0000) >> 16);
1147 vi
->volume_id
[0] = (unsigned char) (volume_id
& 0x000000ff);
1148 vi
->volume_id
[1] = (unsigned char) ((volume_id
& 0x0000ff00) >> 8);
1149 vi
->volume_id
[2] = (unsigned char) ((volume_id
& 0x00ff0000) >> 16);
1150 vi
->volume_id
[3] = (unsigned char) (volume_id
>> 24);
1153 if (!atari_format
) {
1154 memcpy(vi
->volume_label
, volume_name
, 11);
1156 memcpy(bs
.boot_jump
, dummy_boot_jump
, 3);
1157 /* Patch in the correct offset to the boot code */
1158 bs
.boot_jump
[1] = ((size_fat
== 32 ?
1159 (char *)&bs
.fat32
.boot_code
:
1160 (char *)&bs
.oldfat
.boot_code
) -
1163 if (size_fat
== 32) {
1164 if (dummy_boot_code
[BOOTCODE_FAT32_SIZE
-1])
1165 printf ("Warning: message too long; truncated\n");
1166 dummy_boot_code
[BOOTCODE_FAT32_SIZE
-1] = 0;
1167 memcpy(bs
.fat32
.boot_code
, dummy_boot_code
, BOOTCODE_FAT32_SIZE
);
1170 memcpy(bs
.oldfat
.boot_code
, dummy_boot_code
, BOOTCODE_SIZE
);
1172 bs
.boot_sign
= CT_LE_W(BOOT_SIGN
);
1175 memcpy(bs
.boot_jump
, dummy_boot_jump_m68k
, 2);
1178 printf( "Boot jump code is %02x %02x\n",
1179 bs
.boot_jump
[0], bs
.boot_jump
[1] );
1181 if (!reserved_sectors
)
1182 reserved_sectors
= (size_fat
== 32) ? 32 : 1;
1184 if (size_fat
== 32 && reserved_sectors
< 2)
1185 die("On FAT32 at least 2 reserved sectors are needed.");
1187 bs
.reserved
= CT_LE_W(reserved_sectors
);
1189 printf( "Using %d reserved sectors\n", reserved_sectors
);
1190 bs
.fats
= (char) nr_fats
;
1191 if (!atari_format
|| size_fat
== 32)
1192 bs
.hidden
= CT_LE_L(0);
1194 /* In Atari format, hidden is a 16 bit field */
1195 memset( &bs
.hidden
, 0, 2 );
1197 num_sectors
= (ll_t
)blocks
*BLOCK_SIZE
/sector_size
;
1198 if (!atari_format
) {
1199 unsigned fatlength12
, fatlength16
, fatlength32
;
1200 unsigned maxclust12
, maxclust16
, maxclust32
;
1201 unsigned clust12
, clust16
, clust32
;
1204 fatdata
= num_sectors
- cdiv (root_dir_entries
* 32, sector_size
) -
1207 if (sectors_per_cluster
)
1208 bs
.cluster_size
= maxclustsize
= sectors_per_cluster
;
1210 /* An initial guess for bs.cluster_size should already be set */
1214 printf( "%d sectors for FAT+data, starting with %d sectors/cluster\n",
1215 fatdata
, bs
.cluster_size
);
1218 printf( "Trying with %d sectors/cluster:\n", bs
.cluster_size
);
1220 /* The factor 2 below avoids cut-off errors for nr_fats == 1.
1221 * The "nr_fats*3" is for the reserved first two FAT entries */
1222 clust12
= 2*((ll_t
) fatdata
*sector_size
+ nr_fats
*3) /
1223 (2*(int) bs
.cluster_size
* sector_size
+ nr_fats
*3);
1224 fatlength12
= cdiv (((clust12
+2) * 3 + 1) >> 1, sector_size
);
1225 /* Need to recalculate number of clusters, since the unused parts of the
1226 * FATS and data area together could make up space for an additional,
1227 * not really present cluster. */
1228 clust12
= (fatdata
- nr_fats
*fatlength12
)/bs
.cluster_size
;
1229 maxclust12
= (fatlength12
* 2 * sector_size
) / 3;
1230 if (maxclust12
> MAX_CLUST_12
)
1231 maxclust12
= MAX_CLUST_12
;
1233 printf( "FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
1234 clust12
, fatlength12
, maxclust12
, MAX_CLUST_12
);
1235 if (clust12
> maxclust12
-2) {
1238 printf( "FAT12: too much clusters\n" );
1241 clust16
= ((ll_t
) fatdata
*sector_size
+ nr_fats
*4) /
1242 ((int) bs
.cluster_size
* sector_size
+ nr_fats
*2);
1243 fatlength16
= cdiv ((clust16
+2) * 2, sector_size
);
1244 /* Need to recalculate number of clusters, since the unused parts of the
1245 * FATS and data area together could make up space for an additional,
1246 * not really present cluster. */
1247 clust16
= (fatdata
- nr_fats
*fatlength16
)/bs
.cluster_size
;
1248 maxclust16
= (fatlength16
* sector_size
) / 2;
1249 if (maxclust16
> MAX_CLUST_16
)
1250 maxclust16
= MAX_CLUST_16
;
1252 printf( "FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
1253 clust16
, fatlength16
, maxclust16
, MAX_CLUST_16
);
1254 if (clust16
> maxclust16
-2) {
1256 printf( "FAT16: too much clusters\n" );
1259 /* The < 4078 avoids that the filesystem will be misdetected as having a
1261 if (clust16
< FAT12_THRESHOLD
&& !(size_fat_by_user
&& size_fat
== 16)) {
1263 printf( clust16
< FAT12_THRESHOLD
?
1264 "FAT16: would be misdetected as FAT12\n" :
1265 "FAT16: too much clusters\n" );
1269 clust32
= ((ll_t
) fatdata
*sector_size
+ nr_fats
*8) /
1270 ((int) bs
.cluster_size
* sector_size
+ nr_fats
*4);
1271 fatlength32
= cdiv ((clust32
+2) * 4, sector_size
);
1272 /* Need to recalculate number of clusters, since the unused parts of the
1273 * FATS and data area together could make up space for an additional,
1274 * not really present cluster. */
1275 clust32
= (fatdata
- nr_fats
*fatlength32
)/bs
.cluster_size
;
1276 maxclust32
= (fatlength32
* sector_size
) / 4;
1277 if (maxclust32
> MAX_CLUST_32
)
1278 maxclust32
= MAX_CLUST_32
;
1280 printf( "FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
1281 clust32
, fatlength32
, maxclust32
, MAX_CLUST_32
);
1282 if (clust32
> maxclust32
) {
1285 printf( "FAT32: too much clusters\n" );
1288 if ((clust12
&& (size_fat
== 0 || size_fat
== 12)) ||
1289 (clust16
&& (size_fat
== 0 || size_fat
== 16)) ||
1290 (clust32
&& size_fat
== 32))
1293 bs
.cluster_size
<<= 1;
1294 } while (bs
.cluster_size
&& bs
.cluster_size
<= maxclustsize
);
1296 /* Use the optimal FAT size if not specified;
1297 * FAT32 is (not yet) choosen automatically */
1299 size_fat
= (clust16
> clust12
) ? 16 : 12;
1301 printf( "Choosing %d bits for FAT\n", size_fat
);
1306 cluster_count
= clust12
;
1307 fat_length
= fatlength12
;
1308 bs
.fat_length
= CT_LE_W(fatlength12
);
1309 memcpy(vi
->fs_type
, MSDOS_FAT12_SIGN
, 8);
1313 if (clust16
< FAT12_THRESHOLD
) {
1314 if (size_fat_by_user
) {
1315 fprintf( stderr
, "WARNING: Not enough clusters for a "
1316 "16 bit FAT! The filesystem will be\n"
1317 "misinterpreted as having a 12 bit FAT without "
1318 "mount option \"fat=16\".\n" );
1321 fprintf( stderr
, "This filesystem has an unfortunate size. "
1322 "A 12 bit FAT cannot provide\n"
1323 "enough clusters, but a 16 bit FAT takes up a little "
1324 "bit more space so that\n"
1325 "the total number of clusters becomes less than the "
1326 "threshold value for\n"
1327 "distinction between 12 and 16 bit FATs.\n" );
1328 die( "Make the file system a bit smaller manually." );
1331 cluster_count
= clust16
;
1332 fat_length
= fatlength16
;
1333 bs
.fat_length
= CT_LE_W(fatlength16
);
1334 memcpy(vi
->fs_type
, MSDOS_FAT16_SIGN
, 8);
1338 cluster_count
= clust32
;
1339 fat_length
= fatlength32
;
1340 bs
.fat_length
= CT_LE_W(0);
1341 bs
.fat32
.fat32_length
= CT_LE_L(fatlength32
);
1342 memcpy(vi
->fs_type
, MSDOS_FAT32_SIGN
, 8);
1346 die("FAT not 12, 16 or 32 bits");
1350 unsigned clusters
, maxclust
;
1352 /* GEMDOS always uses a 12 bit FAT on floppies, and always a 16 bit FAT on
1353 * hard disks. So use 12 bit if the size of the file system suggests that
1354 * this fs is for a floppy disk, if the user hasn't explicitly requested a
1358 size_fat
= (num_sectors
== 1440 || num_sectors
== 2400 ||
1359 num_sectors
== 2880 || num_sectors
== 5760) ? 12 : 16;
1361 printf( "Choosing %d bits for FAT\n", size_fat
);
1363 /* Atari format: cluster size should be 2, except explicitly requested by
1364 * the user, since GEMDOS doesn't like other cluster sizes very much.
1365 * Instead, tune the sector size for the FS to fit.
1367 bs
.cluster_size
= sectors_per_cluster
? sectors_per_cluster
: 2;
1368 if (!sector_size_set
) {
1369 while( num_sectors
> GEMDOS_MAX_SECTORS
) {
1375 printf( "Sector size must be %d to have less than %d log. sectors\n",
1376 sector_size
, GEMDOS_MAX_SECTORS
);
1378 /* Check if there are enough FAT indices for how much clusters we have */
1380 fatdata
= num_sectors
- cdiv (root_dir_entries
* 32, sector_size
) -
1382 /* The factor 2 below avoids cut-off errors for nr_fats == 1 and
1384 * The "2*nr_fats*size_fat/8" is for the reserved first two FAT entries
1386 clusters
= (2*((ll_t
)fatdata
*sector_size
- 2*nr_fats
*size_fat
/8)) /
1387 (2*((int)bs
.cluster_size
*sector_size
+ nr_fats
*size_fat
/8));
1388 fat_length
= cdiv( (clusters
+2)*size_fat
/8, sector_size
);
1389 /* Need to recalculate number of clusters, since the unused parts of the
1390 * FATS and data area together could make up space for an additional,
1391 * not really present cluster. */
1392 clusters
= (fatdata
- nr_fats
*fat_length
)/bs
.cluster_size
;
1393 maxclust
= (fat_length
*sector_size
*8)/size_fat
;
1395 printf( "ss=%d: #clu=%d, fat_len=%d, maxclu=%d\n",
1396 sector_size
, clusters
, fat_length
, maxclust
);
1398 /* last 10 cluster numbers are special (except FAT32: 4 high bits rsvd);
1399 * first two numbers are reserved */
1400 if (maxclust
<= (size_fat
== 32 ? MAX_CLUST_32
: (1<<size_fat
)-0x10) &&
1401 clusters
<= maxclust
-2)
1404 printf( clusters
> maxclust
-2 ?
1405 "Too many clusters\n" : "FAT too big\n" );
1407 /* need to increment sector_size once more to */
1408 if (sector_size_set
)
1409 die( "With this sector size, the maximum number of FAT entries "
1410 "would be exceeded." );
1413 } while( sector_size
<= GEMDOS_MAX_SECTOR_SIZE
);
1415 if (sector_size
> GEMDOS_MAX_SECTOR_SIZE
)
1416 die( "Would need a sector size > 16k, which GEMDOS can't work with");
1418 cluster_count
= clusters
;
1420 bs
.fat_length
= CT_LE_W(fat_length
);
1423 bs
.fat32
.fat32_length
= CT_LE_L(fat_length
);
1427 bs
.sector_size
[0] = (char) (sector_size
& 0x00ff);
1428 bs
.sector_size
[1] = (char) ((sector_size
& 0xff00) >> 8);
1432 /* set up additional FAT32 fields */
1433 bs
.fat32
.flags
= CT_LE_W(0);
1434 bs
.fat32
.version
[0] = 0;
1435 bs
.fat32
.version
[1] = 0;
1436 bs
.fat32
.root_cluster
= CT_LE_L(2);
1437 bs
.fat32
.info_sector
= CT_LE_W(1);
1439 backup_boot
= (reserved_sectors
>= 7) ? 6 :
1440 (reserved_sectors
>= 2) ? reserved_sectors
-1 : 0;
1443 if (backup_boot
== 1)
1444 die("Backup boot sector must be after sector 1");
1445 else if (backup_boot
>= reserved_sectors
)
1446 die("Backup boot sector must be a reserved sector");
1449 printf( "Using sector %d as backup boot sector (0 = none)\n",
1451 bs
.fat32
.backup_boot
= CT_LE_W(backup_boot
);
1452 memset( &bs
.fat32
.reserved2
, 0, sizeof(bs
.fat32
.reserved2
) );
1456 /* Just some consistency checks */
1457 if (num_sectors
>= GEMDOS_MAX_SECTORS
)
1458 die( "GEMDOS can't handle more than 65531 sectors" );
1459 else if (num_sectors
>= OLDGEMDOS_MAX_SECTORS
)
1460 printf( "Warning: More than 32765 sector need TOS 1.04 "
1463 if (num_sectors
>= 65536)
1465 bs
.sectors
[0] = (char) 0;
1466 bs
.sectors
[1] = (char) 0;
1467 bs
.total_sect
= CT_LE_L(num_sectors
);
1471 bs
.sectors
[0] = (char) (num_sectors
& 0x00ff);
1472 bs
.sectors
[1] = (char) ((num_sectors
& 0xff00) >> 8);
1474 bs
.total_sect
= CT_LE_L(0);
1478 vi
->ext_boot_sign
= MSDOS_EXT_SIGN
;
1482 if (sectors_per_cluster
) /* If yes, die if we'd spec'd sectors per cluster */
1483 die ("Too many clusters for file system - try more sectors per cluster");
1485 die ("Attempting to create a too large file system");
1489 /* The two following vars are in hard sectors, i.e. 512 byte sectors! */
1490 start_data_sector
= (reserved_sectors
+ nr_fats
* fat_length
) *
1491 (sector_size
/HARD_SECTOR_SIZE
);
1492 start_data_block
= (start_data_sector
+ SECTORS_PER_BLOCK
- 1) /
1495 if (blocks
< start_data_block
+ 32) /* Arbitrary undersize file system! */
1496 die ("Too few blocks for viable file system");
1500 printf("%s has %d head%s and %d sector%s per track,\n",
1501 device_name
, CF_LE_W(bs
.heads
), (CF_LE_W(bs
.heads
) != 1) ? "s" : "",
1502 CF_LE_W(bs
.secs_track
), (CF_LE_W(bs
.secs_track
) != 1) ? "s" : "");
1503 printf("logical sector size is %d,\n",sector_size
);
1504 printf("using 0x%02x media descriptor, with %d sectors;\n",
1505 (int) (bs
.media
), num_sectors
);
1506 printf("file system has %d %d-bit FAT%s and %d sector%s per cluster.\n",
1507 (int) (bs
.fats
), size_fat
, (bs
.fats
!= 1) ? "s" : "",
1508 (int) (bs
.cluster_size
), (bs
.cluster_size
!= 1) ? "s" : "");
1509 printf ("FAT size is %d sector%s, and provides %d cluster%s.\n",
1510 fat_length
, (fat_length
!= 1) ? "s" : "",
1511 cluster_count
, (cluster_count
!= 1) ? "s" : "");
1513 printf ("Root directory contains %d slots.\n",
1514 (int) (bs
.dir_entries
[0]) + (int) (bs
.dir_entries
[1]) * 256);
1515 printf ("Volume ID is %08lx, ", volume_id
&
1516 (atari_format
? 0x00ffffff : 0xffffffff));
1517 if ( strcmp(volume_name
, " ") )
1518 printf("volume label %s.\n", volume_name
);
1520 printf("no volume label.\n");
1523 /* Make the file allocation tables! */
1525 if ((fat
= (unsigned char *) malloc (fat_length
* sector_size
)) == NULL
)
1526 die ("unable to allocate space for FAT image in memory");
1528 memset( fat
, 0, fat_length
* sector_size
);
1530 mark_FAT_cluster (0, 0xffffffff); /* Initial fat entries */
1531 mark_FAT_cluster (1, 0xffffffff);
1532 fat
[0] = (unsigned char) bs
.media
; /* Put media type in first byte! */
1533 if (size_fat
== 32) {
1534 /* Mark cluster 2 as EOF (used for root dir) */
1535 mark_FAT_cluster (2, FAT_EOF
);
1538 /* Make the root directory entries */
1540 size_root_dir
= (size_fat
== 32) ?
1541 bs
.cluster_size
*sector_size
:
1542 (((int)bs
.dir_entries
[1]*256+(int)bs
.dir_entries
[0]) *
1543 sizeof (struct msdos_dir_entry
));
1544 if ((root_dir
= (struct msdos_dir_entry
*) malloc (size_root_dir
)) == NULL
)
1546 free (fat
); /* Tidy up before we die! */
1547 die ("unable to allocate space for root directory in memory");
1550 memset(root_dir
, 0, size_root_dir
);
1551 if ( memcmp(volume_name
, " ", 11) )
1553 struct msdos_dir_entry
*de
= &root_dir
[0];
1554 memcpy(de
->name
, volume_name
, 11);
1555 de
->attr
= ATTR_VOLUME
;
1556 ctime
= localtime(&create_time
);
1557 de
->time
= CT_LE_W((unsigned short)((ctime
->tm_sec
>> 1) +
1558 (ctime
->tm_min
<< 5) + (ctime
->tm_hour
<< 11)));
1559 de
->date
= CT_LE_W((unsigned short)(ctime
->tm_mday
+
1560 ((ctime
->tm_mon
+1) << 5) +
1561 ((ctime
->tm_year
-80) << 9)));
1563 de
->ctime
= de
->time
;
1564 de
->cdate
= de
->date
;
1565 de
->adate
= de
->date
;
1566 de
->starthi
= CT_LE_W(0);
1567 de
->start
= CT_LE_W(0);
1568 de
->size
= CT_LE_L(0);
1571 if (size_fat
== 32) {
1572 /* For FAT32, create an info sector */
1573 struct fat32_fsinfo
*info
;
1575 if (!(info_sector
= malloc( sector_size
)))
1576 die("Out of memory");
1577 memset(info_sector
, 0, sector_size
);
1578 /* fsinfo structure is at offset 0x1e0 in info sector by observation */
1579 info
= (struct fat32_fsinfo
*)(info_sector
+ 0x1e0);
1581 /* Info sector magic */
1582 info_sector
[0] = 'R';
1583 info_sector
[1] = 'R';
1584 info_sector
[2] = 'a';
1585 info_sector
[3] = 'A';
1587 /* Magic for fsinfo structure */
1588 info
->signature
= CT_LE_L(0x61417272);
1589 /* We've allocated cluster 2 for the root dir. */
1590 info
->free_clusters
= CT_LE_L(cluster_count
- 1);
1591 info
->next_cluster
= CT_LE_L(2);
1593 /* Info sector also must have boot sign */
1594 *(__u16
*)(info_sector
+ 0x1fe) = CT_LE_W(BOOT_SIGN
);
1597 if (!(blank_sector
= malloc( sector_size
)))
1598 die( "Out of memory" );
1599 memset(blank_sector
, 0, sector_size
);
1603 /* Write the new filesystem's data tables to wherever they're going to end up! */
1605 #define error(str) \
1608 if (info_sector) free (info_sector); \
1613 #define seekto(pos,errstr) \
1615 loff_t __pos = (pos); \
1616 if (llseek (dev, __pos, SEEK_SET) != __pos) \
1617 error ("seek to " errstr " failed whilst writing tables"); \
1620 #define writebuf(buf,size,errstr) \
1622 int __size = (size); \
1623 if (write (dev, buf, __size) != __size) \
1624 error ("failed whilst writing " errstr); \
1637 fat_length
= (size_fat
== 32) ?
1638 CF_LE_L(bs
.fat32
.fat32_length
) : CF_LE_W(bs
.fat_length
);
1640 seekto( 0, "start of device" );
1641 /* clear all reserved sectors */
1642 for( x
= 0; x
< reserved_sectors
; ++x
)
1643 writebuf( blank_sector
, sector_size
, "reserved sector" );
1644 /* seek back to sector 0 and write the boot sector */
1645 seekto( 0, "boot sector" );
1646 writebuf( (char *) &bs
, sizeof (struct msdos_boot_sector
), "boot sector" );
1647 /* on FAT32, write the info sector and backup boot sector */
1650 seekto( CF_LE_W(bs
.fat32
.info_sector
)*sector_size
, "info sector" );
1651 writebuf( info_sector
, 512, "info sector" );
1652 if (backup_boot
!= 0)
1654 seekto( backup_boot
*sector_size
, "backup boot sector" );
1655 writebuf( (char *) &bs
, sizeof (struct msdos_boot_sector
),
1656 "backup boot sector" );
1659 /* seek to start of FATS and write them all */
1660 seekto( reserved_sectors
*sector_size
, "first FAT" );
1661 for (x
= 1; x
<= nr_fats
; x
++)
1664 * WIN32 appearently has problems writing very large chunks directly
1665 * to disk devices. To not produce errors because of resource shortages
1666 * split up the write in sector size chunks.
1668 for (blk
= 0; blk
< fat_length
; blk
++)
1669 writebuf(fat
+blk
*sector_size
, sector_size
, "FAT");
1671 writebuf( fat
, fat_length
* sector_size
, "FAT" );
1673 /* Write the root directory directly after the last FAT. This is the root
1674 * dir area on FAT12/16, and the first cluster on FAT32. */
1675 writebuf( (char *) root_dir
, size_root_dir
, "root directory" );
1677 if (info_sector
) free( info_sector
);
1678 free (root_dir
); /* Free up the root directory space from setup_tables */
1679 free (fat
); /* Free up the fat table space reserved during setup_tables */
1683 /* Report the command usage and return a failure error code */
1689 Usage: mkdosfs [-A] [-c] [-C] [-v] [-I] [-l bad-block-file] [-b backup-boot-sector]\n\
1690 [-m boot-msg-file] [-n volume-name] [-i volume-id]\n\
1691 [-s sectors-per-cluster] [-S logical-sector-size] [-f number-of-FATs]\n\
1692 [-F fat-size] [-r root-dir-entries] [-R reserved-sectors]\n\
1693 /dev/name [blocks]\n");
1697 * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
1698 * of MS-DOS filesystem by default.
1700 static void check_atari( void )
1706 if (!(f
= fopen( "/proc/hardware", "r" ))) {
1707 perror( "/proc/hardware" );
1711 while( fgets( line
, sizeof(line
), f
) ) {
1712 if (strncmp( line
, "Model:", 6 ) == 0) {
1714 p
+= strspn( p
, " \t" );
1715 if (strncmp( p
, "Atari ", 6 ) == 0)
1724 /* The "main" entry point into the utility - we pick up the options and attempt to process them in some sort of sensible
1725 way. In the event that some/all of the options are invalid we need to tell the user so that something can be done! */
1728 main (int argc
, char **argv
)
1732 char *listfile
= NULL
;
1735 static char dev_buf
[] = "\\\\.\\X:";
1737 struct stat statbuf
;
1742 if (argc
&& *argv
) { /* What's the program name? */
1744 program_name
= *argv
;
1746 if ((p
= strrchr( program_name
, '\\' )))
1748 if ((p
= strrchr( program_name
, '/' )))
1754 volume_id
= (long)create_time
; /* Default volume ID = creation time */
1757 printf ("%s " VERSION
" (" VERSION_DATE
")\n"
1759 "Win32 port by Jens-Uwe Mager <jum@anubis.han.de>\n"
1763 while ((c
= getopt (argc
, argv
, "AcCf:F:Ii:l:m:n:r:R:s:S:v")) != EOF
)
1764 /* Scan the command line for options */
1767 case 'A': /* toggle Atari format */
1768 atari_format
= !atari_format
;
1771 case 'b': /* b : location of backup boot sector */
1772 backup_boot
= (int) strtol (optarg
, &tmp
, 0);
1773 if (*tmp
|| backup_boot
< 2 || backup_boot
> 0xffff)
1775 printf ("Bad location for backup boot sector : %s\n", optarg
);
1780 case 'c': /* c : Check FS as we build it */
1784 case 'C': /* C : Create a new file */
1788 case 'f': /* f : Choose number of FATs */
1789 nr_fats
= (int) strtol (optarg
, &tmp
, 0);
1790 if (*tmp
|| nr_fats
< 1 || nr_fats
> 4)
1792 printf ("Bad number of FATs : %s\n", optarg
);
1797 case 'F': /* F : Choose FAT size */
1798 size_fat
= (int) strtol (optarg
, &tmp
, 0);
1799 if (*tmp
|| (size_fat
!= 12 && size_fat
!= 16 && size_fat
!= 32))
1801 printf ("Bad FAT type : %s\n", optarg
);
1804 size_fat_by_user
= 1;
1808 ignore_full_disk
= 1;
1811 case 'i': /* i : specify volume ID */
1812 volume_id
= strtol(optarg
, &tmp
, 16);
1815 printf("Volume ID must be a hexadecimal number\n");
1820 case 'l': /* l : Bad block filename */
1824 case 'm': /* m : Set boot message */
1825 if ( strcmp(optarg
, "-") )
1827 msgfile
= fopen(optarg
, "r");
1836 /* The boot code ends at offset 448 and needs a null terminator */
1838 pos
= 0; /* We are at beginning of line */
1844 case '\r': /* Ignore CRs */
1845 case '\0': /* and nulls */
1848 case '\n': /* LF -> CR+LF if necessary */
1849 if ( pos
) /* If not at beginning of line */
1851 dummy_boot_code
[i
++] = '\r';
1854 dummy_boot_code
[i
++] = '\n';
1857 case '\t': /* Expand tabs */
1860 dummy_boot_code
[i
++] = ' ';
1863 while ( pos
% 8 && i
< BOOTCODE_SIZE
-1 );
1867 dummy_boot_code
[i
++] = '\0'; /* Null terminator */
1871 dummy_boot_code
[i
++] = ch
; /* Store character */
1872 pos
++; /* Advance position */
1876 while ( ch
!= EOF
&& i
< BOOTCODE_SIZE
-1 );
1878 /* Fill up with zeros */
1879 while( i
< BOOTCODE_SIZE
-1 )
1880 dummy_boot_code
[i
++] = '\0';
1881 dummy_boot_code
[BOOTCODE_SIZE
-1] = '\0'; /* Just in case */
1884 printf ("Warning: message too long; truncated\n");
1886 if ( msgfile
!= stdin
)
1891 case 'n': /* n : Volume name */
1892 sprintf(volume_name
, "%-11.11s", optarg
);
1895 case 'r': /* r : Root directory entries */
1896 root_dir_entries
= (int) strtol (optarg
, &tmp
, 0);
1897 if (*tmp
|| root_dir_entries
< 16 || root_dir_entries
> 32768)
1899 printf ("Bad number of root directory entries : %s\n", optarg
);
1904 case 'R': /* R : number of reserved sectors */
1905 reserved_sectors
= (int) strtol (optarg
, &tmp
, 0);
1906 if (*tmp
|| reserved_sectors
< 1 || reserved_sectors
> 0xffff)
1908 printf ("Bad number of reserved sectors : %s\n", optarg
);
1913 case 's': /* s : Sectors per cluster */
1914 sectors_per_cluster
= (int) strtol (optarg
, &tmp
, 0);
1915 if (*tmp
|| (sectors_per_cluster
!= 1 && sectors_per_cluster
!= 2
1916 && sectors_per_cluster
!= 4 && sectors_per_cluster
!= 8
1917 && sectors_per_cluster
!= 16 && sectors_per_cluster
!= 32
1918 && sectors_per_cluster
!= 64 && sectors_per_cluster
!= 128))
1920 printf ("Bad number of sectors per cluster : %s\n", optarg
);
1925 case 'S': /* S : Sector size */
1926 sector_size
= (int) strtol (optarg
, &tmp
, 0);
1927 if (*tmp
|| (sector_size
!= 512 && sector_size
!= 1024 &&
1928 sector_size
!= 2048 && sector_size
!= 4096 &&
1929 sector_size
!= 8192 && sector_size
!= 16384 &&
1930 sector_size
!= 32768))
1932 printf ("Bad logical sector size : %s\n", optarg
);
1935 sector_size_set
= 1;
1938 case 'v': /* v : Verbose execution */
1943 printf( "Unknown option: %c\n", c
);
1949 device_name
= argv
[optind
]; /* Determine the number of blocks in the FS */
1951 if (device_name
[1] == ':' && device_name
[2] == '\0') {
1952 dev_buf
[4] = device_name
[0];
1953 device_name
= dev_buf
;
1958 i
= count_blocks (device_name
); /* Have a look and see! */
1959 if (optind
== argc
- 2) /* Either check the user specified number */
1961 blocks
= (int) strtol (argv
[optind
+ 1], &tmp
, 0);
1962 if (!create
&& blocks
!= i
)
1964 fprintf (stderr
, "Warning: block count mismatch: ");
1965 fprintf (stderr
, "found %d but assuming %d.\n",i
,blocks
);
1968 else if (optind
== argc
- 1) /* Or use value found */
1971 die( "Need intended size with -C." );
1979 printf ("Bad block count : %s\n", argv
[optind
+ 1]);
1983 if (check
&& listfile
) /* Auto and specified bad block handling are mutually */
1984 die ("-c and -l are incompatible"); /* exclusive of each other! */
1987 check_mount (device_name
); /* Is the device already mounted? */
1988 dev
= open (device_name
, O_RDWR
|O_SHARED
); /* Is it a suitable device to build the FS on? */
1990 die ("unable to open %s");
1993 if (fsctl(dev
, FSCTL_LOCK_VOLUME
) == -1)
1994 die("unable to lock %s");
1999 loff_t offset
= blocks
*BLOCK_SIZE
- 1;
2001 /* create the file */
2002 dev
= open( device_name
, O_RDWR
|O_CREAT
|O_TRUNC
, 0775 );
2004 die("unable to create %s");
2005 /* seek to the intended end-1, and write one byte. this creates a
2006 * sparse-as-possible file of appropriate size. */
2007 if (llseek( dev
, offset
, SEEK_SET
) != offset
)
2008 die( "seek failed" );
2009 if (write( dev
, &null
, 1 ) < 0)
2010 die( "write failed" );
2011 if (llseek( dev
, 0, SEEK_SET
) != 0)
2012 die( "seek failed" );
2020 if (fstat (dev
, &statbuf
) < 0)
2021 die ("unable to stat %s");
2022 if (!S_ISBLK (statbuf
.st_mode
)) {
2023 statbuf
.st_rdev
= 0;
2028 * Ignore any 'full' fixed disk devices, if -I is not given.
2029 * On a MO-disk one doesn't need partitions. The filesytem can go
2030 * directly to the whole disk. Under other OSes this is known as
2031 * the 'superfloppy' format. As I don't know how to find out if
2032 * this is a MO disk I introduce a -I (ignore) switch. -Joey
2034 if (!ignore_full_disk
&& (
2035 (statbuf
.st_rdev
& 0xff3f) == 0x0300 || /* hda, hdb */
2036 (statbuf
.st_rdev
& 0xff0f) == 0x0800 || /* sd */
2037 (statbuf
.st_rdev
& 0xff3f) == 0x0d00 || /* xd */
2038 (statbuf
.st_rdev
& 0xff3f) == 0x1600 ) /* hdc, hdd */
2040 die ("Will not try to make filesystem on '%s'");
2042 establish_params (statbuf
.st_rdev
,statbuf
.st_size
);
2043 /* Establish the media parameters */
2046 setup_tables (); /* Establish the file system tables */
2048 if (check
) /* Determine any bad block locations and mark them */
2051 get_list_blocks (listfile
);
2053 write_tables (); /* Write the file system tables away! */
2057 if (fsctl(dev
, FSCTL_DISMOUNT_VOLUME
) == -1)
2058 die("unable to dismount %s");
2059 if (fsctl(dev
, FSCTL_UNLOCK_VOLUME
) == -1)
2060 die("unable to unlock %s");
2063 exit (0); /* Terminate with no errors! */
2067 /* That's All Folks */
2068 /* Local Variables: */