34 #include <sys/types.h>
45 #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
49 #define FAT12_THRESHOLD 4085
50 #define FAT16_THRESHOLD 65525
54 static int curr_num = 0;
60 uint32_t clu_num, prev = 0;
65 while (clu_num > 0 && clu_num != -1) {
75 if ((clu_num =
next_cluster(fs, clu_num)) == 0 || clu_num == -1)
84 die(
"Root directory has no cluster allocated!");
85 for (clu_num = prev + 1; clu_num != prev; clu_num++) {
95 die(
"Root directory full and no free cluster");
100 memset(&d2, 0,
sizeof(d2));
103 fs_write(offset + i,
sizeof(d2), &d2);
105 memset(de, 0,
sizeof(
DIR_ENT));
109 sprintf(expanded, pattern, curr_num);
114 while (clu_num > 0 && clu_num != -1) {
116 if (offset2 != offset &&
117 !strncmp((
const char *)d2.
name, (
const char *)de->
name,
129 if (clu_num == 0 || clu_num == -1)
131 if (++curr_num >= 10000)
132 die(
"Unable to create unique name");
139 int next_free = 0, scan;
144 while (next_free < fs->root_entries)
151 die(
"Root directory is full.");
153 memset(de, 0,
sizeof(
DIR_ENT));
157 sprintf(expanded, pattern, curr_num);
160 if (scan != next_free &&
161 !strncmp((
const char *)
root[scan].name,
166 if (++curr_num >= 10000)
167 die(
"Unable to create unique name");
183 0xf0,
"5.25\" or 3.5\" HD floppy"}, {
184 0xf8,
"hard disk"}, {
185 0xf9,
"3,5\" 720k floppy 2s/80tr/9sec or "
186 "5.25\" 1.2M floppy 2s/80tr/15sec"}, {
187 0xfa,
"5.25\" 320k floppy 1s/80tr/8sec"}, {
188 0xfb,
"3.5\" 640k floppy 2s/80tr/8sec"}, {
189 0xfc,
"5.25\" 180k floppy 1s/40tr/9sec"}, {
190 0xfd,
"5.25\" 360k floppy 2s/40tr/9sec"}, {
191 0xfe,
"5.25\" 160k floppy 1s/40tr/8sec"}, {
192 0xff,
"5.25\" 320k floppy 2s/40tr/8sec"},};
195 #define GET_UNALIGNED_W(f) \
196 ( (uint16_t)f[0] | ((uint16_t)f[1]<<8) )
206 return (
"undefined");
211 unsigned short sectors;
213 printf(
"Boot sector contents:\n");
216 strncpy(
id, (
const char *)b->
system_id, 8);
218 printf(
"System ID \"%s\"\n",
id);
222 printf(
"Serial number 0x%x\n",
224 system_id[7] << 16));
229 printf(
"%10d reserved sector%s\n", le16toh(b->
reserved),
230 le16toh(b->
reserved) == 1 ?
"" :
"s");
231 printf(
"First FAT starts at byte %llu (sector %llu)\n",
233 (
unsigned long long)fs->
fat_start / lss);
234 printf(
"%10d FATs, %d bit entries\n", b->
fats, fs->
fat_bits);
235 printf(
"%10u bytes per FAT (= %u sectors)\n", fs->
fat_size,
238 printf(
"Root directory starts at byte %llu (sector %llu)\n",
241 printf(
"%10d root directory entries\n", fs->
root_entries);
243 printf(
"Root directory start at cluster %lu (arbitrary size)\n",
246 printf(
"Data area starts at byte %llu (sector %llu)\n",
249 printf(
"%10lu data clusters (%llu bytes)\n",
252 printf(
"%u sectors/track, %u heads\n", le16toh(b->
secs_track),
256 (((
unsigned char *)&b->
hidden)[0] |
257 ((
unsigned char *)&b->
hidden)[1] << 8) : le32toh(b->
hidden));
259 printf(
"%10u sectors total\n", sectors ? sectors : le32toh(b->
total_sect));
267 printf(
"There is no backup boot sector.\n");
269 printf(
"And there is no space for creating one!\n");
272 if (
get_choice(1,
" Auto-creating backup boot block.",
275 2,
"Do without a backup") == 1) {
291 printf(
"Created backup of boot sector in sector %d\n", bbs);
298 if (memcmp(b, &b2,
sizeof(b2)) != 0) {
301 int i, pos, first = 1;
304 printf(
"There are differences between boot sector and its backup.\n");
305 printf(
"This is mostly harmless. Differences: (offset:original/backup)\n ");
307 for (p = (uint8_t *) b, q = (uint8_t *) & b2, i = 0; i <
sizeof(b2);
310 sprintf(buf,
"%s%u:%02x/%02x", first ?
"" :
", ",
311 (
unsigned)(p - (uint8_t *) b), *p, *q);
312 if (pos + strlen(buf) > 78)
313 printf(
"\n "), pos = 2;
321 switch (
get_choice(3,
" Not automatically fixing this.",
323 1,
"Copy original to backup",
324 2,
"Copy backup to original",
340 i->
magic = htole32(0x41615252);
352 printf(
"No FSINFO sector\n");
353 if (
get_choice(2,
" Not automatically creating it.",
356 2,
"Do without FSINFO") == 1) {
360 for (s = 1; s < le16toh(b->
reserved); ++s)
363 if (s > 0 && s < le16toh(b->
reserved)) {
366 fs_write((off_t)s * lss,
sizeof(i), &i);
375 printf(
"No free reserved sector found -- "
376 "no space for FSINFO sector!\n");
386 if (i.
magic != htole32(0x41615252) ||
388 printf(
"FSINFO sector has bad magic number(s):\n");
389 if (i.
magic != htole32(0x41615252))
390 printf(
" Offset %llu: 0x%08x != expected 0x%08x\n",
392 le32toh(i.
magic), 0x41615252);
394 printf(
" Offset %llu: 0x%08x != expected 0x%08x\n",
398 printf(
" Offset %llu: 0x%08x != expected 0x%08x\n",
404 2,
"Don't correct (FSINFO invalid then)") == 1) {
418 unsigned total_sectors;
419 unsigned int logical_sector_size,
sectors;
421 unsigned total_fat_entries;
427 if (!logical_sector_size)
428 die(
"Logical sector size is zero.");
434 die(
"Logical sector size (%u bytes) is not a multiple of the physical "
435 "sector size.", logical_sector_size);
439 die(
"Cluster size is zero.");
441 die(
"Currently, only 1 or 2 FATs are supported, not %d.\n", b.
fats);
446 printf(
"Checking we can access the last sector of the filesystem\n");
448 position = (
long long)((total_sectors & ~1) - 1) * logical_sector_size;
450 die(
"Filesystem is too large.");
451 if (!
fs_test(position, logical_sector_size))
452 die(
"Failed to read sector %u.", (total_sectors & ~1) - 1);
457 die(
"FAT size is zero.");
463 die(
"Filesystem is too large.");
468 logical_sector_size);
470 die(
"Filesystem is too large.");
472 position = (
long long)total_sectors * logical_sector_size - fs->
data_start;
474 die(
"Filesystem is too large.");
475 data_size = position;
477 die(
"Filesystem has no space for any data clusters");
492 fprintf(stderr,
"Warning: FAT32 root dir not in cluster chain! "
493 "Compatibility mode...\n");
495 die(
"No root directory!");
497 fprintf(stderr,
"Warning: FAT32 root dir is in a cluster chain, but "
498 "a separate root dir\n"
499 " area is defined. Cannot fix this easily.\n");
501 fprintf(stderr,
"Warning: Filesystem is FAT32 according to fat_length "
502 "and fat32_length fields,\n"
503 " but has only %lu clusters, less than the required "
505 " This may lead to problems on some systems.\n",
517 die(
"Too many clusters (%lu) for FAT16 filesystem.",
527 (total_sectors == 720 || total_sectors == 1440 ||
528 total_sectors == 2880))
535 die(
"Filesystem is too large.");
553 if (position > UINT_MAX)
554 die(
"FAT has space for too many entries (%lld).", (
long long)position);
555 total_fat_entries = position;
557 die(
"Filesystem has %u clusters but only space for %u FAT entries.",
560 die(
"Root directory has zero size.");
562 die(
"Root directory (%d entries) doesn't span an integral number of "
565 die(
"Logical sector size (%u bytes) is not a multiple of the physical "
566 "sector size.", logical_sector_size);
570 die(
"Invalid disk format in boot sector.");
586 memmove(b16.
label,
"NO NAME ", 11);
604 memmove(b.
label,
"NO NAME ", 11);
605 memmove(b.
fs_type,
"FAT32 ", 8);
637 cluster != 0 && cluster != -1;
686 memcpy(de.
name, label, 11);
687 if (de.
name[0] == 0xe5)
691 mtime = (now != (time_t)-1) ? localtime(&now) : NULL;
692 if (mtime && mtime->tm_year >= 80 && mtime->tm_year <= 207) {
693 de.
time = htole16((
unsigned short)((mtime->tm_sec >> 1) +
694 (mtime->tm_min << 5) +
695 (mtime->tm_hour << 11)));
696 de.
date = htole16((
unsigned short)(mtime->tm_mday +
697 ((mtime->tm_mon + 1) << 5) +
698 ((mtime->tm_year - 80) << 9)));
701 de.
time = htole16(0);
702 de.
date = htole16(1 + (1 << 5));
720 int l = strlen(label);
749 static char buffer[256];
755 if (label[
last] !=
' ')
760 for (i = 0; i <=
last && label[i] && p < buffer +
sizeof(buffer) - 1; ++i) {
void write_label(DOS_FS *fs, char *label)
static void read_fsinfo(DOS_FS *fs, struct boot_sector *b, unsigned int lss)
static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, unsigned int lss)
const char * pretty_label(const char *label)
static void init_fsinfo_except_reserved(struct info_sector *i)
#define ROUND_TO_MULTIPLE(n, m)
off_t find_volume_de(DOS_FS *fs, DIR_ENT *de)
static void write_boot_label_or_serial(int label_mode, DOS_FS *fs, const char *label, uint32_t serial)
void write_volume_label(DOS_FS *fs, char *label)
#define GET_UNALIGNED_W(f)
static const char * get_media_descr(unsigned char media)
void remove_label(DOS_FS *fs)
void read_boot(DOS_FS *fs)
off_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern, int gen_name)
void write_serial(DOS_FS *fs, uint32_t serial)
static void dump_boot(DOS_FS *fs, struct boot_sector *b, unsigned lss)
void write_boot_label(DOS_FS *fs, const char *label)
static struct @0 mediabytes[]
int dos_char_to_printable(char **p, unsigned char c, unsigned int out_size)
void die(const char *msg,...)
int get_choice(int noninteractive_result, const char *noninteractive_msg, int choices,...)
uint32_t next_cluster(DOS_FS *fs, uint32_t cluster)
void set_owner(DOS_FS *fs, uint32_t cluster, DOS_FILE *owner)
off_t cluster_start(DOS_FS *fs, uint32_t cluster)
DOS_FILE * get_owner(DOS_FS *fs, uint32_t cluster)
void get_fat(FAT_ENTRY *entry, void *fat, uint32_t cluster, DOS_FS *fs)
void set_fat(DOS_FS *fs, uint32_t cluster, int32_t new)
int fs_test(off_t pos, int size)
void fs_read(off_t pos, int size, void *data)
void fs_write(off_t pos, int size, void *data)
unsigned int cluster_size
unsigned int eff_fat_bits
unsigned int root_entries