ReactOS  r76032
mkdosfs.c
Go to the documentation of this file.
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 }
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 */
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" */
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
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 
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 {
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;
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. */
464 };
465 
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 
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
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
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
783 {
784 #ifdef _WIN32
785  int fd;
786  DISK_GEOMETRY geom;
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  }
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
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) -
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) -
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)
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) /
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) */
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
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: */
static int sectors_per_cluster
Definition: mkdosfs.c:546
unsigned char __u8
Definition: compat.h:88
static struct msdos_dir_entry * root_dir
Definition: mkdosfs.c:544
#define O_SEQUENTIAL
Definition: mkdosfs.c:297
static int ignore_full_disk
Definition: mkdosfs.c:537
static int argc
Definition: ServiceArgs.c:15
long long ll_t
Definition: mkdosfs.c:305
static int start_data_sector
Definition: mkdosfs.c:540
__u32 size
Definition: mkdosfs.c:477
const XML_Char * version
Definition: expat.h:187
int tm_min
Definition: time.h:78
#define MAX_CLUST_32
Definition: mkdosfs.c:392
Definition: get.c:139
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
char dummy_boot_jump[3]
Definition: mkdosfs.c:487
int optopt
Definition: getopt.c:47
#define CloseHandle
Definition: compat.h:398
#define ATTR_VOLUME
Definition: mkdosfs.c:369
_Check_return_ _CRTIMP int __cdecl fscanf(_Inout_ FILE *_File, _In_z_ _Scanf_format_string_ const char *_Format,...)
static int start_data_block
Definition: mkdosfs.c:541
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
__u8 dir_entries[2]
Definition: mkdosfs.c:427
void usage(void)
Definition: mkdosfs.c:1686
LONG WINAPI _llseek(HFILE hFile, LONG lOffset, int iOrigin)
Definition: lfile.c:149
GLuint GLenum GLsizei GLsizei GLint GLint GLboolean packed
Definition: glext.h:9271
__u32 signature
Definition: mkdosfs.c:459
#define S_ISBLK(m)
Definition: ext2fs.h:369
static void establish_params(int device_num, int size)
Definition: mkdosfs.c:924
#define O_NOINHERIT
Definition: mkdosfs.c:294
#define open
Definition: acwin.h:71
#define O_ACCMODE
Definition: fcntl.h:48
static char * program_name
Definition: mkdosfs.c:519
static int WIN32close(HANDLE FileHandle)
Definition: io.c:61
int optind
Definition: getopt.c:47
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define free
Definition: debug_ros.c:5
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
static int size_fat_by_user
Definition: mkdosfs.c:535
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1134
static time_t create_time
Definition: mkdosfs.c:525
int cdiv(int a, int b)
Definition: mkdosfs.c:357
static void write_tables(void)
Definition: mkdosfs.c:1629
int tm_mday
Definition: time.h:80
static int badblocks
Definition: mkdosfs.c:532
__u8 ctime_ms
Definition: mkdosfs.c:471
__u32 reserved1
Definition: mkdosfs.c:458
static char * blank_sector
Definition: mkdosfs.c:548
uint32_t fat32_length
Definition: fsck.fat.h:52
static long do_check(char *buffer, int try, unsigned int current_block)
Definition: mkdosfs.c:644
_Check_return_ _CRTIMP int __cdecl getc(_Inout_ FILE *_File)
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1056
char dummy_boot_jump_m68k[2]
Definition: mkdosfs.c:489
GLuint buffer
Definition: glext.h:5915
static void check_mount(char *device_name)
Definition: mkdosfs.c:847
_Check_return_ _CRTIMP size_t __cdecl strspn(_In_z_ const char *_Str, _In_z_ const char *_Control)
#define O_NONE
Definition: mkdosfs.c:302
__u8 sector_size[2]
Definition: mkdosfs.c:423
FILE * stdin
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static int sector_size_set
Definition: mkdosfs.c:529
_Check_return_opt_ _CRTIMP long __cdecl lseek(_In_ int _FileHandle, _In_ long _Offset, _In_ int _Origin)
#define BOOT_SIGN
Definition: mkdosfs.c:386
__u8 system_id[8]
Definition: mkdosfs.c:421
ULONG TracksPerCylinder
Definition: ntdddisk.h:362
int tm_year
Definition: time.h:82
static int size_fat
Definition: mkdosfs.c:534
int errno
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
__u16 time
Definition: mkdosfs.c:366
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define DeleteFile
Definition: winbase.h:3526
#define FILE_APPEND_DATA
Definition: nt_native.h:634
__u16 cdate
Definition: mkdosfs.c:473
#define NO_ERROR
Definition: dderror.h:5
static void check_atari(void)
Definition: mkdosfs.c:1700
#define FAT12_THRESHOLD
Definition: mkdosfs.c:394
#define O_BACKUP
Definition: mkdosfs.c:299
#define MSDOS_FAT16_SIGN
Definition: mkdosfs.c:383
DWORD DWORD
Definition: winlogon.h:75
static char ** argv
Definition: ServiceArgs.c:14
static int dev
Definition: mkdosfs.c:536
#define FILE_SHARE_READ
Definition: compat.h:125
FILE * stdout
uint8_t sector
Definition: isohybrid.c:61
#define O_TEMPORARY
Definition: mkdosfs.c:295
__u16 start
Definition: mkdosfs.c:366
#define writebuf(buf, size, errstr)
Definition: mkdosfs.c:1620
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
static int atari_format
Definition: mkdosfs.c:521
static void mark_FAT_sector(int sector, unsigned int value)
Definition: mkdosfs.c:628
static _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh)
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static void check_blocks(void)
Definition: mkdosfs.c:684
#define write
Definition: acwin.h:73
__u8 attr
Definition: mkdosfs.c:469
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define MSDOS_FAT32_SIGN
Definition: mkdosfs.c:384
#define va_end(ap)
Definition: acmsvcex.h:90
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
LPCSTR filename
Definition: alphablend.c:63
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
__u16 secs_track
Definition: mkdosfs.c:431
static void mark_FAT_cluster(int cluster, unsigned int value)
Definition: mkdosfs.c:587
#define O_WRONLY
Definition: acwin.h:85
int main(int argc, char **argv)
Definition: mkdosfs.c:1728
#define ioctl
Definition: wintirpc.h:60
#define GENERIC_WRITE
Definition: nt_native.h:90
static char * device_name
Definition: mkdosfs.c:520
__u8 volume_id[4]
Definition: mkdosfs.c:361
__u8 lcase
Definition: mkdosfs.c:470
struct fat32_fsinfo __attribute__
#define CT_LE_L(v)
Definition: mkdosfs.c:98
double __cdecl trunc(double)
static int count_blocks(char *filename)
Definition: mkdosfs.c:782
smooth NULL
Definition: ftsmooth.c:557
#define FALSE
Definition: mkdosfs.c:336
char ext[3]
Definition: mkdosfs.c:358
unsigned char
Definition: typeof.h:27
unsigned long
Definition: typeof.h:99
#define mark_sector_bad(sector)
Definition: mkdosfs.c:352
Definition: parser.c:48
static int WIN32read(HANDLE FileHandle, void *buf, unsigned int len)
Definition: io.c:69
char * va_list
Definition: acmsvcex.h:78
int int pmode
Definition: fci.h:172
char dummy_boot_code[BOOTCODE_SIZE]
Definition: mkdosfs.c:491
#define OLDGEMDOS_MAX_SECTORS
Definition: mkdosfs.c:396
int tm_mon
Definition: time.h:81
#define off_t
Definition: dosfsck.h:5
static int blocks
Definition: mkdosfs.c:527
#define O_SHARED
Definition: mkdosfs.c:300
#define O_EXCL
Definition: fcntl.h:40
#define OPEN_EXISTING
Definition: compat.h:426
#define b
Definition: ke_i.h:79
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
static void get_list_blocks(char *filename)
Definition: mkdosfs.c:736
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define SEEK_SET
Definition: jmemansi.c:26
_Check_return_ _CRTIMP int __cdecl feof(_In_ FILE *_File)
__u16 ctime
Definition: mkdosfs.c:472
__u16 ctime
Definition: mkdosfs.c:362
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define BLOCK_SIZE
Definition: dlist.c:321
uint8_t reserved2[12]
Definition: fsck.fat.h:58
unsigned short __u16
Definition: compat.h:89
#define SECTORS_PER_BLOCK
Definition: mkdosfs.c:340
BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
Definition: fileinfo.c:588
if(!(yy_init))
Definition: macro.lex.yy.c:704
__u32 total_sect
Definition: mkdosfs.c:434
static void setup_tables(void)
Definition: mkdosfs.c:1108
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:360
#define FAT_EOF
Definition: mkdosfs.c:378
ULONG SectorsPerTrack
Definition: ntdddisk.h:363
Definition: mkdosfs.c:466
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define FILE_FLAG_DELETE_ON_CLOSE
Definition: disk.h:42
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define ERROR_BROKEN_PIPE
Definition: winerror.h:183
#define MESSAGE_OFFSET
Definition: mkdosfs.c:515
unsigned int __u32
Definition: compat.h:90
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:55
#define OPEN_ALWAYS
Definition: disk.h:70
int null(void)
Definition: ftp.c:1790
static int WIN32write(HANDLE FileHandle, void *buf, unsigned int len)
Definition: io.c:94
int oflag
Definition: fci.h:172
struct msdos_volume_info vi
Definition: mkdosfs.c:437
GLbitfield flags
Definition: glext.h:7161
__u16 adate
Definition: mkdosfs.c:474
#define MAX_CLUST_16
Definition: mkdosfs.c:389
unsigned __int64 loff_t
Definition: types.h:80
__u8 volume_id[4]
Definition: mkdosfs.c:413
int ret
__u16 starthi
Definition: mkdosfs.c:475
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
int signal
Definition: xcptfil.c:12
#define exit(n)
Definition: config.h:202
#define seekto(pos, errstr)
Definition: mkdosfs.c:1613
#define O_SHORT_LIVED
Definition: mkdosfs.c:296
unsigned short st_mode
Definition: stat.h:58
Definition: stat.h:55
static int backup_boot
Definition: mkdosfs.c:530
#define blk
Definition: linetest.c:70
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define O_TRUNC
Definition: acwin.h:86
GLenum GLsizei len
Definition: glext.h:6722
#define MSDOS_EXT_SIGN
Definition: mkdosfs.c:381
#define GENERIC_READ
Definition: compat.h:124
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
Definition: time.h:76
_dev_t st_rdev
Definition: stat.h:62
#define close
Definition: acwin.h:74
#define err(...)
_CRTIMP struct tm *__cdecl localtime(const time_t *_Time)
Definition: time.h:426
#define SYNCHRONIZE
Definition: nt_native.h:61
__u8 sectors[2]
Definition: mkdosfs.c:428
static int reserved_sectors
Definition: mkdosfs.c:531
#define CF_LE_W(v)
Definition: mkdosfs.c:94
__u8 ext_boot_sign
Definition: mkdosfs.c:412
__u8 volume_label[11]
Definition: mkdosfs.c:414
#define O_RANDOM
Definition: mkdosfs.c:298
static void fatal_error(const char *fmt_string) __attribute__((noreturn))
Definition: mkdosfs.c:577
unsigned __int64 __u64
Definition: types.h:27
unsigned long ulong
Definition: linux.h:275
__u16 fat_length
Definition: mkdosfs.c:430
static int valid_offset(int fd, loff_t offset)
Definition: mkdosfs.c:766
static unsigned char * info_sector
Definition: mkdosfs.c:543
__u16 date
Definition: mkdosfs.c:476
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
static char volume_name[]
Definition: mkdosfs.c:526
static unsigned int currently_testing
Definition: mkdosfs.c:538
#define va_arg(ap, T)
Definition: acmsvcex.h:89
const XML_Char XML_Encoding * info
Definition: expat.h:530
DWORD *typedef HANDLE
Definition: winlogon.h:52
static HANDLE fd
Definition: io.c:55
__u32 next_cluster
Definition: mkdosfs.c:461
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
LPVOID lpSecurityDescriptor
Definition: compat.h:181
static void alarm_intr(int alnum)
Definition: mkdosfs.c:668
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
__u8 fs_type[8]
Definition: mkdosfs.c:415
__kernel_time_t time_t
Definition: linux.h:252
#define FILE_FLAG_SEQUENTIAL_SCAN
Definition: disk.h:43
int opterr
Definition: getopt.c:46
__u16 date
Definition: mkdosfs.c:366
#define O_RDWR
Definition: fcntl.h:36
#define f
Definition: ke_i.h:83
GLsizeiptr size
Definition: glext.h:5919
const char * optarg
Definition: getopt.c:49
#define MAX_CLUST_12
Definition: mkdosfs.c:388
Definition: services.c:311
uint32_t root_cluster
Definition: fsck.fat.h:55
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define CreateFile
Definition: winbase.h:3511
static loff_t llseek(int fd, loff_t offset, int whence)
Definition: mkdosfs.c:321
int tm_sec
Definition: time.h:77
static int check
Definition: mkdosfs.c:522
#define EOF
Definition: stdio.h:24
Definition: name.c:23
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
#define BOOTCODE_FAT32_SIZE
Definition: mkdosfs.c:401
GLuint res
Definition: glext.h:9613
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
_CRTIMP int __cdecl fstat(int _Desc, struct stat *_Stat)
Definition: stat.h:341
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define CF_LE_L(v)
Definition: mkdosfs.c:95
#define c
Definition: ke_i.h:80
int tm_hour
Definition: time.h:79
FILE * stderr
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char name[8]
Definition: mkdosfs.c:468
__u32 free_clusters
Definition: mkdosfs.c:460
#define CT_LE_W(v)
Definition: mkdosfs.c:97
#define malloc
Definition: debug_ros.c:4
#define die(str)
Definition: mkdosfs.c:347
#define CREATE_NEW
Definition: disk.h:69
#define TRUNCATE_EXISTING
Definition: disk.h:71
UINT32 uint
Definition: types.h:83
__u16 time
Definition: mkdosfs.c:476
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
#define GEMDOS_MAX_SECTORS
Definition: mkdosfs.c:397
static int size_root_dir
Definition: mkdosfs.c:545
static int verbose
Definition: mkdosfs.c:523
#define TEST_BUFFER_BLOCKS
Definition: mkdosfs.c:338
static struct msdos_boot_sector bs
Definition: mkdosfs.c:539
#define BOOTCODE_SIZE
Definition: mkdosfs.c:400
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
static const struct access_res create[16]
Definition: package.c:7990
#define memset(x, y, z)
Definition: compat.h:39
#define MSDOS_FAT12_SIGN
Definition: mkdosfs.c:382
#define O_CREAT
Definition: acwin.h:84
static unsigned char * fat
Definition: mkdosfs.c:542
static int nr_fats
Definition: mkdosfs.c:533
#define VERSION
Definition: rdesktop.h:45
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define TRUE
Definition: mkdosfs.c:335
__u8 boot_jump[3]
Definition: mkdosfs.c:420
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
#define __int64
Definition: basetyps.h:16
static int root_dir_entries
Definition: mkdosfs.c:547
#define HARD_SECTOR_SIZE
Definition: mkdosfs.c:339
#define DELETE
Definition: nt_native.h:57
__u8 boot_code[BOOTCODE_SIZE]
Definition: mkdosfs.c:438
LONGLONG QuadPart
Definition: typedefs.h:112
#define O_APPEND
Definition: fcntl.h:37
#define FILE_FLAG_RANDOM_ACCESS
Definition: disk.h:44
_off_t st_size
Definition: stat.h:63
#define printf
Definition: config.h:203
GLintptr offset
Definition: glext.h:5920
__u16 start
Definition: mkdosfs.c:476
#define GEMDOS_MAX_SECTOR_SIZE
Definition: mkdosfs.c:398
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29
INT x
Definition: msvc.h:62
#define O_RDONLY
Definition: acwin.h:82