blob: 2dad23630a685e581ed458558d9d6d22b831de9b [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{
that58a41332015-12-07 21:12:48 +0100501/* older versions of Bionic don't have setmntent (4.x) or an incomplete impl (5.x) */
502#ifdef MOUNTED
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500503 FILE *f;
504 struct mntent *mnt;
505
506 if ((f = setmntent(MOUNTED, "r")) == NULL)
507 return;
508 while ((mnt = getmntent(f)) != NULL)
509 if (strcmp(device_name, mnt->mnt_fsname) == 0)
Matt Mower18794c82015-11-11 16:22:45 -0600510 die("%s contains a mounted filesystem.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500511 endmntent(f);
that58a41332015-12-07 21:12:48 +0100512#endif
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500513}
514
515/* Establish the geometry and media parameters for the device */
516
517static void establish_params(int device_num, int size)
518{
519 long loop_size;
520 struct hd_geometry geometry;
521 struct floppy_struct param;
522 int def_root_dir_entries = 512;
523
524 if ((0 == device_num) || ((device_num & 0xff00) == 0x0200))
525 /* file image or floppy disk */
526 {
527 if (0 == device_num) {
528 param.size = size / 512;
529 switch (param.size) {
530 case 720:
531 param.sect = 9;
532 param.head = 2;
533 break;
534 case 1440:
535 param.sect = 9;
536 param.head = 2;
537 break;
538 case 2400:
539 param.sect = 15;
540 param.head = 2;
541 break;
542 case 2880:
543 param.sect = 18;
544 param.head = 2;
545 break;
546 case 5760:
547 param.sect = 36;
548 param.head = 2;
549 break;
550 default:
551 /* fake values */
552 param.sect = 32;
553 param.head = 64;
554 break;
555 }
556
557 } else { /* is a floppy diskette */
558
559 if (ioctl(dev, FDGETPRM, &param)) /* Can we get the diskette geometry? */
560 die("unable to get diskette geometry for '%s'");
561 }
Matt Mower18794c82015-11-11 16:22:45 -0600562 bs.secs_track = htole16(param.sect); /* Set up the geometry information */
563 bs.heads = htole16(param.head);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500564 switch (param.size) { /* Set up the media descriptor byte */
565 case 720: /* 5.25", 2, 9, 40 - 360K */
566 bs.media = (char)0xfd;
567 bs.cluster_size = (char)2;
568 def_root_dir_entries = 112;
569 break;
570
571 case 1440: /* 3.5", 2, 9, 80 - 720K */
572 bs.media = (char)0xf9;
573 bs.cluster_size = (char)2;
574 def_root_dir_entries = 112;
575 break;
576
577 case 2400: /* 5.25", 2, 15, 80 - 1200K */
578 bs.media = (char)0xf9;
579 bs.cluster_size = (char)(atari_format ? 2 : 1);
580 def_root_dir_entries = 224;
581 break;
582
583 case 5760: /* 3.5", 2, 36, 80 - 2880K */
584 bs.media = (char)0xf0;
585 bs.cluster_size = (char)2;
586 def_root_dir_entries = 224;
587 break;
588
589 case 2880: /* 3.5", 2, 18, 80 - 1440K */
590floppy_default:
591 bs.media = (char)0xf0;
592 bs.cluster_size = (char)(atari_format ? 2 : 1);
593 def_root_dir_entries = 224;
594 break;
595
596 default: /* Anything else */
597 if (0 == device_num)
598 goto def_hd_params;
599 else
600 goto floppy_default;
601 }
602 } else if ((device_num & 0xff00) == 0x0700) { /* This is a loop device */
603 if (ioctl(dev, BLKGETSIZE, &loop_size))
604 die("unable to get loop device size");
605
606 switch (loop_size) { /* Assuming the loop device -> floppy later */
607 case 720: /* 5.25", 2, 9, 40 - 360K */
Matt Mower18794c82015-11-11 16:22:45 -0600608 bs.secs_track = le16toh(9);
609 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500610 bs.media = (char)0xfd;
611 bs.cluster_size = (char)2;
612 def_root_dir_entries = 112;
613 break;
614
615 case 1440: /* 3.5", 2, 9, 80 - 720K */
Matt Mower18794c82015-11-11 16:22:45 -0600616 bs.secs_track = le16toh(9);
617 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500618 bs.media = (char)0xf9;
619 bs.cluster_size = (char)2;
620 def_root_dir_entries = 112;
621 break;
622
623 case 2400: /* 5.25", 2, 15, 80 - 1200K */
Matt Mower18794c82015-11-11 16:22:45 -0600624 bs.secs_track = le16toh(15);
625 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500626 bs.media = (char)0xf9;
627 bs.cluster_size = (char)(atari_format ? 2 : 1);
628 def_root_dir_entries = 224;
629 break;
630
631 case 5760: /* 3.5", 2, 36, 80 - 2880K */
Matt Mower18794c82015-11-11 16:22:45 -0600632 bs.secs_track = le16toh(36);
633 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500634 bs.media = (char)0xf0;
635 bs.cluster_size = (char)2;
636 bs.dir_entries[0] = (char)224;
637 bs.dir_entries[1] = (char)0;
638 break;
639
640 case 2880: /* 3.5", 2, 18, 80 - 1440K */
Matt Mower18794c82015-11-11 16:22:45 -0600641 bs.secs_track = le16toh(18);
642 bs.heads = le16toh(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500643 bs.media = (char)0xf0;
644 bs.cluster_size = (char)(atari_format ? 2 : 1);
645 def_root_dir_entries = 224;
646 break;
647
648 default: /* Anything else: default hd setup */
649 printf("Loop device does not match a floppy size, using "
650 "default hd params\n");
Matt Mower18794c82015-11-11 16:22:45 -0600651 bs.secs_track = htole16(32); /* these are fake values... */
652 bs.heads = htole16(64);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500653 goto def_hd_params;
654 }
655 } else
656 /* Must be a hard disk then! */
657 {
658 /* Can we get the drive geometry? (Note I'm not too sure about */
659 /* whether to use HDIO_GETGEO or HDIO_REQ) */
660 if (ioctl(dev, HDIO_GETGEO, &geometry) || geometry.sectors == 0
661 || geometry.heads == 0) {
662 printf("unable to get drive geometry, using default 255/63\n");
Matt Mower18794c82015-11-11 16:22:45 -0600663 bs.secs_track = htole16(63);
664 bs.heads = htole16(255);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500665 } else {
Matt Mower18794c82015-11-11 16:22:45 -0600666 bs.secs_track = htole16(geometry.sectors); /* Set up the geometry information */
667 bs.heads = htole16(geometry.heads);
668 if (!hidden_sectors_by_user)
669 hidden_sectors = htole32(geometry.start);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500670 }
671def_hd_params:
672 bs.media = (char)0xf8; /* Set up the media descriptor for a hard drive */
673 if (!size_fat && blocks * SECTORS_PER_BLOCK > 1064960) {
674 if (verbose)
675 printf("Auto-selecting FAT32 for large filesystem\n");
676 size_fat = 32;
677 }
678 if (size_fat == 32) {
679 /* For FAT32, try to do the same as M$'s format command
680 * (see http://www.win.tue.nl/~aeb/linux/fs/fat/fatgen103.pdf p. 20):
681 * fs size <= 260M: 0.5k clusters
Matt Mower18794c82015-11-11 16:22:45 -0600682 * fs size <= 8G: 4k clusters
683 * fs size <= 16G: 8k clusters
684 * fs size <= 32G: 16k clusters
685 * fs size > 32G: 32k clusters
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500686 */
Matt Mower18794c82015-11-11 16:22:45 -0600687 uint32_t sz_mb =
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500688 (blocks + (1 << (20 - BLOCK_SIZE_BITS)) - 1) >> (20 -
689 BLOCK_SIZE_BITS);
690 bs.cluster_size =
Matt Mower18794c82015-11-11 16:22:45 -0600691 sz_mb > 32 * 1024 ? 64 : sz_mb > 16 * 1024 ? 32 : sz_mb >
692 8 * 1024 ? 16 : sz_mb > 260 ? 8 : 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500693 } else {
694 /* FAT12 and FAT16: start at 4 sectors per cluster */
695 bs.cluster_size = (char)4;
696 }
697 }
698
699 if (!root_dir_entries)
700 root_dir_entries = def_root_dir_entries;
701}
702
703/*
704 * If alignment is enabled, round the first argument up to the second; the
705 * latter must be a power of two.
706 */
707static unsigned int align_object(unsigned int sectors, unsigned int clustsize)
708{
709 if (align_structures)
710 return (sectors + clustsize - 1) & ~(clustsize - 1);
711 else
712 return sectors;
713}
714
715/* Create the filesystem data tables */
716
717static void setup_tables(void)
718{
719 unsigned num_sectors;
720 unsigned cluster_count = 0, fat_length;
721 struct tm *ctime;
722 struct msdos_volume_info *vi =
723 (size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
724
Matt Mower18794c82015-11-11 16:22:45 -0600725 if (atari_format) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500726 /* On Atari, the first few bytes of the boot sector are assigned
727 * differently: The jump code is only 2 bytes (and m68k machine code
728 * :-), then 6 bytes filler (ignored), then 3 byte serial number. */
Matt Mower18794c82015-11-11 16:22:45 -0600729 bs.boot_jump[2] = 'm';
730 memcpy((char *)bs.system_id, "kdosf", strlen("kdosf"));
731 } else
732 memcpy((char *)bs.system_id, "mkfs.fat", strlen("mkfs.fat"));
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500733 if (sectors_per_cluster)
734 bs.cluster_size = (char)sectors_per_cluster;
Matt Mower18794c82015-11-11 16:22:45 -0600735
736 if (fat_media_byte)
737 bs.media = (char) fat_media_byte;
738
739 if (bs.media == 0xf8)
740 vi->drive_number=0x80;
741 else
742 vi->drive_number=0x00;
743
744 if (drive_number_by_user)
745 vi->drive_number= (char) drive_number_option;
746
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500747 if (size_fat == 32) {
748 /* Under FAT32, the root dir is in a cluster chain, and this is
749 * signalled by bs.dir_entries being 0. */
750 root_dir_entries = 0;
751 }
752
753 if (atari_format) {
754 bs.system_id[5] = (unsigned char)(volume_id & 0x000000ff);
755 bs.system_id[6] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
756 bs.system_id[7] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
757 } else {
758 vi->volume_id[0] = (unsigned char)(volume_id & 0x000000ff);
759 vi->volume_id[1] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
760 vi->volume_id[2] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
761 vi->volume_id[3] = (unsigned char)(volume_id >> 24);
762 }
763
764 if (!atari_format) {
765 memcpy(vi->volume_label, volume_name, 11);
766
767 memcpy(bs.boot_jump, dummy_boot_jump, 3);
768 /* Patch in the correct offset to the boot code */
769 bs.boot_jump[1] = ((size_fat == 32 ?
770 (char *)&bs.fat32.boot_code :
771 (char *)&bs.oldfat.boot_code) - (char *)&bs) - 2;
772
773 if (size_fat == 32) {
774 int offset = (char *)&bs.fat32.boot_code -
775 (char *)&bs + MESSAGE_OFFSET + 0x7c00;
776 if (dummy_boot_code[BOOTCODE_FAT32_SIZE - 1])
777 printf("Warning: message too long; truncated\n");
778 dummy_boot_code[BOOTCODE_FAT32_SIZE - 1] = 0;
779 memcpy(bs.fat32.boot_code, dummy_boot_code, BOOTCODE_FAT32_SIZE);
780 bs.fat32.boot_code[MSG_OFFSET_OFFSET] = offset & 0xff;
781 bs.fat32.boot_code[MSG_OFFSET_OFFSET + 1] = offset >> 8;
782 } else {
783 memcpy(bs.oldfat.boot_code, dummy_boot_code, BOOTCODE_SIZE);
784 }
Matt Mower18794c82015-11-11 16:22:45 -0600785 bs.boot_sign = htole16(BOOT_SIGN);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500786 } else {
787 memcpy(bs.boot_jump, dummy_boot_jump_m68k, 2);
788 }
789 if (verbose >= 2)
790 printf("Boot jump code is %02x %02x\n",
791 bs.boot_jump[0], bs.boot_jump[1]);
792
793 if (!reserved_sectors)
794 reserved_sectors = (size_fat == 32) ? 32 : 1;
795 else {
796 if (size_fat == 32 && reserved_sectors < 2)
797 die("On FAT32 at least 2 reserved sectors are needed.");
798 }
Matt Mower18794c82015-11-11 16:22:45 -0600799 bs.reserved = htole16(reserved_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500800 if (verbose >= 2)
801 printf("Using %d reserved sectors\n", reserved_sectors);
802 bs.fats = (char)nr_fats;
803 if (!atari_format || size_fat == 32)
Matt Mower18794c82015-11-11 16:22:45 -0600804 bs.hidden = htole32(hidden_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500805 else {
806 /* In Atari format, hidden is a 16 bit field */
Matt Mower18794c82015-11-11 16:22:45 -0600807 uint16_t hidden = htole16(hidden_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500808 if (hidden_sectors & ~0xffff)
809 die("#hidden doesn't fit in 16bit field of Atari format\n");
810 memcpy(&bs.hidden, &hidden, 2);
811 }
812
Matt Mower18794c82015-11-11 16:22:45 -0600813 num_sectors =
814 (long long)(blocks * BLOCK_SIZE / sector_size) + orphaned_sectors;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500815
816 if (!atari_format) {
817 unsigned fatdata1216; /* Sectors for FATs + data area (FAT12/16) */
818 unsigned fatdata32; /* Sectors for FATs + data area (FAT32) */
819 unsigned fatlength12, fatlength16, fatlength32;
820 unsigned maxclust12, maxclust16, maxclust32;
821 unsigned clust12, clust16, clust32;
822 int maxclustsize;
823 unsigned root_dir_sectors = cdiv(root_dir_entries * 32, sector_size);
824
825 /*
826 * If the filesystem is 8192 sectors or less (4 MB with 512-byte
827 * sectors, i.e. floppy size), don't align the data structures.
828 */
829 if (num_sectors <= 8192) {
830 if (align_structures && verbose >= 2)
831 printf("Disabling alignment due to tiny filesystem\n");
832
833 align_structures = FALSE;
834 }
835
836 if (sectors_per_cluster)
837 bs.cluster_size = maxclustsize = sectors_per_cluster;
838 else
839 /* An initial guess for bs.cluster_size should already be set */
840 maxclustsize = 128;
841
842 do {
Matt Mower18794c82015-11-11 16:22:45 -0600843 fatdata32 = num_sectors - reserved_sectors;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500844 fatdata1216 = fatdata32
845 - align_object(root_dir_sectors, bs.cluster_size);
846
847 if (verbose >= 2)
848 printf("Trying with %d sectors/cluster:\n", bs.cluster_size);
849
850 /* The factor 2 below avoids cut-off errors for nr_fats == 1.
851 * The "nr_fats*3" is for the reserved first two FAT entries */
852 clust12 = 2 * ((long long)fatdata1216 * sector_size + nr_fats * 3) /
853 (2 * (int)bs.cluster_size * sector_size + nr_fats * 3);
854 fatlength12 = cdiv(((clust12 + 2) * 3 + 1) >> 1, sector_size);
855 fatlength12 = align_object(fatlength12, bs.cluster_size);
856 /* Need to recalculate number of clusters, since the unused parts of the
857 * FATS and data area together could make up space for an additional,
858 * not really present cluster. */
859 clust12 = (fatdata1216 - nr_fats * fatlength12) / bs.cluster_size;
860 maxclust12 = (fatlength12 * 2 * sector_size) / 3;
861 if (maxclust12 > MAX_CLUST_12)
862 maxclust12 = MAX_CLUST_12;
863 if (verbose >= 2)
864 printf("FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
865 clust12, fatlength12, maxclust12, MAX_CLUST_12);
866 if (clust12 > maxclust12 - 2) {
867 clust12 = 0;
868 if (verbose >= 2)
869 printf("FAT12: too much clusters\n");
870 }
871
872 clust16 = ((long long)fatdata1216 * sector_size + nr_fats * 4) /
873 ((int)bs.cluster_size * sector_size + nr_fats * 2);
874 fatlength16 = cdiv((clust16 + 2) * 2, sector_size);
875 fatlength16 = align_object(fatlength16, bs.cluster_size);
876 /* Need to recalculate number of clusters, since the unused parts of the
877 * FATS and data area together could make up space for an additional,
878 * not really present cluster. */
879 clust16 = (fatdata1216 - nr_fats * fatlength16) / bs.cluster_size;
880 maxclust16 = (fatlength16 * sector_size) / 2;
881 if (maxclust16 > MAX_CLUST_16)
882 maxclust16 = MAX_CLUST_16;
883 if (verbose >= 2)
884 printf("FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
885 clust16, fatlength16, maxclust16, MAX_CLUST_16);
886 if (clust16 > maxclust16 - 2) {
887 if (verbose >= 2)
888 printf("FAT16: too much clusters\n");
889 clust16 = 0;
890 }
891 /* The < 4078 avoids that the filesystem will be misdetected as having a
892 * 12 bit FAT. */
893 if (clust16 < FAT12_THRESHOLD
894 && !(size_fat_by_user && size_fat == 16)) {
895 if (verbose >= 2)
896 printf(clust16 < FAT12_THRESHOLD ?
897 "FAT16: would be misdetected as FAT12\n" :
898 "FAT16: too much clusters\n");
899 clust16 = 0;
900 }
901
902 clust32 = ((long long)fatdata32 * sector_size + nr_fats * 8) /
903 ((int)bs.cluster_size * sector_size + nr_fats * 4);
904 fatlength32 = cdiv((clust32 + 2) * 4, sector_size);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500905 /* Need to recalculate number of clusters, since the unused parts of the
906 * FATS and data area together could make up space for an additional,
907 * not really present cluster. */
908 clust32 = (fatdata32 - nr_fats * fatlength32) / bs.cluster_size;
909 maxclust32 = (fatlength32 * sector_size) / 4;
910 if (maxclust32 > MAX_CLUST_32)
911 maxclust32 = MAX_CLUST_32;
912 if (clust32 && clust32 < MIN_CLUST_32
913 && !(size_fat_by_user && size_fat == 32)) {
914 clust32 = 0;
915 if (verbose >= 2)
916 printf("FAT32: not enough clusters (%d)\n", MIN_CLUST_32);
917 }
918 if (verbose >= 2)
919 printf("FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
920 clust32, fatlength32, maxclust32, MAX_CLUST_32);
921 if (clust32 > maxclust32) {
922 clust32 = 0;
923 if (verbose >= 2)
924 printf("FAT32: too much clusters\n");
925 }
926
927 if ((clust12 && (size_fat == 0 || size_fat == 12)) ||
928 (clust16 && (size_fat == 0 || size_fat == 16)) ||
929 (clust32 && size_fat == 32))
930 break;
931
932 bs.cluster_size <<= 1;
933 } while (bs.cluster_size && bs.cluster_size <= maxclustsize);
934
935 /* Use the optimal FAT size if not specified;
936 * FAT32 is (not yet) choosen automatically */
937 if (!size_fat) {
938 size_fat = (clust16 > clust12) ? 16 : 12;
939 if (verbose >= 2)
940 printf("Choosing %d bits for FAT\n", size_fat);
941 }
942
943 switch (size_fat) {
944 case 12:
945 cluster_count = clust12;
946 fat_length = fatlength12;
Matt Mower18794c82015-11-11 16:22:45 -0600947 bs.fat_length = htole16(fatlength12);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500948 memcpy(vi->fs_type, MSDOS_FAT12_SIGN, 8);
949 break;
950
951 case 16:
952 if (clust16 < FAT12_THRESHOLD) {
953 if (size_fat_by_user) {
954 fprintf(stderr, "WARNING: Not enough clusters for a "
955 "16 bit FAT! The filesystem will be\n"
956 "misinterpreted as having a 12 bit FAT without "
957 "mount option \"fat=16\".\n");
958 } else {
959 fprintf(stderr, "This filesystem has an unfortunate size. "
960 "A 12 bit FAT cannot provide\n"
961 "enough clusters, but a 16 bit FAT takes up a little "
962 "bit more space so that\n"
963 "the total number of clusters becomes less than the "
964 "threshold value for\n"
965 "distinction between 12 and 16 bit FATs.\n");
Matt Mower18794c82015-11-11 16:22:45 -0600966 die("Make the filesystem a bit smaller manually.");
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500967 }
968 }
969 cluster_count = clust16;
970 fat_length = fatlength16;
Matt Mower18794c82015-11-11 16:22:45 -0600971 bs.fat_length = htole16(fatlength16);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500972 memcpy(vi->fs_type, MSDOS_FAT16_SIGN, 8);
973 break;
974
975 case 32:
976 if (clust32 < MIN_CLUST_32)
977 fprintf(stderr,
978 "WARNING: Not enough clusters for a 32 bit FAT!\n");
979 cluster_count = clust32;
980 fat_length = fatlength32;
Matt Mower18794c82015-11-11 16:22:45 -0600981 bs.fat_length = htole16(0);
982 bs.fat32.fat32_length = htole32(fatlength32);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500983 memcpy(vi->fs_type, MSDOS_FAT32_SIGN, 8);
984 root_dir_entries = 0;
985 break;
986
987 default:
988 die("FAT not 12, 16 or 32 bits");
989 }
990
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500991 /* Adjust the number of root directory entries to help enforce alignment */
992 if (align_structures) {
993 root_dir_entries = align_object(root_dir_sectors, bs.cluster_size)
994 * (sector_size >> 5);
995 }
996 } else {
997 unsigned clusters, maxclust, fatdata;
998
999 /* GEMDOS always uses a 12 bit FAT on floppies, and always a 16 bit FAT on
Matt Mower18794c82015-11-11 16:22:45 -06001000 * hard disks. So use 12 bit if the size of the filesystem suggests that
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001001 * this fs is for a floppy disk, if the user hasn't explicitly requested a
1002 * size.
1003 */
1004 if (!size_fat)
1005 size_fat = (num_sectors == 1440 || num_sectors == 2400 ||
1006 num_sectors == 2880 || num_sectors == 5760) ? 12 : 16;
1007 if (verbose >= 2)
1008 printf("Choosing %d bits for FAT\n", size_fat);
1009
1010 /* Atari format: cluster size should be 2, except explicitly requested by
1011 * the user, since GEMDOS doesn't like other cluster sizes very much.
1012 * Instead, tune the sector size for the FS to fit.
1013 */
1014 bs.cluster_size = sectors_per_cluster ? sectors_per_cluster : 2;
1015 if (!sector_size_set) {
1016 while (num_sectors > GEMDOS_MAX_SECTORS) {
1017 num_sectors >>= 1;
1018 sector_size <<= 1;
1019 }
1020 }
1021 if (verbose >= 2)
1022 printf("Sector size must be %d to have less than %d log. sectors\n",
1023 sector_size, GEMDOS_MAX_SECTORS);
1024
1025 /* Check if there are enough FAT indices for how much clusters we have */
1026 do {
1027 fatdata = num_sectors - cdiv(root_dir_entries * 32, sector_size) -
1028 reserved_sectors;
1029 /* The factor 2 below avoids cut-off errors for nr_fats == 1 and
1030 * size_fat == 12
1031 * The "2*nr_fats*size_fat/8" is for the reserved first two FAT entries
1032 */
1033 clusters =
1034 (2 *
1035 ((long long)fatdata * sector_size -
1036 2 * nr_fats * size_fat / 8)) / (2 * ((int)bs.cluster_size *
1037 sector_size +
1038 nr_fats * size_fat / 8));
1039 fat_length = cdiv((clusters + 2) * size_fat / 8, sector_size);
1040 /* Need to recalculate number of clusters, since the unused parts of the
1041 * FATS and data area together could make up space for an additional,
1042 * not really present cluster. */
1043 clusters = (fatdata - nr_fats * fat_length) / bs.cluster_size;
1044 maxclust = (fat_length * sector_size * 8) / size_fat;
1045 if (verbose >= 2)
1046 printf("ss=%d: #clu=%d, fat_len=%d, maxclu=%d\n",
1047 sector_size, clusters, fat_length, maxclust);
1048
1049 /* last 10 cluster numbers are special (except FAT32: 4 high bits rsvd);
1050 * first two numbers are reserved */
1051 if (maxclust <=
1052 (size_fat == 32 ? MAX_CLUST_32 : (1 << size_fat) - 0x10)
1053 && clusters <= maxclust - 2)
1054 break;
1055 if (verbose >= 2)
1056 printf(clusters > maxclust - 2 ?
1057 "Too many clusters\n" : "FAT too big\n");
1058
1059 /* need to increment sector_size once more to */
1060 if (sector_size_set)
1061 die("With this sector size, the maximum number of FAT entries "
1062 "would be exceeded.");
1063 num_sectors >>= 1;
1064 sector_size <<= 1;
1065 } while (sector_size <= GEMDOS_MAX_SECTOR_SIZE);
1066
1067 if (sector_size > GEMDOS_MAX_SECTOR_SIZE)
1068 die("Would need a sector size > 16k, which GEMDOS can't work with");
1069
1070 cluster_count = clusters;
1071 if (size_fat != 32)
Matt Mower18794c82015-11-11 16:22:45 -06001072 bs.fat_length = htole16(fat_length);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001073 else {
1074 bs.fat_length = 0;
Matt Mower18794c82015-11-11 16:22:45 -06001075 bs.fat32.fat32_length = htole32(fat_length);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001076 }
1077 }
1078
1079 bs.sector_size[0] = (char)(sector_size & 0x00ff);
1080 bs.sector_size[1] = (char)((sector_size & 0xff00) >> 8);
1081
1082 bs.dir_entries[0] = (char)(root_dir_entries & 0x00ff);
1083 bs.dir_entries[1] = (char)((root_dir_entries & 0xff00) >> 8);
1084
1085 if (size_fat == 32) {
1086 /* set up additional FAT32 fields */
Matt Mower18794c82015-11-11 16:22:45 -06001087 bs.fat32.flags = htole16(0);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001088 bs.fat32.version[0] = 0;
1089 bs.fat32.version[1] = 0;
Matt Mower18794c82015-11-11 16:22:45 -06001090 bs.fat32.root_cluster = htole32(2);
1091 bs.fat32.info_sector = htole16(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001092 if (!backup_boot)
1093 backup_boot = (reserved_sectors >= 7) ? 6 :
1094 (reserved_sectors >= 2) ? reserved_sectors - 1 : 0;
1095 else {
1096 if (backup_boot == 1)
1097 die("Backup boot sector must be after sector 1");
1098 else if (backup_boot >= reserved_sectors)
1099 die("Backup boot sector must be a reserved sector");
1100 }
1101 if (verbose >= 2)
1102 printf("Using sector %d as backup boot sector (0 = none)\n",
1103 backup_boot);
Matt Mower18794c82015-11-11 16:22:45 -06001104 bs.fat32.backup_boot = htole16(backup_boot);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001105 memset(&bs.fat32.reserved2, 0, sizeof(bs.fat32.reserved2));
1106 }
1107
1108 if (atari_format) {
1109 /* Just some consistency checks */
1110 if (num_sectors >= GEMDOS_MAX_SECTORS)
1111 die("GEMDOS can't handle more than 65531 sectors");
1112 else if (num_sectors >= OLDGEMDOS_MAX_SECTORS)
1113 printf("Warning: More than 32765 sector need TOS 1.04 "
1114 "or higher.\n");
1115 }
1116 if (num_sectors >= 65536) {
1117 bs.sectors[0] = (char)0;
1118 bs.sectors[1] = (char)0;
Matt Mower18794c82015-11-11 16:22:45 -06001119 bs.total_sect = htole32(num_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001120 } else {
1121 bs.sectors[0] = (char)(num_sectors & 0x00ff);
1122 bs.sectors[1] = (char)((num_sectors & 0xff00) >> 8);
1123 if (!atari_format)
Matt Mower18794c82015-11-11 16:22:45 -06001124 bs.total_sect = htole32(0);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001125 }
1126
1127 if (!atari_format)
1128 vi->ext_boot_sign = MSDOS_EXT_SIGN;
1129
1130 if (!cluster_count) {
1131 if (sectors_per_cluster) /* If yes, die if we'd spec'd sectors per cluster */
Matt Mower18794c82015-11-11 16:22:45 -06001132 die("Too many clusters for filesystem - try more sectors per cluster");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001133 else
Matt Mower18794c82015-11-11 16:22:45 -06001134 die("Attempting to create a too large filesystem");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001135 }
1136
1137 /* The two following vars are in hard sectors, i.e. 512 byte sectors! */
1138 start_data_sector = (reserved_sectors + nr_fats * fat_length) *
1139 (sector_size / HARD_SECTOR_SIZE);
1140 start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) /
1141 SECTORS_PER_BLOCK;
1142
Matt Mower18794c82015-11-11 16:22:45 -06001143 if (blocks < start_data_block + 32) /* Arbitrary undersize filesystem! */
1144 die("Too few blocks for viable filesystem");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001145
1146 if (verbose) {
1147 printf("%s has %d head%s and %d sector%s per track,\n",
Matt Mower18794c82015-11-11 16:22:45 -06001148 device_name, le16toh(bs.heads),
1149 (le16toh(bs.heads) != 1) ? "s" : "", le16toh(bs.secs_track),
1150 (le16toh(bs.secs_track) != 1) ? "s" : "");
1151 printf("hidden sectors 0x%04x;\n", hidden_sectors);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001152 printf("logical sector size is %d,\n", sector_size);
1153 printf("using 0x%02x media descriptor, with %d sectors;\n",
1154 (int)(bs.media), num_sectors);
Matt Mower18794c82015-11-11 16:22:45 -06001155 printf("drive number 0x%02x;\n", (int) (vi->drive_number));
1156 printf("filesystem has %d %d-bit FAT%s and %d sector%s per cluster.\n",
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001157 (int)(bs.fats), size_fat, (bs.fats != 1) ? "s" : "",
1158 (int)(bs.cluster_size), (bs.cluster_size != 1) ? "s" : "");
1159 printf("FAT size is %d sector%s, and provides %d cluster%s.\n",
1160 fat_length, (fat_length != 1) ? "s" : "",
1161 cluster_count, (cluster_count != 1) ? "s" : "");
1162 printf("There %s %u reserved sector%s.\n",
1163 (reserved_sectors != 1) ? "are" : "is",
1164 reserved_sectors, (reserved_sectors != 1) ? "s" : "");
1165
1166 if (size_fat != 32) {
1167 unsigned root_dir_entries =
1168 bs.dir_entries[0] + ((bs.dir_entries[1]) * 256);
1169 unsigned root_dir_sectors =
1170 cdiv(root_dir_entries * 32, sector_size);
1171 printf("Root directory contains %u slots and uses %u sectors.\n",
1172 root_dir_entries, root_dir_sectors);
1173 }
1174 printf("Volume ID is %08lx, ", volume_id &
1175 (atari_format ? 0x00ffffff : 0xffffffff));
Matt Mower18794c82015-11-11 16:22:45 -06001176 if (strcmp(volume_name, NO_NAME))
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001177 printf("volume label %s.\n", volume_name);
1178 else
1179 printf("no volume label.\n");
1180 }
1181
1182 /* Make the file allocation tables! */
1183
1184 if (malloc_entire_fat)
1185 alloced_fat_length = fat_length;
1186 else
1187 alloced_fat_length = 1;
1188
1189 if ((fat =
1190 (unsigned char *)malloc(alloced_fat_length * sector_size)) == NULL)
1191 die("unable to allocate space for FAT image in memory");
1192
1193 memset(fat, 0, alloced_fat_length * sector_size);
1194
1195 mark_FAT_cluster(0, 0xffffffff); /* Initial fat entries */
1196 mark_FAT_cluster(1, 0xffffffff);
1197 fat[0] = (unsigned char)bs.media; /* Put media type in first byte! */
1198 if (size_fat == 32) {
1199 /* Mark cluster 2 as EOF (used for root dir) */
1200 mark_FAT_cluster(2, FAT_EOF);
1201 }
1202
1203 /* Make the root directory entries */
1204
1205 size_root_dir = (size_fat == 32) ?
1206 bs.cluster_size * sector_size :
1207 (((int)bs.dir_entries[1] * 256 + (int)bs.dir_entries[0]) *
1208 sizeof(struct msdos_dir_entry));
1209 if ((root_dir = (struct msdos_dir_entry *)malloc(size_root_dir)) == NULL) {
1210 free(fat); /* Tidy up before we die! */
1211 die("unable to allocate space for root directory in memory");
1212 }
1213
1214 memset(root_dir, 0, size_root_dir);
Matt Mower18794c82015-11-11 16:22:45 -06001215 if (memcmp(volume_name, NO_NAME, 11)) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001216 struct msdos_dir_entry *de = &root_dir[0];
1217 memcpy(de->name, volume_name, 8);
1218 memcpy(de->ext, volume_name + 8, 3);
1219 de->attr = ATTR_VOLUME;
Matt Mower18794c82015-11-11 16:22:45 -06001220 if (!invariant)
1221 ctime = localtime(&create_time);
1222 else
1223 ctime = gmtime(&create_time);
1224 de->time = htole16((unsigned short)((ctime->tm_sec >> 1) +
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001225 (ctime->tm_min << 5) +
1226 (ctime->tm_hour << 11)));
1227 de->date =
Matt Mower18794c82015-11-11 16:22:45 -06001228 htole16((unsigned short)(ctime->tm_mday +
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001229 ((ctime->tm_mon + 1) << 5) +
1230 ((ctime->tm_year - 80) << 9)));
Matt Mower18794c82015-11-11 16:22:45 -06001231 de->ctime_cs = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001232 de->ctime = de->time;
1233 de->cdate = de->date;
1234 de->adate = de->date;
Matt Mower18794c82015-11-11 16:22:45 -06001235 de->starthi = htole16(0);
1236 de->start = htole16(0);
1237 de->size = htole32(0);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001238 }
1239
1240 if (size_fat == 32) {
1241 /* For FAT32, create an info sector */
1242 struct fat32_fsinfo *info;
1243
1244 if (!(info_sector = malloc(sector_size)))
1245 die("Out of memory");
1246 memset(info_sector, 0, sector_size);
1247 /* fsinfo structure is at offset 0x1e0 in info sector by observation */
1248 info = (struct fat32_fsinfo *)(info_sector + 0x1e0);
1249
1250 /* Info sector magic */
1251 info_sector[0] = 'R';
1252 info_sector[1] = 'R';
1253 info_sector[2] = 'a';
1254 info_sector[3] = 'A';
1255
1256 /* Magic for fsinfo structure */
Matt Mower18794c82015-11-11 16:22:45 -06001257 info->signature = htole32(0x61417272);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001258 /* We've allocated cluster 2 for the root dir. */
Matt Mower18794c82015-11-11 16:22:45 -06001259 info->free_clusters = htole32(cluster_count - 1);
1260 info->next_cluster = htole32(2);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001261
1262 /* Info sector also must have boot sign */
Matt Mower18794c82015-11-11 16:22:45 -06001263 *(uint16_t *) (info_sector + 0x1fe) = htole16(BOOT_SIGN);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001264 }
1265
1266 if (!(blank_sector = malloc(sector_size)))
1267 die("Out of memory");
1268 memset(blank_sector, 0, sector_size);
1269}
1270
1271/* Write the new filesystem's data tables to wherever they're going to end up! */
1272
1273#define error(str) \
1274 do { \
1275 free (fat); \
1276 if (info_sector) free (info_sector); \
1277 free (root_dir); \
1278 die (str); \
1279 } while(0)
1280
1281#define seekto(pos,errstr) \
1282 do { \
1283 loff_t __pos = (pos); \
1284 if (llseek (dev, __pos, SEEK_SET) != __pos) \
1285 error ("seek to " errstr " failed whilst writing tables"); \
1286 } while(0)
1287
1288#define writebuf(buf,size,errstr) \
1289 do { \
1290 int __size = (size); \
1291 if (write (dev, buf, __size) != __size) \
1292 error ("failed whilst writing " errstr); \
1293 } while(0)
1294
1295static void write_tables(void)
1296{
1297 int x;
1298 int fat_length;
1299
1300 fat_length = (size_fat == 32) ?
Matt Mower18794c82015-11-11 16:22:45 -06001301 le32toh(bs.fat32.fat32_length) : le16toh(bs.fat_length);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001302
1303 seekto(0, "start of device");
1304 /* clear all reserved sectors */
1305 for (x = 0; x < reserved_sectors; ++x)
1306 writebuf(blank_sector, sector_size, "reserved sector");
1307 /* seek back to sector 0 and write the boot sector */
1308 seekto(0, "boot sector");
1309 writebuf((char *)&bs, sizeof(struct msdos_boot_sector), "boot sector");
1310 /* on FAT32, write the info sector and backup boot sector */
1311 if (size_fat == 32) {
Matt Mower18794c82015-11-11 16:22:45 -06001312 seekto(le16toh(bs.fat32.info_sector) * sector_size, "info sector");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001313 writebuf(info_sector, 512, "info sector");
1314 if (backup_boot != 0) {
1315 seekto(backup_boot * sector_size, "backup boot sector");
1316 writebuf((char *)&bs, sizeof(struct msdos_boot_sector),
1317 "backup boot sector");
1318 }
1319 }
1320 /* seek to start of FATS and write them all */
1321 seekto(reserved_sectors * sector_size, "first FAT");
1322 for (x = 1; x <= nr_fats; x++) {
1323 int y;
1324 int blank_fat_length = fat_length - alloced_fat_length;
1325 writebuf(fat, alloced_fat_length * sector_size, "FAT");
1326 for (y = 0; y < blank_fat_length; y++)
1327 writebuf(blank_sector, sector_size, "FAT");
1328 }
1329 /* Write the root directory directly after the last FAT. This is the root
1330 * dir area on FAT12/16, and the first cluster on FAT32. */
1331 writebuf((char *)root_dir, size_root_dir, "root directory");
1332
1333 if (blank_sector)
1334 free(blank_sector);
1335 if (info_sector)
1336 free(info_sector);
1337 free(root_dir); /* Free up the root directory space from setup_tables */
1338 free(fat); /* Free up the fat table space reserved during setup_tables */
1339}
1340
Matt Mower18794c82015-11-11 16:22:45 -06001341/* Report the command usage and exit with the given error code */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001342
Matt Mower18794c82015-11-11 16:22:45 -06001343static void usage(int exitval)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001344{
Matt Mower18794c82015-11-11 16:22:45 -06001345 fprintf(stderr, "\
1346Usage: mkfs.fat [-a][-A][-c][-C][-v][-I][-l bad-block-file][-b backup-boot-sector]\n\
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001347 [-m boot-msg-file][-n volume-name][-i volume-id]\n\
1348 [-s sectors-per-cluster][-S logical-sector-size][-f number-of-FATs]\n\
1349 [-h hidden-sectors][-F fat-size][-r root-dir-entries][-R reserved-sectors]\n\
Matt Mower18794c82015-11-11 16:22:45 -06001350 [-M FAT-media-byte][-D drive_number]\n\
1351 [--invariant]\n\
1352 [--help]\n\
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001353 /dev/name [blocks]\n");
Matt Mower18794c82015-11-11 16:22:45 -06001354 exit(exitval);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001355}
1356
1357/*
1358 * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
1359 * of MS-DOS filesystem by default.
1360 */
1361static void check_atari(void)
1362{
1363#ifdef __mc68000__
1364 FILE *f;
1365 char line[128], *p;
1366
1367 if (!(f = fopen("/proc/hardware", "r"))) {
1368 perror("/proc/hardware");
1369 return;
1370 }
1371
1372 while (fgets(line, sizeof(line), f)) {
1373 if (strncmp(line, "Model:", 6) == 0) {
1374 p = line + 6;
1375 p += strspn(p, " \t");
1376 if (strncmp(p, "Atari ", 6) == 0)
1377 atari_format = 1;
1378 break;
1379 }
1380 }
1381 fclose(f);
1382#endif
1383}
1384
1385/* The "main" entry point into the utility - we pick up the options and attempt to process them in some sort of sensible
1386 way. In the event that some/all of the options are invalid we need to tell the user so that something can be done! */
1387
1388int main(int argc, char **argv)
1389{
1390 int c;
1391 char *tmp;
1392 char *listfile = NULL;
1393 FILE *msgfile;
1394 struct stat statbuf;
1395 int i = 0, pos, ch;
1396 int create = 0;
Matt Mower18794c82015-11-11 16:22:45 -06001397 uint64_t cblocks = 0;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001398 int min_sector_size;
Matt Mower18794c82015-11-11 16:22:45 -06001399 int bad_block_count = 0;
1400 struct timeval create_timeval;
1401
1402 enum {OPT_HELP=1000, OPT_INVARIANT,};
1403 const struct option long_options[] = {
1404 {"help", no_argument, NULL, OPT_HELP},
1405 {"invariant", no_argument, NULL, OPT_INVARIANT},
1406 {0,}
1407 };
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001408
1409 if (argc && *argv) { /* What's the program name? */
1410 char *p;
1411 program_name = *argv;
1412 if ((p = strrchr(program_name, '/')))
1413 program_name = p + 1;
1414 }
1415
1416 gettimeofday(&create_timeval, NULL);
1417 create_time = create_timeval.tv_sec;
Matt Mower18794c82015-11-11 16:22:45 -06001418 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 -05001419 check_atari();
1420
Matt Mower18794c82015-11-11 16:22:45 -06001421 printf("mkfs.fat " VERSION " (" VERSION_DATE ")\n");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001422
Matt Mower18794c82015-11-11 16:22:45 -06001423 while ((c = getopt_long(argc, argv, "aAb:cCf:D:F:Ii:l:m:M:n:r:R:s:S:h:v",
1424 long_options, NULL)) != -1)
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001425 /* Scan the command line for options */
1426 switch (c) {
1427 case 'A': /* toggle Atari format */
1428 atari_format = !atari_format;
1429 break;
1430
1431 case 'a': /* a : skip alignment */
1432 align_structures = FALSE;
1433 break;
1434
1435 case 'b': /* b : location of backup boot sector */
1436 backup_boot = (int)strtol(optarg, &tmp, 0);
1437 if (*tmp || backup_boot < 2 || backup_boot > 0xffff) {
1438 printf("Bad location for backup boot sector : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001439 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001440 }
1441 break;
1442
1443 case 'c': /* c : Check FS as we build it */
1444 check = TRUE;
1445 malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
1446 break;
1447
1448 case 'C': /* C : Create a new file */
1449 create = TRUE;
1450 break;
1451
Matt Mower18794c82015-11-11 16:22:45 -06001452 case 'D': /* D : Choose Drive Number */
1453 drive_number_option = (int) strtol (optarg, &tmp, 0);
1454 if (*tmp || (drive_number_option != 0 && drive_number_option != 0x80)) {
1455 printf ("Drive number must be 0 or 0x80: %s\n", optarg);
1456 usage(1);
1457 }
1458 drive_number_by_user=1;
1459 break;
1460
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001461 case 'f': /* f : Choose number of FATs */
1462 nr_fats = (int)strtol(optarg, &tmp, 0);
1463 if (*tmp || nr_fats < 1 || nr_fats > 4) {
1464 printf("Bad number of FATs : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001465 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001466 }
1467 break;
1468
1469 case 'F': /* F : Choose FAT size */
1470 size_fat = (int)strtol(optarg, &tmp, 0);
1471 if (*tmp || (size_fat != 12 && size_fat != 16 && size_fat != 32)) {
1472 printf("Bad FAT type : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001473 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001474 }
1475 size_fat_by_user = 1;
1476 break;
1477
1478 case 'h': /* h : number of hidden sectors */
1479 hidden_sectors = (int)strtol(optarg, &tmp, 0);
1480 if (*tmp || hidden_sectors < 0) {
1481 printf("Bad number of hidden sectors : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001482 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001483 }
Matt Mower18794c82015-11-11 16:22:45 -06001484 hidden_sectors_by_user = 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001485 break;
1486
1487 case 'I':
1488 ignore_full_disk = 1;
1489 break;
1490
1491 case 'i': /* i : specify volume ID */
1492 volume_id = strtoul(optarg, &tmp, 16);
1493 if (*tmp) {
1494 printf("Volume ID must be a hexadecimal number\n");
Matt Mower18794c82015-11-11 16:22:45 -06001495 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001496 }
1497 break;
1498
1499 case 'l': /* l : Bad block filename */
1500 listfile = optarg;
1501 malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
1502 break;
1503
1504 case 'm': /* m : Set boot message */
1505 if (strcmp(optarg, "-")) {
1506 msgfile = fopen(optarg, "r");
1507 if (!msgfile)
1508 perror(optarg);
1509 } else
1510 msgfile = stdin;
1511
1512 if (msgfile) {
1513 /* The boot code ends at offset 448 and needs a null terminator */
1514 i = MESSAGE_OFFSET;
1515 pos = 0; /* We are at beginning of line */
1516 do {
1517 ch = getc(msgfile);
1518 switch (ch) {
1519 case '\r': /* Ignore CRs */
1520 case '\0': /* and nulls */
1521 break;
1522
1523 case '\n': /* LF -> CR+LF if necessary */
1524 if (pos) { /* If not at beginning of line */
1525 dummy_boot_code[i++] = '\r';
1526 pos = 0;
1527 }
1528 dummy_boot_code[i++] = '\n';
1529 break;
1530
1531 case '\t': /* Expand tabs */
1532 do {
1533 dummy_boot_code[i++] = ' ';
1534 pos++;
1535 }
1536 while (pos % 8 && i < BOOTCODE_SIZE - 1);
1537 break;
1538
1539 case EOF:
1540 dummy_boot_code[i++] = '\0'; /* Null terminator */
1541 break;
1542
1543 default:
1544 dummy_boot_code[i++] = ch; /* Store character */
1545 pos++; /* Advance position */
1546 break;
1547 }
1548 }
1549 while (ch != EOF && i < BOOTCODE_SIZE - 1);
1550
1551 /* Fill up with zeros */
1552 while (i < BOOTCODE_SIZE - 1)
1553 dummy_boot_code[i++] = '\0';
1554 dummy_boot_code[BOOTCODE_SIZE - 1] = '\0'; /* Just in case */
1555
1556 if (ch != EOF)
1557 printf("Warning: message too long; truncated\n");
1558
1559 if (msgfile != stdin)
1560 fclose(msgfile);
1561 }
1562 break;
1563
Matt Mower18794c82015-11-11 16:22:45 -06001564 case 'M': /* M : FAT Media byte */
1565 fat_media_byte = (int)strtol(optarg, &tmp, 0);
1566 if (*tmp) {
1567 printf("Bad number for media descriptor : %s\n", optarg);
1568 usage(1);
1569 }
1570 if (fat_media_byte != 0xf0 && (fat_media_byte < 0xf8 || fat_media_byte > 0xff)) {
1571 printf("FAT Media byte must either be between 0xF8 and 0xFF or be 0xF0 : %s\n", optarg);
1572 usage(1);
1573 }
1574 break;
1575
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001576 case 'n': /* n : Volume name */
1577 sprintf(volume_name, "%-11.11s", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001578 for (i = 0; volume_name[i] && i < 11; i++)
1579 /* don't know if here should be more strict !uppercase(label[i]) */
1580 if (islower(volume_name[i])) {
1581 fprintf(stderr,
1582 "mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows\n");
1583 break;
1584 }
1585
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001586 break;
1587
1588 case 'r': /* r : Root directory entries */
1589 root_dir_entries = (int)strtol(optarg, &tmp, 0);
1590 if (*tmp || root_dir_entries < 16 || root_dir_entries > 32768) {
1591 printf("Bad number of root directory entries : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001592 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001593 }
1594 break;
1595
1596 case 'R': /* R : number of reserved sectors */
1597 reserved_sectors = (int)strtol(optarg, &tmp, 0);
1598 if (*tmp || reserved_sectors < 1 || reserved_sectors > 0xffff) {
1599 printf("Bad number of reserved sectors : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001600 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001601 }
1602 break;
1603
1604 case 's': /* s : Sectors per cluster */
1605 sectors_per_cluster = (int)strtol(optarg, &tmp, 0);
1606 if (*tmp || (sectors_per_cluster != 1 && sectors_per_cluster != 2
1607 && sectors_per_cluster != 4 && sectors_per_cluster != 8
1608 && sectors_per_cluster != 16
1609 && sectors_per_cluster != 32
1610 && sectors_per_cluster != 64
1611 && sectors_per_cluster != 128)) {
1612 printf("Bad number of sectors per cluster : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001613 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001614 }
1615 break;
1616
1617 case 'S': /* S : Sector size */
1618 sector_size = (int)strtol(optarg, &tmp, 0);
1619 if (*tmp || (sector_size != 512 && sector_size != 1024 &&
1620 sector_size != 2048 && sector_size != 4096 &&
1621 sector_size != 8192 && sector_size != 16384 &&
1622 sector_size != 32768)) {
1623 printf("Bad logical sector size : %s\n", optarg);
Matt Mower18794c82015-11-11 16:22:45 -06001624 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001625 }
1626 sector_size_set = 1;
1627 break;
1628
1629 case 'v': /* v : Verbose execution */
1630 ++verbose;
1631 break;
1632
Matt Mower18794c82015-11-11 16:22:45 -06001633 case OPT_HELP:
1634 usage(0);
1635 break;
1636
1637 case OPT_INVARIANT:
1638 invariant = 1;
1639 volume_id = 0x1234abcd;
1640 create_time = 1426325213;
1641 break;
1642
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001643 default:
1644 printf("Unknown option: %c\n", c);
Matt Mower18794c82015-11-11 16:22:45 -06001645 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001646 }
1647 if (optind < argc) {
1648 device_name = argv[optind]; /* Determine the number of blocks in the FS */
1649
1650 if (!device_name) {
1651 printf("No device specified.\n");
Matt Mower18794c82015-11-11 16:22:45 -06001652 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001653 }
1654
1655 if (!create)
1656 cblocks = count_blocks(device_name, &orphaned_sectors); /* Have a look and see! */
1657 }
1658 if (optind == argc - 2) { /* Either check the user specified number */
1659 blocks = strtoull(argv[optind + 1], &tmp, 0);
1660 if (!create && blocks != cblocks) {
1661 fprintf(stderr, "Warning: block count mismatch: ");
Matt Mower18794c82015-11-11 16:22:45 -06001662 fprintf(stderr, "found %llu but assuming %llu.\n", (unsigned long long)cblocks, (unsigned long long)blocks);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001663 }
Matt Mower18794c82015-11-11 16:22:45 -06001664 if (*tmp)
1665 bad_block_count = 1;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001666 } else if (optind == argc - 1) { /* Or use value found */
1667 if (create)
1668 die("Need intended size with -C.");
1669 blocks = cblocks;
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001670 } else {
1671 fprintf(stderr, "No device specified!\n");
Matt Mower18794c82015-11-11 16:22:45 -06001672 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001673 }
Matt Mower18794c82015-11-11 16:22:45 -06001674 if (bad_block_count) {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001675 printf("Bad block count : %s\n", argv[optind + 1]);
Matt Mower18794c82015-11-11 16:22:45 -06001676 usage(1);
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001677 }
1678
1679 if (check && listfile) /* Auto and specified bad block handling are mutually */
1680 die("-c and -l are incompatible"); /* exclusive of each other! */
1681
1682 if (!create) {
1683 check_mount(device_name); /* Is the device already mounted? */
1684 dev = open(device_name, O_EXCL | O_RDWR); /* Is it a suitable device to build the FS on? */
1685 if (dev < 0) {
1686 fprintf(stderr, "%s: unable to open %s: %s\n", program_name,
1687 device_name, strerror(errno));
1688 exit(1); /* The error exit code is 1! */
1689 }
1690 } else {
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001691 /* create the file */
Matt Mower18794c82015-11-11 16:22:45 -06001692 dev = open(device_name, O_EXCL | O_RDWR | O_CREAT, 0666);
1693 if (dev < 0) {
1694 if (errno == EEXIST)
1695 die("file %s already exists");
1696 else
1697 die("unable to create %s");
1698 }
1699 /* expand to desired size */
1700 if (ftruncate(dev, blocks * BLOCK_SIZE))
1701 die("unable to resize %s");
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001702 }
1703
1704 if (fstat(dev, &statbuf) < 0)
1705 die("unable to stat %s");
1706 if (!S_ISBLK(statbuf.st_mode)) {
1707 statbuf.st_rdev = 0;
1708 check = 0;
1709 } else
1710 /*
1711 * Ignore any 'full' fixed disk devices, if -I is not given.
1712 * On a MO-disk one doesn't need partitions. The filesytem can go
1713 * directly to the whole disk. Under other OSes this is known as
1714 * the 'superfloppy' format. As I don't know how to find out if
1715 * this is a MO disk I introduce a -I (ignore) switch. -Joey
1716 */
Matt Mower18794c82015-11-11 16:22:45 -06001717 if (!ignore_full_disk && ((statbuf.st_rdev & 0xffffff3f) == 0x0300 || /* hda, hdb */
1718 (statbuf.st_rdev & 0xffffff0f) == 0x0800 || /* sd */
1719 (statbuf.st_rdev & 0xffffff3f) == 0x0d00 || /* xd */
1720 (statbuf.st_rdev & 0xffffff3f) == 0x1600) /* hdc, hdd */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001721 )
1722 die("Device partition expected, not making filesystem on entire device '%s' (use -I to override)");
1723
1724 if (sector_size_set) {
1725 if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0)
1726 if (sector_size < min_sector_size) {
1727 sector_size = min_sector_size;
1728 fprintf(stderr,
1729 "Warning: sector size was set to %d (minimal for this device)\n",
1730 sector_size);
1731 }
1732 } else {
1733 if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0) {
1734 sector_size = min_sector_size;
1735 sector_size_set = 1;
1736 }
1737 }
1738
1739 if (sector_size > 4096)
1740 fprintf(stderr,
1741 "Warning: sector size is set to %d > 4096, such filesystem will not propably mount\n",
1742 sector_size);
1743
1744 establish_params(statbuf.st_rdev, statbuf.st_size);
1745 /* Establish the media parameters */
1746
Matt Mower18794c82015-11-11 16:22:45 -06001747 setup_tables(); /* Establish the filesystem tables */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001748
1749 if (check) /* Determine any bad block locations and mark them */
1750 check_blocks();
1751 else if (listfile)
1752 get_list_blocks(listfile);
1753
Matt Mower18794c82015-11-11 16:22:45 -06001754 write_tables(); /* Write the filesystem tables away! */
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001755
1756 exit(0); /* Terminate with no errors! */
1757}