blob: f6c6519d08ef28af30fa5a9110ee1979344284fb [file] [log] [blame]
Matt Mower18794c82015-11-11 16:22:45 -06001/* mkfs.fat.c - utility to create FAT/MS-DOS filesystems
bigbiff bigbiff9c754052013-01-09 09:09:08 -05002
3 Copyright (C) 1991 Linus Torvalds <torvalds@klaava.helsinki.fi>
4 Copyright (C) 1992-1993 Remy Card <card@masi.ibp.fr>
5 Copyright (C) 1993-1994 David Hudson <dave@humbug.demon.co.uk>
6 Copyright (C) 1998 H. Peter Anvin <hpa@zytor.com>
7 Copyright (C) 1998-2005 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
Matt Mower18794c82015-11-11 16:22:45 -06008 Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
bigbiff bigbiff9c754052013-01-09 09:09:08 -05009
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
Matt Mower18794c82015-11-11 16:22:45 -060023 The complete text of the GNU General Public License
bigbiff bigbiff9c754052013-01-09 09:09:08 -050024 can be found in /usr/share/common-licenses/GPL-3 file.
25*/
26
27/* Description: Utility to allow an MS-DOS filesystem to be created
28 under Linux. A lot of the basic structure of this program has been
29 borrowed from Remy Card's "mke2fs" code.
30
Matt Mower18794c82015-11-11 16:22:45 -060031 As far as possible the aim here is to make the "mkfs.fat" command
bigbiff bigbiff9c754052013-01-09 09:09:08 -050032 look almost identical to the other Linux filesystem make utilties,
33 eg bad blocks are still specified as blocks, not sectors, but when
34 it comes down to it, DOS is tied to the idea of a sector (512 bytes
35 as a rule), and not the block. For example the boot block does not
36 occupy a full cluster.
37
38 Fixes/additions May 1998 by Roman Hodek
39 <Roman.Hodek@informatik.uni-erlangen.de>:
40 - Atari format support
41 - New options -A, -S, -C
42 - Support for filesystems > 2GB
43 - FAT32 support */
44
45/* Include the header files */
46
47#include "version.h"
48
49#include <fcntl.h>
50#include <linux/hdreg.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050051#include <sys/mount.h>
Matt Mower18794c82015-11-11 16:22:45 -060052#include <linux/fs.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050053#include <linux/fd.h>
54#include <endian.h>
55#include <mntent.h>
56#include <signal.h>
57#include <string.h>
58#include <stdio.h>
59#include <stdlib.h>
60#include <sys/ioctl.h>
61#include <sys/stat.h>
62#include <sys/time.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050063#include <unistd.h>
64#include <time.h>
65#include <errno.h>
Matt Mower18794c82015-11-11 16:22:45 -060066#include <ctype.h>
67#include <stdint.h>
68#include <endian.h>
69#include <getopt.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050070
Matt Mower18794c82015-11-11 16:22:45 -060071#include "msdos_fs.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050072
73/* In earlier versions, an own llseek() was used, but glibc lseek() is
74 * sufficient (or even better :) for 64 bit offsets in the meantime */
Dees_Troy00bc7022013-01-31 21:46:57 +000075#define llseek lseek64
bigbiff bigbiff9c754052013-01-09 09:09:08 -050076
77/* Constant definitions */
78
79#define TRUE 1 /* Boolean constants */
80#define FALSE 0
81
82#define TEST_BUFFER_BLOCKS 16
83#define HARD_SECTOR_SIZE 512
84#define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE )
85
Matt Mower18794c82015-11-11 16:22:45 -060086#define NO_NAME "NO NAME "
87
bigbiff bigbiff9c754052013-01-09 09:09:08 -050088/* Macro definitions */
89
90/* Report a failure message and return a failure error code */
91
92#define die( str ) fatal_error( "%s: " str "\n" )
93
94/* Mark a cluster in the FAT as bad */
95
96#define mark_sector_bad( sector ) mark_FAT_sector( sector, FAT_BAD )
97
98/* Compute ceil(a/b) */
99
Matt Mower18794c82015-11-11 16:22:45 -0600100static inline int cdiv(int a, int b)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500101{
102 return (a + b - 1) / b;
103}
104
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500105/* FAT values */
106#define FAT_EOF (atari_format ? 0x0fffffff : 0x0ffffff8)
107#define FAT_BAD 0x0ffffff7
108
109#define MSDOS_EXT_SIGN 0x29 /* extended boot sector signature */
110#define MSDOS_FAT12_SIGN "FAT12 " /* FAT12 filesystem signature */
111#define MSDOS_FAT16_SIGN "FAT16 " /* FAT16 filesystem signature */
112#define MSDOS_FAT32_SIGN "FAT32 " /* FAT32 filesystem signature */
113
114#define BOOT_SIGN 0xAA55 /* Boot sector magic number */
115
116#define MAX_CLUST_12 ((1 << 12) - 16)
117#define MAX_CLUST_16 ((1 << 16) - 16)
118#define MIN_CLUST_32 65529
119/* M$ says the high 4 bits of a FAT32 FAT entry are reserved and don't belong
120 * to the cluster number. So the max. cluster# is based on 2^28 */
121#define MAX_CLUST_32 ((1 << 28) - 16)
122
123#define FAT12_THRESHOLD 4085
124
125#define OLDGEMDOS_MAX_SECTORS 32765
126#define GEMDOS_MAX_SECTORS 65531
127#define GEMDOS_MAX_SECTOR_SIZE (16*1024)
128
129#define BOOTCODE_SIZE 448
130#define BOOTCODE_FAT32_SIZE 420
131
132/* __attribute__ ((packed)) is used on all structures to make gcc ignore any
133 * alignments */
134
135struct msdos_volume_info {
Matt Mower18794c82015-11-11 16:22:45 -0600136 uint8_t drive_number; /* BIOS drive number */
137 uint8_t RESERVED; /* Unused */
138 uint8_t ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
139 uint8_t volume_id[4]; /* Volume ID number */
140 uint8_t volume_label[11]; /* Volume label */
141 uint8_t fs_type[8]; /* Typically FAT12 or FAT16 */
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500142} __attribute__ ((packed));
143
144struct msdos_boot_sector {
Matt Mower18794c82015-11-11 16:22:45 -0600145 uint8_t boot_jump[3]; /* Boot strap short or near jump */
146 uint8_t system_id[8]; /* Name - can be used to special case
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500147 partition manager volumes */
Matt Mower18794c82015-11-11 16:22:45 -0600148 uint8_t sector_size[2]; /* bytes per logical sector */
149 uint8_t cluster_size; /* sectors/cluster */
150 uint16_t reserved; /* reserved sectors */
151 uint8_t fats; /* number of FATs */
152 uint8_t dir_entries[2]; /* root directory entries */
153 uint8_t sectors[2]; /* number of sectors */
154 uint8_t media; /* media code (unused) */
155 uint16_t fat_length; /* sectors/FAT */
156 uint16_t secs_track; /* sectors per track */
157 uint16_t heads; /* number of heads */
158 uint32_t hidden; /* hidden sectors (unused) */
159 uint32_t total_sect; /* number of sectors (if sectors == 0) */
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500160 union {
161 struct {
162 struct msdos_volume_info vi;
Matt Mower18794c82015-11-11 16:22:45 -0600163 uint8_t boot_code[BOOTCODE_SIZE];
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500164 } __attribute__ ((packed)) _oldfat;
165 struct {
Matt Mower18794c82015-11-11 16:22:45 -0600166 uint32_t fat32_length; /* sectors/FAT */
167 uint16_t flags; /* bit 8: fat mirroring, low 4: active fat */
168 uint8_t version[2]; /* major, minor filesystem version */
169 uint32_t root_cluster; /* first cluster in root directory */
170 uint16_t info_sector; /* filesystem info sector */
171 uint16_t backup_boot; /* backup boot sector */
172 uint16_t reserved2[6]; /* Unused */
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500173 struct msdos_volume_info vi;
Matt Mower18794c82015-11-11 16:22:45 -0600174 uint8_t boot_code[BOOTCODE_FAT32_SIZE];
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500175 } __attribute__ ((packed)) _fat32;
176 } __attribute__ ((packed)) fstype;
Matt Mower18794c82015-11-11 16:22:45 -0600177 uint16_t boot_sign;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500178} __attribute__ ((packed));
179#define fat32 fstype._fat32
180#define oldfat fstype._oldfat
181
182struct fat32_fsinfo {
Matt Mower18794c82015-11-11 16:22:45 -0600183 uint32_t reserved1; /* Nothing as far as I can tell */
184 uint32_t signature; /* 0x61417272L */
185 uint32_t free_clusters; /* Free cluster count. -1 if unknown */
186 uint32_t next_cluster; /* Most recently allocated cluster.
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500187 * Unused under Linux. */
Matt Mower18794c82015-11-11 16:22:45 -0600188 uint32_t reserved2[4];
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500189};
190
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500191/* The "boot code" we put into the filesystem... it writes a message and
192 tells the user to try again */
193
Matt Mower18794c82015-11-11 16:22:45 -0600194unsigned char dummy_boot_jump[3] = { 0xeb, 0x3c, 0x90 };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500195
Matt Mower18794c82015-11-11 16:22:45 -0600196unsigned char dummy_boot_jump_m68k[2] = { 0x60, 0x1c };
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500197
198#define MSG_OFFSET_OFFSET 3
199char dummy_boot_code[BOOTCODE_SIZE] = "\x0e" /* push cs */
200 "\x1f" /* pop ds */
201 "\xbe\x5b\x7c" /* mov si, offset message_txt */
202 /* write_msg: */
203 "\xac" /* lodsb */
204 "\x22\xc0" /* and al, al */
205 "\x74\x0b" /* jz key_press */
206 "\x56" /* push si */
207 "\xb4\x0e" /* mov ah, 0eh */
208 "\xbb\x07\x00" /* mov bx, 0007h */
209 "\xcd\x10" /* int 10h */
210 "\x5e" /* pop si */
211 "\xeb\xf0" /* jmp write_msg */
212 /* key_press: */
213 "\x32\xe4" /* xor ah, ah */
214 "\xcd\x16" /* int 16h */
215 "\xcd\x19" /* int 19h */
216 "\xeb\xfe" /* foo: jmp foo */
217 /* message_txt: */
218 "This is not a bootable disk. Please insert a bootable floppy and\r\n"
219 "press any key to try again ... \r\n";
220
221#define MESSAGE_OFFSET 29 /* Offset of message in above code */
222
223/* Global variables - the root of all evil :-) - see these and weep! */
224
Matt Mower18794c82015-11-11 16:22:45 -0600225static const char *program_name = "mkfs.fat"; /* Name of the program */
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500226static char *device_name = NULL; /* Name of the device on which to create the filesystem */
227static int atari_format = 0; /* Use Atari variation of MS-DOS FS format */
228static int check = FALSE; /* Default to no readablity checking */
229static int verbose = 0; /* Default to verbose mode off */
230static long volume_id; /* Volume ID number */
231static time_t create_time; /* Creation time */
Matt Mower18794c82015-11-11 16:22:45 -0600232static char volume_name[] = NO_NAME; /* Volume name */
233static uint64_t blocks; /* Number of blocks in filesystem */
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500234static int sector_size = 512; /* Size of a logical sector */
235static int sector_size_set = 0; /* User selected sector size */
236static int backup_boot = 0; /* Sector# of backup boot sector */
237static int reserved_sectors = 0; /* Number of reserved sectors */
238static int badblocks = 0; /* Number of bad blocks in the filesystem */
239static int nr_fats = 2; /* Default number of FATs to produce */
240static int size_fat = 0; /* Size in bits of FAT entries */
241static int size_fat_by_user = 0; /* 1 if FAT size user selected */
242static int dev = -1; /* FS block device file handle */
243static int ignore_full_disk = 0; /* Ignore warning about 'full' disk devices */
244static off_t currently_testing = 0; /* Block currently being tested (if autodetect bad blocks) */
245static struct msdos_boot_sector bs; /* Boot sector data */
246static int start_data_sector; /* Sector number for the start of the data area */
247static int start_data_block; /* Block number for the start of the data area */
248static unsigned char *fat; /* File allocation table */
249static unsigned alloced_fat_length; /* # of FAT sectors we can keep in memory */
250static unsigned char *info_sector; /* FAT32 info sector */
251static struct msdos_dir_entry *root_dir; /* Root directory */
252static int size_root_dir; /* Size of the root directory in bytes */
253static int sectors_per_cluster = 0; /* Number of sectors per disk cluster */
254static int root_dir_entries = 0; /* Number of root directory entries */
255static char *blank_sector; /* Blank sector - all zeros */
256static int hidden_sectors = 0; /* Number of hidden sectors */
Matt Mower18794c82015-11-11 16:22:45 -0600257static int hidden_sectors_by_user = 0; /* -h option invoked */
258static int drive_number_option = 0; /* drive number */
259static int drive_number_by_user = 0; /* drive number option invoked */
260static int fat_media_byte = 0; /* media byte in header and starting FAT */
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500261static int malloc_entire_fat = FALSE; /* Whether we should malloc() the entire FAT or not */
262static int align_structures = TRUE; /* Whether to enforce alignment */
263static int orphaned_sectors = 0; /* Sectors that exist in the last block of filesystem */
Matt Mower18794c82015-11-11 16:22:45 -0600264static int invariant = 0; /* Whether to set normally randomized or
265 current time based values to
266 constants */
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500267
268/* Function prototype definitions */
269
270static void fatal_error(const char *fmt_string) __attribute__ ((noreturn));
271static void mark_FAT_cluster(int cluster, unsigned int value);
272static void mark_FAT_sector(int sector, unsigned int value);
273static long do_check(char *buffer, int try, off_t current_block);
274static void alarm_intr(int alnum);
275static void check_blocks(void);
276static void get_list_blocks(char *filename);
277static int valid_offset(int fd, loff_t offset);
Matt Mower18794c82015-11-11 16:22:45 -0600278static uint64_t count_blocks(char *filename, int *remainder);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500279static void check_mount(char *device_name);
280static void establish_params(int device_num, int size);
281static void setup_tables(void);
282static void write_tables(void);
283
284/* The function implementations */
285
286/* Handle the reporting of fatal errors. Volatile to let gcc know that this doesn't return */
287
288static void fatal_error(const char *fmt_string)
289{
290 fprintf(stderr, fmt_string, program_name, device_name);
291 exit(1); /* The error exit code is 1! */
292}
293
294/* Mark the specified cluster as having a particular value */
295
296static void mark_FAT_cluster(int cluster, unsigned int value)
297{
298 switch (size_fat) {
299 case 12:
300 value &= 0x0fff;
301 if (((cluster * 3) & 0x1) == 0) {
302 fat[3 * cluster / 2] = (unsigned char)(value & 0x00ff);
303 fat[(3 * cluster / 2) + 1] =
304 (unsigned char)((fat[(3 * cluster / 2) + 1] & 0x00f0)
305 | ((value & 0x0f00) >> 8));
306 } else {
307 fat[3 * cluster / 2] =
308 (unsigned char)((fat[3 * cluster / 2] & 0x000f) |
309 ((value & 0x000f) << 4));
310 fat[(3 * cluster / 2) + 1] = (unsigned char)((value & 0x0ff0) >> 4);
311 }
312 break;
313
314 case 16:
315 value &= 0xffff;
316 fat[2 * cluster] = (unsigned char)(value & 0x00ff);
317 fat[(2 * cluster) + 1] = (unsigned char)(value >> 8);
318 break;
319
320 case 32:
321 value &= 0xfffffff;
322 fat[4 * cluster] = (unsigned char)(value & 0x000000ff);
323 fat[(4 * cluster) + 1] = (unsigned char)((value & 0x0000ff00) >> 8);
324 fat[(4 * cluster) + 2] = (unsigned char)((value & 0x00ff0000) >> 16);
325 fat[(4 * cluster) + 3] = (unsigned char)((value & 0xff000000) >> 24);
326 break;
327
328 default:
329 die("Bad FAT size (not 12, 16, or 32)");
330 }
331}
332
333/* Mark a specified sector as having a particular value in it's FAT entry */
334
335static void mark_FAT_sector(int sector, unsigned int value)
336{
337 int cluster;
338
339 cluster = (sector - start_data_sector) / (int)(bs.cluster_size) /
340 (sector_size / HARD_SECTOR_SIZE);
341 if (cluster < 0)
342 die("Invalid cluster number in mark_FAT_sector: probably bug!");
343
344 mark_FAT_cluster(cluster, value);
345}
346
347/* Perform a test on a block. Return the number of blocks that could be read successfully */
348
349static long do_check(char *buffer, int try, off_t current_block)
350{
351 long got;
352
353 if (llseek(dev, current_block * BLOCK_SIZE, SEEK_SET) /* Seek to the correct location */
354 !=current_block * BLOCK_SIZE)
355 die("seek failed during testing for blocks");
356
357 got = read(dev, buffer, try * BLOCK_SIZE); /* Try reading! */
358 if (got < 0)
359 got = 0;
360
361 if (got & (BLOCK_SIZE - 1))
362 printf("Unexpected values in do_check: probably bugs\n");
363 got /= BLOCK_SIZE;
364
365 return got;
366}
367
368/* Alarm clock handler - display the status of the quest for bad blocks! Then retrigger the alarm for five senconds
369 later (so we can come here again) */
370
371static void alarm_intr(int alnum)
372{
Matt Mower18794c82015-11-11 16:22:45 -0600373 (void)alnum;
374
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500375 if (currently_testing >= blocks)
376 return;
377
378 signal(SIGALRM, alarm_intr);
379 alarm(5);
380 if (!currently_testing)
381 return;
382
383 printf("%lld... ", (unsigned long long)currently_testing);
384 fflush(stdout);
385}
386
387static void check_blocks(void)
388{
389 int try, got;
390 int i;
391 static char blkbuf[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
392
393 if (verbose) {
394 printf("Searching for bad blocks ");
395 fflush(stdout);
396 }
397 currently_testing = 0;
398 if (verbose) {
399 signal(SIGALRM, alarm_intr);
400 alarm(5);
401 }
402 try = TEST_BUFFER_BLOCKS;
403 while (currently_testing < blocks) {
404 if (currently_testing + try > blocks)
405 try = blocks - currently_testing;
406 got = do_check(blkbuf, try, currently_testing);
407 currently_testing += got;
408 if (got == try) {
409 try = TEST_BUFFER_BLOCKS;
410 continue;
411 } else
412 try = 1;
413 if (currently_testing < start_data_block)
414 die("bad blocks before data-area: cannot make fs");
415
416 for (i = 0; i < SECTORS_PER_BLOCK; i++) /* Mark all of the sectors in the block as bad */
417 mark_sector_bad(currently_testing * SECTORS_PER_BLOCK + i);
418 badblocks++;
419 currently_testing++;
420 }
421
422 if (verbose)
423 printf("\n");
424
425 if (badblocks)
426 printf("%d bad block%s\n", badblocks, (badblocks > 1) ? "s" : "");
427}
428
429static void get_list_blocks(char *filename)
430{
431 int i;
432 FILE *listfile;
Matt Mower18794c82015-11-11 16:22:45 -0600433 long blockno;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500434
435 listfile = fopen(filename, "r");
436 if (listfile == (FILE *) NULL)
437 die("Can't open file of bad blocks");
438
439 while (!feof(listfile)) {
440 fscanf(listfile, "%ld\n", &blockno);
441 for (i = 0; i < SECTORS_PER_BLOCK; i++) /* Mark all of the sectors in the block as bad */
442 mark_sector_bad(blockno * SECTORS_PER_BLOCK + i);
443 badblocks++;
444 }
445 fclose(listfile);
446
447 if (badblocks)
448 printf("%d bad block%s\n", badblocks, (badblocks > 1) ? "s" : "");
449}
450
451/* Given a file descriptor and an offset, check whether the offset is a valid offset for the file - return FALSE if it
452 isn't valid or TRUE if it is */
453
454static int valid_offset(int fd, loff_t offset)
455{
456 char ch;
457
458 if (llseek(fd, offset, SEEK_SET) < 0)
459 return FALSE;
460 if (read(fd, &ch, 1) < 1)
461 return FALSE;
462 return TRUE;
463}
464
465/* Given a filename, look to see how many blocks of BLOCK_SIZE are present, returning the answer */
466
Matt Mower18794c82015-11-11 16:22:45 -0600467static uint64_t count_blocks(char *filename, int *remainder)
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500468{
469 loff_t high, low;
470 int fd;
471
472 if ((fd = open(filename, O_RDONLY)) < 0) {
473 perror(filename);
474 exit(1);
475 }
476
477 /* first try SEEK_END, which should work on most devices nowadays */
478 if ((low = llseek(fd, 0, SEEK_END)) <= 0) {
479 low = 0;
480 for (high = 1; valid_offset(fd, high); high *= 2)
481 low = high;
482 while (low < high - 1) {
483 const loff_t mid = (low + high) / 2;
484 if (valid_offset(fd, mid))
485 low = mid;
486 else
487 high = mid;
488 }
489 ++low;
490 }
491
492 close(fd);
Matt Mower18794c82015-11-11 16:22:45 -0600493 *remainder = (low % BLOCK_SIZE) / sector_size;
494 return (low / BLOCK_SIZE);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500495}
496
497/* Check to see if the specified device is currently mounted - abort if it is */
498
499static void check_mount(char *device_name)
500{
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500501 FILE *f;
502 struct mntent *mnt;
503
504 if ((f = setmntent(MOUNTED, "r")) == NULL)
505 return;
506 while ((mnt = getmntent(f)) != NULL)
507 if (strcmp(device_name, mnt->mnt_fsname) == 0)
Matt Mower18794c82015-11-11 16:22:45 -0600508 die("%s contains a mounted filesystem.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500509 endmntent(f);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500510}
511
512/* Establish the geometry and media parameters for the device */
513
514static void establish_params(int device_num, int size)
515{
516 long loop_size;
517 struct hd_geometry geometry;
518 struct floppy_struct param;
519 int def_root_dir_entries = 512;
520
521 if ((0 == device_num) || ((device_num & 0xff00) == 0x0200))
522 /* file image or floppy disk */
523 {
524 if (0 == device_num) {
525 param.size = size / 512;
526 switch (param.size) {
527 case 720:
528 param.sect = 9;
529 param.head = 2;
530 break;
531 case 1440:
532 param.sect = 9;
533 param.head = 2;
534 break;
535 case 2400:
536 param.sect = 15;
537 param.head = 2;
538 break;
539 case 2880:
540 param.sect = 18;
541 param.head = 2;
542 break;
543 case 5760:
544 param.sect = 36;
545 param.head = 2;
546 break;
547 default:
548 /* fake values */
549 param.sect = 32;
550 param.head = 64;
551 break;
552 }
553
554 } else { /* is a floppy diskette */
555
556 if (ioctl(dev, FDGETPRM, &param)) /* Can we get the diskette geometry? */
557 die("unable to get diskette geometry for '%s'");
558 }
Matt Mower18794c82015-11-11 16:22:45 -0600559 bs.secs_track = htole16(param.sect); /* Set up the geometry information */
560 bs.heads = htole16(param.head);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500561 switch (param.size) { /* Set up the media descriptor byte */
562 case 720: /* 5.25", 2, 9, 40 - 360K */
563 bs.media = (char)0xfd;
564 bs.cluster_size = (char)2;
565 def_root_dir_entries = 112;
566 break;
567
568 case 1440: /* 3.5", 2, 9, 80 - 720K */
569 bs.media = (char)0xf9;
570 bs.cluster_size = (char)2;
571 def_root_dir_entries = 112;
572 break;
573
574 case 2400: /* 5.25", 2, 15, 80 - 1200K */
575 bs.media = (char)0xf9;
576 bs.cluster_size = (char)(atari_format ? 2 : 1);
577 def_root_dir_entries = 224;
578 break;
579
580 case 5760: /* 3.5", 2, 36, 80 - 2880K */
581 bs.media = (char)0xf0;
582 bs.cluster_size = (char)2;
583 def_root_dir_entries = 224;
584 break;
585
586 case 2880: /* 3.5", 2, 18, 80 - 1440K */
587floppy_default:
588 bs.media = (char)0xf0;
589 bs.cluster_size = (char)(atari_format ? 2 : 1);
590 def_root_dir_entries = 224;
591 break;
592
593 default: /* Anything else */
594 if (0 == device_num)
595 goto def_hd_params;
596 else
597 goto floppy_default;
598 }
599 } else if ((device_num & 0xff00) == 0x0700) { /* This is a loop device */
600 if (ioctl(dev, BLKGETSIZE, &loop_size))
601 die("unable to get loop device size");
602
603 switch (loop_size) { /* Assuming the loop device -> floppy later */
604 case 720: /* 5.25", 2, 9, 40 - 360K */
Matt Mower18794c82015-11-11 16:22:45 -0600605 bs.secs_track = le16toh(9);
606 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500607 bs.media = (char)0xfd;
608 bs.cluster_size = (char)2;
609 def_root_dir_entries = 112;
610 break;
611
612 case 1440: /* 3.5", 2, 9, 80 - 720K */
Matt Mower18794c82015-11-11 16:22:45 -0600613 bs.secs_track = le16toh(9);
614 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500615 bs.media = (char)0xf9;
616 bs.cluster_size = (char)2;
617 def_root_dir_entries = 112;
618 break;
619
620 case 2400: /* 5.25", 2, 15, 80 - 1200K */
Matt Mower18794c82015-11-11 16:22:45 -0600621 bs.secs_track = le16toh(15);
622 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500623 bs.media = (char)0xf9;
624 bs.cluster_size = (char)(atari_format ? 2 : 1);
625 def_root_dir_entries = 224;
626 break;
627
628 case 5760: /* 3.5", 2, 36, 80 - 2880K */
Matt Mower18794c82015-11-11 16:22:45 -0600629 bs.secs_track = le16toh(36);
630 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500631 bs.media = (char)0xf0;
632 bs.cluster_size = (char)2;
633 bs.dir_entries[0] = (char)224;
634 bs.dir_entries[1] = (char)0;
635 break;
636
637 case 2880: /* 3.5", 2, 18, 80 - 1440K */
Matt Mower18794c82015-11-11 16:22:45 -0600638 bs.secs_track = le16toh(18);
639 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500640 bs.media = (char)0xf0;
641 bs.cluster_size = (char)(atari_format ? 2 : 1);
642 def_root_dir_entries = 224;
643 break;
644
645 default: /* Anything else: default hd setup */
646 printf("Loop device does not match a floppy size, using "
647 "default hd params\n");
Matt Mower18794c82015-11-11 16:22:45 -0600648 bs.secs_track = htole16(32); /* these are fake values... */
649 bs.heads = htole16(64);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500650 goto def_hd_params;
651 }
652 } else
653 /* Must be a hard disk then! */
654 {
655 /* Can we get the drive geometry? (Note I'm not too sure about */
656 /* whether to use HDIO_GETGEO or HDIO_REQ) */
657 if (ioctl(dev, HDIO_GETGEO, &geometry) || geometry.sectors == 0
658 || geometry.heads == 0) {
659 printf("unable to get drive geometry, using default 255/63\n");
Matt Mower18794c82015-11-11 16:22:45 -0600660 bs.secs_track = htole16(63);
661 bs.heads = htole16(255);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500662 } else {
Matt Mower18794c82015-11-11 16:22:45 -0600663 bs.secs_track = htole16(geometry.sectors); /* Set up the geometry information */
664 bs.heads = htole16(geometry.heads);
665 if (!hidden_sectors_by_user)
666 hidden_sectors = htole32(geometry.start);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500667 }
668def_hd_params:
669 bs.media = (char)0xf8; /* Set up the media descriptor for a hard drive */
670 if (!size_fat && blocks * SECTORS_PER_BLOCK > 1064960) {
671 if (verbose)
672 printf("Auto-selecting FAT32 for large filesystem\n");
673 size_fat = 32;
674 }
675 if (size_fat == 32) {
676 /* For FAT32, try to do the same as M$'s format command
677 * (see http://www.win.tue.nl/~aeb/linux/fs/fat/fatgen103.pdf p. 20):
678 * fs size <= 260M: 0.5k clusters
Matt Mower18794c82015-11-11 16:22:45 -0600679 * fs size <= 8G: 4k clusters
680 * fs size <= 16G: 8k clusters
681 * fs size <= 32G: 16k clusters
682 * fs size > 32G: 32k clusters
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500683 */
Matt Mower18794c82015-11-11 16:22:45 -0600684 uint32_t sz_mb =
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500685 (blocks + (1 << (20 - BLOCK_SIZE_BITS)) - 1) >> (20 -
686 BLOCK_SIZE_BITS);
687 bs.cluster_size =
Matt Mower18794c82015-11-11 16:22:45 -0600688 sz_mb > 32 * 1024 ? 64 : sz_mb > 16 * 1024 ? 32 : sz_mb >
689 8 * 1024 ? 16 : sz_mb > 260 ? 8 : 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500690 } else {
691 /* FAT12 and FAT16: start at 4 sectors per cluster */
692 bs.cluster_size = (char)4;
693 }
694 }
695
696 if (!root_dir_entries)
697 root_dir_entries = def_root_dir_entries;
698}
699
700/*
701 * If alignment is enabled, round the first argument up to the second; the
702 * latter must be a power of two.
703 */
704static unsigned int align_object(unsigned int sectors, unsigned int clustsize)
705{
706 if (align_structures)
707 return (sectors + clustsize - 1) & ~(clustsize - 1);
708 else
709 return sectors;
710}
711
712/* Create the filesystem data tables */
713
714static void setup_tables(void)
715{
716 unsigned num_sectors;
717 unsigned cluster_count = 0, fat_length;
718 struct tm *ctime;
719 struct msdos_volume_info *vi =
720 (size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
721
Matt Mower18794c82015-11-11 16:22:45 -0600722 if (atari_format) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500723 /* On Atari, the first few bytes of the boot sector are assigned
724 * differently: The jump code is only 2 bytes (and m68k machine code
725 * :-), then 6 bytes filler (ignored), then 3 byte serial number. */
Matt Mower18794c82015-11-11 16:22:45 -0600726 bs.boot_jump[2] = 'm';
727 memcpy((char *)bs.system_id, "kdosf", strlen("kdosf"));
728 } else
729 memcpy((char *)bs.system_id, "mkfs.fat", strlen("mkfs.fat"));
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500730 if (sectors_per_cluster)
731 bs.cluster_size = (char)sectors_per_cluster;
Matt Mower18794c82015-11-11 16:22:45 -0600732
733 if (fat_media_byte)
734 bs.media = (char) fat_media_byte;
735
736 if (bs.media == 0xf8)
737 vi->drive_number=0x80;
738 else
739 vi->drive_number=0x00;
740
741 if (drive_number_by_user)
742 vi->drive_number= (char) drive_number_option;
743
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500744 if (size_fat == 32) {
745 /* Under FAT32, the root dir is in a cluster chain, and this is
746 * signalled by bs.dir_entries being 0. */
747 root_dir_entries = 0;
748 }
749
750 if (atari_format) {
751 bs.system_id[5] = (unsigned char)(volume_id & 0x000000ff);
752 bs.system_id[6] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
753 bs.system_id[7] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
754 } else {
755 vi->volume_id[0] = (unsigned char)(volume_id & 0x000000ff);
756 vi->volume_id[1] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
757 vi->volume_id[2] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
758 vi->volume_id[3] = (unsigned char)(volume_id >> 24);
759 }
760
761 if (!atari_format) {
762 memcpy(vi->volume_label, volume_name, 11);
763
764 memcpy(bs.boot_jump, dummy_boot_jump, 3);
765 /* Patch in the correct offset to the boot code */
766 bs.boot_jump[1] = ((size_fat == 32 ?
767 (char *)&bs.fat32.boot_code :
768 (char *)&bs.oldfat.boot_code) - (char *)&bs) - 2;
769
770 if (size_fat == 32) {
771 int offset = (char *)&bs.fat32.boot_code -
772 (char *)&bs + MESSAGE_OFFSET + 0x7c00;
773 if (dummy_boot_code[BOOTCODE_FAT32_SIZE - 1])
774 printf("Warning: message too long; truncated\n");
775 dummy_boot_code[BOOTCODE_FAT32_SIZE - 1] = 0;
776 memcpy(bs.fat32.boot_code, dummy_boot_code, BOOTCODE_FAT32_SIZE);
777 bs.fat32.boot_code[MSG_OFFSET_OFFSET] = offset & 0xff;
778 bs.fat32.boot_code[MSG_OFFSET_OFFSET + 1] = offset >> 8;
779 } else {
780 memcpy(bs.oldfat.boot_code, dummy_boot_code, BOOTCODE_SIZE);
781 }
Matt Mower18794c82015-11-11 16:22:45 -0600782 bs.boot_sign = htole16(BOOT_SIGN);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500783 } else {
784 memcpy(bs.boot_jump, dummy_boot_jump_m68k, 2);
785 }
786 if (verbose >= 2)
787 printf("Boot jump code is %02x %02x\n",
788 bs.boot_jump[0], bs.boot_jump[1]);
789
790 if (!reserved_sectors)
791 reserved_sectors = (size_fat == 32) ? 32 : 1;
792 else {
793 if (size_fat == 32 && reserved_sectors < 2)
794 die("On FAT32 at least 2 reserved sectors are needed.");
795 }
Matt Mower18794c82015-11-11 16:22:45 -0600796 bs.reserved = htole16(reserved_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500797 if (verbose >= 2)
798 printf("Using %d reserved sectors\n", reserved_sectors);
799 bs.fats = (char)nr_fats;
800 if (!atari_format || size_fat == 32)
Matt Mower18794c82015-11-11 16:22:45 -0600801 bs.hidden = htole32(hidden_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500802 else {
803 /* In Atari format, hidden is a 16 bit field */
Matt Mower18794c82015-11-11 16:22:45 -0600804 uint16_t hidden = htole16(hidden_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500805 if (hidden_sectors & ~0xffff)
806 die("#hidden doesn't fit in 16bit field of Atari format\n");
807 memcpy(&bs.hidden, &hidden, 2);
808 }
809
Matt Mower18794c82015-11-11 16:22:45 -0600810 num_sectors =
811 (long long)(blocks * BLOCK_SIZE / sector_size) + orphaned_sectors;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500812
813 if (!atari_format) {
814 unsigned fatdata1216; /* Sectors for FATs + data area (FAT12/16) */
815 unsigned fatdata32; /* Sectors for FATs + data area (FAT32) */
816 unsigned fatlength12, fatlength16, fatlength32;
817 unsigned maxclust12, maxclust16, maxclust32;
818 unsigned clust12, clust16, clust32;
819 int maxclustsize;
820 unsigned root_dir_sectors = cdiv(root_dir_entries * 32, sector_size);
821
822 /*
823 * If the filesystem is 8192 sectors or less (4 MB with 512-byte
824 * sectors, i.e. floppy size), don't align the data structures.
825 */
826 if (num_sectors <= 8192) {
827 if (align_structures && verbose >= 2)
828 printf("Disabling alignment due to tiny filesystem\n");
829
830 align_structures = FALSE;
831 }
832
833 if (sectors_per_cluster)
834 bs.cluster_size = maxclustsize = sectors_per_cluster;
835 else
836 /* An initial guess for bs.cluster_size should already be set */
837 maxclustsize = 128;
838
839 do {
Matt Mower18794c82015-11-11 16:22:45 -0600840 fatdata32 = num_sectors - reserved_sectors;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500841 fatdata1216 = fatdata32
842 - align_object(root_dir_sectors, bs.cluster_size);
843
844 if (verbose >= 2)
845 printf("Trying with %d sectors/cluster:\n", bs.cluster_size);
846
847 /* The factor 2 below avoids cut-off errors for nr_fats == 1.
848 * The "nr_fats*3" is for the reserved first two FAT entries */
849 clust12 = 2 * ((long long)fatdata1216 * sector_size + nr_fats * 3) /
850 (2 * (int)bs.cluster_size * sector_size + nr_fats * 3);
851 fatlength12 = cdiv(((clust12 + 2) * 3 + 1) >> 1, sector_size);
852 fatlength12 = align_object(fatlength12, bs.cluster_size);
853 /* Need to recalculate number of clusters, since the unused parts of the
854 * FATS and data area together could make up space for an additional,
855 * not really present cluster. */
856 clust12 = (fatdata1216 - nr_fats * fatlength12) / bs.cluster_size;
857 maxclust12 = (fatlength12 * 2 * sector_size) / 3;
858 if (maxclust12 > MAX_CLUST_12)
859 maxclust12 = MAX_CLUST_12;
860 if (verbose >= 2)
861 printf("FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
862 clust12, fatlength12, maxclust12, MAX_CLUST_12);
863 if (clust12 > maxclust12 - 2) {
864 clust12 = 0;
865 if (verbose >= 2)
866 printf("FAT12: too much clusters\n");
867 }
868
869 clust16 = ((long long)fatdata1216 * sector_size + nr_fats * 4) /
870 ((int)bs.cluster_size * sector_size + nr_fats * 2);
871 fatlength16 = cdiv((clust16 + 2) * 2, sector_size);
872 fatlength16 = align_object(fatlength16, bs.cluster_size);
873 /* Need to recalculate number of clusters, since the unused parts of the
874 * FATS and data area together could make up space for an additional,
875 * not really present cluster. */
876 clust16 = (fatdata1216 - nr_fats * fatlength16) / bs.cluster_size;
877 maxclust16 = (fatlength16 * sector_size) / 2;
878 if (maxclust16 > MAX_CLUST_16)
879 maxclust16 = MAX_CLUST_16;
880 if (verbose >= 2)
881 printf("FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
882 clust16, fatlength16, maxclust16, MAX_CLUST_16);
883 if (clust16 > maxclust16 - 2) {
884 if (verbose >= 2)
885 printf("FAT16: too much clusters\n");
886 clust16 = 0;
887 }
888 /* The < 4078 avoids that the filesystem will be misdetected as having a
889 * 12 bit FAT. */
890 if (clust16 < FAT12_THRESHOLD
891 && !(size_fat_by_user && size_fat == 16)) {
892 if (verbose >= 2)
893 printf(clust16 < FAT12_THRESHOLD ?
894 "FAT16: would be misdetected as FAT12\n" :
895 "FAT16: too much clusters\n");
896 clust16 = 0;
897 }
898
899 clust32 = ((long long)fatdata32 * sector_size + nr_fats * 8) /
900 ((int)bs.cluster_size * sector_size + nr_fats * 4);
901 fatlength32 = cdiv((clust32 + 2) * 4, sector_size);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500902 /* Need to recalculate number of clusters, since the unused parts of the
903 * FATS and data area together could make up space for an additional,
904 * not really present cluster. */
905 clust32 = (fatdata32 - nr_fats * fatlength32) / bs.cluster_size;
906 maxclust32 = (fatlength32 * sector_size) / 4;
907 if (maxclust32 > MAX_CLUST_32)
908 maxclust32 = MAX_CLUST_32;
909 if (clust32 && clust32 < MIN_CLUST_32
910 && !(size_fat_by_user && size_fat == 32)) {
911 clust32 = 0;
912 if (verbose >= 2)
913 printf("FAT32: not enough clusters (%d)\n", MIN_CLUST_32);
914 }
915 if (verbose >= 2)
916 printf("FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
917 clust32, fatlength32, maxclust32, MAX_CLUST_32);
918 if (clust32 > maxclust32) {
919 clust32 = 0;
920 if (verbose >= 2)
921 printf("FAT32: too much clusters\n");
922 }
923
924 if ((clust12 && (size_fat == 0 || size_fat == 12)) ||
925 (clust16 && (size_fat == 0 || size_fat == 16)) ||
926 (clust32 && size_fat == 32))
927 break;
928
929 bs.cluster_size <<= 1;
930 } while (bs.cluster_size && bs.cluster_size <= maxclustsize);
931
932 /* Use the optimal FAT size if not specified;
933 * FAT32 is (not yet) choosen automatically */
934 if (!size_fat) {
935 size_fat = (clust16 > clust12) ? 16 : 12;
936 if (verbose >= 2)
937 printf("Choosing %d bits for FAT\n", size_fat);
938 }
939
940 switch (size_fat) {
941 case 12:
942 cluster_count = clust12;
943 fat_length = fatlength12;
Matt Mower18794c82015-11-11 16:22:45 -0600944 bs.fat_length = htole16(fatlength12);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500945 memcpy(vi->fs_type, MSDOS_FAT12_SIGN, 8);
946 break;
947
948 case 16:
949 if (clust16 < FAT12_THRESHOLD) {
950 if (size_fat_by_user) {
951 fprintf(stderr, "WARNING: Not enough clusters for a "
952 "16 bit FAT! The filesystem will be\n"
953 "misinterpreted as having a 12 bit FAT without "
954 "mount option \"fat=16\".\n");
955 } else {
956 fprintf(stderr, "This filesystem has an unfortunate size. "
957 "A 12 bit FAT cannot provide\n"
958 "enough clusters, but a 16 bit FAT takes up a little "
959 "bit more space so that\n"
960 "the total number of clusters becomes less than the "
961 "threshold value for\n"
962 "distinction between 12 and 16 bit FATs.\n");
Matt Mower18794c82015-11-11 16:22:45 -0600963 die("Make the filesystem a bit smaller manually.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500964 }
965 }
966 cluster_count = clust16;
967 fat_length = fatlength16;
Matt Mower18794c82015-11-11 16:22:45 -0600968 bs.fat_length = htole16(fatlength16);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500969 memcpy(vi->fs_type, MSDOS_FAT16_SIGN, 8);
970 break;
971
972 case 32:
973 if (clust32 < MIN_CLUST_32)
974 fprintf(stderr,
975 "WARNING: Not enough clusters for a 32 bit FAT!\n");
976 cluster_count = clust32;
977 fat_length = fatlength32;
Matt Mower18794c82015-11-11 16:22:45 -0600978 bs.fat_length = htole16(0);
979 bs.fat32.fat32_length = htole32(fatlength32);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500980 memcpy(vi->fs_type, MSDOS_FAT32_SIGN, 8);
981 root_dir_entries = 0;
982 break;
983
984 default:
985 die("FAT not 12, 16 or 32 bits");
986 }
987
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500988 /* Adjust the number of root directory entries to help enforce alignment */
989 if (align_structures) {
990 root_dir_entries = align_object(root_dir_sectors, bs.cluster_size)
991 * (sector_size >> 5);
992 }
993 } else {
994 unsigned clusters, maxclust, fatdata;
995
996 /* GEMDOS always uses a 12 bit FAT on floppies, and always a 16 bit FAT on
Matt Mower18794c82015-11-11 16:22:45 -0600997 * hard disks. So use 12 bit if the size of the filesystem suggests that
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500998 * this fs is for a floppy disk, if the user hasn't explicitly requested a
999 * size.
1000 */
1001 if (!size_fat)
1002 size_fat = (num_sectors == 1440 || num_sectors == 2400 ||
1003 num_sectors == 2880 || num_sectors == 5760) ? 12 : 16;
1004 if (verbose >= 2)
1005 printf("Choosing %d bits for FAT\n", size_fat);
1006
1007 /* Atari format: cluster size should be 2, except explicitly requested by
1008 * the user, since GEMDOS doesn't like other cluster sizes very much.
1009 * Instead, tune the sector size for the FS to fit.
1010 */
1011 bs.cluster_size = sectors_per_cluster ? sectors_per_cluster : 2;
1012 if (!sector_size_set) {
1013 while (num_sectors > GEMDOS_MAX_SECTORS) {
1014 num_sectors >>= 1;
1015 sector_size <<= 1;
1016 }
1017 }
1018 if (verbose >= 2)
1019 printf("Sector size must be %d to have less than %d log. sectors\n",
1020 sector_size, GEMDOS_MAX_SECTORS);
1021
1022 /* Check if there are enough FAT indices for how much clusters we have */
1023 do {
1024 fatdata = num_sectors - cdiv(root_dir_entries * 32, sector_size) -
1025 reserved_sectors;
1026 /* The factor 2 below avoids cut-off errors for nr_fats == 1 and
1027 * size_fat == 12
1028 * The "2*nr_fats*size_fat/8" is for the reserved first two FAT entries
1029 */
1030 clusters =
1031 (2 *
1032 ((long long)fatdata * sector_size -
1033 2 * nr_fats * size_fat / 8)) / (2 * ((int)bs.cluster_size *
1034 sector_size +
1035 nr_fats * size_fat / 8));
1036 fat_length = cdiv((clusters + 2) * size_fat / 8, sector_size);
1037 /* Need to recalculate number of clusters, since the unused parts of the
1038 * FATS and data area together could make up space for an additional,
1039 * not really present cluster. */
1040 clusters = (fatdata - nr_fats * fat_length) / bs.cluster_size;
1041 maxclust = (fat_length * sector_size * 8) / size_fat;
1042 if (verbose >= 2)
1043 printf("ss=%d: #clu=%d, fat_len=%d, maxclu=%d\n",
1044 sector_size, clusters, fat_length, maxclust);
1045
1046 /* last 10 cluster numbers are special (except FAT32: 4 high bits rsvd);
1047 * first two numbers are reserved */
1048 if (maxclust <=
1049 (size_fat == 32 ? MAX_CLUST_32 : (1 << size_fat) - 0x10)
1050 && clusters <= maxclust - 2)
1051 break;
1052 if (verbose >= 2)
1053 printf(clusters > maxclust - 2 ?
1054 "Too many clusters\n" : "FAT too big\n");
1055
1056 /* need to increment sector_size once more to */
1057 if (sector_size_set)
1058 die("With this sector size, the maximum number of FAT entries "
1059 "would be exceeded.");
1060 num_sectors >>= 1;
1061 sector_size <<= 1;
1062 } while (sector_size <= GEMDOS_MAX_SECTOR_SIZE);
1063
1064 if (sector_size > GEMDOS_MAX_SECTOR_SIZE)
1065 die("Would need a sector size > 16k, which GEMDOS can't work with");
1066
1067 cluster_count = clusters;
1068 if (size_fat != 32)
Matt Mower18794c82015-11-11 16:22:45 -06001069 bs.fat_length = htole16(fat_length);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001070 else {
1071 bs.fat_length = 0;
Matt Mower18794c82015-11-11 16:22:45 -06001072 bs.fat32.fat32_length = htole32(fat_length);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001073 }
1074 }
1075
1076 bs.sector_size[0] = (char)(sector_size & 0x00ff);
1077 bs.sector_size[1] = (char)((sector_size & 0xff00) >> 8);
1078
1079 bs.dir_entries[0] = (char)(root_dir_entries & 0x00ff);
1080 bs.dir_entries[1] = (char)((root_dir_entries & 0xff00) >> 8);
1081
1082 if (size_fat == 32) {
1083 /* set up additional FAT32 fields */
Matt Mower18794c82015-11-11 16:22:45 -06001084 bs.fat32.flags = htole16(0);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001085 bs.fat32.version[0] = 0;
1086 bs.fat32.version[1] = 0;
Matt Mower18794c82015-11-11 16:22:45 -06001087 bs.fat32.root_cluster = htole32(2);
1088 bs.fat32.info_sector = htole16(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001089 if (!backup_boot)
1090 backup_boot = (reserved_sectors >= 7) ? 6 :
1091 (reserved_sectors >= 2) ? reserved_sectors - 1 : 0;
1092 else {
1093 if (backup_boot == 1)
1094 die("Backup boot sector must be after sector 1");
1095 else if (backup_boot >= reserved_sectors)
1096 die("Backup boot sector must be a reserved sector");
1097 }
1098 if (verbose >= 2)
1099 printf("Using sector %d as backup boot sector (0 = none)\n",
1100 backup_boot);
Matt Mower18794c82015-11-11 16:22:45 -06001101 bs.fat32.backup_boot = htole16(backup_boot);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001102 memset(&bs.fat32.reserved2, 0, sizeof(bs.fat32.reserved2));
1103 }
1104
1105 if (atari_format) {
1106 /* Just some consistency checks */
1107 if (num_sectors >= GEMDOS_MAX_SECTORS)
1108 die("GEMDOS can't handle more than 65531 sectors");
1109 else if (num_sectors >= OLDGEMDOS_MAX_SECTORS)
1110 printf("Warning: More than 32765 sector need TOS 1.04 "
1111 "or higher.\n");
1112 }
1113 if (num_sectors >= 65536) {
1114 bs.sectors[0] = (char)0;
1115 bs.sectors[1] = (char)0;
Matt Mower18794c82015-11-11 16:22:45 -06001116 bs.total_sect = htole32(num_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001117 } else {
1118 bs.sectors[0] = (char)(num_sectors & 0x00ff);
1119 bs.sectors[1] = (char)((num_sectors & 0xff00) >> 8);
1120 if (!atari_format)
Matt Mower18794c82015-11-11 16:22:45 -06001121 bs.total_sect = htole32(0);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001122 }
1123
1124 if (!atari_format)
1125 vi->ext_boot_sign = MSDOS_EXT_SIGN;
1126
1127 if (!cluster_count) {
1128 if (sectors_per_cluster) /* If yes, die if we'd spec'd sectors per cluster */
Matt Mower18794c82015-11-11 16:22:45 -06001129 die("Too many clusters for filesystem - try more sectors per cluster");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001130 else
Matt Mower18794c82015-11-11 16:22:45 -06001131 die("Attempting to create a too large filesystem");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001132 }
1133
1134 /* The two following vars are in hard sectors, i.e. 512 byte sectors! */
1135 start_data_sector = (reserved_sectors + nr_fats * fat_length) *
1136 (sector_size / HARD_SECTOR_SIZE);
1137 start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) /
1138 SECTORS_PER_BLOCK;
1139
Matt Mower18794c82015-11-11 16:22:45 -06001140 if (blocks < start_data_block + 32) /* Arbitrary undersize filesystem! */
1141 die("Too few blocks for viable filesystem");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001142
1143 if (verbose) {
1144 printf("%s has %d head%s and %d sector%s per track,\n",
Matt Mower18794c82015-11-11 16:22:45 -06001145 device_name, le16toh(bs.heads),
1146 (le16toh(bs.heads) != 1) ? "s" : "", le16toh(bs.secs_track),
1147 (le16toh(bs.secs_track) != 1) ? "s" : "");
1148 printf("hidden sectors 0x%04x;\n", hidden_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001149 printf("logical sector size is %d,\n", sector_size);
1150 printf("using 0x%02x media descriptor, with %d sectors;\n",
1151 (int)(bs.media), num_sectors);
Matt Mower18794c82015-11-11 16:22:45 -06001152 printf("drive number 0x%02x;\n", (int) (vi->drive_number));
1153 printf("filesystem has %d %d-bit FAT%s and %d sector%s per cluster.\n",
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001154 (int)(bs.fats), size_fat, (bs.fats != 1) ? "s" : "",
1155 (int)(bs.cluster_size), (bs.cluster_size != 1) ? "s" : "");
1156 printf("FAT size is %d sector%s, and provides %d cluster%s.\n",
1157 fat_length, (fat_length != 1) ? "s" : "",
1158 cluster_count, (cluster_count != 1) ? "s" : "");
1159 printf("There %s %u reserved sector%s.\n",
1160 (reserved_sectors != 1) ? "are" : "is",
1161 reserved_sectors, (reserved_sectors != 1) ? "s" : "");
1162
1163 if (size_fat != 32) {
1164 unsigned root_dir_entries =
1165 bs.dir_entries[0] + ((bs.dir_entries[1]) * 256);
1166 unsigned root_dir_sectors =
1167 cdiv(root_dir_entries * 32, sector_size);
1168 printf("Root directory contains %u slots and uses %u sectors.\n",
1169 root_dir_entries, root_dir_sectors);
1170 }
1171 printf("Volume ID is %08lx, ", volume_id &
1172 (atari_format ? 0x00ffffff : 0xffffffff));
Matt Mower18794c82015-11-11 16:22:45 -06001173 if (strcmp(volume_name, NO_NAME))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001174 printf("volume label %s.\n", volume_name);
1175 else
1176 printf("no volume label.\n");
1177 }
1178
1179 /* Make the file allocation tables! */
1180
1181 if (malloc_entire_fat)
1182 alloced_fat_length = fat_length;
1183 else
1184 alloced_fat_length = 1;
1185
1186 if ((fat =
1187 (unsigned char *)malloc(alloced_fat_length * sector_size)) == NULL)
1188 die("unable to allocate space for FAT image in memory");
1189
1190 memset(fat, 0, alloced_fat_length * sector_size);
1191
1192 mark_FAT_cluster(0, 0xffffffff); /* Initial fat entries */
1193 mark_FAT_cluster(1, 0xffffffff);
1194 fat[0] = (unsigned char)bs.media; /* Put media type in first byte! */
1195 if (size_fat == 32) {
1196 /* Mark cluster 2 as EOF (used for root dir) */
1197 mark_FAT_cluster(2, FAT_EOF);
1198 }
1199
1200 /* Make the root directory entries */
1201
1202 size_root_dir = (size_fat == 32) ?
1203 bs.cluster_size * sector_size :
1204 (((int)bs.dir_entries[1] * 256 + (int)bs.dir_entries[0]) *
1205 sizeof(struct msdos_dir_entry));
1206 if ((root_dir = (struct msdos_dir_entry *)malloc(size_root_dir)) == NULL) {
1207 free(fat); /* Tidy up before we die! */
1208 die("unable to allocate space for root directory in memory");
1209 }
1210
1211 memset(root_dir, 0, size_root_dir);
Matt Mower18794c82015-11-11 16:22:45 -06001212 if (memcmp(volume_name, NO_NAME, 11)) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001213 struct msdos_dir_entry *de = &root_dir[0];
1214 memcpy(de->name, volume_name, 8);
1215 memcpy(de->ext, volume_name + 8, 3);
1216 de->attr = ATTR_VOLUME;
Matt Mower18794c82015-11-11 16:22:45 -06001217 if (!invariant)
1218 ctime = localtime(&create_time);
1219 else
1220 ctime = gmtime(&create_time);
1221 de->time = htole16((unsigned short)((ctime->tm_sec >> 1) +
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001222 (ctime->tm_min << 5) +
1223 (ctime->tm_hour << 11)));
1224 de->date =
Matt Mower18794c82015-11-11 16:22:45 -06001225 htole16((unsigned short)(ctime->tm_mday +
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001226 ((ctime->tm_mon + 1) << 5) +
1227 ((ctime->tm_year - 80) << 9)));
Matt Mower18794c82015-11-11 16:22:45 -06001228 de->ctime_cs = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001229 de->ctime = de->time;
1230 de->cdate = de->date;
1231 de->adate = de->date;
Matt Mower18794c82015-11-11 16:22:45 -06001232 de->starthi = htole16(0);
1233 de->start = htole16(0);
1234 de->size = htole32(0);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001235 }
1236
1237 if (size_fat == 32) {
1238 /* For FAT32, create an info sector */
1239 struct fat32_fsinfo *info;
1240
1241 if (!(info_sector = malloc(sector_size)))
1242 die("Out of memory");
1243 memset(info_sector, 0, sector_size);
1244 /* fsinfo structure is at offset 0x1e0 in info sector by observation */
1245 info = (struct fat32_fsinfo *)(info_sector + 0x1e0);
1246
1247 /* Info sector magic */
1248 info_sector[0] = 'R';
1249 info_sector[1] = 'R';
1250 info_sector[2] = 'a';
1251 info_sector[3] = 'A';
1252
1253 /* Magic for fsinfo structure */
Matt Mower18794c82015-11-11 16:22:45 -06001254 info->signature = htole32(0x61417272);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001255 /* We've allocated cluster 2 for the root dir. */
Matt Mower18794c82015-11-11 16:22:45 -06001256 info->free_clusters = htole32(cluster_count - 1);
1257 info->next_cluster = htole32(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001258
1259 /* Info sector also must have boot sign */
Matt Mower18794c82015-11-11 16:22:45 -06001260 *(uint16_t *) (info_sector + 0x1fe) = htole16(BOOT_SIGN);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001261 }
1262
1263 if (!(blank_sector = malloc(sector_size)))
1264 die("Out of memory");
1265 memset(blank_sector, 0, sector_size);
1266}
1267
1268/* Write the new filesystem's data tables to wherever they're going to end up! */
1269
1270#define error(str) \
1271 do { \
1272 free (fat); \
1273 if (info_sector) free (info_sector); \
1274 free (root_dir); \
1275 die (str); \
1276 } while(0)
1277
1278#define seekto(pos,errstr) \
1279 do { \
1280 loff_t __pos = (pos); \
1281 if (llseek (dev, __pos, SEEK_SET) != __pos) \
1282 error ("seek to " errstr " failed whilst writing tables"); \
1283 } while(0)
1284
1285#define writebuf(buf,size,errstr) \
1286 do { \
1287 int __size = (size); \
1288 if (write (dev, buf, __size) != __size) \
1289 error ("failed whilst writing " errstr); \
1290 } while(0)
1291
1292static void write_tables(void)
1293{
1294 int x;
1295 int fat_length;
1296
1297 fat_length = (size_fat == 32) ?
Matt Mower18794c82015-11-11 16:22:45 -06001298 le32toh(bs.fat32.fat32_length) : le16toh(bs.fat_length);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001299
1300 seekto(0, "start of device");
1301 /* clear all reserved sectors */
1302 for (x = 0; x < reserved_sectors; ++x)
1303 writebuf(blank_sector, sector_size, "reserved sector");
1304 /* seek back to sector 0 and write the boot sector */
1305 seekto(0, "boot sector");
1306 writebuf((char *)&bs, sizeof(struct msdos_boot_sector), "boot sector");
1307 /* on FAT32, write the info sector and backup boot sector */
1308 if (size_fat == 32) {
Matt Mower18794c82015-11-11 16:22:45 -06001309 seekto(le16toh(bs.fat32.info_sector) * sector_size, "info sector");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001310 writebuf(info_sector, 512, "info sector");
1311 if (backup_boot != 0) {
1312 seekto(backup_boot * sector_size, "backup boot sector");
1313 writebuf((char *)&bs, sizeof(struct msdos_boot_sector),
1314 "backup boot sector");
1315 }
1316 }
1317 /* seek to start of FATS and write them all */
1318 seekto(reserved_sectors * sector_size, "first FAT");
1319 for (x = 1; x <= nr_fats; x++) {
1320 int y;
1321 int blank_fat_length = fat_length - alloced_fat_length;
1322 writebuf(fat, alloced_fat_length * sector_size, "FAT");
1323 for (y = 0; y < blank_fat_length; y++)
1324 writebuf(blank_sector, sector_size, "FAT");
1325 }
1326 /* Write the root directory directly after the last FAT. This is the root
1327 * dir area on FAT12/16, and the first cluster on FAT32. */
1328 writebuf((char *)root_dir, size_root_dir, "root directory");
1329
1330 if (blank_sector)
1331 free(blank_sector);
1332 if (info_sector)
1333 free(info_sector);
1334 free(root_dir); /* Free up the root directory space from setup_tables */
1335 free(fat); /* Free up the fat table space reserved during setup_tables */
1336}
1337
Matt Mower18794c82015-11-11 16:22:45 -06001338/* Report the command usage and exit with the given error code */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001339
Matt Mower18794c82015-11-11 16:22:45 -06001340static void usage(int exitval)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001341{
Matt Mower18794c82015-11-11 16:22:45 -06001342 fprintf(stderr, "\
1343Usage: mkfs.fat [-a][-A][-c][-C][-v][-I][-l bad-block-file][-b backup-boot-sector]\n\
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001344 [-m boot-msg-file][-n volume-name][-i volume-id]\n\
1345 [-s sectors-per-cluster][-S logical-sector-size][-f number-of-FATs]\n\
1346 [-h hidden-sectors][-F fat-size][-r root-dir-entries][-R reserved-sectors]\n\
Matt Mower18794c82015-11-11 16:22:45 -06001347 [-M FAT-media-byte][-D drive_number]\n\
1348 [--invariant]\n\
1349 [--help]\n\
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001350 /dev/name [blocks]\n");
Matt Mower18794c82015-11-11 16:22:45 -06001351 exit(exitval);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001352}
1353
1354/*
1355 * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
1356 * of MS-DOS filesystem by default.
1357 */
1358static void check_atari(void)
1359{
1360#ifdef __mc68000__
1361 FILE *f;
1362 char line[128], *p;
1363
1364 if (!(f = fopen("/proc/hardware", "r"))) {
1365 perror("/proc/hardware");
1366 return;
1367 }
1368
1369 while (fgets(line, sizeof(line), f)) {
1370 if (strncmp(line, "Model:", 6) == 0) {
1371 p = line + 6;
1372 p += strspn(p, " \t");
1373 if (strncmp(p, "Atari ", 6) == 0)
1374 atari_format = 1;
1375 break;
1376 }
1377 }
1378 fclose(f);
1379#endif
1380}
1381
1382/* The "main" entry point into the utility - we pick up the options and attempt to process them in some sort of sensible
1383 way. In the event that some/all of the options are invalid we need to tell the user so that something can be done! */
1384
1385int main(int argc, char **argv)
1386{
1387 int c;
1388 char *tmp;
1389 char *listfile = NULL;
1390 FILE *msgfile;
1391 struct stat statbuf;
1392 int i = 0, pos, ch;
1393 int create = 0;
Matt Mower18794c82015-11-11 16:22:45 -06001394 uint64_t cblocks = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001395 int min_sector_size;
Matt Mower18794c82015-11-11 16:22:45 -06001396 int bad_block_count = 0;
1397 struct timeval create_timeval;
1398
1399 enum {OPT_HELP=1000, OPT_INVARIANT,};
1400 const struct option long_options[] = {
1401 {"help", no_argument, NULL, OPT_HELP},
1402 {"invariant", no_argument, NULL, OPT_INVARIANT},
1403 {0,}
1404 };
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001405
1406 if (argc && *argv) { /* What's the program name? */
1407 char *p;
1408 program_name = *argv;
1409 if ((p = strrchr(program_name, '/')))
1410 program_name = p + 1;
1411 }
1412
1413 gettimeofday(&create_timeval, NULL);
1414 create_time = create_timeval.tv_sec;
Matt Mower18794c82015-11-11 16:22:45 -06001415 volume_id = (uint32_t) ((create_timeval.tv_sec << 20) | create_timeval.tv_usec); /* Default volume ID = creation time, fudged for more uniqueness */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001416 check_atari();
1417
Matt Mower18794c82015-11-11 16:22:45 -06001418 printf("mkfs.fat " VERSION " (" VERSION_DATE ")\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001419
Matt Mower18794c82015-11-11 16:22:45 -06001420 while ((c = getopt_long(argc, argv, "aAb:cCf:D:F:Ii:l:m:M:n:r:R:s:S:h:v",
1421 long_options, NULL)) != -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001422 /* Scan the command line for options */
1423 switch (c) {
1424 case 'A': /* toggle Atari format */
1425 atari_format = !atari_format;
1426 break;
1427
1428 case 'a': /* a : skip alignment */
1429 align_structures = FALSE;
1430 break;
1431
1432 case 'b': /* b : location of backup boot sector */
1433 backup_boot = (int)strtol(optarg, &tmp, 0);
1434 if (*tmp || backup_boot < 2 || backup_boot > 0xffff) {
1435 printf("Bad location for backup boot sector : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001436 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001437 }
1438 break;
1439
1440 case 'c': /* c : Check FS as we build it */
1441 check = TRUE;
1442 malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
1443 break;
1444
1445 case 'C': /* C : Create a new file */
1446 create = TRUE;
1447 break;
1448
Matt Mower18794c82015-11-11 16:22:45 -06001449 case 'D': /* D : Choose Drive Number */
1450 drive_number_option = (int) strtol (optarg, &tmp, 0);
1451 if (*tmp || (drive_number_option != 0 && drive_number_option != 0x80)) {
1452 printf ("Drive number must be 0 or 0x80: %s\n", optarg);
1453 usage(1);
1454 }
1455 drive_number_by_user=1;
1456 break;
1457
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001458 case 'f': /* f : Choose number of FATs */
1459 nr_fats = (int)strtol(optarg, &tmp, 0);
1460 if (*tmp || nr_fats < 1 || nr_fats > 4) {
1461 printf("Bad number of FATs : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001462 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001463 }
1464 break;
1465
1466 case 'F': /* F : Choose FAT size */
1467 size_fat = (int)strtol(optarg, &tmp, 0);
1468 if (*tmp || (size_fat != 12 && size_fat != 16 && size_fat != 32)) {
1469 printf("Bad FAT type : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001470 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001471 }
1472 size_fat_by_user = 1;
1473 break;
1474
1475 case 'h': /* h : number of hidden sectors */
1476 hidden_sectors = (int)strtol(optarg, &tmp, 0);
1477 if (*tmp || hidden_sectors < 0) {
1478 printf("Bad number of hidden sectors : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001479 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001480 }
Matt Mower18794c82015-11-11 16:22:45 -06001481 hidden_sectors_by_user = 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001482 break;
1483
1484 case 'I':
1485 ignore_full_disk = 1;
1486 break;
1487
1488 case 'i': /* i : specify volume ID */
1489 volume_id = strtoul(optarg, &tmp, 16);
1490 if (*tmp) {
1491 printf("Volume ID must be a hexadecimal number\n");
Matt Mower18794c82015-11-11 16:22:45 -06001492 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001493 }
1494 break;
1495
1496 case 'l': /* l : Bad block filename */
1497 listfile = optarg;
1498 malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
1499 break;
1500
1501 case 'm': /* m : Set boot message */
1502 if (strcmp(optarg, "-")) {
1503 msgfile = fopen(optarg, "r");
1504 if (!msgfile)
1505 perror(optarg);
1506 } else
1507 msgfile = stdin;
1508
1509 if (msgfile) {
1510 /* The boot code ends at offset 448 and needs a null terminator */
1511 i = MESSAGE_OFFSET;
1512 pos = 0; /* We are at beginning of line */
1513 do {
1514 ch = getc(msgfile);
1515 switch (ch) {
1516 case '\r': /* Ignore CRs */
1517 case '\0': /* and nulls */
1518 break;
1519
1520 case '\n': /* LF -> CR+LF if necessary */
1521 if (pos) { /* If not at beginning of line */
1522 dummy_boot_code[i++] = '\r';
1523 pos = 0;
1524 }
1525 dummy_boot_code[i++] = '\n';
1526 break;
1527
1528 case '\t': /* Expand tabs */
1529 do {
1530 dummy_boot_code[i++] = ' ';
1531 pos++;
1532 }
1533 while (pos % 8 && i < BOOTCODE_SIZE - 1);
1534 break;
1535
1536 case EOF:
1537 dummy_boot_code[i++] = '\0'; /* Null terminator */
1538 break;
1539
1540 default:
1541 dummy_boot_code[i++] = ch; /* Store character */
1542 pos++; /* Advance position */
1543 break;
1544 }
1545 }
1546 while (ch != EOF && i < BOOTCODE_SIZE - 1);
1547
1548 /* Fill up with zeros */
1549 while (i < BOOTCODE_SIZE - 1)
1550 dummy_boot_code[i++] = '\0';
1551 dummy_boot_code[BOOTCODE_SIZE - 1] = '\0'; /* Just in case */
1552
1553 if (ch != EOF)
1554 printf("Warning: message too long; truncated\n");
1555
1556 if (msgfile != stdin)
1557 fclose(msgfile);
1558 }
1559 break;
1560
Matt Mower18794c82015-11-11 16:22:45 -06001561 case 'M': /* M : FAT Media byte */
1562 fat_media_byte = (int)strtol(optarg, &tmp, 0);
1563 if (*tmp) {
1564 printf("Bad number for media descriptor : %s\n", optarg);
1565 usage(1);
1566 }
1567 if (fat_media_byte != 0xf0 && (fat_media_byte < 0xf8 || fat_media_byte > 0xff)) {
1568 printf("FAT Media byte must either be between 0xF8 and 0xFF or be 0xF0 : %s\n", optarg);
1569 usage(1);
1570 }
1571 break;
1572
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001573 case 'n': /* n : Volume name */
1574 sprintf(volume_name, "%-11.11s", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001575 for (i = 0; volume_name[i] && i < 11; i++)
1576 /* don't know if here should be more strict !uppercase(label[i]) */
1577 if (islower(volume_name[i])) {
1578 fprintf(stderr,
1579 "mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows\n");
1580 break;
1581 }
1582
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001583 break;
1584
1585 case 'r': /* r : Root directory entries */
1586 root_dir_entries = (int)strtol(optarg, &tmp, 0);
1587 if (*tmp || root_dir_entries < 16 || root_dir_entries > 32768) {
1588 printf("Bad number of root directory entries : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001589 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001590 }
1591 break;
1592
1593 case 'R': /* R : number of reserved sectors */
1594 reserved_sectors = (int)strtol(optarg, &tmp, 0);
1595 if (*tmp || reserved_sectors < 1 || reserved_sectors > 0xffff) {
1596 printf("Bad number of reserved sectors : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001597 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001598 }
1599 break;
1600
1601 case 's': /* s : Sectors per cluster */
1602 sectors_per_cluster = (int)strtol(optarg, &tmp, 0);
1603 if (*tmp || (sectors_per_cluster != 1 && sectors_per_cluster != 2
1604 && sectors_per_cluster != 4 && sectors_per_cluster != 8
1605 && sectors_per_cluster != 16
1606 && sectors_per_cluster != 32
1607 && sectors_per_cluster != 64
1608 && sectors_per_cluster != 128)) {
1609 printf("Bad number of sectors per cluster : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001610 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001611 }
1612 break;
1613
1614 case 'S': /* S : Sector size */
1615 sector_size = (int)strtol(optarg, &tmp, 0);
1616 if (*tmp || (sector_size != 512 && sector_size != 1024 &&
1617 sector_size != 2048 && sector_size != 4096 &&
1618 sector_size != 8192 && sector_size != 16384 &&
1619 sector_size != 32768)) {
1620 printf("Bad logical sector size : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001621 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001622 }
1623 sector_size_set = 1;
1624 break;
1625
1626 case 'v': /* v : Verbose execution */
1627 ++verbose;
1628 break;
1629
Matt Mower18794c82015-11-11 16:22:45 -06001630 case OPT_HELP:
1631 usage(0);
1632 break;
1633
1634 case OPT_INVARIANT:
1635 invariant = 1;
1636 volume_id = 0x1234abcd;
1637 create_time = 1426325213;
1638 break;
1639
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001640 default:
1641 printf("Unknown option: %c\n", c);
Matt Mower18794c82015-11-11 16:22:45 -06001642 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001643 }
1644 if (optind < argc) {
1645 device_name = argv[optind]; /* Determine the number of blocks in the FS */
1646
1647 if (!device_name) {
1648 printf("No device specified.\n");
Matt Mower18794c82015-11-11 16:22:45 -06001649 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001650 }
1651
1652 if (!create)
1653 cblocks = count_blocks(device_name, &orphaned_sectors); /* Have a look and see! */
1654 }
1655 if (optind == argc - 2) { /* Either check the user specified number */
1656 blocks = strtoull(argv[optind + 1], &tmp, 0);
1657 if (!create && blocks != cblocks) {
1658 fprintf(stderr, "Warning: block count mismatch: ");
Matt Mower18794c82015-11-11 16:22:45 -06001659 fprintf(stderr, "found %llu but assuming %llu.\n", (unsigned long long)cblocks, (unsigned long long)blocks);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001660 }
Matt Mower18794c82015-11-11 16:22:45 -06001661 if (*tmp)
1662 bad_block_count = 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001663 } else if (optind == argc - 1) { /* Or use value found */
1664 if (create)
1665 die("Need intended size with -C.");
1666 blocks = cblocks;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001667 } else {
1668 fprintf(stderr, "No device specified!\n");
Matt Mower18794c82015-11-11 16:22:45 -06001669 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001670 }
Matt Mower18794c82015-11-11 16:22:45 -06001671 if (bad_block_count) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001672 printf("Bad block count : %s\n", argv[optind + 1]);
Matt Mower18794c82015-11-11 16:22:45 -06001673 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001674 }
1675
1676 if (check && listfile) /* Auto and specified bad block handling are mutually */
1677 die("-c and -l are incompatible"); /* exclusive of each other! */
1678
1679 if (!create) {
1680 check_mount(device_name); /* Is the device already mounted? */
1681 dev = open(device_name, O_EXCL | O_RDWR); /* Is it a suitable device to build the FS on? */
1682 if (dev < 0) {
1683 fprintf(stderr, "%s: unable to open %s: %s\n", program_name,
1684 device_name, strerror(errno));
1685 exit(1); /* The error exit code is 1! */
1686 }
1687 } else {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001688 /* create the file */
Matt Mower18794c82015-11-11 16:22:45 -06001689 dev = open(device_name, O_EXCL | O_RDWR | O_CREAT, 0666);
1690 if (dev < 0) {
1691 if (errno == EEXIST)
1692 die("file %s already exists");
1693 else
1694 die("unable to create %s");
1695 }
1696 /* expand to desired size */
1697 if (ftruncate(dev, blocks * BLOCK_SIZE))
1698 die("unable to resize %s");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001699 }
1700
1701 if (fstat(dev, &statbuf) < 0)
1702 die("unable to stat %s");
1703 if (!S_ISBLK(statbuf.st_mode)) {
1704 statbuf.st_rdev = 0;
1705 check = 0;
1706 } else
1707 /*
1708 * Ignore any 'full' fixed disk devices, if -I is not given.
1709 * On a MO-disk one doesn't need partitions. The filesytem can go
1710 * directly to the whole disk. Under other OSes this is known as
1711 * the 'superfloppy' format. As I don't know how to find out if
1712 * this is a MO disk I introduce a -I (ignore) switch. -Joey
1713 */
Matt Mower18794c82015-11-11 16:22:45 -06001714 if (!ignore_full_disk && ((statbuf.st_rdev & 0xffffff3f) == 0x0300 || /* hda, hdb */
1715 (statbuf.st_rdev & 0xffffff0f) == 0x0800 || /* sd */
1716 (statbuf.st_rdev & 0xffffff3f) == 0x0d00 || /* xd */
1717 (statbuf.st_rdev & 0xffffff3f) == 0x1600) /* hdc, hdd */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001718 )
1719 die("Device partition expected, not making filesystem on entire device '%s' (use -I to override)");
1720
1721 if (sector_size_set) {
1722 if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0)
1723 if (sector_size < min_sector_size) {
1724 sector_size = min_sector_size;
1725 fprintf(stderr,
1726 "Warning: sector size was set to %d (minimal for this device)\n",
1727 sector_size);
1728 }
1729 } else {
1730 if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0) {
1731 sector_size = min_sector_size;
1732 sector_size_set = 1;
1733 }
1734 }
1735
1736 if (sector_size > 4096)
1737 fprintf(stderr,
1738 "Warning: sector size is set to %d > 4096, such filesystem will not propably mount\n",
1739 sector_size);
1740
1741 establish_params(statbuf.st_rdev, statbuf.st_size);
1742 /* Establish the media parameters */
1743
Matt Mower18794c82015-11-11 16:22:45 -06001744 setup_tables(); /* Establish the filesystem tables */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001745
1746 if (check) /* Determine any bad block locations and mark them */
1747 check_blocks();
1748 else if (listfile)
1749 get_list_blocks(listfile);
1750
Matt Mower18794c82015-11-11 16:22:45 -06001751 write_tables(); /* Write the filesystem tables away! */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001752
1753 exit(0); /* Terminate with no errors! */
1754}