Indenting source files.
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
This commit is contained in:
parent
697af859b6
commit
2d8be9c628
111
src/boot.c
111
src/boot.c
@ -35,7 +35,6 @@
|
||||
#include "io.h"
|
||||
#include "boot.h"
|
||||
|
||||
|
||||
#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
|
||||
/* don't divide by zero */
|
||||
|
||||
@ -47,17 +46,17 @@ static struct {
|
||||
__u8 media;
|
||||
char *descr;
|
||||
} mediabytes[] = {
|
||||
{ 0xf0, "5.25\" or 3.5\" HD floppy" },
|
||||
{ 0xf8, "hard disk" },
|
||||
{ 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
|
||||
"5.25\" 1.2M floppy 2s/80tr/15sec" },
|
||||
{ 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" },
|
||||
{ 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" },
|
||||
{ 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" },
|
||||
{ 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" },
|
||||
{ 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" },
|
||||
{ 0xff, "5.25\" 320k floppy 2s/40tr/8sec" },
|
||||
};
|
||||
{
|
||||
0xf0, "5.25\" or 3.5\" HD floppy"}, {
|
||||
0xf8, "hard disk"}, {
|
||||
0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
|
||||
"5.25\" 1.2M floppy 2s/80tr/15sec"}, {
|
||||
0xfa, "5.25\" 320k floppy 1s/80tr/8sec"}, {
|
||||
0xfb, "3.5\" 640k floppy 2s/80tr/8sec"}, {
|
||||
0xfc, "5.25\" 180k floppy 1s/40tr/9sec"}, {
|
||||
0xfd, "5.25\" 360k floppy 2s/40tr/9sec"}, {
|
||||
0xfe, "5.25\" 160k floppy 1s/40tr/8sec"}, {
|
||||
0xff, "5.25\" 320k floppy 2s/40tr/8sec"},};
|
||||
|
||||
#if defined __alpha || defined __arm || defined __arm__ || defined __ia64__ || defined __x86_64__ \
|
||||
|| defined __ppc64__ || defined __bfin__ || defined __MICROBLAZE__
|
||||
@ -72,7 +71,6 @@ static struct {
|
||||
#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f )
|
||||
#endif
|
||||
|
||||
|
||||
static char *get_media_descr(unsigned char media)
|
||||
{
|
||||
int i;
|
||||
@ -94,12 +92,12 @@ static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss)
|
||||
strncpy(id, b->system_id, 8);
|
||||
id[8] = 0;
|
||||
printf("System ID \"%s\"\n", id);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* On Atari, a 24 bit serial number is stored at offset 8 of the boot
|
||||
* sector */
|
||||
printf("Serial number 0x%x\n",
|
||||
b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16));
|
||||
b->system_id[5] | (b->system_id[6] << 8) | (b->
|
||||
system_id[7] << 16));
|
||||
}
|
||||
printf("Media byte 0x%02x (%s)\n", b->media, get_media_descr(b->media));
|
||||
printf("%10d bytes per logical sector\n", GET_UNALIGNED_W(b->sector_size));
|
||||
@ -117,8 +115,7 @@ static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss)
|
||||
(unsigned long long)fs->root_start,
|
||||
(unsigned long long)fs->root_start / lss);
|
||||
printf("%10d root directory entries\n", fs->root_entries);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printf("Root directory start at cluster %lu (arbitrary size)\n",
|
||||
fs->root_cluster);
|
||||
}
|
||||
@ -129,12 +126,10 @@ static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss)
|
||||
(unsigned long long)fs->clusters * fs->cluster_size);
|
||||
printf("%u sectors/track, %u heads\n", CF_LE_W(b->secs_track),
|
||||
CF_LE_W(b->heads));
|
||||
printf("%10u hidden sectors\n",
|
||||
atari_format ?
|
||||
printf("%10u hidden sectors\n", atari_format ?
|
||||
/* On Atari, the hidden field is only 16 bit wide and unused */
|
||||
(((unsigned char *)&b->hidden)[0] |
|
||||
((unsigned char *)&b->hidden)[1] << 8) :
|
||||
CF_LE_L(b->hidden));
|
||||
((unsigned char *)&b->hidden)[1] << 8) : CF_LE_L(b->hidden));
|
||||
sectors = GET_UNALIGNED_W(b->sectors);
|
||||
printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect));
|
||||
}
|
||||
@ -151,7 +146,8 @@ static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
|
||||
}
|
||||
if (interactive)
|
||||
printf("1) Create one\n2) Do without a backup\n");
|
||||
else printf( " Auto-creating backup boot block.\n" );
|
||||
else
|
||||
printf(" Auto-creating backup boot block.\n");
|
||||
if (!interactive || get_key("12", "?") == '1') {
|
||||
int bbs;
|
||||
/* The usual place for the backup boot sector is sector 6. Choose
|
||||
@ -170,8 +166,8 @@ static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
|
||||
sizeof(b->backup_boot), &b->backup_boot);
|
||||
printf("Created backup of boot sector in sector %d\n", bbs);
|
||||
return;
|
||||
}
|
||||
else return;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
fs_read(fs->backupboot_start, sizeof(b2), &b2);
|
||||
@ -189,7 +185,8 @@ static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
|
||||
if (*p != *q) {
|
||||
sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ",
|
||||
(unsigned)(p - (__u8 *) b), *p, *q);
|
||||
if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2;
|
||||
if (pos + strlen(buf) > 78)
|
||||
printf("\n "), pos = 2;
|
||||
printf("%s", buf);
|
||||
pos += strlen(buf);
|
||||
first = 0;
|
||||
@ -199,9 +196,9 @@ static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
|
||||
|
||||
if (interactive)
|
||||
printf("1) Copy original to backup\n"
|
||||
"2) Copy backup to original\n"
|
||||
"3) No action\n" );
|
||||
else printf( " Not automatically fixing this.\n" );
|
||||
"2) Copy backup to original\n" "3) No action\n");
|
||||
else
|
||||
printf(" Not automatically fixing this.\n");
|
||||
switch (interactive ? get_key("123", "?") : '3') {
|
||||
case '1':
|
||||
fs_write(fs->backupboot_start, sizeof(*b), b);
|
||||
@ -232,13 +229,15 @@ static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss)
|
||||
printf("No FSINFO sector\n");
|
||||
if (interactive)
|
||||
printf("1) Create one\n2) Do without FSINFO\n");
|
||||
else printf( " Not automatically creating it.\n" );
|
||||
else
|
||||
printf(" Not automatically creating it.\n");
|
||||
if (interactive && get_key("12", "?") == '1') {
|
||||
/* search for a free reserved sector (not boot sector and not
|
||||
* backup boot sector) */
|
||||
__u32 s;
|
||||
for (s = 1; s < CF_LE_W(b->reserved); ++s)
|
||||
if (s != CF_LE_W(b->backup_boot)) break;
|
||||
if (s != CF_LE_W(b->backup_boot))
|
||||
break;
|
||||
if (s > 0 && s < CF_LE_W(b->reserved)) {
|
||||
init_fsinfo(&i);
|
||||
fs_write((loff_t) s * lss, sizeof(i), &i);
|
||||
@ -249,22 +248,20 @@ static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss)
|
||||
fs_write(fs->backupboot_start +
|
||||
offsetof(struct boot_sector, info_sector),
|
||||
sizeof(b->info_sector), &b->info_sector);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printf("No free reserved sector found -- "
|
||||
"no space for FSINFO sector!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else return;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
fs->fsinfo_start = CF_LE_W(b->info_sector) * lss;
|
||||
fs_read(fs->fsinfo_start, sizeof(i), &i);
|
||||
|
||||
if (i.magic != CT_LE_L(0x41615252) ||
|
||||
i.signature != CT_LE_L(0x61417272) ||
|
||||
i.boot_sign != CT_LE_W(0xaa55)) {
|
||||
i.signature != CT_LE_L(0x61417272) || i.boot_sign != CT_LE_W(0xaa55)) {
|
||||
printf("FSINFO sector has bad magic number(s):\n");
|
||||
if (i.magic != CT_LE_L(0x41615252))
|
||||
printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
|
||||
@ -280,12 +277,13 @@ static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss)
|
||||
CF_LE_W(i.boot_sign), 0xaa55);
|
||||
if (interactive)
|
||||
printf("1) Correct\n2) Don't correct (FSINFO invalid then)\n");
|
||||
else printf( " Auto-correcting it.\n" );
|
||||
else
|
||||
printf(" Auto-correcting it.\n");
|
||||
if (!interactive || get_key("12", "?") == '1') {
|
||||
init_fsinfo(&i);
|
||||
fs_write(fs->fsinfo_start, sizeof(i), &i);
|
||||
}
|
||||
else fs->fsinfo_start = 0;
|
||||
} else
|
||||
fs->fsinfo_start = 0;
|
||||
}
|
||||
|
||||
if (fs->fsinfo_start)
|
||||
@ -302,7 +300,8 @@ void read_boot(DOS_FS *fs)
|
||||
|
||||
fs_read(0, sizeof(b), &b);
|
||||
logical_sector_size = GET_UNALIGNED_W(b.sector_size);
|
||||
if (!logical_sector_size) die("Logical sector size is zero.");
|
||||
if (!logical_sector_size)
|
||||
die("Logical sector size is zero.");
|
||||
|
||||
/* This was moved up because it's the first thing that will fail */
|
||||
/* if the platform needs special handling of unaligned multibyte accesses */
|
||||
@ -312,13 +311,15 @@ void read_boot(DOS_FS *fs)
|
||||
"sector size.", logical_sector_size);
|
||||
|
||||
fs->cluster_size = b.cluster_size * logical_sector_size;
|
||||
if (!fs->cluster_size) die("Cluster size is zero.");
|
||||
if (!fs->cluster_size)
|
||||
die("Cluster size is zero.");
|
||||
if (b.fats != 2 && b.fats != 1)
|
||||
die("Currently, only 1 or 2 FATs are supported, not %d.\n", b.fats);
|
||||
fs->nfats = b.fats;
|
||||
sectors = GET_UNALIGNED_W(b.sectors);
|
||||
total_sectors = sectors ? sectors : CF_LE_L(b.total_sect);
|
||||
if (verbose) printf("Checking we can access the last sector of the filesystem\n");
|
||||
if (verbose)
|
||||
printf("Checking we can access the last sector of the filesystem\n");
|
||||
/* Can't access last odd sector anyway, so round down */
|
||||
fs_test((loff_t) ((total_sectors & ~1) - 1) * (loff_t) logical_sector_size,
|
||||
logical_sector_size);
|
||||
@ -329,7 +330,8 @@ void read_boot(DOS_FS *fs)
|
||||
logical_sector_size;
|
||||
fs->root_entries = GET_UNALIGNED_W(b.dir_entries);
|
||||
fs->data_start = fs->root_start + ROUND_TO_MULTIPLE(fs->root_entries <<
|
||||
MSDOS_DIR_BITS,logical_sector_size);
|
||||
MSDOS_DIR_BITS,
|
||||
logical_sector_size);
|
||||
data_size = (loff_t) total_sectors *logical_sector_size - fs->data_start;
|
||||
fs->clusters = data_size / fs->cluster_size;
|
||||
fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
|
||||
@ -364,16 +366,13 @@ void read_boot(DOS_FS *fs)
|
||||
check_backup_boot(fs, &b, logical_sector_size);
|
||||
|
||||
read_fsinfo(fs, &b, logical_sector_size);
|
||||
}
|
||||
else if (!atari_format) {
|
||||
} else if (!atari_format) {
|
||||
/* On real MS-DOS, a 16 bit FAT is used whenever there would be too
|
||||
* much clusers otherwise. */
|
||||
fs->fat_bits = (fs->clusters >= FAT12_THRESHOLD) ? 16 : 12;
|
||||
if (fs->clusters >= FAT16_THRESHOLD)
|
||||
die("Too many clusters (%lu) for FAT16 filesystem.",
|
||||
fs->clusters);
|
||||
}
|
||||
else {
|
||||
die("Too many clusters (%lu) for FAT16 filesystem.", fs->clusters);
|
||||
} else {
|
||||
/* On Atari, things are more difficult: GEMDOS always uses 12bit FATs
|
||||
* on floppies, and always 16 bit on harddisks. */
|
||||
fs->fat_bits = 16; /* assume 16 bit FAT for now */
|
||||
@ -407,9 +406,11 @@ void read_boot(DOS_FS *fs)
|
||||
fs->label = NULL;
|
||||
}
|
||||
|
||||
if (fs->clusters > ((unsigned long long)fs->fat_size*8/fs->fat_bits)-2)
|
||||
if (fs->clusters >
|
||||
((unsigned long long)fs->fat_size * 8 / fs->fat_bits) - 2)
|
||||
die("File system has %d clusters but only space for %d FAT entries.",
|
||||
fs->clusters,((unsigned long long)fs->fat_size*8/fs->fat_bits)-2);
|
||||
fs->clusters,
|
||||
((unsigned long long)fs->fat_size * 8 / fs->fat_bits) - 2);
|
||||
if (!fs->root_entries && !fs->root_cluster)
|
||||
die("Root directory has zero size.");
|
||||
if (fs->root_entries & (MSDOS_DPS - 1))
|
||||
@ -423,7 +424,8 @@ void read_boot(DOS_FS *fs)
|
||||
if (!atari_format && (!b.secs_track || !b.heads))
|
||||
die("Invalid disk format in boot sector.");
|
||||
#endif
|
||||
if (verbose) dump_boot(fs,&b,logical_sector_size);
|
||||
if (verbose)
|
||||
dump_boot(fs, &b, logical_sector_size);
|
||||
}
|
||||
|
||||
static void write_boot_label(DOS_FS * fs, char *label)
|
||||
@ -436,7 +438,8 @@ static void write_boot_label(DOS_FS *fs, char *label)
|
||||
if (b16->extended_sig != 0x29) {
|
||||
b16->extended_sig = 0x29;
|
||||
b16->serial = 0;
|
||||
memmove(b16->fs_type, fs->fat_bits == 12 ?"FAT12 ":"FAT16 ", 8);
|
||||
memmove(b16->fs_type, fs->fat_bits == 12 ? "FAT12 " : "FAT16 ",
|
||||
8);
|
||||
}
|
||||
memmove(b16->label, label, 11);
|
||||
} else if (fs->fat_bits == 32) {
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
can be found in /usr/share/common-licenses/GPL-3 file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BOOT_H
|
||||
#define _BOOT_H
|
||||
|
||||
|
||||
340
src/check.c
340
src/check.c
@ -23,7 +23,6 @@
|
||||
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
|
||||
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -38,7 +37,6 @@
|
||||
#include "lfn.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
static DOS_FILE *root;
|
||||
|
||||
/* get start field of a dir entry */
|
||||
@ -76,7 +74,6 @@ static DOS_FILE *root;
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
loff_t alloc_rootdir_entry(DOS_FS * fs, DIR_ENT * de, const char *pattern)
|
||||
{
|
||||
static int curr_num = 0;
|
||||
@ -113,7 +110,8 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
|
||||
for (clu_num = prev + 1; clu_num != prev; clu_num++) {
|
||||
FAT_ENTRY entry;
|
||||
|
||||
if (clu_num >= fs->clusters+2) clu_num = 2;
|
||||
if (clu_num >= fs->clusters + 2)
|
||||
clu_num = 2;
|
||||
get_fat(&entry, fs->fat, clu_num, fs);
|
||||
if (!entry.value)
|
||||
break;
|
||||
@ -154,10 +152,10 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
|
||||
}
|
||||
if (clu_num == 0 || clu_num == -1)
|
||||
break;
|
||||
if (++curr_num >= 10000) die("Unable to create unique name");
|
||||
if (++curr_num >= 10000)
|
||||
die("Unable to create unique name");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
DIR_ENT *root;
|
||||
int next_free = 0, scan;
|
||||
|
||||
@ -168,7 +166,8 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
|
||||
if (IS_FREE(root[next_free].name) &&
|
||||
root[next_free].attr != VFAT_LN_ATTR)
|
||||
break;
|
||||
else next_free++;
|
||||
else
|
||||
next_free++;
|
||||
if (next_free == fs->root_entries)
|
||||
die("Root directory is full.");
|
||||
offset = fs->root_start + next_free * sizeof(DIR_ENT);
|
||||
@ -179,8 +178,10 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
|
||||
if (scan != next_free &&
|
||||
!strncmp(root[scan].name, de->name, MSDOS_NAME))
|
||||
break;
|
||||
if (scan == fs->root_entries) break;
|
||||
if (++curr_num >= 10000) die("Unable to create unique name");
|
||||
if (scan == fs->root_entries)
|
||||
break;
|
||||
if (++curr_num >= 10000)
|
||||
die("Unable to create unique name");
|
||||
}
|
||||
free(root);
|
||||
}
|
||||
@ -188,7 +189,6 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a full path (starting with '/') for the specified dentry,
|
||||
* relative to the partition. All components are "long" names where possible.
|
||||
@ -201,25 +201,27 @@ static char *path_name(DOS_FILE *file)
|
||||
{
|
||||
static char path[PATH_MAX * 2];
|
||||
|
||||
if (!file) *path = 0; /* Reached the root directory */
|
||||
if (!file)
|
||||
*path = 0; /* Reached the root directory */
|
||||
else {
|
||||
if (strlen(path_name(file->parent)) > PATH_MAX)
|
||||
die("Path name too long.");
|
||||
if (strcmp(path,"/") != 0) strcat(path,"/");
|
||||
if (strcmp(path, "/") != 0)
|
||||
strcat(path, "/");
|
||||
|
||||
/* Append the long name to the path,
|
||||
* or the short name if there isn't a long one
|
||||
*/
|
||||
strcpy(strrchr(path,0),file->lfn?file->lfn:file_name(file->dir_ent.name));
|
||||
strcpy(strrchr(path, 0),
|
||||
file->lfn ? file->lfn : file_name(file->dir_ent.name));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
|
||||
static int day_n[] =
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0 };
|
||||
/* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
|
||||
|
||||
|
||||
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
|
||||
|
||||
time_t date_dos2unix(unsigned short time, unsigned short date)
|
||||
@ -229,14 +231,14 @@ time_t date_dos2unix(unsigned short time,unsigned short date)
|
||||
|
||||
month = ((date >> 5) & 15) - 1;
|
||||
year = date >> 9;
|
||||
secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
|
||||
((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
|
||||
month < 2 ? 1 : 0)+3653);
|
||||
secs =
|
||||
(time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
|
||||
86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 -
|
||||
((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
|
||||
/* days since 1.1.70 plus 80's leap day */
|
||||
return secs;
|
||||
}
|
||||
|
||||
|
||||
static char *file_stat(DOS_FILE * file)
|
||||
{
|
||||
static char temp[100];
|
||||
@ -244,15 +246,14 @@ static char *file_stat(DOS_FILE *file)
|
||||
char tmp[100];
|
||||
time_t date;
|
||||
|
||||
date = date_dos2unix(CF_LE_W(file->dir_ent.time),CF_LE_W(file->
|
||||
dir_ent.date));
|
||||
date =
|
||||
date_dos2unix(CF_LE_W(file->dir_ent.time), CF_LE_W(file->dir_ent.date));
|
||||
tm = localtime(&date);
|
||||
strftime(tmp, 99, "%H:%M:%S %b %d %Y", tm);
|
||||
sprintf(temp, " Size %u bytes, date %s", CF_LE_L(file->dir_ent.size), tmp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
static int bad_name(DOS_FILE * file)
|
||||
{
|
||||
int i, spc, suspicious = 0;
|
||||
@ -262,22 +263,30 @@ static int bad_name(DOS_FILE *file)
|
||||
/* Do not complain about (and auto-correct) the extended attribute files
|
||||
* of OS/2. */
|
||||
if (strncmp(name, "EA DATA SF", 11) == 0 ||
|
||||
strncmp(name,"WP ROOT SF",11) == 0) return 0;
|
||||
strncmp(name, "WP ROOT SF", 11) == 0)
|
||||
return 0;
|
||||
|
||||
/* don't complain about the dummy 11 bytes used by patched Linux
|
||||
kernels */
|
||||
if (file->dir_ent.lcase & FAT_NO_83NAME) return 0;
|
||||
if (file->dir_ent.lcase & FAT_NO_83NAME)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (name[i] < ' ' || name[i] == 0x7f) return 1;
|
||||
if (name[i] > 0x7f) ++suspicious;
|
||||
if (strchr(bad_chars,name[i])) return 1;
|
||||
if (name[i] < ' ' || name[i] == 0x7f)
|
||||
return 1;
|
||||
if (name[i] > 0x7f)
|
||||
++suspicious;
|
||||
if (strchr(bad_chars, name[i]))
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 8; i < 11; i++) {
|
||||
if (name[i] < ' ' || name[i] == 0x7f) return 1;
|
||||
if (name[i] > 0x7f) ++suspicious;
|
||||
if (strchr(bad_chars,name[i])) return 1;
|
||||
if (name[i] < ' ' || name[i] == 0x7f)
|
||||
return 1;
|
||||
if (name[i] > 0x7f)
|
||||
++suspicious;
|
||||
if (strchr(bad_chars, name[i]))
|
||||
return 1;
|
||||
}
|
||||
|
||||
spc = 0;
|
||||
@ -333,14 +342,14 @@ static void drop_file(DOS_FS *fs,DOS_FILE *file)
|
||||
unsigned long cluster;
|
||||
|
||||
MODIFY(file, name[0], DELETED_FLAG);
|
||||
if (file->lfn) lfn_remove(file->lfn_offset, file->offset);
|
||||
if (file->lfn)
|
||||
lfn_remove(file->lfn_offset, file->offset);
|
||||
for (cluster = FSTART(file, fs); cluster > 0 && cluster <
|
||||
fs->clusters + 2; cluster = next_cluster(fs, cluster))
|
||||
set_owner(fs, cluster, NULL);
|
||||
--n_files;
|
||||
}
|
||||
|
||||
|
||||
static void truncate_file(DOS_FS * fs, DOS_FILE * file, unsigned long clusters)
|
||||
{
|
||||
int deleting;
|
||||
@ -348,23 +357,26 @@ static void truncate_file(DOS_FS *fs,DOS_FILE *file,unsigned long clusters)
|
||||
|
||||
walk = FSTART(file, fs);
|
||||
prev = 0;
|
||||
if ((deleting = !clusters)) MODIFY_START(file,0,fs);
|
||||
if ((deleting = !clusters))
|
||||
MODIFY_START(file, 0, fs);
|
||||
while (walk > 0 && walk != -1) {
|
||||
next = next_cluster(fs, walk);
|
||||
if (deleting) set_fat(fs,walk,0);
|
||||
else if ((deleting = !--clusters)) set_fat(fs,walk,-1);
|
||||
if (deleting)
|
||||
set_fat(fs, walk, 0);
|
||||
else if ((deleting = !--clusters))
|
||||
set_fat(fs, walk, -1);
|
||||
prev = walk;
|
||||
walk = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void auto_rename(DOS_FILE * file)
|
||||
{
|
||||
DOS_FILE *first, *walk;
|
||||
unsigned long int number;
|
||||
|
||||
if (!file->offset) return; /* cannot rename FAT32 root dir */
|
||||
if (!file->offset)
|
||||
return; /* cannot rename FAT32 root dir */
|
||||
first = file->parent ? file->parent->first : root;
|
||||
number = 0;
|
||||
while (1) {
|
||||
@ -374,11 +386,14 @@ static void auto_rename(DOS_FILE *file)
|
||||
memcpy(file->dir_ent.name + 4, num, 4);
|
||||
memcpy(file->dir_ent.ext, num + 4, 3);
|
||||
for (walk = first; walk; walk = walk->next)
|
||||
if (walk != file && !strncmp(walk->dir_ent.name,file->dir_ent.
|
||||
name,MSDOS_NAME)) break;
|
||||
if (walk != file
|
||||
&& !strncmp(walk->dir_ent.name, file->dir_ent.name, MSDOS_NAME))
|
||||
break;
|
||||
if (!walk) {
|
||||
fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
|
||||
if (file->lfn) lfn_fix_checksum(file->lfn_offset, file->offset, file->dir_ent.name);
|
||||
if (file->lfn)
|
||||
lfn_fix_checksum(file->lfn_offset, file->offset,
|
||||
file->dir_ent.name);
|
||||
return;
|
||||
}
|
||||
number++;
|
||||
@ -389,7 +404,6 @@ static void auto_rename(DOS_FILE *file)
|
||||
die("Can't generate a unique name.");
|
||||
}
|
||||
|
||||
|
||||
static void rename_file(DOS_FILE * file)
|
||||
{
|
||||
unsigned char name[46];
|
||||
@ -403,21 +417,24 @@ static void rename_file(DOS_FILE *file)
|
||||
printf("New name: ");
|
||||
fflush(stdout);
|
||||
if (fgets(name, 45, stdin)) {
|
||||
if ((here = strchr(name,'\n'))) *here = 0;
|
||||
if ((here = strchr(name, '\n')))
|
||||
*here = 0;
|
||||
for (walk = strrchr(name, 0); walk >= name && (*walk == ' ' ||
|
||||
*walk == '\t'); walk--);
|
||||
*walk == '\t');
|
||||
walk--) ;
|
||||
walk[1] = 0;
|
||||
for (walk = name; *walk == ' ' || *walk == '\t'; walk++) ;
|
||||
if (file_cvt(walk, file->dir_ent.name)) {
|
||||
fs_write(file->offset, MSDOS_NAME, file->dir_ent.name);
|
||||
if (file->lfn) lfn_fix_checksum(file->lfn_offset, file->offset, file->dir_ent.name);
|
||||
if (file->lfn)
|
||||
lfn_fix_checksum(file->lfn_offset, file->offset,
|
||||
file->dir_ent.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int handle_dot(DOS_FS * fs, DOS_FILE * file, int dots)
|
||||
{
|
||||
char *name;
|
||||
@ -428,7 +445,8 @@ static int handle_dot(DOS_FS *fs,DOS_FILE *file,int dots)
|
||||
if (interactive)
|
||||
printf("1) Drop it\n2) Auto-rename\n3) Rename\n"
|
||||
"4) Convert to directory\n");
|
||||
else printf(" Auto-renaming it.\n");
|
||||
else
|
||||
printf(" Auto-renaming it.\n");
|
||||
switch (interactive ? get_key("1234", "?") : '2') {
|
||||
case '1':
|
||||
drop_file(fs, file);
|
||||
@ -454,7 +472,6 @@ static int handle_dot(DOS_FS *fs,DOS_FILE *file,int dots)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int check_file(DOS_FS * fs, DOS_FILE * file)
|
||||
{
|
||||
DOS_FILE *owner;
|
||||
@ -478,7 +495,8 @@ static int check_file(DOS_FS *fs,DOS_FILE *file)
|
||||
}
|
||||
if (file->parent && !strncmp(file->dir_ent.name, MSDOS_DOTDOT,
|
||||
MSDOS_NAME)) {
|
||||
expect = file->parent->parent ? FSTART(file->parent->parent,fs):0;
|
||||
expect =
|
||||
file->parent->parent ? FSTART(file->parent->parent, fs) : 0;
|
||||
if (fs->root_cluster && expect == fs->root_cluster)
|
||||
expect = 0;
|
||||
if (FSTART(file, fs) != expect) {
|
||||
@ -496,7 +514,8 @@ static int check_file(DOS_FS *fs,DOS_FILE *file)
|
||||
}
|
||||
}
|
||||
if (FSTART(file, fs) >= fs->clusters + 2) {
|
||||
printf("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n",
|
||||
printf
|
||||
("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n",
|
||||
path_name(file), FSTART(file, fs), fs->clusters + 1);
|
||||
if (!file->offset)
|
||||
die("Bad FAT32 root directory! (bad start cluster)\n");
|
||||
@ -511,17 +530,21 @@ static int check_file(DOS_FS *fs,DOS_FILE *file)
|
||||
if (!curEntry.value || bad_cluster(fs, curr)) {
|
||||
printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n",
|
||||
path_name(file), curEntry.value ? "bad" : "free", curr);
|
||||
if (prev) set_fat(fs,prev,-1);
|
||||
if (prev)
|
||||
set_fat(fs, prev, -1);
|
||||
else if (!file->offset)
|
||||
die("FAT32 root dir starts with a bad cluster!");
|
||||
else MODIFY_START(file,0,fs);
|
||||
else
|
||||
MODIFY_START(file, 0, fs);
|
||||
break;
|
||||
}
|
||||
if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) <=
|
||||
(unsigned long long)clusters * fs->cluster_size) {
|
||||
printf("%s\n File size is %u bytes, cluster chain length is > %llu "
|
||||
printf
|
||||
("%s\n File size is %u bytes, cluster chain length is > %llu "
|
||||
"bytes.\n Truncating file to %u bytes.\n", path_name(file),
|
||||
CF_LE_L(file->dir_ent.size),(unsigned long long)clusters*fs->cluster_size,
|
||||
CF_LE_L(file->dir_ent.size),
|
||||
(unsigned long long)clusters * fs->cluster_size,
|
||||
CF_LE_L(file->dir_ent.size));
|
||||
truncate_file(fs, file, clusters);
|
||||
break;
|
||||
@ -533,37 +556,47 @@ static int check_file(DOS_FS *fs,DOS_FILE *file)
|
||||
clusters2 = 0;
|
||||
for (walk = FSTART(owner, fs); walk > 0 && walk != -1; walk =
|
||||
next_cluster(fs, walk))
|
||||
if (walk == curr) break;
|
||||
else clusters2++;
|
||||
if (walk == curr)
|
||||
break;
|
||||
else
|
||||
clusters2++;
|
||||
restart = file->dir_ent.attr & ATTR_DIR;
|
||||
if (!owner->offset) {
|
||||
printf(" Truncating second to %llu bytes because first "
|
||||
"is FAT32 root dir.\n", (unsigned long long)clusters2*fs->cluster_size );
|
||||
"is FAT32 root dir.\n",
|
||||
(unsigned long long)clusters2 * fs->cluster_size);
|
||||
do_trunc = 2;
|
||||
}
|
||||
else if (!file->offset) {
|
||||
} else if (!file->offset) {
|
||||
printf(" Truncating first to %llu bytes because second "
|
||||
"is FAT32 root dir.\n", (unsigned long long)clusters*fs->cluster_size );
|
||||
"is FAT32 root dir.\n",
|
||||
(unsigned long long)clusters * fs->cluster_size);
|
||||
do_trunc = 1;
|
||||
}
|
||||
else if (interactive)
|
||||
} else if (interactive)
|
||||
printf("1) Truncate first to %llu bytes%s\n"
|
||||
"2) Truncate second to %llu bytes\n",(unsigned long long)clusters*fs->cluster_size,
|
||||
restart ? " and restart" : "",(unsigned long long)clusters2*fs->cluster_size);
|
||||
else printf(" Truncating second to %llu bytes.\n",(unsigned long long)clusters2*
|
||||
fs->cluster_size);
|
||||
if (do_trunc != 2 &&
|
||||
(do_trunc == 1 ||
|
||||
(interactive && get_key("12","?") == '1'))) {
|
||||
"2) Truncate second to %llu bytes\n",
|
||||
(unsigned long long)clusters * fs->cluster_size,
|
||||
restart ? " and restart" : "",
|
||||
(unsigned long long)clusters2 * fs->cluster_size);
|
||||
else
|
||||
printf(" Truncating second to %llu bytes.\n",
|
||||
(unsigned long long)clusters2 * fs->cluster_size);
|
||||
if (do_trunc != 2
|
||||
&& (do_trunc == 1
|
||||
|| (interactive && get_key("12", "?") == '1'))) {
|
||||
prev = 0;
|
||||
clusters = 0;
|
||||
for (this = FSTART(owner, fs); this > 0 && this != -1; this =
|
||||
next_cluster(fs, this)) {
|
||||
if (this == curr) {
|
||||
if (prev) set_fat(fs,prev,-1);
|
||||
else MODIFY_START(owner,0,fs);
|
||||
MODIFY(owner,size,CT_LE_L((unsigned long long)clusters*fs->cluster_size));
|
||||
if (restart) return 1;
|
||||
if (prev)
|
||||
set_fat(fs, prev, -1);
|
||||
else
|
||||
MODIFY_START(owner, 0, fs);
|
||||
MODIFY(owner, size,
|
||||
CT_LE_L((unsigned long long)clusters *
|
||||
fs->cluster_size));
|
||||
if (restart)
|
||||
return 1;
|
||||
while (this > 0 && this != -1) {
|
||||
set_owner(fs, this, NULL);
|
||||
this = next_cluster(fs, this);
|
||||
@ -577,10 +610,11 @@ static int check_file(DOS_FS *fs,DOS_FILE *file)
|
||||
if (this != curr)
|
||||
die("Internal error: didn't find cluster %d in chain"
|
||||
" starting at %d", curr, FSTART(owner, fs));
|
||||
}
|
||||
else {
|
||||
if (prev) set_fat(fs,prev,-1);
|
||||
else MODIFY_START(file,0,fs);
|
||||
} else {
|
||||
if (prev)
|
||||
set_fat(fs, prev, -1);
|
||||
else
|
||||
MODIFY_START(file, 0, fs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -590,42 +624,50 @@ static int check_file(DOS_FS *fs,DOS_FILE *file)
|
||||
}
|
||||
if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) >
|
||||
(unsigned long long)clusters * fs->cluster_size) {
|
||||
printf("%s\n File size is %u bytes, cluster chain length is %llu bytes."
|
||||
"\n Truncating file to %lu bytes.\n",path_name(file),CF_LE_L(file->
|
||||
dir_ent.size),(unsigned long long)clusters*fs->cluster_size,(unsigned long long)clusters*fs->cluster_size);
|
||||
MODIFY(file,size,CT_LE_L((unsigned long long)clusters*fs->cluster_size));
|
||||
printf
|
||||
("%s\n File size is %u bytes, cluster chain length is %llu bytes."
|
||||
"\n Truncating file to %lu bytes.\n", path_name(file),
|
||||
CF_LE_L(file->dir_ent.size),
|
||||
(unsigned long long)clusters * fs->cluster_size,
|
||||
(unsigned long long)clusters * fs->cluster_size);
|
||||
MODIFY(file, size,
|
||||
CT_LE_L((unsigned long long)clusters * fs->cluster_size));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int check_files(DOS_FS * fs, DOS_FILE * start)
|
||||
{
|
||||
while (start) {
|
||||
if (check_file(fs,start)) return 1;
|
||||
if (check_file(fs, start))
|
||||
return 1;
|
||||
start = start->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int check_dir(DOS_FS * fs, DOS_FILE ** root, int dots)
|
||||
{
|
||||
DOS_FILE *parent, **walk, **scan;
|
||||
int dot, dotdot, skip, redo;
|
||||
int good, bad;
|
||||
|
||||
if (!*root) return 0;
|
||||
if (!*root)
|
||||
return 0;
|
||||
parent = (*root)->parent;
|
||||
good = bad = 0;
|
||||
for (walk = root; *walk; walk = &(*walk)->next)
|
||||
if (bad_name(*walk)) bad++;
|
||||
else good++;
|
||||
if (bad_name(*walk))
|
||||
bad++;
|
||||
else
|
||||
good++;
|
||||
if (*root && parent && good + bad > 4 && bad > good / 2) {
|
||||
printf("%s\n Has a large number of bad entries. (%d/%d)\n",
|
||||
path_name(parent), bad, good + bad);
|
||||
if (!dots) printf( " Not dropping root directory.\n" );
|
||||
else if (!interactive) printf(" Not dropping it in auto-mode.\n");
|
||||
if (!dots)
|
||||
printf(" Not dropping root directory.\n");
|
||||
else if (!interactive)
|
||||
printf(" Not dropping it in auto-mode.\n");
|
||||
else if (get_key("yn", "Drop directory ? (y/n)") == 'y') {
|
||||
truncate_file(fs, parent, 0);
|
||||
MODIFY(parent, name[0], DELETED_FLAG);
|
||||
@ -642,17 +684,20 @@ static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots)
|
||||
*walk = (*walk)->next;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) dot++;
|
||||
else dotdot++;
|
||||
if (!strncmp((*walk)->dir_ent.name, MSDOS_DOT, MSDOS_NAME))
|
||||
dot++;
|
||||
else
|
||||
dotdot++;
|
||||
}
|
||||
if (!((*walk)->dir_ent.attr & ATTR_VOLUME) &&
|
||||
bad_name(*walk)) {
|
||||
if (!((*walk)->dir_ent.attr & ATTR_VOLUME) && bad_name(*walk)) {
|
||||
puts(path_name(*walk));
|
||||
printf(" Bad short file name (%s).\n", file_name((*walk)->dir_ent.name));
|
||||
printf(" Bad short file name (%s).\n",
|
||||
file_name((*walk)->dir_ent.name));
|
||||
if (interactive)
|
||||
printf("1) Drop file\n2) Rename file\n3) Auto-rename\n"
|
||||
"4) Keep it\n");
|
||||
else printf(" Auto-renaming it.\n");
|
||||
else
|
||||
printf(" Auto-renaming it.\n");
|
||||
switch (interactive ? get_key("1234", "?") : '3') {
|
||||
case '1':
|
||||
drop_file(fs, *walk);
|
||||
@ -664,8 +709,7 @@ static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots)
|
||||
break;
|
||||
case '3':
|
||||
auto_rename(*walk);
|
||||
printf(" Renamed to %s\n",file_name((*walk)->dir_ent.
|
||||
name));
|
||||
printf(" Renamed to %s\n", file_name((*walk)->dir_ent.name));
|
||||
break;
|
||||
case '4':
|
||||
break;
|
||||
@ -677,15 +721,18 @@ static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots)
|
||||
skip = 0;
|
||||
while (*scan && !skip) {
|
||||
if (!((*scan)->dir_ent.attr & ATTR_VOLUME) &&
|
||||
!memcmp((*walk)->dir_ent.name,(*scan)->dir_ent.name,MSDOS_NAME)) {
|
||||
!memcmp((*walk)->dir_ent.name, (*scan)->dir_ent.name,
|
||||
MSDOS_NAME)) {
|
||||
printf("%s\n Duplicate directory entry.\n First %s\n",
|
||||
path_name(*walk), file_stat(*walk));
|
||||
printf(" Second %s\n", file_stat(*scan));
|
||||
if (interactive)
|
||||
printf("1) Drop first\n2) Drop second\n3) Rename first\n"
|
||||
printf
|
||||
("1) Drop first\n2) Drop second\n3) Rename first\n"
|
||||
"4) Rename second\n5) Auto-rename first\n"
|
||||
"6) Auto-rename second\n");
|
||||
else printf(" Auto-renaming second.\n");
|
||||
else
|
||||
printf(" Auto-renaming second.\n");
|
||||
switch (interactive ? get_key("123456", "?") : '6') {
|
||||
case '1':
|
||||
drop_file(fs, *walk);
|
||||
@ -708,21 +755,23 @@ static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots)
|
||||
break;
|
||||
case '5':
|
||||
auto_rename(*walk);
|
||||
printf(" Renamed to %s\n",file_name((*walk)->dir_ent.
|
||||
name));
|
||||
printf(" Renamed to %s\n",
|
||||
file_name((*walk)->dir_ent.name));
|
||||
break;
|
||||
case '6':
|
||||
auto_rename(*scan);
|
||||
printf(" Renamed to %s\n",file_name((*scan)->dir_ent.
|
||||
name));
|
||||
printf(" Renamed to %s\n",
|
||||
file_name((*scan)->dir_ent.name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
scan = &(*scan)->next;
|
||||
}
|
||||
if (skip) continue;
|
||||
if (skip)
|
||||
continue;
|
||||
}
|
||||
if (!redo) walk = &(*walk)->next;
|
||||
if (!redo)
|
||||
walk = &(*walk)->next;
|
||||
else {
|
||||
walk = root;
|
||||
dot = dotdot = redo = 0;
|
||||
@ -737,7 +786,6 @@ static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check a dentry's cluster chain for bad clusters.
|
||||
* If requested, we verify readability and mark unreadable clusters as bad.
|
||||
@ -764,26 +812,30 @@ static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test)
|
||||
if ((owner = get_owner(fs, walk))) {
|
||||
if (owner == file) {
|
||||
printf("%s\n Circular cluster chain. Truncating to %lu "
|
||||
"cluster%s.\n",path_name(file),clusters,clusters == 1 ? "" :
|
||||
"s");
|
||||
if (prev) set_fat(fs,prev,-1);
|
||||
"cluster%s.\n", path_name(file), clusters,
|
||||
clusters == 1 ? "" : "s");
|
||||
if (prev)
|
||||
set_fat(fs, prev, -1);
|
||||
else if (!file->offset)
|
||||
die("Bad FAT32 root directory! (bad start cluster)\n");
|
||||
else MODIFY_START(file,0,fs);
|
||||
else
|
||||
MODIFY_START(file, 0, fs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (bad_cluster(fs,walk)) break;
|
||||
if (bad_cluster(fs, walk))
|
||||
break;
|
||||
if (read_test) {
|
||||
if (fs_test(cluster_start(fs, walk), fs->cluster_size)) {
|
||||
prev = walk;
|
||||
clusters++;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n",
|
||||
path_name(file), clusters, walk);
|
||||
if (prev) set_fat(fs,prev,next_cluster(fs,walk));
|
||||
else MODIFY_START(file,next_cluster(fs,walk),fs);
|
||||
if (prev)
|
||||
set_fat(fs, prev, next_cluster(fs, walk));
|
||||
else
|
||||
MODIFY_START(file, next_cluster(fs, walk), fs);
|
||||
set_fat(fs, walk, -2);
|
||||
}
|
||||
}
|
||||
@ -792,12 +844,14 @@ static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test)
|
||||
/* Revert ownership (for now) */
|
||||
for (walk = FSTART(file, fs); walk > 0 && walk < fs->clusters + 2;
|
||||
walk = next_cluster(fs, walk))
|
||||
if (bad_cluster(fs,walk)) break;
|
||||
else if (get_owner(fs,walk) == file) set_owner(fs,walk,NULL);
|
||||
else break;
|
||||
if (bad_cluster(fs, walk))
|
||||
break;
|
||||
else if (get_owner(fs, walk) == file)
|
||||
set_owner(fs, walk, NULL);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
static void undelete(DOS_FS * fs, DOS_FILE * file)
|
||||
{
|
||||
unsigned long clusters, left, prev, walk;
|
||||
@ -817,25 +871,26 @@ static void undelete(DOS_FS *fs,DOS_FILE *file)
|
||||
break;
|
||||
|
||||
left--;
|
||||
if (prev) set_fat(fs,prev,walk);
|
||||
if (prev)
|
||||
set_fat(fs, prev, walk);
|
||||
prev = walk;
|
||||
walk++;
|
||||
}
|
||||
if (prev) set_fat(fs,prev,-1);
|
||||
else MODIFY_START(file,0,fs);
|
||||
if (prev)
|
||||
set_fat(fs, prev, -1);
|
||||
else
|
||||
MODIFY_START(file, 0, fs);
|
||||
if (left)
|
||||
printf("Warning: Did only undelete %lu of %lu cluster%s.\n",clusters-left,
|
||||
clusters,clusters == 1 ? "" : "s");
|
||||
printf("Warning: Did only undelete %lu of %lu cluster%s.\n",
|
||||
clusters - left, clusters, clusters == 1 ? "" : "s");
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void new_dir(void)
|
||||
{
|
||||
lfn_reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a description for a referenced dentry and insert it in our dentry
|
||||
* tree. Then, go check the dentry's cluster chain for bad clusters and
|
||||
@ -886,7 +941,8 @@ static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent,
|
||||
memcpy(&new->dir_ent, &de, sizeof(de));
|
||||
new->next = new->first = NULL;
|
||||
new->parent = parent;
|
||||
if (type == fdt_undelete) undelete(fs,new);
|
||||
if (type == fdt_undelete)
|
||||
undelete(fs, new);
|
||||
**chain = new;
|
||||
*chain = &new->next;
|
||||
if (list) {
|
||||
@ -903,10 +959,8 @@ static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent,
|
||||
test_file(fs, new, test); /* Bad cluster check */
|
||||
}
|
||||
|
||||
|
||||
static int subdirs(DOS_FS * fs, DOS_FILE * parent, FDSC ** cp);
|
||||
|
||||
|
||||
static int scan_dir(DOS_FS * fs, DOS_FILE * this, FDSC ** cp)
|
||||
{
|
||||
DOS_FILE **chain;
|
||||
@ -918,20 +972,21 @@ static int scan_dir(DOS_FS *fs,DOS_FILE *this,FDSC **cp)
|
||||
clu_num = FSTART(this, fs);
|
||||
new_dir();
|
||||
while (clu_num > 0 && clu_num != -1) {
|
||||
add_file(fs,&chain,this,cluster_start(fs,clu_num)+(i % fs->
|
||||
cluster_size),cp);
|
||||
add_file(fs, &chain, this,
|
||||
cluster_start(fs, clu_num) + (i % fs->cluster_size), cp);
|
||||
i += sizeof(DIR_ENT);
|
||||
if (!(i % fs->cluster_size))
|
||||
if ((clu_num = next_cluster(fs, clu_num)) == 0 || clu_num == -1)
|
||||
break;
|
||||
}
|
||||
lfn_check_orphaned();
|
||||
if (check_dir(fs,&this->first,this->offset)) return 0;
|
||||
if (check_files(fs,this->first)) return 1;
|
||||
if (check_dir(fs, &this->first, this->offset))
|
||||
return 0;
|
||||
if (check_files(fs, this->first))
|
||||
return 1;
|
||||
return subdirs(fs, this, cp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively scan subdirectories of the specified parent directory.
|
||||
*
|
||||
@ -950,11 +1005,11 @@ static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp)
|
||||
if (walk->dir_ent.attr & ATTR_DIR)
|
||||
if (strncmp(walk->dir_ent.name, MSDOS_DOT, MSDOS_NAME) &&
|
||||
strncmp(walk->dir_ent.name, MSDOS_DOTDOT, MSDOS_NAME))
|
||||
if (scan_dir(fs,walk,file_cd(cp,walk->dir_ent.name))) return 1;
|
||||
if (scan_dir(fs, walk, file_cd(cp, walk->dir_ent.name)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scan all directory and file information for errors.
|
||||
*
|
||||
@ -973,13 +1028,14 @@ int scan_root(DOS_FS *fs)
|
||||
new_dir();
|
||||
if (fs->root_cluster) {
|
||||
add_file(fs, &chain, NULL, 0, &fp_root);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (i = 0; i < fs->root_entries; i++)
|
||||
add_file(fs,&chain,NULL,fs->root_start+i*sizeof(DIR_ENT),&fp_root);
|
||||
add_file(fs, &chain, NULL, fs->root_start + i * sizeof(DIR_ENT),
|
||||
&fp_root);
|
||||
}
|
||||
lfn_check_orphaned();
|
||||
(void)check_dir(fs, &root, 0);
|
||||
if (check_files(fs,root)) return 1;
|
||||
if (check_files(fs, root))
|
||||
return 1;
|
||||
return subdirs(fs, NULL, &fp_root);
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
can be found in /usr/share/common-licenses/GPL-3 file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CHECK_H
|
||||
#define _CHECK_H
|
||||
|
||||
|
||||
27
src/common.c
27
src/common.c
@ -23,7 +23,6 @@
|
||||
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
|
||||
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -32,13 +31,11 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
typedef struct _link {
|
||||
void *data;
|
||||
struct _link *next;
|
||||
} LINK;
|
||||
|
||||
|
||||
void die(char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
@ -50,7 +47,6 @@ void die(char *msg,...)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void pdie(char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
@ -62,17 +58,16 @@ void pdie(char *msg,...)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void *alloc(int size)
|
||||
{
|
||||
void *this;
|
||||
|
||||
if ((this = malloc(size))) return this;
|
||||
if ((this = malloc(size)))
|
||||
return this;
|
||||
pdie("malloc");
|
||||
return NULL; /* for GCC */
|
||||
}
|
||||
|
||||
|
||||
void *qalloc(void **root, int size)
|
||||
{
|
||||
LINK *link;
|
||||
@ -83,7 +78,6 @@ void *qalloc(void **root,int size)
|
||||
return link->data = alloc(size);
|
||||
}
|
||||
|
||||
|
||||
void qfree(void **root)
|
||||
{
|
||||
LINK *this;
|
||||
@ -96,26 +90,29 @@ void qfree(void **root)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int min(int a, int b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
|
||||
char get_key(char *valid, char *prompt)
|
||||
{
|
||||
int ch, okay;
|
||||
|
||||
while (1) {
|
||||
if (prompt) printf("%s ",prompt);
|
||||
if (prompt)
|
||||
printf("%s ", prompt);
|
||||
fflush(stdout);
|
||||
while (ch = getchar(), ch == ' ' || ch == '\t') ;
|
||||
if (ch == EOF) exit(1);
|
||||
if (!strchr(valid,okay = ch)) okay = 0;
|
||||
if (ch == EOF)
|
||||
exit(1);
|
||||
if (!strchr(valid, okay = ch))
|
||||
okay = 0;
|
||||
while (ch = getchar(), ch != '\n' && ch != EOF) ;
|
||||
if (ch == EOF) exit(1);
|
||||
if (okay) return okay;
|
||||
if (ch == EOF)
|
||||
exit(1);
|
||||
if (okay)
|
||||
return okay;
|
||||
printf("Invalid input.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
|
||||
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
|
||||
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@ -41,13 +40,11 @@
|
||||
#include "file.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0;
|
||||
int atari_format = 0;
|
||||
unsigned n_files = 0;
|
||||
void *mem_queue = NULL;
|
||||
|
||||
|
||||
static void usage(char *name)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-aAflrtvVwy] [-d path -d ...] "
|
||||
@ -57,7 +54,8 @@ static void usage(char *name)
|
||||
fprintf(stderr, " -d path drop that file\n");
|
||||
fprintf(stderr, " -f salvage unused chains to files\n");
|
||||
fprintf(stderr, " -l list path names\n");
|
||||
fprintf(stderr," -n no-op, check non-interactively without changing\n");
|
||||
fprintf(stderr,
|
||||
" -n no-op, check non-interactively without changing\n");
|
||||
fprintf(stderr, " -p same as -a, for compat with other *fsck\n");
|
||||
fprintf(stderr, " -r interactively repair the file system\n");
|
||||
fprintf(stderr, " -t test for bad clusters\n");
|
||||
@ -69,7 +67,6 @@ static void usage(char *name)
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
|
||||
* of MS-DOS filesystem by default.
|
||||
@ -98,7 +95,6 @@ static void check_atari( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DOS_FS fs;
|
||||
@ -163,16 +159,22 @@ int main(int argc,char **argv)
|
||||
fprintf(stderr, "-t and -w require -a or -r\n");
|
||||
exit(2);
|
||||
}
|
||||
if (optind != argc-1) usage(argv[0]);
|
||||
if (optind != argc - 1)
|
||||
usage(argv[0]);
|
||||
|
||||
printf("dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n");
|
||||
fs_open(argv[optind], rw);
|
||||
read_boot(&fs);
|
||||
if (verify) printf("Starting check/repair pass.\n");
|
||||
while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue);
|
||||
if (test) fix_bad(&fs);
|
||||
if (salvage_files) reclaim_file(&fs);
|
||||
else reclaim_free(&fs);
|
||||
if (verify)
|
||||
printf("Starting check/repair pass.\n");
|
||||
while (read_fat(&fs), scan_root(&fs))
|
||||
qfree(&mem_queue);
|
||||
if (test)
|
||||
fix_bad(&fs);
|
||||
if (salvage_files)
|
||||
reclaim_file(&fs);
|
||||
else
|
||||
reclaim_free(&fs);
|
||||
free_clusters = update_free(&fs);
|
||||
file_unused();
|
||||
qfree(&mem_queue);
|
||||
@ -191,9 +193,9 @@ int main(int argc,char **argv)
|
||||
if (rw) {
|
||||
if (interactive)
|
||||
rw = get_key("yn", "Perform changes ? (y/n)") == 'y';
|
||||
else printf("Performing changes.\n");
|
||||
}
|
||||
else
|
||||
printf("Performing changes.\n");
|
||||
} else
|
||||
printf("Leaving file system unchanged.\n");
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
|
||||
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
|
||||
|
||||
|
||||
#ifndef _DOSFSCK_H
|
||||
#define _DOSFSCK_H
|
||||
|
||||
|
||||
@ -38,13 +38,11 @@
|
||||
#include "file.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0;
|
||||
int atari_format = 0;
|
||||
unsigned n_files = 0;
|
||||
void *mem_queue = NULL;
|
||||
|
||||
|
||||
static void usage(int error)
|
||||
{
|
||||
FILE *f = error ? stderr : stdout;
|
||||
@ -82,7 +80,6 @@ static void check_atari( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
DOS_FS fs;
|
||||
|
||||
49
src/fat.c
49
src/fat.c
@ -23,7 +23,6 @@
|
||||
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
|
||||
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -35,7 +34,6 @@
|
||||
#include "check.h"
|
||||
#include "fat.h"
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the FAT entry for a specified cluster.
|
||||
*
|
||||
@ -71,7 +69,6 @@ void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build a bookkeeping structure from the partition's FAT table.
|
||||
* If the partition has multiple FATs and they don't agree, try to pick a winner,
|
||||
@ -127,8 +124,7 @@ void read_fat(DOS_FS *fs)
|
||||
fs_write(fs->fat_start, eff_size, second);
|
||||
memcpy(first, second, eff_size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printf("FATs differ but appear to be intact. Using first "
|
||||
"FAT.\n");
|
||||
fs_write(fs->fat_start + fs->fat_size, eff_size, first);
|
||||
@ -152,8 +148,7 @@ void read_fat(DOS_FS *fs)
|
||||
FAT_ENTRY curEntry;
|
||||
get_fat(&curEntry, fs->fat, i, fs);
|
||||
if (curEntry.value == 1) {
|
||||
printf("Cluster %ld out of range (1). Setting to EOF.\n",
|
||||
i-2);
|
||||
printf("Cluster %ld out of range (1). Setting to EOF.\n", i - 2);
|
||||
set_fat(fs, i, -1);
|
||||
}
|
||||
if (curEntry.value >= fs->clusters + 2 &&
|
||||
@ -165,7 +160,6 @@ void read_fat(DOS_FS *fs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the FAT entry for a specified cluster
|
||||
* (i.e., change the cluster it links to).
|
||||
@ -198,8 +192,7 @@ void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new)
|
||||
get_fat(&prevEntry, fs->fat, cluster - 1, fs);
|
||||
data[0] = ((new & 0xf) << 4) | (prevEntry.value >> 8);
|
||||
data[1] = new >> 4;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
FAT_ENTRY subseqEntry;
|
||||
get_fat(&subseqEntry, fs->fat, cluster + 1, fs);
|
||||
data[0] = new & 0xff;
|
||||
@ -237,7 +230,6 @@ void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int bad_cluster(DOS_FS * fs, unsigned long cluster)
|
||||
{
|
||||
FAT_ENTRY curEntry;
|
||||
@ -246,7 +238,6 @@ int bad_cluster(DOS_FS *fs,unsigned long cluster)
|
||||
return FAT_IS_BAD(fs, curEntry.value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the cluster to which the specified cluster is linked.
|
||||
* If the linked cluster is marked bad, abort.
|
||||
@ -270,13 +261,12 @@ unsigned long next_cluster(DOS_FS *fs,unsigned long cluster)
|
||||
return FAT_IS_EOF(fs, value) ? -1 : value;
|
||||
}
|
||||
|
||||
|
||||
loff_t cluster_start(DOS_FS * fs, unsigned long cluster)
|
||||
{
|
||||
return fs->data_start+((loff_t)cluster-2)*(unsigned long long)fs->cluster_size;
|
||||
return fs->data_start + ((loff_t) cluster -
|
||||
2) * (unsigned long long)fs->cluster_size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update internal bookkeeping to show that the specified cluster belongs
|
||||
* to the specified dentry.
|
||||
@ -291,12 +281,12 @@ void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner)
|
||||
if (fs->cluster_owner == NULL)
|
||||
die("Internal error: attempt to set owner in non-existent table");
|
||||
|
||||
if (owner && fs->cluster_owner[cluster] && (fs->cluster_owner[cluster] != owner))
|
||||
if (owner && fs->cluster_owner[cluster]
|
||||
&& (fs->cluster_owner[cluster] != owner))
|
||||
die("Internal error: attempt to change file owner");
|
||||
fs->cluster_owner[cluster] = owner;
|
||||
}
|
||||
|
||||
|
||||
DOS_FILE *get_owner(DOS_FS * fs, unsigned long cluster)
|
||||
{
|
||||
if (fs->cluster_owner == NULL)
|
||||
@ -305,7 +295,6 @@ DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster)
|
||||
return fs->cluster_owner[cluster];
|
||||
}
|
||||
|
||||
|
||||
void fix_bad(DOS_FS * fs)
|
||||
{
|
||||
unsigned long i;
|
||||
@ -324,7 +313,6 @@ void fix_bad(DOS_FS *fs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reclaim_free(DOS_FS * fs)
|
||||
{
|
||||
int reclaimed;
|
||||
@ -345,10 +333,10 @@ void reclaim_free(DOS_FS *fs)
|
||||
}
|
||||
if (reclaimed)
|
||||
printf("Reclaimed %d unused cluster%s (%llu bytes).\n", reclaimed,
|
||||
reclaimed == 1 ? "" : "s",(unsigned long long)reclaimed*fs->cluster_size);
|
||||
reclaimed == 1 ? "" : "s",
|
||||
(unsigned long long)reclaimed * fs->cluster_size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assign the specified owner to all orphan chains (except cycles).
|
||||
* Break cross-links between orphan chains.
|
||||
@ -377,8 +365,7 @@ static void tag_free(DOS_FS *fs, DOS_FILE *owner, unsigned long *num_refs,
|
||||
!get_owner(fs, i) && !num_refs[i]) {
|
||||
prev = 0;
|
||||
/* Walk the chain, claiming ownership as we go */
|
||||
for (walk = i; walk != -1;
|
||||
walk = next_cluster(fs,walk)) {
|
||||
for (walk = i; walk != -1; walk = next_cluster(fs, walk)) {
|
||||
if (!get_owner(fs, walk)) {
|
||||
set_owner(fs, walk, owner);
|
||||
} else {
|
||||
@ -442,7 +429,8 @@ void reclaim_file(DOS_FS *fs)
|
||||
* a free cluster, or a bad cluster.
|
||||
*/
|
||||
if (get_owner(fs, next) || !nextEntry.value ||
|
||||
FAT_IS_BAD(fs, nextEntry.value)) set_fat(fs,i,-1);
|
||||
FAT_IS_BAD(fs, nextEntry.value))
|
||||
set_fat(fs, i, -1);
|
||||
else
|
||||
num_refs[next]++;
|
||||
}
|
||||
@ -499,13 +487,13 @@ void reclaim_file(DOS_FS *fs)
|
||||
}
|
||||
if (reclaimed)
|
||||
printf("Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n",
|
||||
reclaimed,reclaimed == 1 ? "" : "s",(unsigned long long)reclaimed*fs->cluster_size,files,
|
||||
reclaimed, reclaimed == 1 ? "" : "s",
|
||||
(unsigned long long)reclaimed * fs->cluster_size, files,
|
||||
files == 1 ? "" : "s");
|
||||
|
||||
free(num_refs);
|
||||
}
|
||||
|
||||
|
||||
unsigned long update_free(DOS_FS * fs)
|
||||
{
|
||||
unsigned long i;
|
||||
@ -531,17 +519,18 @@ unsigned long update_free(DOS_FS *fs)
|
||||
fs->free_clusters, free);
|
||||
if (interactive)
|
||||
printf("1) Correct\n2) Don't correct\n");
|
||||
else printf( " Auto-correcting.\n" );
|
||||
else
|
||||
printf(" Auto-correcting.\n");
|
||||
if (!interactive || get_key("12", "?") == '1')
|
||||
do_set = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printf("Free cluster summary uninitialized (should be %ld)\n", free);
|
||||
if (rw) {
|
||||
if (interactive)
|
||||
printf("1) Set it\n2) Leave it uninitialized\n");
|
||||
else printf( " Auto-setting.\n" );
|
||||
else
|
||||
printf(" Auto-setting.\n");
|
||||
if (!interactive || get_key("12", "?") == '1')
|
||||
do_set = 1;
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
can be found in /usr/share/common-licenses/GPL-3 file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FAT_H
|
||||
#define _FAT_H
|
||||
|
||||
|
||||
75
src/file.c
75
src/file.c
@ -23,7 +23,6 @@
|
||||
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
|
||||
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -41,13 +40,12 @@
|
||||
#include "common.h"
|
||||
#include "file.h"
|
||||
|
||||
|
||||
FDSC *fp_root = NULL;
|
||||
|
||||
|
||||
static void put_char(char **p, unsigned char c)
|
||||
{
|
||||
if ((c >= ' ' && c < 0x7f) || c >= 0xa0) *(*p)++ = c;
|
||||
if ((c >= ' ' && c < 0x7f) || c >= 0xa0)
|
||||
*(*p)++ = c;
|
||||
else {
|
||||
*(*p)++ = '\\';
|
||||
*(*p)++ = '0' + (c >> 6);
|
||||
@ -56,7 +54,6 @@ static void put_char(char **p,unsigned char c)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct the "pretty-printed" representation of the name in a short directory entry.
|
||||
*
|
||||
@ -74,14 +71,16 @@ char *file_name(unsigned char *fixed)
|
||||
p = path;
|
||||
for (i = j = 0; i < 8; i++)
|
||||
if (fixed[i] != ' ') {
|
||||
while (j++ < i) *p++ = ' ';
|
||||
while (j++ < i)
|
||||
*p++ = ' ';
|
||||
put_char(&p, fixed[i]);
|
||||
}
|
||||
if (strncmp(fixed + 8, " ", 3)) {
|
||||
*p++ = '.';
|
||||
for (i = j = 0; i < 3; i++)
|
||||
if (fixed[i + 8] != ' ') {
|
||||
while (j++ < i) *p++ = ' ';
|
||||
while (j++ < i)
|
||||
*p++ = ' ';
|
||||
put_char(&p, fixed[i + 8]);
|
||||
}
|
||||
}
|
||||
@ -89,7 +88,6 @@ char *file_name(unsigned char *fixed)
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
int file_cvt(unsigned char *name, unsigned char *fixed)
|
||||
{
|
||||
unsigned char c;
|
||||
@ -109,7 +107,8 @@ int file_cvt(unsigned char *name,unsigned char *fixed)
|
||||
printf("Duplicate dots in name.\n");
|
||||
return 0;
|
||||
}
|
||||
while (size--) *fixed++ = ' ';
|
||||
while (size--)
|
||||
*fixed++ = ' ';
|
||||
size = 3;
|
||||
ext = 1;
|
||||
name++;
|
||||
@ -130,23 +129,26 @@ int file_cvt(unsigned char *name,unsigned char *fixed)
|
||||
}
|
||||
name += 3;
|
||||
}
|
||||
if (islower(c)) c = toupper(c);
|
||||
if (islower(c))
|
||||
c = toupper(c);
|
||||
if (size) {
|
||||
*fixed++ = c;
|
||||
size--;
|
||||
}
|
||||
name++;
|
||||
}
|
||||
if (*name || size == 8) return 0;
|
||||
if (*name || size == 8)
|
||||
return 0;
|
||||
if (!ext) {
|
||||
while (size--) *fixed++ = ' ';
|
||||
while (size--)
|
||||
*fixed++ = ' ';
|
||||
size = 3;
|
||||
}
|
||||
while (size--) *fixed++ = ' ';
|
||||
while (size--)
|
||||
*fixed++ = ' ';
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void file_add(char *path, FD_TYPE type)
|
||||
{
|
||||
FDSC **current, *walk;
|
||||
@ -154,16 +156,27 @@ void file_add(char *path,FD_TYPE type)
|
||||
char *here;
|
||||
|
||||
current = &fp_root;
|
||||
if (*path != '/') die("%s: Absolute path required.",path);
|
||||
if (*path != '/')
|
||||
die("%s: Absolute path required.", path);
|
||||
path++;
|
||||
while (1) {
|
||||
if ((here = strchr(path,'/'))) *here = 0;
|
||||
if (!file_cvt(path,name)) exit(2);
|
||||
if ((here = strchr(path, '/')))
|
||||
*here = 0;
|
||||
if (!file_cvt(path, name))
|
||||
exit(2);
|
||||
for (walk = *current; walk; walk = walk->next)
|
||||
if (!here && (!strncmp(name, walk->name, MSDOS_NAME) || (type ==
|
||||
fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1))))
|
||||
fdt_undelete
|
||||
&&
|
||||
!strncmp
|
||||
(name + 1,
|
||||
walk->
|
||||
name + 1,
|
||||
MSDOS_NAME
|
||||
- 1))))
|
||||
die("Ambiguous name: \"%s\"", path);
|
||||
else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break;
|
||||
else if (here && !strncmp(name, walk->name, MSDOS_NAME))
|
||||
break;
|
||||
if (!walk) {
|
||||
walk = alloc(sizeof(FDSC));
|
||||
strncpy(walk->name, name, MSDOS_NAME);
|
||||
@ -173,31 +186,33 @@ void file_add(char *path,FD_TYPE type)
|
||||
*current = walk;
|
||||
}
|
||||
current = &walk->first;
|
||||
if (!here) break;
|
||||
if (!here)
|
||||
break;
|
||||
*here = '/';
|
||||
path = here + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FDSC **file_cd(FDSC ** curr, char *fixed)
|
||||
{
|
||||
FDSC **walk;
|
||||
|
||||
if (!curr || !*curr) return NULL;
|
||||
if (!curr || !*curr)
|
||||
return NULL;
|
||||
for (walk = curr; *walk; walk = &(*walk)->next)
|
||||
if (!strncmp((*walk)->name, fixed, MSDOS_NAME) && (*walk)->first)
|
||||
return &(*walk)->first;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static FDSC **file_find(FDSC ** dir, char *fixed)
|
||||
{
|
||||
if (!dir || !*dir) return NULL;
|
||||
if (!dir || !*dir)
|
||||
return NULL;
|
||||
if (*(unsigned char *)fixed == DELETED_FLAG) {
|
||||
while (*dir) {
|
||||
if (!strncmp((*dir)->name+1,fixed+1,MSDOS_NAME-1) && !(*dir)->first)
|
||||
if (!strncmp((*dir)->name + 1, fixed + 1, MSDOS_NAME - 1)
|
||||
&& !(*dir)->first)
|
||||
return dir;
|
||||
dir = &(*dir)->next;
|
||||
}
|
||||
@ -211,18 +226,17 @@ static FDSC **file_find(FDSC **dir,char *fixed)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no
|
||||
such file exists or if CURR is NULL. */
|
||||
FD_TYPE file_type(FDSC ** curr, char *fixed)
|
||||
{
|
||||
FDSC **this;
|
||||
|
||||
if ((this = file_find(curr,fixed))) return (*this)->type;
|
||||
if ((this = file_find(curr, fixed)))
|
||||
return (*this)->type;
|
||||
return fdt_none;
|
||||
}
|
||||
|
||||
|
||||
void file_modify(FDSC ** curr, char *fixed)
|
||||
{
|
||||
FDSC **this, *next;
|
||||
@ -246,14 +260,14 @@ void file_modify(FDSC **curr,char *fixed)
|
||||
*this = next;
|
||||
}
|
||||
|
||||
|
||||
static void report_unused(FDSC * this)
|
||||
{
|
||||
FDSC *next;
|
||||
|
||||
while (this) {
|
||||
next = this->next;
|
||||
if (this->first) report_unused(this->first);
|
||||
if (this->first)
|
||||
report_unused(this->first);
|
||||
else if (this->type != fdt_none)
|
||||
printf("Warning: did not %s file %s\n", this->type == fdt_drop ?
|
||||
"drop" : "undelete", file_name(this->name));
|
||||
@ -262,7 +276,6 @@ static void report_unused(FDSC *this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void file_unused(void)
|
||||
{
|
||||
report_unused(fp_root);
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
can be found in /usr/share/common-licenses/GPL-3 file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FILE_H
|
||||
#define _FILE_H
|
||||
|
||||
@ -32,10 +31,8 @@ typedef struct _fptr {
|
||||
struct _fptr *next; /* next file in directory */
|
||||
} FDSC;
|
||||
|
||||
|
||||
extern FDSC *fp_root;
|
||||
|
||||
|
||||
char *file_name(unsigned char *fixed);
|
||||
|
||||
/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file
|
||||
|
||||
66
src/io.c
66
src/io.c
@ -45,7 +45,6 @@
|
||||
#include "common.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
typedef struct _change {
|
||||
void *data;
|
||||
loff_t pos;
|
||||
@ -53,20 +52,20 @@ typedef struct _change {
|
||||
struct _change *next;
|
||||
} CHANGE;
|
||||
|
||||
|
||||
static CHANGE *changes, *last;
|
||||
static int fd, did_change = 0;
|
||||
|
||||
unsigned device_no;
|
||||
|
||||
|
||||
#ifdef __DJGPP__
|
||||
#include "volume.h" /* DOS lowlevel disk access functions */
|
||||
loff_t llseek(int fd, loff_t offset, int whence)
|
||||
{
|
||||
if ((whence != SEEK_SET) || (fd == 4711)) return -1; /* only those supported */
|
||||
if ((whence != SEEK_SET) || (fd == 4711))
|
||||
return -1; /* only those supported */
|
||||
return VolumeSeek(offset);
|
||||
}
|
||||
|
||||
#define open OpenVolume
|
||||
#define close CloseVolume
|
||||
#define read(a,b,c) ReadVolume(b,c)
|
||||
@ -98,8 +97,7 @@ void fs_open(char *path,int rw)
|
||||
if (fstat(GetVolumeHandle(), &stbuf) < 0)
|
||||
pdie("fstat image %s", path);
|
||||
device_no = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* return 2 for floppy, 1 for ramdisk, 7 for loopback */
|
||||
/* used by boot.c in Atari mode: floppy always FAT12, */
|
||||
/* loopback / ramdisk only FAT12 if usual floppy size, */
|
||||
@ -110,7 +108,6 @@ void fs_open(char *path,int rw)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read data from the partition, accounting for any pending updates that are
|
||||
* queued for writing.
|
||||
@ -125,34 +122,41 @@ void fs_read(loff_t pos,int size,void *data)
|
||||
CHANGE *walk;
|
||||
int got;
|
||||
|
||||
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
|
||||
if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos);
|
||||
if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos);
|
||||
if (llseek(fd, pos, 0) != pos)
|
||||
pdie("Seek to %lld", pos);
|
||||
if ((got = read(fd, data, size)) < 0)
|
||||
pdie("Read %d bytes at %lld", size, pos);
|
||||
if (got != size)
|
||||
die("Got %d bytes instead of %d at %lld", got, size, pos);
|
||||
for (walk = changes; walk; walk = walk->next) {
|
||||
if (walk->pos < pos + size && walk->pos + walk->size > pos) {
|
||||
if (walk->pos < pos)
|
||||
memcpy(data, (char *)walk->data + pos - walk->pos, min(size,
|
||||
walk->size-pos+walk->pos));
|
||||
else memcpy((char *) data+walk->pos-pos,walk->data,min(walk->size,
|
||||
size+pos-walk->pos));
|
||||
walk->
|
||||
size -
|
||||
pos +
|
||||
walk->
|
||||
pos));
|
||||
else
|
||||
memcpy((char *)data + walk->pos - pos, walk->data,
|
||||
min(walk->size, size + pos - walk->pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int fs_test(loff_t pos, int size)
|
||||
{
|
||||
void *scratch;
|
||||
int okay;
|
||||
|
||||
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
|
||||
if (llseek(fd, pos, 0) != pos)
|
||||
pdie("Seek to %lld", pos);
|
||||
scratch = alloc(size);
|
||||
okay = read(fd, scratch, size) == size;
|
||||
free(scratch);
|
||||
return okay;
|
||||
}
|
||||
|
||||
|
||||
void fs_write(loff_t pos, int size, void *data)
|
||||
{
|
||||
CHANGE *new;
|
||||
@ -160,21 +164,25 @@ void fs_write(loff_t pos,int size,void *data)
|
||||
|
||||
if (write_immed) {
|
||||
did_change = 1;
|
||||
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
|
||||
if ((did = write(fd,data,size)) == size) return;
|
||||
if (did < 0) pdie("Write %d bytes at %lld",size,pos);
|
||||
if (llseek(fd, pos, 0) != pos)
|
||||
pdie("Seek to %lld", pos);
|
||||
if ((did = write(fd, data, size)) == size)
|
||||
return;
|
||||
if (did < 0)
|
||||
pdie("Write %d bytes at %lld", size, pos);
|
||||
die("Wrote %d bytes instead of %d at %lld", did, size, pos);
|
||||
}
|
||||
new = alloc(sizeof(CHANGE));
|
||||
new->pos = pos;
|
||||
memcpy(new->data = alloc(new->size = size), data, size);
|
||||
new->next = NULL;
|
||||
if (last) last->next = new;
|
||||
else changes = new;
|
||||
if (last)
|
||||
last->next = new;
|
||||
else
|
||||
changes = new;
|
||||
last = new;
|
||||
}
|
||||
|
||||
|
||||
static void fs_flush(void)
|
||||
{
|
||||
CHANGE *this;
|
||||
@ -184,7 +192,8 @@ static void fs_flush(void)
|
||||
this = changes;
|
||||
changes = changes->next;
|
||||
if (llseek(fd, this->pos, 0) != this->pos)
|
||||
fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n",
|
||||
fprintf(stderr,
|
||||
"Seek to %lld failed: %s\n Did not write %d bytes.\n",
|
||||
(long long)this->pos, strerror(errno), this->size);
|
||||
else if ((size = write(fd, this->data, this->size)) < 0)
|
||||
fprintf(stderr, "Writing %d bytes at %lld failed: %s\n", this->size,
|
||||
@ -197,25 +206,26 @@ static void fs_flush(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int fs_close(int write)
|
||||
{
|
||||
CHANGE *next;
|
||||
int changed;
|
||||
|
||||
changed = ! !changes;
|
||||
if (write) fs_flush();
|
||||
else while (changes) {
|
||||
if (write)
|
||||
fs_flush();
|
||||
else
|
||||
while (changes) {
|
||||
next = changes->next;
|
||||
free(changes->data);
|
||||
free(changes);
|
||||
changes = next;
|
||||
}
|
||||
if (close(fd) < 0) pdie("closing file system");
|
||||
if (close(fd) < 0)
|
||||
pdie("closing file system");
|
||||
return changed || did_change;
|
||||
}
|
||||
|
||||
|
||||
int fs_changed(void)
|
||||
{
|
||||
return ! !changes || did_change;
|
||||
|
||||
1
src/io.h
1
src/io.h
@ -23,7 +23,6 @@
|
||||
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
|
||||
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
|
||||
|
||||
|
||||
#ifndef _IO_H
|
||||
#define _IO_H
|
||||
|
||||
|
||||
61
src/lfn.c
61
src/lfn.c
@ -94,7 +94,8 @@ static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q )
|
||||
unsigned char *out, *cp;
|
||||
int len, val;
|
||||
|
||||
for( len = 0, up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ){
|
||||
for (len = 0, up = uni; (up - uni) / 2 < maxlen && (up[0] || up[1]);
|
||||
up += 2) {
|
||||
if (UNICODE_CONVERTABLE(up[0], up[1]))
|
||||
++len;
|
||||
else
|
||||
@ -122,7 +123,6 @@ static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q )
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
static void copy_lfn_part(char *dst, LFN_ENT * lfn)
|
||||
{
|
||||
memcpy(dst, lfn->name0_4, 10);
|
||||
@ -130,7 +130,6 @@ static void copy_lfn_part( char *dst, LFN_ENT *lfn )
|
||||
memcpy(dst + 22, lfn->name11_12, 4);
|
||||
}
|
||||
|
||||
|
||||
static void clear_lfn_slots(int start, int end)
|
||||
{
|
||||
int i;
|
||||
@ -171,7 +170,6 @@ void lfn_reset( void )
|
||||
lfn_slot = -1;
|
||||
}
|
||||
|
||||
|
||||
/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part
|
||||
* of the long name. */
|
||||
void lfn_add_slot(DIR_ENT * de, loff_t dir_offset)
|
||||
@ -180,7 +178,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
int slot = lfn->id & LFN_ID_SLOTMASK;
|
||||
unsigned offset;
|
||||
|
||||
if (lfn_slot == 0) lfn_check_orphaned();
|
||||
if (lfn_slot == 0)
|
||||
lfn_check_orphaned();
|
||||
|
||||
if (de->attr != VFAT_LN_ATTR)
|
||||
die("lfn_add_slot called with non-LFN directory entry");
|
||||
@ -197,8 +196,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
/* XXX: Should delay that until next LFN known (then can better
|
||||
* display the name) */
|
||||
printf("A new long file name starts within an old one.\n");
|
||||
if (slot == lfn_slot &&
|
||||
lfn->alias_checksum == lfn_checksum) {
|
||||
if (slot == lfn_slot && lfn->alias_checksum == lfn_checksum) {
|
||||
char *part1 = CNV_THIS_PART(lfn);
|
||||
char *part2 = CNV_PARTS_SO_FAR();
|
||||
printf(" It could be that the LFN start bit is wrong here\n"
|
||||
@ -211,8 +209,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
printf("1: Delete previous LFN\n2: Leave it as it is.\n");
|
||||
if (can_clear)
|
||||
printf("3: Clear start bit and concatenate LFNs\n");
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
} else
|
||||
printf(" Not auto-correcting this.\n");
|
||||
if (interactive) {
|
||||
switch (get_key(can_clear ? "123" : "12", "?")) {
|
||||
case '1':
|
||||
@ -234,8 +232,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
lfn_unicode = alloc((lfn_slot * CHARS_PER_LFN + 1) * 2);
|
||||
lfn_offsets = alloc(lfn_slot * sizeof(loff_t));
|
||||
lfn_parts = 0;
|
||||
}
|
||||
else if (lfn_slot == -1 && slot != 0) {
|
||||
} else if (lfn_slot == -1 && slot != 0) {
|
||||
/* No LFN in progress, but slot found; start bit missing */
|
||||
/* Causes: 1) start bit got lost, 2) Previous slot with start bit got
|
||||
* lost */
|
||||
@ -247,8 +244,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
if (interactive) {
|
||||
printf("1: Delete fragment\n2: Leave it as it is.\n"
|
||||
"3: Set start bit\n");
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
} else
|
||||
printf(" Not auto-correcting this.\n");
|
||||
switch (interactive ? get_key("123", "?") : '2') {
|
||||
case '1':
|
||||
if (!lfn_offsets)
|
||||
@ -271,8 +268,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
lfn_parts = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (slot != lfn_slot) {
|
||||
} else if (slot != lfn_slot) {
|
||||
/* wrong sequence number */
|
||||
/* Causes: 1) seq-no destroyed */
|
||||
/* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts
|
||||
@ -280,8 +276,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
* for name was allocated before!) */
|
||||
int can_fix = 0;
|
||||
printf("Unexpected long filename sequence number "
|
||||
"(%d vs. expected %d).\n",
|
||||
slot, lfn_slot );
|
||||
"(%d vs. expected %d).\n", slot, lfn_slot);
|
||||
if (lfn->alias_checksum == lfn_checksum && lfn_slot > 0) {
|
||||
char *part1 = CNV_THIS_PART(lfn);
|
||||
char *part2 = CNV_PARTS_SO_FAR();
|
||||
@ -292,11 +287,12 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
can_fix = 1;
|
||||
}
|
||||
if (interactive) {
|
||||
printf( "1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n" );
|
||||
printf
|
||||
("1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n");
|
||||
if (can_fix)
|
||||
printf("3: Correct sequence number\n");
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
} else
|
||||
printf(" Not auto-correcting this.\n");
|
||||
switch (interactive ? get_key(can_fix ? "123" : "12", "?") : '2') {
|
||||
case '1':
|
||||
if (!lfn_offsets) {
|
||||
@ -328,8 +324,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
if (interactive) {
|
||||
printf("1: Delete LFN\n2: Leave it as it is.\n"
|
||||
"3: Correct checksum\n");
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
} else
|
||||
printf(" Not auto-correcting this.\n");
|
||||
if (interactive) {
|
||||
switch (get_key("123", "?")) {
|
||||
case '1':
|
||||
@ -362,7 +358,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
"(but 0x%02x).\n", lfn->reserved);
|
||||
if (interactive)
|
||||
printf("1: Fix.\n2: Leave it.\n");
|
||||
else printf( "Auto-setting to 0.\n" );
|
||||
else
|
||||
printf("Auto-setting to 0.\n");
|
||||
if (!interactive || get_key("12", "?") == '1') {
|
||||
lfn->reserved = 0;
|
||||
fs_write(dir_offset + offsetof(LFN_ENT, reserved),
|
||||
@ -374,7 +371,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
"(but 0x%04x).\n", lfn->start);
|
||||
if (interactive)
|
||||
printf("1: Fix.\n2: Leave it.\n");
|
||||
else printf( "Auto-setting to 0.\n" );
|
||||
else
|
||||
printf("Auto-setting to 0.\n");
|
||||
if (!interactive || get_key("12", "?") == '1') {
|
||||
lfn->start = CT_LE_W(0);
|
||||
fs_write(dir_offset + offsetof(LFN_ENT, start),
|
||||
@ -383,7 +381,6 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function is always called when de->attr != VFAT_LN_ATTR is found, to
|
||||
* retrieve the previously constructed LFN. */
|
||||
char *lfn_get(DIR_ENT * de, loff_t * lfn_offset)
|
||||
@ -421,8 +418,8 @@ char *lfn_get( DIR_ENT *de, loff_t *lfn_offset )
|
||||
printf("1: Delete LFN\n2: Leave it as it is.\n"
|
||||
"3: Fix numbering (truncates long name and attaches "
|
||||
"it to short name %s)\n", short_name);
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
} else
|
||||
printf(" Not auto-correcting this.\n");
|
||||
switch (interactive ? get_key("123", "?") : '2') {
|
||||
case '1':
|
||||
clear_lfn_slots(0, lfn_parts - 1);
|
||||
@ -457,10 +454,9 @@ char *lfn_get( DIR_ENT *de, loff_t *lfn_offset )
|
||||
free(long_name);
|
||||
if (interactive) {
|
||||
printf("1: Delete LFN\n2: Leave it as it is.\n"
|
||||
"3: Fix checksum (attaches to short name %s)\n",
|
||||
short_name );
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
"3: Fix checksum (attaches to short name %s)\n", short_name);
|
||||
} else
|
||||
printf(" Not auto-correcting this.\n");
|
||||
if (interactive) {
|
||||
switch (get_key("123", "?")) {
|
||||
case '1':
|
||||
@ -497,7 +493,8 @@ void lfn_check_orphaned(void)
|
||||
printf("Orphaned long file name part \"%s\"\n", long_name);
|
||||
if (interactive)
|
||||
printf("1: Delete.\n2: Leave it.\n");
|
||||
else printf( " Auto-deleting.\n" );
|
||||
else
|
||||
printf(" Auto-deleting.\n");
|
||||
if (!interactive || get_key("12", "?") == '1') {
|
||||
clear_lfn_slots(0, lfn_parts - 1);
|
||||
}
|
||||
|
||||
372
src/mkdosfs.c
372
src/mkdosfs.c
@ -105,22 +105,19 @@
|
||||
#define HARD_SECTOR_SIZE 512
|
||||
#define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE )
|
||||
|
||||
|
||||
/* Macro definitions */
|
||||
|
||||
/* Report a failure message and return a failure error code */
|
||||
|
||||
#define die( str ) fatal_error( "%s: " str "\n" )
|
||||
|
||||
|
||||
/* Mark a cluster in the FAT as bad */
|
||||
|
||||
#define mark_sector_bad( sector ) mark_FAT_sector( sector, FAT_BAD )
|
||||
|
||||
/* Compute ceil(a/b) */
|
||||
|
||||
inline int
|
||||
cdiv (int a, int b)
|
||||
inline int cdiv(int a, int b)
|
||||
{
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
@ -179,8 +176,7 @@ struct msdos_volume_info {
|
||||
__u8 fs_type[8]; /* Typically FAT12 or FAT16 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct msdos_boot_sector
|
||||
{
|
||||
struct msdos_boot_sector {
|
||||
__u8 boot_jump[3]; /* Boot strap short or near jump */
|
||||
__u8 system_id[8]; /* Name - can be used to special case
|
||||
partition manager volumes */
|
||||
@ -227,8 +223,7 @@ struct fat32_fsinfo {
|
||||
__u32 reserved2[4];
|
||||
};
|
||||
|
||||
struct msdos_dir_entry
|
||||
{
|
||||
struct msdos_dir_entry {
|
||||
char name[8], ext[3]; /* name and extension */
|
||||
__u8 attr; /* attribute bits */
|
||||
__u8 lcase; /* Case for base and extension */
|
||||
@ -249,8 +244,7 @@ char dummy_boot_jump[3] = { 0xeb, 0x3c, 0x90 };
|
||||
char dummy_boot_jump_m68k[2] = { 0x60, 0x1c };
|
||||
|
||||
#define MSG_OFFSET_OFFSET 3
|
||||
char dummy_boot_code[BOOTCODE_SIZE] =
|
||||
"\x0e" /* push cs */
|
||||
char dummy_boot_code[BOOTCODE_SIZE] = "\x0e" /* push cs */
|
||||
"\x1f" /* pop ds */
|
||||
"\xbe\x5b\x7c" /* mov si, offset message_txt */
|
||||
/* write_msg: */
|
||||
@ -269,7 +263,6 @@ char dummy_boot_code[BOOTCODE_SIZE] =
|
||||
"\xcd\x19" /* int 19h */
|
||||
"\xeb\xfe" /* foo: jmp foo */
|
||||
/* message_txt: */
|
||||
|
||||
"This is not a bootable disk. Please insert a bootable floppy and\r\n"
|
||||
"press any key to try again ... \r\n";
|
||||
|
||||
@ -329,36 +322,32 @@ static void establish_params (int device_num, int size);
|
||||
static void setup_tables(void);
|
||||
static void write_tables(void);
|
||||
|
||||
|
||||
/* The function implementations */
|
||||
|
||||
/* Handle the reporting of fatal errors. Volatile to let gcc know that this doesn't return */
|
||||
|
||||
static void
|
||||
fatal_error (const char *fmt_string)
|
||||
static void fatal_error(const char *fmt_string)
|
||||
{
|
||||
fprintf(stderr, fmt_string, program_name, device_name);
|
||||
exit(1); /* The error exit code is 1! */
|
||||
}
|
||||
|
||||
|
||||
/* Mark the specified cluster as having a particular value */
|
||||
|
||||
static void
|
||||
mark_FAT_cluster (int cluster, unsigned int value)
|
||||
static void mark_FAT_cluster(int cluster, unsigned int value)
|
||||
{
|
||||
switch (size_fat) {
|
||||
case 12:
|
||||
value &= 0x0fff;
|
||||
if (((cluster * 3) & 0x1) == 0)
|
||||
{
|
||||
if (((cluster * 3) & 0x1) == 0) {
|
||||
fat[3 * cluster / 2] = (unsigned char)(value & 0x00ff);
|
||||
fat[(3 * cluster / 2) + 1] = (unsigned char) ((fat[(3 * cluster / 2) + 1] & 0x00f0)
|
||||
fat[(3 * cluster / 2) + 1] =
|
||||
(unsigned char)((fat[(3 * cluster / 2) + 1] & 0x00f0)
|
||||
| ((value & 0x0f00) >> 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
fat[3 * cluster / 2] = (unsigned char) ((fat[3 * cluster / 2] & 0x000f) | ((value & 0x000f) << 4));
|
||||
} else {
|
||||
fat[3 * cluster / 2] =
|
||||
(unsigned char)((fat[3 * cluster / 2] & 0x000f) |
|
||||
((value & 0x000f) << 4));
|
||||
fat[(3 * cluster / 2) + 1] = (unsigned char)((value & 0x0ff0) >> 4);
|
||||
}
|
||||
break;
|
||||
@ -382,11 +371,9 @@ mark_FAT_cluster (int cluster, unsigned int value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Mark a specified sector as having a particular value in it's FAT entry */
|
||||
|
||||
static void
|
||||
mark_FAT_sector (int sector, unsigned int value)
|
||||
static void mark_FAT_sector(int sector, unsigned int value)
|
||||
{
|
||||
int cluster;
|
||||
|
||||
@ -398,11 +385,9 @@ mark_FAT_sector (int sector, unsigned int value)
|
||||
mark_FAT_cluster(cluster, value);
|
||||
}
|
||||
|
||||
|
||||
/* Perform a test on a block. Return the number of blocks that could be read successfully */
|
||||
|
||||
static long
|
||||
do_check (char *buffer, int try, off_t current_block)
|
||||
static long do_check(char *buffer, int try, off_t current_block)
|
||||
{
|
||||
long got;
|
||||
|
||||
@ -421,12 +406,10 @@ do_check (char *buffer, int try, off_t current_block)
|
||||
return got;
|
||||
}
|
||||
|
||||
|
||||
/* Alarm clock handler - display the status of the quest for bad blocks! Then retrigger the alarm for five senconds
|
||||
later (so we can come here again) */
|
||||
|
||||
static void
|
||||
alarm_intr (int alnum)
|
||||
static void alarm_intr(int alnum)
|
||||
{
|
||||
if (currently_testing >= blocks)
|
||||
return;
|
||||
@ -440,38 +423,31 @@ alarm_intr (int alnum)
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
check_blocks (void)
|
||||
static void check_blocks(void)
|
||||
{
|
||||
int try, got;
|
||||
int i;
|
||||
static char blkbuf[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (verbose) {
|
||||
printf("Searching for bad blocks ");
|
||||
fflush(stdout);
|
||||
}
|
||||
currently_testing = 0;
|
||||
if (verbose)
|
||||
{
|
||||
if (verbose) {
|
||||
signal(SIGALRM, alarm_intr);
|
||||
alarm(5);
|
||||
}
|
||||
try = TEST_BUFFER_BLOCKS;
|
||||
while (currently_testing < blocks)
|
||||
{
|
||||
while (currently_testing < blocks) {
|
||||
if (currently_testing + try > blocks)
|
||||
try = blocks - currently_testing;
|
||||
got = do_check(blkbuf, try, currently_testing);
|
||||
currently_testing += got;
|
||||
if (got == try)
|
||||
{
|
||||
if (got == try) {
|
||||
try = TEST_BUFFER_BLOCKS;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
} else
|
||||
try = 1;
|
||||
if (currently_testing < start_data_block)
|
||||
die("bad blocks before data-area: cannot make fs");
|
||||
@ -486,13 +462,10 @@ check_blocks (void)
|
||||
printf("\n");
|
||||
|
||||
if (badblocks)
|
||||
printf ("%d bad block%s\n", badblocks,
|
||||
(badblocks > 1) ? "s" : "");
|
||||
printf("%d bad block%s\n", badblocks, (badblocks > 1) ? "s" : "");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_list_blocks (char *filename)
|
||||
static void get_list_blocks(char *filename)
|
||||
{
|
||||
int i;
|
||||
FILE *listfile;
|
||||
@ -502,8 +475,7 @@ get_list_blocks (char *filename)
|
||||
if (listfile == (FILE *) NULL)
|
||||
die("Can't open file of bad blocks");
|
||||
|
||||
while (!feof (listfile))
|
||||
{
|
||||
while (!feof(listfile)) {
|
||||
fscanf(listfile, "%ld\n", &blockno);
|
||||
for (i = 0; i < SECTORS_PER_BLOCK; i++) /* Mark all of the sectors in the block as bad */
|
||||
mark_sector_bad(blockno * SECTORS_PER_BLOCK + i);
|
||||
@ -512,16 +484,13 @@ get_list_blocks (char *filename)
|
||||
fclose(listfile);
|
||||
|
||||
if (badblocks)
|
||||
printf ("%d bad block%s\n", badblocks,
|
||||
(badblocks > 1) ? "s" : "");
|
||||
printf("%d bad block%s\n", badblocks, (badblocks > 1) ? "s" : "");
|
||||
}
|
||||
|
||||
|
||||
/* Given a file descriptor and an offset, check whether the offset is a valid offset for the file - return FALSE if it
|
||||
isn't valid or TRUE if it is */
|
||||
|
||||
static int
|
||||
valid_offset (int fd, loff_t offset)
|
||||
static int valid_offset(int fd, loff_t offset)
|
||||
{
|
||||
char ch;
|
||||
|
||||
@ -532,17 +501,14 @@ valid_offset (int fd, loff_t offset)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Given a filename, look to see how many blocks of BLOCK_SIZE are present, returning the answer */
|
||||
|
||||
static unsigned long long
|
||||
count_blocks (char *filename)
|
||||
static unsigned long long count_blocks(char *filename)
|
||||
{
|
||||
loff_t high, low;
|
||||
int fd;
|
||||
|
||||
if ((fd = open (filename, O_RDONLY)) < 0)
|
||||
{
|
||||
if ((fd = open(filename, O_RDONLY)) < 0) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
@ -566,11 +532,9 @@ count_blocks (char *filename)
|
||||
return low / BLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/* Check to see if the specified device is currently mounted - abort if it is */
|
||||
|
||||
static void
|
||||
check_mount (char *device_name)
|
||||
static void check_mount(char *device_name)
|
||||
{
|
||||
FILE *f;
|
||||
struct mntent *mnt;
|
||||
@ -583,11 +547,9 @@ check_mount (char *device_name)
|
||||
endmntent(f);
|
||||
}
|
||||
|
||||
|
||||
/* Establish the geometry and media parameters for the device */
|
||||
|
||||
static void
|
||||
establish_params (int device_num,int size)
|
||||
static void establish_params(int device_num, int size)
|
||||
{
|
||||
long loop_size;
|
||||
struct hd_geometry geometry;
|
||||
@ -597,11 +559,9 @@ establish_params (int device_num,int size)
|
||||
if ((0 == device_num) || ((device_num & 0xff00) == 0x0200))
|
||||
/* file image or floppy disk */
|
||||
{
|
||||
if (0 == device_num)
|
||||
{
|
||||
if (0 == device_num) {
|
||||
param.size = size / 512;
|
||||
switch(param.size)
|
||||
{
|
||||
switch (param.size) {
|
||||
case 720:
|
||||
param.sect = 9;
|
||||
param.head = 2;
|
||||
@ -629,16 +589,14 @@ establish_params (int device_num,int size)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else /* is a floppy diskette */
|
||||
{
|
||||
} else { /* is a floppy diskette */
|
||||
|
||||
if (ioctl(dev, FDGETPRM, ¶m)) /* Can we get the diskette geometry? */
|
||||
die("unable to get diskette geometry for '%s'");
|
||||
}
|
||||
bs.secs_track = CT_LE_W(param.sect); /* Set up the geometry information */
|
||||
bs.heads = CT_LE_W(param.head);
|
||||
switch (param.size) /* Set up the media descriptor byte */
|
||||
{
|
||||
switch (param.size) { /* Set up the media descriptor byte */
|
||||
case 720: /* 5.25", 2, 9, 40 - 360K */
|
||||
bs.media = (char)0xfd;
|
||||
bs.cluster_size = (char)2;
|
||||
@ -676,14 +634,11 @@ establish_params (int device_num,int size)
|
||||
else
|
||||
goto floppy_default;
|
||||
}
|
||||
}
|
||||
else if ((device_num & 0xff00) == 0x0700) /* This is a loop device */
|
||||
{
|
||||
} else if ((device_num & 0xff00) == 0x0700) { /* This is a loop device */
|
||||
if (ioctl(dev, BLKGETSIZE, &loop_size))
|
||||
die("unable to get loop device size");
|
||||
|
||||
switch (loop_size) /* Assuming the loop device -> floppy later */
|
||||
{
|
||||
switch (loop_size) { /* Assuming the loop device -> floppy later */
|
||||
case 720: /* 5.25", 2, 9, 40 - 360K */
|
||||
bs.secs_track = CF_LE_W(9);
|
||||
bs.heads = CF_LE_W(2);
|
||||
@ -732,25 +687,25 @@ establish_params (int device_num,int size)
|
||||
bs.heads = CT_LE_W(64);
|
||||
goto def_hd_params;
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
/* Must be a hard disk then! */
|
||||
{
|
||||
/* Can we get the drive geometry? (Note I'm not too sure about */
|
||||
/* whether to use HDIO_GETGEO or HDIO_REQ) */
|
||||
if (ioctl (dev, HDIO_GETGEO, &geometry) || geometry.sectors == 0 || geometry.heads == 0) {
|
||||
if (ioctl(dev, HDIO_GETGEO, &geometry) || geometry.sectors == 0
|
||||
|| geometry.heads == 0) {
|
||||
printf("unable to get drive geometry, using default 255/63\n");
|
||||
bs.secs_track = CT_LE_W(63);
|
||||
bs.heads = CT_LE_W(255);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
bs.secs_track = CT_LE_W(geometry.sectors); /* Set up the geometry information */
|
||||
bs.heads = CT_LE_W(geometry.heads);
|
||||
}
|
||||
def_hd_params:
|
||||
bs.media = (char)0xf8; /* Set up the media descriptor for a hard drive */
|
||||
if (!size_fat && blocks * SECTORS_PER_BLOCK > 1064960) {
|
||||
if (verbose) printf("Auto-selecting FAT32 for large filesystem\n");
|
||||
if (verbose)
|
||||
printf("Auto-selecting FAT32 for large filesystem\n");
|
||||
size_fat = 32;
|
||||
}
|
||||
if (size_fat == 32) {
|
||||
@ -762,13 +717,12 @@ establish_params (int device_num,int size)
|
||||
* fs size > 16G: 16k clusters
|
||||
*/
|
||||
unsigned long sz_mb =
|
||||
(blocks+(1<<(20-BLOCK_SIZE_BITS))-1) >> (20-BLOCK_SIZE_BITS);
|
||||
bs.cluster_size = sz_mb > 16*1024 ? 32 :
|
||||
sz_mb > 8*1024 ? 16 :
|
||||
sz_mb > 260 ? 8 :
|
||||
1;
|
||||
}
|
||||
else {
|
||||
(blocks + (1 << (20 - BLOCK_SIZE_BITS)) - 1) >> (20 -
|
||||
BLOCK_SIZE_BITS);
|
||||
bs.cluster_size =
|
||||
sz_mb > 16 * 1024 ? 32 : sz_mb > 8 * 1024 ? 16 : sz_mb >
|
||||
260 ? 8 : 1;
|
||||
} else {
|
||||
/* FAT12 and FAT16: start at 4 sectors per cluster */
|
||||
bs.cluster_size = (char)4;
|
||||
}
|
||||
@ -782,8 +736,7 @@ establish_params (int device_num,int size)
|
||||
* If alignment is enabled, round the first argument up to the second; the
|
||||
* latter must be a power of two.
|
||||
*/
|
||||
static unsigned int
|
||||
align_object (unsigned int sectors, unsigned int clustsize)
|
||||
static unsigned int align_object(unsigned int sectors, unsigned int clustsize)
|
||||
{
|
||||
if (align_structures)
|
||||
return (sectors + clustsize - 1) & ~(clustsize - 1);
|
||||
@ -793,13 +746,13 @@ align_object (unsigned int sectors, unsigned int clustsize)
|
||||
|
||||
/* Create the filesystem data tables */
|
||||
|
||||
static void
|
||||
setup_tables (void)
|
||||
static void setup_tables(void)
|
||||
{
|
||||
unsigned num_sectors;
|
||||
unsigned cluster_count = 0, fat_length;
|
||||
struct tm *ctime;
|
||||
struct msdos_volume_info *vi = (size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
|
||||
struct msdos_volume_info *vi =
|
||||
(size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
|
||||
|
||||
if (atari_format)
|
||||
/* On Atari, the first few bytes of the boot sector are assigned
|
||||
@ -810,8 +763,7 @@ setup_tables (void)
|
||||
strcpy(bs.system_id, "mkdosfs");
|
||||
if (sectors_per_cluster)
|
||||
bs.cluster_size = (char)sectors_per_cluster;
|
||||
if (size_fat == 32)
|
||||
{
|
||||
if (size_fat == 32) {
|
||||
/* Under FAT32, the root dir is in a cluster chain, and this is
|
||||
* signalled by bs.dir_entries being 0. */
|
||||
root_dir_entries = 0;
|
||||
@ -821,8 +773,7 @@ setup_tables (void)
|
||||
bs.system_id[5] = (unsigned char)(volume_id & 0x000000ff);
|
||||
bs.system_id[6] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
|
||||
bs.system_id[7] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
vi->volume_id[0] = (unsigned char)(volume_id & 0x000000ff);
|
||||
vi->volume_id[1] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
|
||||
vi->volume_id[2] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
|
||||
@ -836,8 +787,7 @@ setup_tables (void)
|
||||
/* Patch in the correct offset to the boot code */
|
||||
bs.boot_jump[1] = ((size_fat == 32 ?
|
||||
(char *)&bs.fat32.boot_code :
|
||||
(char *)&bs.oldfat.boot_code) -
|
||||
(char *)&bs) - 2;
|
||||
(char *)&bs.oldfat.boot_code) - (char *)&bs) - 2;
|
||||
|
||||
if (size_fat == 32) {
|
||||
int offset = (char *)&bs.fat32.boot_code -
|
||||
@ -848,13 +798,11 @@ setup_tables (void)
|
||||
memcpy(bs.fat32.boot_code, dummy_boot_code, BOOTCODE_FAT32_SIZE);
|
||||
bs.fat32.boot_code[MSG_OFFSET_OFFSET] = offset & 0xff;
|
||||
bs.fat32.boot_code[MSG_OFFSET_OFFSET + 1] = offset >> 8;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
memcpy(bs.oldfat.boot_code, dummy_boot_code, BOOTCODE_SIZE);
|
||||
}
|
||||
bs.boot_sign = CT_LE_W(BOOT_SIGN);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
memcpy(bs.boot_jump, dummy_boot_jump_m68k, 2);
|
||||
}
|
||||
if (verbose >= 2)
|
||||
@ -960,7 +908,8 @@ setup_tables (void)
|
||||
}
|
||||
/* The < 4078 avoids that the filesystem will be misdetected as having a
|
||||
* 12 bit FAT. */
|
||||
if (clust16 < FAT12_THRESHOLD && !(size_fat_by_user && size_fat == 16)) {
|
||||
if (clust16 < FAT12_THRESHOLD
|
||||
&& !(size_fat_by_user && size_fat == 16)) {
|
||||
if (verbose >= 2)
|
||||
printf(clust16 < FAT12_THRESHOLD ?
|
||||
"FAT16: would be misdetected as FAT12\n" :
|
||||
@ -979,7 +928,8 @@ setup_tables (void)
|
||||
maxclust32 = (fatlength32 * sector_size) / 4;
|
||||
if (maxclust32 > MAX_CLUST_32)
|
||||
maxclust32 = MAX_CLUST_32;
|
||||
if (clust32 && clust32 < MIN_CLUST_32 && !(size_fat_by_user && size_fat == 32)) {
|
||||
if (clust32 && clust32 < MIN_CLUST_32
|
||||
&& !(size_fat_by_user && size_fat == 32)) {
|
||||
clust32 = 0;
|
||||
if (verbose >= 2)
|
||||
printf("FAT32: not enough clusters (%d)\n", MIN_CLUST_32);
|
||||
@ -1024,8 +974,7 @@ setup_tables (void)
|
||||
"16 bit FAT! The filesystem will be\n"
|
||||
"misinterpreted as having a 12 bit FAT without "
|
||||
"mount option \"fat=16\".\n");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fprintf(stderr, "This filesystem has an unfortunate size. "
|
||||
"A 12 bit FAT cannot provide\n"
|
||||
"enough clusters, but a 16 bit FAT takes up a little "
|
||||
@ -1044,7 +993,8 @@ setup_tables (void)
|
||||
|
||||
case 32:
|
||||
if (clust32 < MIN_CLUST_32)
|
||||
fprintf(stderr, "WARNING: Not enough clusters for a 32 bit FAT!\n");
|
||||
fprintf(stderr,
|
||||
"WARNING: Not enough clusters for a 32 bit FAT!\n");
|
||||
cluster_count = clust32;
|
||||
fat_length = fatlength32;
|
||||
bs.fat_length = CT_LE_W(0);
|
||||
@ -1066,8 +1016,7 @@ setup_tables (void)
|
||||
root_dir_entries = align_object(root_dir_sectors, bs.cluster_size)
|
||||
* (sector_size >> 5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
unsigned clusters, maxclust, fatdata;
|
||||
|
||||
/* GEMDOS always uses a 12 bit FAT on floppies, and always a 16 bit FAT on
|
||||
@ -1104,8 +1053,12 @@ setup_tables (void)
|
||||
* size_fat == 12
|
||||
* The "2*nr_fats*size_fat/8" is for the reserved first two FAT entries
|
||||
*/
|
||||
clusters = (2*((long long)fatdata*sector_size - 2*nr_fats*size_fat/8)) /
|
||||
(2*((int)bs.cluster_size*sector_size + nr_fats*size_fat/8));
|
||||
clusters =
|
||||
(2 *
|
||||
((long long)fatdata * sector_size -
|
||||
2 * nr_fats * size_fat / 8)) / (2 * ((int)bs.cluster_size *
|
||||
sector_size +
|
||||
nr_fats * size_fat / 8));
|
||||
fat_length = cdiv((clusters + 2) * size_fat / 8, sector_size);
|
||||
/* Need to recalculate number of clusters, since the unused parts of the
|
||||
* FATS and data area together could make up space for an additional,
|
||||
@ -1118,8 +1071,9 @@ setup_tables (void)
|
||||
|
||||
/* last 10 cluster numbers are special (except FAT32: 4 high bits rsvd);
|
||||
* first two numbers are reserved */
|
||||
if (maxclust <= (size_fat == 32 ? MAX_CLUST_32 : (1<<size_fat)-0x10) &&
|
||||
clusters <= maxclust-2)
|
||||
if (maxclust <=
|
||||
(size_fat == 32 ? MAX_CLUST_32 : (1 << size_fat) - 0x10)
|
||||
&& clusters <= maxclust - 2)
|
||||
break;
|
||||
if (verbose >= 2)
|
||||
printf(clusters > maxclust - 2 ?
|
||||
@ -1151,8 +1105,7 @@ setup_tables (void)
|
||||
bs.dir_entries[0] = (char)(root_dir_entries & 0x00ff);
|
||||
bs.dir_entries[1] = (char)((root_dir_entries & 0xff00) >> 8);
|
||||
|
||||
if (size_fat == 32)
|
||||
{
|
||||
if (size_fat == 32) {
|
||||
/* set up additional FAT32 fields */
|
||||
bs.fat32.flags = CT_LE_W(0);
|
||||
bs.fat32.version[0] = 0;
|
||||
@ -1162,8 +1115,7 @@ setup_tables (void)
|
||||
if (!backup_boot)
|
||||
backup_boot = (reserved_sectors >= 7) ? 6 :
|
||||
(reserved_sectors >= 2) ? reserved_sectors - 1 : 0;
|
||||
else
|
||||
{
|
||||
else {
|
||||
if (backup_boot == 1)
|
||||
die("Backup boot sector must be after sector 1");
|
||||
else if (backup_boot >= reserved_sectors)
|
||||
@ -1184,14 +1136,11 @@ setup_tables (void)
|
||||
printf("Warning: More than 32765 sector need TOS 1.04 "
|
||||
"or higher.\n");
|
||||
}
|
||||
if (num_sectors >= 65536)
|
||||
{
|
||||
if (num_sectors >= 65536) {
|
||||
bs.sectors[0] = (char)0;
|
||||
bs.sectors[1] = (char)0;
|
||||
bs.total_sect = CT_LE_L(num_sectors);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
bs.sectors[0] = (char)(num_sectors & 0x00ff);
|
||||
bs.sectors[1] = (char)((num_sectors & 0xff00) >> 8);
|
||||
if (!atari_format)
|
||||
@ -1201,15 +1150,13 @@ setup_tables (void)
|
||||
if (!atari_format)
|
||||
vi->ext_boot_sign = MSDOS_EXT_SIGN;
|
||||
|
||||
if (!cluster_count)
|
||||
{
|
||||
if (!cluster_count) {
|
||||
if (sectors_per_cluster) /* If yes, die if we'd spec'd sectors per cluster */
|
||||
die("Too many clusters for file system - try more sectors per cluster");
|
||||
else
|
||||
die("Attempting to create a too large file system");
|
||||
}
|
||||
|
||||
|
||||
/* The two following vars are in hard sectors, i.e. 512 byte sectors! */
|
||||
start_data_sector = (reserved_sectors + nr_fats * fat_length) *
|
||||
(sector_size / HARD_SECTOR_SIZE);
|
||||
@ -1219,11 +1166,11 @@ setup_tables (void)
|
||||
if (blocks < start_data_block + 32) /* Arbitrary undersize file system! */
|
||||
die("Too few blocks for viable file system");
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (verbose) {
|
||||
printf("%s has %d head%s and %d sector%s per track,\n",
|
||||
device_name, CF_LE_W(bs.heads), (CF_LE_W(bs.heads) != 1) ? "s" : "",
|
||||
CF_LE_W(bs.secs_track), (CF_LE_W(bs.secs_track) != 1) ? "s" : "");
|
||||
device_name, CF_LE_W(bs.heads),
|
||||
(CF_LE_W(bs.heads) != 1) ? "s" : "", CF_LE_W(bs.secs_track),
|
||||
(CF_LE_W(bs.secs_track) != 1) ? "s" : "");
|
||||
printf("logical sector size is %d,\n", sector_size);
|
||||
printf("using 0x%02x media descriptor, with %d sectors;\n",
|
||||
(int)(bs.media), num_sectors);
|
||||
@ -1235,8 +1182,7 @@ setup_tables (void)
|
||||
cluster_count, (cluster_count != 1) ? "s" : "");
|
||||
printf("There %s %u reserved sector%s.\n",
|
||||
(reserved_sectors != 1) ? "are" : "is",
|
||||
reserved_sectors,
|
||||
(reserved_sectors != 1) ? "s" : "");
|
||||
reserved_sectors, (reserved_sectors != 1) ? "s" : "");
|
||||
|
||||
if (size_fat != 32) {
|
||||
unsigned root_dir_entries =
|
||||
@ -1261,7 +1207,8 @@ setup_tables (void)
|
||||
else
|
||||
alloced_fat_length = 1;
|
||||
|
||||
if ((fat = (unsigned char *) malloc (alloced_fat_length * sector_size)) == NULL)
|
||||
if ((fat =
|
||||
(unsigned char *)malloc(alloced_fat_length * sector_size)) == NULL)
|
||||
die("unable to allocate space for FAT image in memory");
|
||||
|
||||
memset(fat, 0, alloced_fat_length * sector_size);
|
||||
@ -1280,23 +1227,23 @@ setup_tables (void)
|
||||
bs.cluster_size * sector_size :
|
||||
(((int)bs.dir_entries[1] * 256 + (int)bs.dir_entries[0]) *
|
||||
sizeof(struct msdos_dir_entry));
|
||||
if ((root_dir = (struct msdos_dir_entry *) malloc (size_root_dir)) == NULL)
|
||||
{
|
||||
if ((root_dir = (struct msdos_dir_entry *)malloc(size_root_dir)) == NULL) {
|
||||
free(fat); /* Tidy up before we die! */
|
||||
die("unable to allocate space for root directory in memory");
|
||||
}
|
||||
|
||||
memset(root_dir, 0, size_root_dir);
|
||||
if ( memcmp(volume_name, " ", 11) )
|
||||
{
|
||||
if (memcmp(volume_name, " ", 11)) {
|
||||
struct msdos_dir_entry *de = &root_dir[0];
|
||||
memcpy(de->name, volume_name, 8);
|
||||
memcpy(de->ext, volume_name + 8, 3);
|
||||
de->attr = ATTR_VOLUME;
|
||||
ctime = localtime(&create_time);
|
||||
de->time = CT_LE_W((unsigned short)((ctime->tm_sec >> 1) +
|
||||
(ctime->tm_min << 5) + (ctime->tm_hour << 11)));
|
||||
de->date = CT_LE_W((unsigned short)(ctime->tm_mday +
|
||||
(ctime->tm_min << 5) +
|
||||
(ctime->tm_hour << 11)));
|
||||
de->date =
|
||||
CT_LE_W((unsigned short)(ctime->tm_mday +
|
||||
((ctime->tm_mon + 1) << 5) +
|
||||
((ctime->tm_year - 80) << 9)));
|
||||
de->ctime_ms = 0;
|
||||
@ -1339,7 +1286,6 @@ setup_tables (void)
|
||||
memset(blank_sector, 0, sector_size);
|
||||
}
|
||||
|
||||
|
||||
/* Write the new filesystem's data tables to wherever they're going to end up! */
|
||||
|
||||
#define error(str) \
|
||||
@ -1364,9 +1310,7 @@ setup_tables (void)
|
||||
error ("failed whilst writing " errstr); \
|
||||
} while(0)
|
||||
|
||||
|
||||
static void
|
||||
write_tables (void)
|
||||
static void write_tables(void)
|
||||
{
|
||||
int x;
|
||||
int fat_length;
|
||||
@ -1382,12 +1326,10 @@ write_tables (void)
|
||||
seekto(0, "boot sector");
|
||||
writebuf((char *)&bs, sizeof(struct msdos_boot_sector), "boot sector");
|
||||
/* on FAT32, write the info sector and backup boot sector */
|
||||
if (size_fat == 32)
|
||||
{
|
||||
if (size_fat == 32) {
|
||||
seekto(CF_LE_W(bs.fat32.info_sector) * sector_size, "info sector");
|
||||
writebuf(info_sector, 512, "info sector");
|
||||
if (backup_boot != 0)
|
||||
{
|
||||
if (backup_boot != 0) {
|
||||
seekto(backup_boot * sector_size, "backup boot sector");
|
||||
writebuf((char *)&bs, sizeof(struct msdos_boot_sector),
|
||||
"backup boot sector");
|
||||
@ -1406,17 +1348,17 @@ write_tables (void)
|
||||
* dir area on FAT12/16, and the first cluster on FAT32. */
|
||||
writebuf((char *)root_dir, size_root_dir, "root directory");
|
||||
|
||||
if (blank_sector) free( blank_sector );
|
||||
if (info_sector) free( info_sector );
|
||||
if (blank_sector)
|
||||
free(blank_sector);
|
||||
if (info_sector)
|
||||
free(info_sector);
|
||||
free(root_dir); /* Free up the root directory space from setup_tables */
|
||||
free(fat); /* Free up the fat table space reserved during setup_tables */
|
||||
}
|
||||
|
||||
|
||||
/* Report the command usage and return a failure error code */
|
||||
|
||||
void
|
||||
usage (void)
|
||||
void usage(void)
|
||||
{
|
||||
fatal_error("\
|
||||
Usage: mkdosfs [-a][-A][-c][-C][-v][-I][-l bad-block-file][-b backup-boot-sector]\n\
|
||||
@ -1457,8 +1399,7 @@ static void check_atari( void )
|
||||
/* The "main" entry point into the utility - we pick up the options and attempt to process them in some sort of sensible
|
||||
way. In the event that some/all of the options are invalid we need to tell the user so that something can be done! */
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
char *tmp;
|
||||
@ -1482,13 +1423,11 @@ main (int argc, char **argv)
|
||||
volume_id = (u_int32_t) ((create_timeval.tv_sec << 20) | create_timeval.tv_usec); /* Default volume ID = creation time, fudged for more uniqueness */
|
||||
check_atari();
|
||||
|
||||
printf ("%s " VERSION " (" VERSION_DATE ")\n",
|
||||
program_name);
|
||||
printf("%s " VERSION " (" VERSION_DATE ")\n", program_name);
|
||||
|
||||
while ((c = getopt(argc, argv, "aAb:cCf:F:Ii:l:m:n:r:R:s:S:h:v")) != EOF)
|
||||
/* Scan the command line for options */
|
||||
switch (c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'A': /* toggle Atari format */
|
||||
atari_format = !atari_format;
|
||||
break;
|
||||
@ -1499,8 +1438,7 @@ main (int argc, char **argv)
|
||||
|
||||
case 'b': /* b : location of backup boot sector */
|
||||
backup_boot = (int)strtol(optarg, &tmp, 0);
|
||||
if (*tmp || backup_boot < 2 || backup_boot > 0xffff)
|
||||
{
|
||||
if (*tmp || backup_boot < 2 || backup_boot > 0xffff) {
|
||||
printf("Bad location for backup boot sector : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1517,8 +1455,7 @@ main (int argc, char **argv)
|
||||
|
||||
case 'f': /* f : Choose number of FATs */
|
||||
nr_fats = (int)strtol(optarg, &tmp, 0);
|
||||
if (*tmp || nr_fats < 1 || nr_fats > 4)
|
||||
{
|
||||
if (*tmp || nr_fats < 1 || nr_fats > 4) {
|
||||
printf("Bad number of FATs : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1526,8 +1463,7 @@ main (int argc, char **argv)
|
||||
|
||||
case 'F': /* F : Choose FAT size */
|
||||
size_fat = (int)strtol(optarg, &tmp, 0);
|
||||
if (*tmp || (size_fat != 12 && size_fat != 16 && size_fat != 32))
|
||||
{
|
||||
if (*tmp || (size_fat != 12 && size_fat != 16 && size_fat != 32)) {
|
||||
printf("Bad FAT type : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1536,8 +1472,7 @@ main (int argc, char **argv)
|
||||
|
||||
case 'h': /* h : number of hidden sectors */
|
||||
hidden_sectors = (int)strtol(optarg, &tmp, 0);
|
||||
if ( *tmp || hidden_sectors < 0 )
|
||||
{
|
||||
if (*tmp || hidden_sectors < 0) {
|
||||
printf("Bad number of hidden sectors : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1549,8 +1484,7 @@ main (int argc, char **argv)
|
||||
|
||||
case 'i': /* i : specify volume ID */
|
||||
volume_id = strtoul(optarg, &tmp, 16);
|
||||
if ( *tmp )
|
||||
{
|
||||
if (*tmp) {
|
||||
printf("Volume ID must be a hexadecimal number\n");
|
||||
usage();
|
||||
}
|
||||
@ -1562,32 +1496,26 @@ main (int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'm': /* m : Set boot message */
|
||||
if ( strcmp(optarg, "-") )
|
||||
{
|
||||
if (strcmp(optarg, "-")) {
|
||||
msgfile = fopen(optarg, "r");
|
||||
if (!msgfile)
|
||||
perror(optarg);
|
||||
}
|
||||
else
|
||||
} else
|
||||
msgfile = stdin;
|
||||
|
||||
if ( msgfile )
|
||||
{
|
||||
if (msgfile) {
|
||||
/* The boot code ends at offset 448 and needs a null terminator */
|
||||
i = MESSAGE_OFFSET;
|
||||
pos = 0; /* We are at beginning of line */
|
||||
do
|
||||
{
|
||||
do {
|
||||
ch = getc(msgfile);
|
||||
switch (ch)
|
||||
{
|
||||
switch (ch) {
|
||||
case '\r': /* Ignore CRs */
|
||||
case '\0': /* and nulls */
|
||||
break;
|
||||
|
||||
case '\n': /* LF -> CR+LF if necessary */
|
||||
if ( pos ) /* If not at beginning of line */
|
||||
{
|
||||
if (pos) { /* If not at beginning of line */
|
||||
dummy_boot_code[i++] = '\r';
|
||||
pos = 0;
|
||||
}
|
||||
@ -1595,8 +1523,7 @@ main (int argc, char **argv)
|
||||
break;
|
||||
|
||||
case '\t': /* Expand tabs */
|
||||
do
|
||||
{
|
||||
do {
|
||||
dummy_boot_code[i++] = ' ';
|
||||
pos++;
|
||||
}
|
||||
@ -1634,8 +1561,7 @@ main (int argc, char **argv)
|
||||
|
||||
case 'r': /* r : Root directory entries */
|
||||
root_dir_entries = (int)strtol(optarg, &tmp, 0);
|
||||
if (*tmp || root_dir_entries < 16 || root_dir_entries > 32768)
|
||||
{
|
||||
if (*tmp || root_dir_entries < 16 || root_dir_entries > 32768) {
|
||||
printf("Bad number of root directory entries : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1643,8 +1569,7 @@ main (int argc, char **argv)
|
||||
|
||||
case 'R': /* R : number of reserved sectors */
|
||||
reserved_sectors = (int)strtol(optarg, &tmp, 0);
|
||||
if (*tmp || reserved_sectors < 1 || reserved_sectors > 0xffff)
|
||||
{
|
||||
if (*tmp || reserved_sectors < 1 || reserved_sectors > 0xffff) {
|
||||
printf("Bad number of reserved sectors : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1654,9 +1579,10 @@ main (int argc, char **argv)
|
||||
sectors_per_cluster = (int)strtol(optarg, &tmp, 0);
|
||||
if (*tmp || (sectors_per_cluster != 1 && sectors_per_cluster != 2
|
||||
&& sectors_per_cluster != 4 && sectors_per_cluster != 8
|
||||
&& sectors_per_cluster != 16 && sectors_per_cluster != 32
|
||||
&& sectors_per_cluster != 64 && sectors_per_cluster != 128))
|
||||
{
|
||||
&& sectors_per_cluster != 16
|
||||
&& sectors_per_cluster != 32
|
||||
&& sectors_per_cluster != 64
|
||||
&& sectors_per_cluster != 128)) {
|
||||
printf("Bad number of sectors per cluster : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1667,8 +1593,7 @@ main (int argc, char **argv)
|
||||
if (*tmp || (sector_size != 512 && sector_size != 1024 &&
|
||||
sector_size != 2048 && sector_size != 4096 &&
|
||||
sector_size != 8192 && sector_size != 16384 &&
|
||||
sector_size != 32768))
|
||||
{
|
||||
sector_size != 32768)) {
|
||||
printf("Bad logical sector size : %s\n", optarg);
|
||||
usage();
|
||||
}
|
||||
@ -1683,8 +1608,7 @@ main (int argc, char **argv)
|
||||
printf("Unknown option: %c\n", c);
|
||||
usage();
|
||||
}
|
||||
if (optind < argc)
|
||||
{
|
||||
if (optind < argc) {
|
||||
device_name = argv[optind]; /* Determine the number of blocks in the FS */
|
||||
|
||||
if (!device_name) {
|
||||
@ -1695,29 +1619,22 @@ main (int argc, char **argv)
|
||||
if (!create)
|
||||
cblocks = count_blocks(device_name); /* Have a look and see! */
|
||||
}
|
||||
if (optind == argc - 2) /* Either check the user specified number */
|
||||
{
|
||||
if (optind == argc - 2) { /* Either check the user specified number */
|
||||
blocks = strtoull(argv[optind + 1], &tmp, 0);
|
||||
if (!create && blocks != cblocks)
|
||||
{
|
||||
if (!create && blocks != cblocks) {
|
||||
fprintf(stderr, "Warning: block count mismatch: ");
|
||||
fprintf(stderr, "found %llu but assuming %llu.\n", cblocks, blocks);
|
||||
}
|
||||
}
|
||||
else if (optind == argc - 1) /* Or use value found */
|
||||
{
|
||||
} else if (optind == argc - 1) { /* Or use value found */
|
||||
if (create)
|
||||
die("Need intended size with -C.");
|
||||
blocks = cblocks;
|
||||
tmp = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fprintf(stderr, "No device specified!\n");
|
||||
usage();
|
||||
}
|
||||
if (*tmp)
|
||||
{
|
||||
if (*tmp) {
|
||||
printf("Bad block count : %s\n", argv[optind + 1]);
|
||||
usage();
|
||||
}
|
||||
@ -1729,11 +1646,11 @@ main (int argc, char **argv)
|
||||
check_mount(device_name); /* Is the device already mounted? */
|
||||
dev = open(device_name, O_EXCL | O_RDWR); /* Is it a suitable device to build the FS on? */
|
||||
if (dev < 0) {
|
||||
fprintf (stderr, "%s: unable to open %s: %s\n", program_name, device_name, strerror(errno));
|
||||
fprintf(stderr, "%s: unable to open %s: %s\n", program_name,
|
||||
device_name, strerror(errno));
|
||||
exit(1); /* The error exit code is 1! */
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
loff_t offset = blocks * BLOCK_SIZE - 1;
|
||||
char null = 0;
|
||||
/* create the file */
|
||||
@ -1755,8 +1672,7 @@ main (int argc, char **argv)
|
||||
if (!S_ISBLK(statbuf.st_mode)) {
|
||||
statbuf.st_rdev = 0;
|
||||
check = 0;
|
||||
}
|
||||
else
|
||||
} else
|
||||
/*
|
||||
* Ignore any 'full' fixed disk devices, if -I is not given.
|
||||
* On a MO-disk one doesn't need partitions. The filesytem can go
|
||||
@ -1764,27 +1680,23 @@ main (int argc, char **argv)
|
||||
* the 'superfloppy' format. As I don't know how to find out if
|
||||
* this is a MO disk I introduce a -I (ignore) switch. -Joey
|
||||
*/
|
||||
if (!ignore_full_disk && (
|
||||
(statbuf.st_rdev & 0xff3f) == 0x0300 || /* hda, hdb */
|
||||
if (!ignore_full_disk && ((statbuf.st_rdev & 0xff3f) == 0x0300 || /* hda, hdb */
|
||||
(statbuf.st_rdev & 0xff0f) == 0x0800 || /* sd */
|
||||
(statbuf.st_rdev & 0xff3f) == 0x0d00 || /* xd */
|
||||
(statbuf.st_rdev & 0xff3f) == 0x1600) /* hdc, hdd */
|
||||
)
|
||||
die("Device partition expected, not making filesystem on entire device '%s' (use -I to override)");
|
||||
|
||||
if (sector_size_set)
|
||||
{
|
||||
if (sector_size_set) {
|
||||
if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0)
|
||||
if (sector_size < min_sector_size)
|
||||
{
|
||||
if (sector_size < min_sector_size) {
|
||||
sector_size = min_sector_size;
|
||||
fprintf(stderr, "Warning: sector size was set to %d (minimal for this device)\n", sector_size);
|
||||
fprintf(stderr,
|
||||
"Warning: sector size was set to %d (minimal for this device)\n",
|
||||
sector_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0)
|
||||
{
|
||||
} else {
|
||||
if (ioctl(dev, BLKSSZGET, &min_sector_size) >= 0) {
|
||||
sector_size = min_sector_size;
|
||||
sector_size_set = 1;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user