- Start rosapps rearrange and cleanup process.
[reactos.git] / rosapps / applications / sysutils / mkdosfs / mkdosfs.c
1 /*
2 Filename: mkdosfs.c
3 Version: 0.3b (Yggdrasil)
4 Author: Dave Hudson
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)
9
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.
13
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.
20
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
26 - FAT32 support
27
28 Port to work under Windows NT/2K/XP Dec 2002 by
29 Jens-Uwe Mager <jum@anubis.han.de>
30
31 Copying: Copyright 1993, 1994 David Hudson (dave@humbug.demon.co.uk)
32
33 Portions copyright 1992, 1993 Remy Card (card@masi.ibp.fr)
34 and 1991 Linus Torvalds (torvalds@klaava.helsinki.fi)
35
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)
39 any later version.
40
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.
45
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. */
49
50
51 /* Include the header files */
52
53 #include "../version.h"
54
55 #ifdef _WIN32
56 #define _WIN32_WINNT 0x0400
57 #include <windows.h>
58 #include <winioctl.h>
59 #define __LITTLE_ENDIAN 1234
60 #define __BIG_ENDIAN 4321
61 #define __BYTE_ORDER __LITTLE_ENDIAN
62 #define inline
63 #define __attribute__(x)
64 #define BLOCK_SIZE 512
65 #else
66 #include <linux/hdreg.h>
67 #include <linux/fs.h>
68 #include <linux/fd.h>
69 #include <endian.h>
70 #include <mntent.h>
71 #include <signal.h>
72 #include <sys/ioctl.h>
73 #include <unistd.h>
74 #endif
75 #include <fcntl.h>
76 #include <string.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <sys/stat.h>
80 #include <sys/types.h>
81 #include <time.h>
82
83 #if __BYTE_ORDER == __BIG_ENDIAN
84
85 #include <asm/byteorder.h>
86 #ifdef __le16_to_cpu
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
93 #else
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) */
100
101 #else
102
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)
107
108 #endif /* __BIG_ENDIAN */
109
110 #ifdef _WIN32
111
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;
118
119 extern char *optarg;
120 extern int optind;
121 extern int opterr;
122 extern int optopt;
123 int getopt(int argc, char *const argv[], const char * optstring);
124
125 static int is_device = 0;
126
127 #define open WIN32open
128 #define close WIN32close
129 #define read WIN32read
130 #define write WIN32write
131 #define llseek WIN32llseek
132
133 #define O_SHORT_LIVED _O_SHORT_LIVED
134 #define O_ACCMODE 3
135 #define O_NONE 3
136 #define O_BACKUP 0x10000
137 #define O_SHARED 0x20000
138
139 static int WIN32open(const char *path, int oflag, ...)
140 {
141 HANDLE fh;
142 DWORD desiredAccess;
143 DWORD shareMode;
144 DWORD creationDisposition;
145 DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL;
146 SECURITY_ATTRIBUTES securityAttributes;
147 va_list ap;
148 int pmode;
149 int trunc = FALSE;
150
151 securityAttributes.nLength = sizeof(securityAttributes);
152 securityAttributes.lpSecurityDescriptor = NULL;
153 securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE;
154 switch (oflag & O_ACCMODE) {
155 case O_RDONLY:
156 desiredAccess = GENERIC_READ;
157 shareMode = FILE_SHARE_READ;
158 break;
159 case O_WRONLY:
160 desiredAccess = GENERIC_WRITE;
161 shareMode = 0;
162 break;
163 case O_RDWR:
164 desiredAccess = GENERIC_READ|GENERIC_WRITE;
165 shareMode = 0;
166 break;
167 case O_NONE:
168 desiredAccess = 0;
169 shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
170 }
171 if (oflag & O_APPEND) {
172 desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE;
173 shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
174 }
175 if (oflag & O_SHARED)
176 shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE;
177 switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) {
178 case 0:
179 case O_EXCL:
180 creationDisposition = OPEN_EXISTING;
181 break;
182 case O_CREAT:
183 creationDisposition = OPEN_ALWAYS;
184 break;
185 case O_CREAT|O_EXCL:
186 case O_CREAT|O_TRUNC|O_EXCL:
187 creationDisposition = CREATE_NEW;
188 break;
189 case O_TRUNC:
190 case O_TRUNC|O_EXCL:
191 creationDisposition = TRUNCATE_EXISTING;
192 break;
193 case O_CREAT|O_TRUNC:
194 creationDisposition = OPEN_ALWAYS;
195 trunc = TRUE;
196 break;
197 }
198 if (oflag & O_CREAT) {
199 va_start(ap, oflag);
200 pmode = va_arg(ap, int);
201 va_end(ap);
202 if ((pmode & 0222) == 0)
203 flagsAttributes |= FILE_ATTRIBUTE_READONLY;
204 }
205 if (oflag & O_TEMPORARY) {
206 flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
207 desiredAccess |= DELETE;
208 }
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();
220 return -1;
221 }
222 if (trunc) {
223 if (!SetEndOfFile(fh)) {
224 errno = GetLastError();
225 CloseHandle(fh);
226 DeleteFile(path);
227 return -1;
228 }
229 }
230 return (int)fh;
231 }
232
233 static int WIN32close(int fd)
234 {
235 if (!CloseHandle((HANDLE)fd)) {
236 errno = GetLastError();
237 return -1;
238 }
239 return 0;
240 }
241
242 static int WIN32read(int fd, void *buf, unsigned int len)
243 {
244 DWORD actualLen;
245
246 if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
247 errno = GetLastError();
248 if (errno == ERROR_BROKEN_PIPE)
249 return 0;
250 else
251 return -1;
252 }
253 return (int)actualLen;
254 }
255
256 static int WIN32write(int fd, void *buf, unsigned int len)
257 {
258 DWORD actualLen;
259
260 if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
261 errno = GetLastError();
262 return -1;
263 }
264 return (int)actualLen;
265 }
266
267 static loff_t WIN32llseek(int fd, loff_t offset, int whence)
268 {
269 long lo, hi;
270 DWORD err;
271
272 lo = offset & 0xffffffff;
273 hi = offset >> 32;
274 lo = SetFilePointer((HANDLE)fd, lo, &hi, whence);
275 if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) {
276 errno = err;
277 return -1;
278 }
279 return ((loff_t)hi << 32) | (off_t)lo;
280 }
281
282 int fsctl(int fd, int code)
283 {
284 DWORD ret;
285 if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) {
286 errno = GetLastError();
287 return -1;
288 }
289 return 0;
290 }
291
292 #else
293
294 #define O_NOINHERIT 0
295 #define O_TEMPORARY 0
296 #define O_SHORT_LIVED 0
297 #define O_SEQUENTIAL 0
298 #define O_RANDOM 0
299 #define O_BACKUP 0
300 #define O_SHARED 0
301 #ifndef O_NONE
302 # define O_NONE 0
303 #endif
304
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 )
312 {
313 return lseek(fd, offset, whence);
314 }
315 #else
316 # ifndef __NR__llseek
317 # error _llseek system call not present
318 # endif
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 )
322 {
323 loff_t actual;
324
325 if (_llseek(fd, offset>>32, offset&0xffffffff, &actual, whence) != 0)
326 return (loff_t)-1;
327 return actual;
328 }
329 #endif
330
331 #endif
332
333 /* Constant definitions */
334
335 #define TRUE 1 /* Boolean constants */
336 #define FALSE 0
337
338 #define TEST_BUFFER_BLOCKS 16
339 #define HARD_SECTOR_SIZE 512
340 #define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE )
341
342
343 /* Macro definitions */
344
345 /* Report a failure message and return a failure error code */
346
347 #define die( str ) fatal_error( "%s: " str "\n" )
348
349
350 /* Mark a cluster in the FAT as bad */
351
352 #define mark_sector_bad( sector ) mark_FAT_sector( sector, FAT_BAD )
353
354 /* Compute ceil(a/b) */
355
356 inline int
357 cdiv (int a, int b)
358 {
359 return (a + b - 1) / b;
360 }
361
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
364 need */
365
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 */
372
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" */
376
377 /* FAT values */
378 #define FAT_EOF (atari_format ? 0x0fffffff : 0x0ffffff8)
379 #define FAT_BAD 0x0ffffff7
380
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 */
385
386 #define BOOT_SIGN 0xAA55 /* Boot sector magic number */
387
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)
393
394 #define FAT12_THRESHOLD 4078
395
396 #define OLDGEMDOS_MAX_SECTORS 32765
397 #define GEMDOS_MAX_SECTORS 65531
398 #define GEMDOS_MAX_SECTOR_SIZE (16*1024)
399
400 #define BOOTCODE_SIZE 448
401 #define BOOTCODE_FAT32_SIZE 420
402
403 /* __attribute__ ((packed)) is used on all structures to make gcc ignore any
404 * alignments */
405
406 #ifdef _WIN32
407 #pragma pack(push, 1)
408 #endif
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));
417
418 struct msdos_boot_sector
419 {
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) */
435 union {
436 struct {
437 struct msdos_volume_info vi;
438 __u8 boot_code[BOOTCODE_SIZE];
439 } __attribute__ ((packed)) _oldfat;
440 struct {
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;
452 __u16 boot_sign;
453 } __attribute__ ((packed));
454 #define fat32 fstype._fat32
455 #define oldfat fstype._oldfat
456
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. */
463 __u32 reserved2[4];
464 };
465
466 struct msdos_dir_entry
467 {
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));
479
480 #ifdef _WIN32
481 #pragma pack(pop)
482 #endif
483
484 /* The "boot code" we put into the filesystem... it writes a message and
485 tells the user to try again */
486
487 char dummy_boot_jump[3] = { 0xeb, 0x3c, 0x90 };
488
489 char dummy_boot_jump_m68k[2] = { 0x60, 0x1c };
490
491 char dummy_boot_code[BOOTCODE_SIZE] =
492 "\x0e" /* push cs */
493 "\x1f" /* pop ds */
494 "\xbe\x5b\x7c" /* mov si, offset message_txt */
495 /* write_msg: */
496 "\xac" /* lodsb */
497 "\x22\xc0" /* and al, al */
498 "\x74\x0b" /* jz key_press */
499 "\x56" /* push si */
500 "\xb4\x0e" /* mov ah, 0eh */
501 "\xbb\x07\x00" /* mov bx, 0007h */
502 "\xcd\x10" /* int 10h */
503 "\x5e" /* pop si */
504 "\xeb\xf0" /* jmp write_msg */
505 /* key_press: */
506 "\x32\xe4" /* xor ah, ah */
507 "\xcd\x16" /* int 16h */
508 "\xcd\x19" /* int 19h */
509 "\xeb\xfe" /* foo: jmp foo */
510 /* message_txt: */
511
512 "This is not a bootable disk. Please insert a bootable floppy and\r\n"
513 "press any key to try again ... \r\n";
514
515 #define MESSAGE_OFFSET 29 /* Offset of message in above code */
516
517 /* Global variables - the root of all evil :-) - see these and weep! */
518
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 */
549
550
551 /* Function prototype definitions */
552
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);
563 #ifdef _WIN32
564 static void establish_params (void);
565 #else
566 static void establish_params (int device_num, int size);
567 #endif
568 static void setup_tables (void);
569 static void write_tables (void);
570
571
572 /* The function implementations */
573
574 /* Handle the reporting of fatal errors. Volatile to let gcc know that this doesn't return */
575
576 static void
577 fatal_error (const char *fmt_string)
578 {
579 fprintf (stderr, fmt_string, program_name, device_name);
580 exit (1); /* The error exit code is 1! */
581 }
582
583
584 /* Mark the specified cluster as having a particular value */
585
586 static void
587 mark_FAT_cluster (int cluster, unsigned int value)
588 {
589 switch( size_fat ) {
590 case 12:
591 value &= 0x0fff;
592 if (((cluster * 3) & 0x1) == 0)
593 {
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));
597 }
598 else
599 {
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);
602 }
603 break;
604
605 case 16:
606 value &= 0xffff;
607 fat[2 * cluster] = (unsigned char) (value & 0x00ff);
608 fat[(2 * cluster) + 1] = (unsigned char) (value >> 8);
609 break;
610
611 case 32:
612 value &= 0xfffffff;
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);
617 break;
618
619 default:
620 die("Bad FAT size (not 12, 16, or 32)");
621 }
622 }
623
624
625 /* Mark a specified sector as having a particular value in it's FAT entry */
626
627 static void
628 mark_FAT_sector (int sector, unsigned int value)
629 {
630 int cluster;
631
632 cluster = (sector - start_data_sector) / (int) (bs.cluster_size) /
633 (sector_size/HARD_SECTOR_SIZE);
634 if (cluster < 0)
635 die ("Invalid cluster number in mark_FAT_sector: probably bug!");
636
637 mark_FAT_cluster (cluster, value);
638 }
639
640
641 /* Perform a test on a block. Return the number of blocks that could be read successfully */
642
643 static long
644 do_check (char *buffer, int try, unsigned int current_block)
645 {
646 long got;
647
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");
651
652 got = read (dev, buffer, try * BLOCK_SIZE); /* Try reading! */
653 if (got < 0)
654 got = 0;
655
656 if (got & (BLOCK_SIZE - 1))
657 printf ("Unexpected values in do_check: probably bugs\n");
658 got /= BLOCK_SIZE;
659
660 return got;
661 }
662
663 #ifndef _WIN32
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) */
666
667 static void
668 alarm_intr (int alnum)
669 {
670 if (currently_testing >= blocks)
671 return;
672
673 signal (SIGALRM, alarm_intr);
674 alarm (5);
675 if (!currently_testing)
676 return;
677
678 printf ("%d... ", currently_testing);
679 fflush (stdout);
680 }
681 #endif
682
683 static void
684 check_blocks (void)
685 {
686 int try, got;
687 int i;
688 static char blkbuf[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
689
690 if (verbose)
691 {
692 printf ("Searching for bad blocks ");
693 fflush (stdout);
694 }
695 currently_testing = 0;
696 #ifndef _WIN32
697 if (verbose)
698 {
699 signal (SIGALRM, alarm_intr);
700 alarm (5);
701 }
702 #endif
703 try = TEST_BUFFER_BLOCKS;
704 while (currently_testing < blocks)
705 {
706 if (currently_testing + try > blocks)
707 try = blocks - currently_testing;
708 got = do_check (blkbuf, try, currently_testing);
709 currently_testing += got;
710 if (got == try)
711 {
712 try = TEST_BUFFER_BLOCKS;
713 continue;
714 }
715 else
716 try = 1;
717 if (currently_testing < start_data_block)
718 die ("bad blocks before data-area: cannot make fs");
719
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);
722 badblocks++;
723 currently_testing++;
724 }
725
726 if (verbose)
727 printf ("\n");
728
729 if (badblocks)
730 printf ("%d bad block%s\n", badblocks,
731 (badblocks > 1) ? "s" : "");
732 }
733
734
735 static void
736 get_list_blocks (char *filename)
737 {
738 int i;
739 FILE *listfile;
740 unsigned long blockno;
741
742 listfile = fopen (filename, "r");
743 if (listfile == (FILE *) NULL)
744 die ("Can't open file of bad blocks");
745
746 while (!feof (listfile))
747 {
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);
751 badblocks++;
752 }
753 fclose (listfile);
754
755 if (badblocks)
756 printf ("%d bad block%s\n", badblocks,
757 (badblocks > 1) ? "s" : "");
758 }
759
760
761 #ifndef _WIN32
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 */
764
765 static int
766 valid_offset (int fd, loff_t offset)
767 {
768 char ch;
769
770 if (llseek (fd, offset, SEEK_SET) < 0)
771 return FALSE;
772 if (read (fd, &ch, 1) < 1)
773 return FALSE;
774 return TRUE;
775 }
776 #endif
777
778
779 /* Given a filename, look to see how many blocks of BLOCK_SIZE are present, returning the answer */
780
781 static int
782 count_blocks (char *filename)
783 {
784 #ifdef _WIN32
785 int fd;
786 DISK_GEOMETRY geom;
787 BY_HANDLE_FILE_INFORMATION hinfo;
788 DWORD ret;
789 loff_t len = 0;
790
791 if ((fd = open(filename, O_RDONLY)) < 0) {
792 perror(filename);
793 exit(1);
794 }
795 /*
796 * This should probably use IOCTL_DISK_GET_LENGTH_INFO here, but
797 * this ioctl is only available in XP and up.
798 */
799 if (is_device) {
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'");
803 }
804 len = geom.Cylinders.QuadPart*geom.TracksPerCylinder*geom.SectorsPerTrack*BLOCK_SIZE;
805 } else {
806 if (!GetFileInformationByHandle((HANDLE)fd, &hinfo)) {
807 errno = GetLastError();
808 die("unable to get length for '%s'");
809 }
810 len = ((loff_t)hinfo.nFileSizeHigh << 32) | (loff_t)hinfo.nFileSizeLow;
811 }
812 close(fd);
813 return len/BLOCK_SIZE;
814 #else
815 loff_t high, low;
816 int fd;
817
818 if ((fd = open (filename, O_RDONLY)) < 0)
819 {
820 perror (filename);
821 exit (1);
822 }
823 low = 0;
824
825 for (high = 1; valid_offset (fd, high); high *= 2)
826 low = high;
827 while (low < high - 1)
828 {
829 const loff_t mid = (low + high) / 2;
830
831 if (valid_offset (fd, mid))
832 low = mid;
833 else
834 high = mid;
835 }
836 valid_offset (fd, 0);
837 close (fd);
838
839 return (low + 1) / BLOCK_SIZE;
840 #endif
841 }
842
843
844 /* Check to see if the specified device is currently mounted - abort if it is */
845
846 static void
847 check_mount (char *device_name)
848 {
849 #ifndef _WIN32
850 FILE *f;
851 struct mntent *mnt;
852
853 if ((f = setmntent (MOUNTED, "r")) == NULL)
854 return;
855 while ((mnt = getmntent (f)) != NULL)
856 if (strcmp (device_name, mnt->mnt_fsname) == 0)
857 die ("%s contains a mounted file system.");
858 endmntent (f);
859 #endif
860 }
861
862
863 /* Establish the geometry and media parameters for the device */
864 #ifdef _WIN32
865 static void
866 establish_params (void)
867 {
868 DISK_GEOMETRY geometry;
869 DWORD ret;
870
871 if (!is_device) {
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)
879 (size_fat == 32 ?
880 ((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) :
881 4); /* FAT12 and FAT16: start at 4 sectors per cluster */
882 return;
883 }
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'");
887 }
888 bs.secs_track = geometry.SectorsPerTrack;
889 bs.heads = geometry.TracksPerCylinder;
890 switch (geometry.MediaType) {
891 case F3_1Pt44_512:
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;
896 break;
897 case F3_2Pt88_512:
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;
902 break;
903 case F3_720_512:
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;
908 break;
909 default:
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)
917 (size_fat == 32 ?
918 ((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) :
919 4); /* FAT12 and FAT16: start at 4 sectors per cluster */
920 }
921 }
922 #else
923 static void
924 establish_params (int device_num,int size)
925 {
926 long loop_size;
927 struct hd_geometry geometry;
928 struct floppy_struct param;
929
930 if ((0 == device_num) || ((device_num & 0xff00) == 0x0200))
931 /* file image or floppy disk */
932 {
933 if (0 == device_num)
934 {
935 param.size = size/512;
936 switch(param.size)
937 {
938 case 720:
939 param.sect = 9 ;
940 param.head = 2;
941 break;
942 case 1440:
943 param.sect = 9;
944 param.head = 2;
945 break;
946 case 2400:
947 param.sect = 15;
948 param.head = 2;
949 break;
950 case 2880:
951 param.sect = 18;
952 param.head = 2;
953 break;
954 case 5760:
955 param.sect = 36;
956 param.head = 2;
957 break;
958 default:
959 /* fake values */
960 param.sect = 32;
961 param.head = 64;
962 break;
963 }
964
965 }
966 else /* is a floppy diskette */
967 {
968 if (ioctl (dev, FDGETPRM, &param)) /* Can we get the diskette geometry? */
969 die ("unable to get diskette geometry for '%s'");
970 }
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 */
974 {
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;
980 break;
981
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;
987 break;
988
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;
994 break;
995
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;
1001 break;
1002
1003 case 2880: /* 3.5", 2, 18, 80 - 1440K */
1004 floppy_default:
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;
1009 break;
1010
1011 default: /* Anything else */
1012 if (0 == device_num)
1013 goto def_hd_params;
1014 else
1015 goto floppy_default;
1016 }
1017 }
1018 else if ((device_num & 0xff00) == 0x0700) /* This is a loop device */
1019 {
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;
1024
1025 switch (loop_size) /* Assuming the loop device -> floppy later */
1026 {
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;
1034 break;
1035
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;
1043 break;
1044
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;
1052 break;
1053
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;
1061 break;
1062
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;
1070 break;
1071
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);
1077 goto def_hd_params;
1078 }
1079 }
1080 else
1081 /* Must be a hard disk then! */
1082 {
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);
1089 def_hd_params:
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)
1097 (size_fat == 32 ?
1098 ((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) :
1099 4); /* FAT12 and FAT16: start at 4 sectors per cluster */
1100 }
1101 }
1102 #endif
1103
1104
1105 /* Create the filesystem data tables */
1106
1107 static void
1108 setup_tables (void)
1109 {
1110 unsigned num_sectors;
1111 unsigned cluster_count = 0, fat_length;
1112 unsigned fatdata; /* Sectors for FATs + data area */
1113 struct tm *ctime;
1114 struct msdos_volume_info *vi = (size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
1115
1116 if (atari_format)
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 );
1121 else
1122 strcpy (bs.system_id, "mkdosfs");
1123 if (sectors_per_cluster)
1124 bs.cluster_size = (char) sectors_per_cluster;
1125 if (size_fat == 32)
1126 {
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;
1131 }
1132 else if (root_dir_entries)
1133 {
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);
1137 }
1138 else
1139 root_dir_entries = bs.dir_entries[0] + (bs.dir_entries[1] << 8);
1140
1141 if (atari_format) {
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);
1145 }
1146 else {
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);
1151 }
1152
1153 if (!atari_format) {
1154 memcpy(vi->volume_label, volume_name, 11);
1155
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) -
1161 (char *)&bs) - 2;
1162
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);
1168 }
1169 else {
1170 memcpy(bs.oldfat.boot_code, dummy_boot_code, BOOTCODE_SIZE);
1171 }
1172 bs.boot_sign = CT_LE_W(BOOT_SIGN);
1173 }
1174 else {
1175 memcpy(bs.boot_jump, dummy_boot_jump_m68k, 2);
1176 }
1177 if (verbose >= 2)
1178 printf( "Boot jump code is %02x %02x\n",
1179 bs.boot_jump[0], bs.boot_jump[1] );
1180
1181 if (!reserved_sectors)
1182 reserved_sectors = (size_fat == 32) ? 32 : 1;
1183 else {
1184 if (size_fat == 32 && reserved_sectors < 2)
1185 die("On FAT32 at least 2 reserved sectors are needed.");
1186 }
1187 bs.reserved = CT_LE_W(reserved_sectors);
1188 if (verbose >= 2)
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);
1193 else
1194 /* In Atari format, hidden is a 16 bit field */
1195 memset( &bs.hidden, 0, 2 );
1196
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;
1202 int maxclustsize;
1203
1204 fatdata = num_sectors - cdiv (root_dir_entries * 32, sector_size) -
1205 reserved_sectors;
1206
1207 if (sectors_per_cluster)
1208 bs.cluster_size = maxclustsize = sectors_per_cluster;
1209 else
1210 /* An initial guess for bs.cluster_size should already be set */
1211 maxclustsize = 128;
1212
1213 if (verbose >= 2)
1214 printf( "%d sectors for FAT+data, starting with %d sectors/cluster\n",
1215 fatdata, bs.cluster_size );
1216 do {
1217 if (verbose >= 2)
1218 printf( "Trying with %d sectors/cluster:\n", bs.cluster_size );
1219
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;
1232 if (verbose >= 2)
1233 printf( "FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
1234 clust12, fatlength12, maxclust12, MAX_CLUST_12 );
1235 if (clust12 > maxclust12-2) {
1236 clust12 = 0;
1237 if (verbose >= 2)
1238 printf( "FAT12: too much clusters\n" );
1239 }
1240
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;
1251 if (verbose >= 2)
1252 printf( "FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
1253 clust16, fatlength16, maxclust16, MAX_CLUST_16 );
1254 if (clust16 > maxclust16-2) {
1255 if (verbose >= 2)
1256 printf( "FAT16: too much clusters\n" );
1257 clust16 = 0;
1258 }
1259 /* The < 4078 avoids that the filesystem will be misdetected as having a
1260 * 12 bit FAT. */
1261 if (clust16 < FAT12_THRESHOLD && !(size_fat_by_user && size_fat == 16)) {
1262 if (verbose >= 2)
1263 printf( clust16 < FAT12_THRESHOLD ?
1264 "FAT16: would be misdetected as FAT12\n" :
1265 "FAT16: too much clusters\n" );
1266 clust16 = 0;
1267 }
1268
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;
1279 if (verbose >= 2)
1280 printf( "FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
1281 clust32, fatlength32, maxclust32, MAX_CLUST_32 );
1282 if (clust32 > maxclust32) {
1283 clust32 = 0;
1284 if (verbose >= 2)
1285 printf( "FAT32: too much clusters\n" );
1286 }
1287
1288 if ((clust12 && (size_fat == 0 || size_fat == 12)) ||
1289 (clust16 && (size_fat == 0 || size_fat == 16)) ||
1290 (clust32 && size_fat == 32))
1291 break;
1292
1293 bs.cluster_size <<= 1;
1294 } while (bs.cluster_size && bs.cluster_size <= maxclustsize);
1295
1296 /* Use the optimal FAT size if not specified;
1297 * FAT32 is (not yet) choosen automatically */
1298 if (!size_fat) {
1299 size_fat = (clust16 > clust12) ? 16 : 12;
1300 if (verbose >= 2)
1301 printf( "Choosing %d bits for FAT\n", size_fat );
1302 }
1303
1304 switch (size_fat) {
1305 case 12:
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);
1310 break;
1311
1312 case 16:
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" );
1319 }
1320 else {
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." );
1329 }
1330 }
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);
1335 break;
1336
1337 case 32:
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);
1343 break;
1344
1345 default:
1346 die("FAT not 12, 16 or 32 bits");
1347 }
1348 }
1349 else {
1350 unsigned clusters, maxclust;
1351
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
1355 * size.
1356 */
1357 if (!size_fat)
1358 size_fat = (num_sectors == 1440 || num_sectors == 2400 ||
1359 num_sectors == 2880 || num_sectors == 5760) ? 12 : 16;
1360 if (verbose >= 2)
1361 printf( "Choosing %d bits for FAT\n", size_fat );
1362
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.
1366 */
1367 bs.cluster_size = sectors_per_cluster ? sectors_per_cluster : 2;
1368 if (!sector_size_set) {
1369 while( num_sectors > GEMDOS_MAX_SECTORS ) {
1370 num_sectors >>= 1;
1371 sector_size <<= 1;
1372 }
1373 }
1374 if (verbose >= 2)
1375 printf( "Sector size must be %d to have less than %d log. sectors\n",
1376 sector_size, GEMDOS_MAX_SECTORS );
1377
1378 /* Check if there are enough FAT indices for how much clusters we have */
1379 do {
1380 fatdata = num_sectors - cdiv (root_dir_entries * 32, sector_size) -
1381 reserved_sectors;
1382 /* The factor 2 below avoids cut-off errors for nr_fats == 1 and
1383 * size_fat == 12
1384 * The "2*nr_fats*size_fat/8" is for the reserved first two FAT entries
1385 */
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;
1394 if (verbose >= 2)
1395 printf( "ss=%d: #clu=%d, fat_len=%d, maxclu=%d\n",
1396 sector_size, clusters, fat_length, maxclust );
1397
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)
1402 break;
1403 if (verbose >= 2)
1404 printf( clusters > maxclust-2 ?
1405 "Too many clusters\n" : "FAT too big\n" );
1406
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." );
1411 num_sectors >>= 1;
1412 sector_size <<= 1;
1413 } while( sector_size <= GEMDOS_MAX_SECTOR_SIZE );
1414
1415 if (sector_size > GEMDOS_MAX_SECTOR_SIZE)
1416 die( "Would need a sector size > 16k, which GEMDOS can't work with");
1417
1418 cluster_count = clusters;
1419 if (size_fat != 32)
1420 bs.fat_length = CT_LE_W(fat_length);
1421 else {
1422 bs.fat_length = 0;
1423 bs.fat32.fat32_length = CT_LE_L(fat_length);
1424 }
1425 }
1426
1427 bs.sector_size[0] = (char) (sector_size & 0x00ff);
1428 bs.sector_size[1] = (char) ((sector_size & 0xff00) >> 8);
1429
1430 if (size_fat == 32)
1431 {
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);
1438 if (!backup_boot)
1439 backup_boot = (reserved_sectors >= 7) ? 6 :
1440 (reserved_sectors >= 2) ? reserved_sectors-1 : 0;
1441 else
1442 {
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");
1447 }
1448 if (verbose >= 2)
1449 printf( "Using sector %d as backup boot sector (0 = none)\n",
1450 backup_boot );
1451 bs.fat32.backup_boot = CT_LE_W(backup_boot);
1452 memset( &bs.fat32.reserved2, 0, sizeof(bs.fat32.reserved2) );
1453 }
1454
1455 if (atari_format) {
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 "
1461 "or higher.\n" );
1462 }
1463 if (num_sectors >= 65536)
1464 {
1465 bs.sectors[0] = (char) 0;
1466 bs.sectors[1] = (char) 0;
1467 bs.total_sect = CT_LE_L(num_sectors);
1468 }
1469 else
1470 {
1471 bs.sectors[0] = (char) (num_sectors & 0x00ff);
1472 bs.sectors[1] = (char) ((num_sectors & 0xff00) >> 8);
1473 if (!atari_format)
1474 bs.total_sect = CT_LE_L(0);
1475 }
1476
1477 if (!atari_format)
1478 vi->ext_boot_sign = MSDOS_EXT_SIGN;
1479
1480 if (!cluster_count)
1481 {
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");
1484 else
1485 die ("Attempting to create a too large file system");
1486 }
1487
1488
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) /
1493 SECTORS_PER_BLOCK;
1494
1495 if (blocks < start_data_block + 32) /* Arbitrary undersize file system! */
1496 die ("Too few blocks for viable file system");
1497
1498 if (verbose)
1499 {
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" : "");
1512 if (size_fat != 32)
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);
1519 else
1520 printf("no volume label.\n");
1521 }
1522
1523 /* Make the file allocation tables! */
1524
1525 if ((fat = (unsigned char *) malloc (fat_length * sector_size)) == NULL)
1526 die ("unable to allocate space for FAT image in memory");
1527
1528 memset( fat, 0, fat_length * sector_size );
1529
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);
1536 }
1537
1538 /* Make the root directory entries */
1539
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)
1545 {
1546 free (fat); /* Tidy up before we die! */
1547 die ("unable to allocate space for root directory in memory");
1548 }
1549
1550 memset(root_dir, 0, size_root_dir);
1551 if ( memcmp(volume_name, " ", 11) )
1552 {
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)));
1562 de->ctime_ms = 0;
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);
1569 }
1570
1571 if (size_fat == 32) {
1572 /* For FAT32, create an info sector */
1573 struct fat32_fsinfo *info;
1574
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);
1580
1581 /* Info sector magic */
1582 info_sector[0] = 'R';
1583 info_sector[1] = 'R';
1584 info_sector[2] = 'a';
1585 info_sector[3] = 'A';
1586
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);
1592
1593 /* Info sector also must have boot sign */
1594 *(__u16 *)(info_sector + 0x1fe) = CT_LE_W(BOOT_SIGN);
1595 }
1596
1597 if (!(blank_sector = malloc( sector_size )))
1598 die( "Out of memory" );
1599 memset(blank_sector, 0, sector_size);
1600 }
1601
1602
1603 /* Write the new filesystem's data tables to wherever they're going to end up! */
1604
1605 #define error(str) \
1606 do { \
1607 free (fat); \
1608 if (info_sector) free (info_sector); \
1609 free (root_dir); \
1610 die (str); \
1611 } while(0)
1612
1613 #define seekto(pos,errstr) \
1614 do { \
1615 loff_t __pos = (pos); \
1616 if (llseek (dev, __pos, SEEK_SET) != __pos) \
1617 error ("seek to " errstr " failed whilst writing tables"); \
1618 } while(0)
1619
1620 #define writebuf(buf,size,errstr) \
1621 do { \
1622 int __size = (size); \
1623 if (write (dev, buf, __size) != __size) \
1624 error ("failed whilst writing " errstr); \
1625 } while(0)
1626
1627
1628 static void
1629 write_tables (void)
1630 {
1631 int x;
1632 int fat_length;
1633 #ifdef _WIN32
1634 int blk;
1635 #endif
1636
1637 fat_length = (size_fat == 32) ?
1638 CF_LE_L(bs.fat32.fat32_length) : CF_LE_W(bs.fat_length);
1639
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 */
1648 if (size_fat == 32)
1649 {
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)
1653 {
1654 seekto( backup_boot*sector_size, "backup boot sector" );
1655 writebuf( (char *) &bs, sizeof (struct msdos_boot_sector),
1656 "backup boot sector" );
1657 }
1658 }
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++)
1662 #ifdef _WIN32
1663 /*
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.
1667 */
1668 for (blk = 0; blk < fat_length; blk++)
1669 writebuf(fat+blk*sector_size, sector_size, "FAT");
1670 #else
1671 writebuf( fat, fat_length * sector_size, "FAT" );
1672 #endif
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" );
1676
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 */
1680 }
1681
1682
1683 /* Report the command usage and return a failure error code */
1684
1685 void
1686 usage (void)
1687 {
1688 fatal_error("\
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");
1694 }
1695
1696 /*
1697 * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
1698 * of MS-DOS filesystem by default.
1699 */
1700 static void check_atari( void )
1701 {
1702 #ifdef __mc68000__
1703 FILE *f;
1704 char line[128], *p;
1705
1706 if (!(f = fopen( "/proc/hardware", "r" ))) {
1707 perror( "/proc/hardware" );
1708 return;
1709 }
1710
1711 while( fgets( line, sizeof(line), f ) ) {
1712 if (strncmp( line, "Model:", 6 ) == 0) {
1713 p = line + 6;
1714 p += strspn( p, " \t" );
1715 if (strncmp( p, "Atari ", 6 ) == 0)
1716 atari_format = 1;
1717 break;
1718 }
1719 }
1720 fclose( f );
1721 #endif
1722 }
1723
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! */
1726
1727 int
1728 main (int argc, char **argv)
1729 {
1730 int c;
1731 char *tmp;
1732 char *listfile = NULL;
1733 FILE *msgfile;
1734 #ifdef _WIN32
1735 static char dev_buf[] = "\\\\.\\X:";
1736 #else
1737 struct stat statbuf;
1738 #endif
1739 int i = 0, pos, ch;
1740 int create = 0;
1741
1742 if (argc && *argv) { /* What's the program name? */
1743 char *p;
1744 program_name = *argv;
1745 #ifdef _WIN32
1746 if ((p = strrchr( program_name, '\\' )))
1747 #else
1748 if ((p = strrchr( program_name, '/' )))
1749 #endif
1750 program_name = p+1;
1751 }
1752
1753 time(&create_time);
1754 volume_id = (long)create_time; /* Default volume ID = creation time */
1755 check_atari();
1756
1757 printf ("%s " VERSION " (" VERSION_DATE ")\n"
1758 #ifdef _WIN32
1759 "Win32 port by Jens-Uwe Mager <jum@anubis.han.de>\n"
1760 #endif
1761 , program_name);
1762
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 */
1765 switch (c)
1766 {
1767 case 'A': /* toggle Atari format */
1768 atari_format = !atari_format;
1769 break;
1770
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)
1774 {
1775 printf ("Bad location for backup boot sector : %s\n", optarg);
1776 usage ();
1777 }
1778 break;
1779
1780 case 'c': /* c : Check FS as we build it */
1781 check = TRUE;
1782 break;
1783
1784 case 'C': /* C : Create a new file */
1785 create = TRUE;
1786 break;
1787
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)
1791 {
1792 printf ("Bad number of FATs : %s\n", optarg);
1793 usage ();
1794 }
1795 break;
1796
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))
1800 {
1801 printf ("Bad FAT type : %s\n", optarg);
1802 usage ();
1803 }
1804 size_fat_by_user = 1;
1805 break;
1806
1807 case 'I':
1808 ignore_full_disk = 1;
1809 break;
1810
1811 case 'i': /* i : specify volume ID */
1812 volume_id = strtol(optarg, &tmp, 16);
1813 if ( *tmp )
1814 {
1815 printf("Volume ID must be a hexadecimal number\n");
1816 usage();
1817 }
1818 break;
1819
1820 case 'l': /* l : Bad block filename */
1821 listfile = optarg;
1822 break;
1823
1824 case 'm': /* m : Set boot message */
1825 if ( strcmp(optarg, "-") )
1826 {
1827 msgfile = fopen(optarg, "r");
1828 if ( !msgfile )
1829 perror(optarg);
1830 }
1831 else
1832 msgfile = stdin;
1833
1834 if ( msgfile )
1835 {
1836 /* The boot code ends at offset 448 and needs a null terminator */
1837 i = MESSAGE_OFFSET;
1838 pos = 0; /* We are at beginning of line */
1839 do
1840 {
1841 ch = getc(msgfile);
1842 switch (ch)
1843 {
1844 case '\r': /* Ignore CRs */
1845 case '\0': /* and nulls */
1846 break;
1847
1848 case '\n': /* LF -> CR+LF if necessary */
1849 if ( pos ) /* If not at beginning of line */
1850 {
1851 dummy_boot_code[i++] = '\r';
1852 pos = 0;
1853 }
1854 dummy_boot_code[i++] = '\n';
1855 break;
1856
1857 case '\t': /* Expand tabs */
1858 do
1859 {
1860 dummy_boot_code[i++] = ' ';
1861 pos++;
1862 }
1863 while ( pos % 8 && i < BOOTCODE_SIZE-1 );
1864 break;
1865
1866 case EOF:
1867 dummy_boot_code[i++] = '\0'; /* Null terminator */
1868 break;
1869
1870 default:
1871 dummy_boot_code[i++] = ch; /* Store character */
1872 pos++; /* Advance position */
1873 break;
1874 }
1875 }
1876 while ( ch != EOF && i < BOOTCODE_SIZE-1 );
1877
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 */
1882
1883 if ( ch != EOF )
1884 printf ("Warning: message too long; truncated\n");
1885
1886 if ( msgfile != stdin )
1887 fclose(msgfile);
1888 }
1889 break;
1890
1891 case 'n': /* n : Volume name */
1892 sprintf(volume_name, "%-11.11s", optarg);
1893 break;
1894
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)
1898 {
1899 printf ("Bad number of root directory entries : %s\n", optarg);
1900 usage ();
1901 }
1902 break;
1903
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)
1907 {
1908 printf ("Bad number of reserved sectors : %s\n", optarg);
1909 usage ();
1910 }
1911 break;
1912
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))
1919 {
1920 printf ("Bad number of sectors per cluster : %s\n", optarg);
1921 usage ();
1922 }
1923 break;
1924
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))
1931 {
1932 printf ("Bad logical sector size : %s\n", optarg);
1933 usage ();
1934 }
1935 sector_size_set = 1;
1936 break;
1937
1938 case 'v': /* v : Verbose execution */
1939 ++verbose;
1940 break;
1941
1942 default:
1943 printf( "Unknown option: %c\n", c );
1944 usage ();
1945 }
1946
1947 if (optind >= argc)
1948 usage();
1949 device_name = argv[optind]; /* Determine the number of blocks in the FS */
1950 #ifdef _WIN32
1951 if (device_name[1] == ':' && device_name[2] == '\0') {
1952 dev_buf[4] = device_name[0];
1953 device_name = dev_buf;
1954 is_device = 1;
1955 }
1956 #endif
1957 if (!create)
1958 i = count_blocks (device_name); /* Have a look and see! */
1959 if (optind == argc - 2) /* Either check the user specified number */
1960 {
1961 blocks = (int) strtol (argv[optind + 1], &tmp, 0);
1962 if (!create && blocks != i)
1963 {
1964 fprintf (stderr, "Warning: block count mismatch: ");
1965 fprintf (stderr, "found %d but assuming %d.\n",i,blocks);
1966 }
1967 }
1968 else if (optind == argc - 1) /* Or use value found */
1969 {
1970 if (create)
1971 die( "Need intended size with -C." );
1972 blocks = i;
1973 tmp = "";
1974 }
1975 else
1976 usage ();
1977 if (*tmp)
1978 {
1979 printf ("Bad block count : %s\n", argv[optind + 1]);
1980 usage ();
1981 }
1982
1983 if (check && listfile) /* Auto and specified bad block handling are mutually */
1984 die ("-c and -l are incompatible"); /* exclusive of each other! */
1985
1986 if (!create) {
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? */
1989 if (dev < 0)
1990 die ("unable to open %s");
1991 #ifdef _WIN32
1992 if (is_device) {
1993 if (fsctl(dev, FSCTL_LOCK_VOLUME) == -1)
1994 die("unable to lock %s");
1995 }
1996 #endif
1997 }
1998 else {
1999 loff_t offset = blocks*BLOCK_SIZE - 1;
2000 char null = 0;
2001 /* create the file */
2002 dev = open( device_name, O_RDWR|O_CREAT|O_TRUNC, 0775 );
2003 if (dev < 0)
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" );
2013 }
2014
2015 #ifdef _WIN32
2016 if (!is_device)
2017 check = 0;
2018 establish_params();
2019 #else
2020 if (fstat (dev, &statbuf) < 0)
2021 die ("unable to stat %s");
2022 if (!S_ISBLK (statbuf.st_mode)) {
2023 statbuf.st_rdev = 0;
2024 check = 0;
2025 }
2026 else
2027 /*
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
2033 */
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 */
2039 )
2040 die ("Will not try to make filesystem on '%s'");
2041
2042 establish_params (statbuf.st_rdev,statbuf.st_size);
2043 /* Establish the media parameters */
2044 #endif
2045
2046 setup_tables (); /* Establish the file system tables */
2047
2048 if (check) /* Determine any bad block locations and mark them */
2049 check_blocks ();
2050 else if (listfile)
2051 get_list_blocks (listfile);
2052
2053 write_tables (); /* Write the file system tables away! */
2054
2055 #ifdef _WIN32
2056 if (is_device) {
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");
2061 }
2062 #endif
2063 exit (0); /* Terminate with no errors! */
2064 }
2065
2066
2067 /* That's All Folks */
2068 /* Local Variables: */
2069 /* tab-width: 8 */
2070 /* End: */