Indenting source files.

Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
This commit is contained in:
Daniel Baumann 2011-01-02 15:41:44 +01:00
parent 697af859b6
commit 2d8be9c628
18 changed files with 2669 additions and 2701 deletions

View File

@ -35,7 +35,6 @@
#include "io.h" #include "io.h"
#include "boot.h" #include "boot.h"
#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
/* don't divide by zero */ /* don't divide by zero */
@ -47,17 +46,17 @@ static struct {
__u8 media; __u8 media;
char *descr; char *descr;
} mediabytes[] = { } mediabytes[] = {
{ 0xf0, "5.25\" or 3.5\" HD floppy" }, {
{ 0xf8, "hard disk" }, 0xf0, "5.25\" or 3.5\" HD floppy"}, {
{ 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or " 0xf8, "hard disk"}, {
"5.25\" 1.2M floppy 2s/80tr/15sec" }, 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
{ 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" }, "5.25\" 1.2M floppy 2s/80tr/15sec"}, {
{ 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" }, 0xfa, "5.25\" 320k floppy 1s/80tr/8sec"}, {
{ 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" }, 0xfb, "3.5\" 640k floppy 2s/80tr/8sec"}, {
{ 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" }, 0xfc, "5.25\" 180k floppy 1s/40tr/9sec"}, {
{ 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" }, 0xfd, "5.25\" 360k floppy 2s/40tr/9sec"}, {
{ 0xff, "5.25\" 320k floppy 2s/40tr/8sec" }, 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__ \ #if defined __alpha || defined __arm || defined __arm__ || defined __ia64__ || defined __x86_64__ \
|| defined __ppc64__ || defined __bfin__ || defined __MICROBLAZE__ || defined __ppc64__ || defined __bfin__ || defined __MICROBLAZE__
@ -72,87 +71,84 @@ static struct {
#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f ) #define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f )
#endif #endif
static char *get_media_descr(unsigned char media)
static char *get_media_descr( unsigned char media )
{ {
int i; int i;
for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) { for (i = 0; i < sizeof(mediabytes) / sizeof(*mediabytes); ++i) {
if (mediabytes[i].media == media) if (mediabytes[i].media == media)
return( mediabytes[i].descr ); return (mediabytes[i].descr);
} }
return( "undefined" ); return ("undefined");
} }
static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss) static void dump_boot(DOS_FS * fs, struct boot_sector *b, unsigned lss)
{ {
unsigned short sectors; unsigned short sectors;
printf("Boot sector contents:\n"); printf("Boot sector contents:\n");
if (!atari_format) { if (!atari_format) {
char id[9]; char id[9];
strncpy(id,b->system_id,8); strncpy(id, b->system_id, 8);
id[8] = 0; id[8] = 0;
printf("System ID \"%s\"\n",id); printf("System ID \"%s\"\n", id);
} } else {
else {
/* On Atari, a 24 bit serial number is stored at offset 8 of the boot /* On Atari, a 24 bit serial number is stored at offset 8 of the boot
* sector */ * sector */
printf("Serial number 0x%x\n", 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("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)); printf("%10d bytes per logical sector\n", GET_UNALIGNED_W(b->sector_size));
printf("%10d bytes per cluster\n",fs->cluster_size); printf("%10d bytes per cluster\n", fs->cluster_size);
printf("%10d reserved sector%s\n",CF_LE_W(b->reserved), printf("%10d reserved sector%s\n", CF_LE_W(b->reserved),
CF_LE_W(b->reserved) == 1 ? "" : "s"); CF_LE_W(b->reserved) == 1 ? "" : "s");
printf("First FAT starts at byte %llu (sector %llu)\n", printf("First FAT starts at byte %llu (sector %llu)\n",
(unsigned long long)fs->fat_start, (unsigned long long)fs->fat_start,
(unsigned long long)fs->fat_start/lss); (unsigned long long)fs->fat_start / lss);
printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits); printf("%10d FATs, %d bit entries\n", b->fats, fs->fat_bits);
printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size, printf("%10d bytes per FAT (= %u sectors)\n", fs->fat_size,
fs->fat_size/lss); fs->fat_size / lss);
if (!fs->root_cluster) { if (!fs->root_cluster) {
printf("Root directory starts at byte %llu (sector %llu)\n", printf("Root directory starts at byte %llu (sector %llu)\n",
(unsigned long long)fs->root_start, (unsigned long long)fs->root_start,
(unsigned long long)fs->root_start/lss); (unsigned long long)fs->root_start / lss);
printf("%10d root directory entries\n",fs->root_entries); printf("%10d root directory entries\n", fs->root_entries);
} } else {
else { printf("Root directory start at cluster %lu (arbitrary size)\n",
printf( "Root directory start at cluster %lu (arbitrary size)\n",
fs->root_cluster); fs->root_cluster);
} }
printf("Data area starts at byte %llu (sector %llu)\n", printf("Data area starts at byte %llu (sector %llu)\n",
(unsigned long long)fs->data_start, (unsigned long long)fs->data_start,
(unsigned long long)fs->data_start/lss); (unsigned long long)fs->data_start / lss);
printf("%10lu data clusters (%llu bytes)\n",fs->clusters, printf("%10lu data clusters (%llu bytes)\n", fs->clusters,
(unsigned long long)fs->clusters*fs->cluster_size); (unsigned long long)fs->clusters * fs->cluster_size);
printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track), printf("%u sectors/track, %u heads\n", CF_LE_W(b->secs_track),
CF_LE_W(b->heads)); CF_LE_W(b->heads));
printf("%10u hidden sectors\n", printf("%10u hidden sectors\n", atari_format ?
atari_format ?
/* On Atari, the hidden field is only 16 bit wide and unused */ /* On Atari, the hidden field is only 16 bit wide and unused */
(((unsigned char *)&b->hidden)[0] | (((unsigned char *)&b->hidden)[0] |
((unsigned char *)&b->hidden)[1] << 8) : ((unsigned char *)&b->hidden)[1] << 8) : CF_LE_L(b->hidden));
CF_LE_L(b->hidden)); sectors = GET_UNALIGNED_W(b->sectors);
sectors = GET_UNALIGNED_W( b->sectors );
printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect)); printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect));
} }
static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss) static void check_backup_boot(DOS_FS * fs, struct boot_sector *b, int lss)
{ {
struct boot_sector b2; struct boot_sector b2;
if (!fs->backupboot_start) { if (!fs->backupboot_start) {
printf( "There is no backup boot sector.\n" ); printf("There is no backup boot sector.\n");
if (CF_LE_W(b->reserved) < 3) { if (CF_LE_W(b->reserved) < 3) {
printf( "And there is no space for creating one!\n" ); printf("And there is no space for creating one!\n");
return; return;
} }
if (interactive) if (interactive)
printf( "1) Create one\n2) Do without a backup\n" ); printf("1) Create one\n2) Do without a backup\n");
else printf( " Auto-creating backup boot block.\n" ); else
if (!interactive || get_key("12","?") == '1') { printf(" Auto-creating backup boot block.\n");
if (!interactive || get_key("12", "?") == '1') {
int bbs; int bbs;
/* The usual place for the backup boot sector is sector 6. Choose /* The usual place for the backup boot sector is sector 6. Choose
* that or the last reserved sector. */ * that or the last reserved sector. */
@ -163,51 +159,52 @@ static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
if (bbs == CF_LE_W(b->info_sector)) if (bbs == CF_LE_W(b->info_sector))
--bbs; /* this is never 0, as we checked reserved >= 3! */ --bbs; /* this is never 0, as we checked reserved >= 3! */
} }
fs->backupboot_start = bbs*lss; fs->backupboot_start = bbs * lss;
b->backup_boot = CT_LE_W(bbs); b->backup_boot = CT_LE_W(bbs);
fs_write(fs->backupboot_start,sizeof(*b),b); fs_write(fs->backupboot_start, sizeof(*b), b);
fs_write((loff_t)offsetof(struct boot_sector,backup_boot), fs_write((loff_t) offsetof(struct boot_sector, backup_boot),
sizeof(b->backup_boot),&b->backup_boot); sizeof(b->backup_boot), &b->backup_boot);
printf( "Created backup of boot sector in sector %d\n", bbs ); printf("Created backup of boot sector in sector %d\n", bbs);
return;
} else
return; return;
} }
else return;
}
fs_read(fs->backupboot_start,sizeof(b2),&b2); fs_read(fs->backupboot_start, sizeof(b2), &b2);
if (memcmp(b,&b2,sizeof(b2)) != 0) { if (memcmp(b, &b2, sizeof(b2)) != 0) {
/* there are any differences */ /* there are any differences */
__u8 *p, *q; __u8 *p, *q;
int i, pos, first = 1; int i, pos, first = 1;
char buf[20]; char buf[20];
printf( "There are differences between boot sector and its backup.\n" ); printf("There are differences between boot sector and its backup.\n");
printf( "Differences: (offset:original/backup)\n " ); printf("Differences: (offset:original/backup)\n ");
pos = 2; pos = 2;
for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2); for (p = (__u8 *) b, q = (__u8 *) & b2, i = 0; i < sizeof(b2);
++p, ++q, ++i ) { ++p, ++q, ++i) {
if (*p != *q) { if (*p != *q) {
sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ", sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ",
(unsigned)(p-(__u8 *)b), *p, *q ); (unsigned)(p - (__u8 *) b), *p, *q);
if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2; if (pos + strlen(buf) > 78)
printf( "%s", buf ); printf("\n "), pos = 2;
printf("%s", buf);
pos += strlen(buf); pos += strlen(buf);
first = 0; first = 0;
} }
} }
printf( "\n" ); printf("\n");
if (interactive) if (interactive)
printf( "1) Copy original to backup\n" printf("1) Copy original to backup\n"
"2) Copy backup to original\n" "2) Copy backup to original\n" "3) No action\n");
"3) No action\n" ); else
else printf( " Not automatically fixing this.\n" ); printf(" Not automatically fixing this.\n");
switch (interactive ? get_key("123","?") : '3') { switch (interactive ? get_key("123", "?") : '3') {
case '1': case '1':
fs_write(fs->backupboot_start,sizeof(*b),b); fs_write(fs->backupboot_start, sizeof(*b), b);
break; break;
case '2': case '2':
fs_write(0,sizeof(b2),&b2); fs_write(0, sizeof(b2), &b2);
break; break;
default: default:
break; break;
@ -224,75 +221,76 @@ static void init_fsinfo(struct info_sector *i)
i->boot_sign = CT_LE_W(0xaa55); i->boot_sign = CT_LE_W(0xaa55);
} }
static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss) static void read_fsinfo(DOS_FS * fs, struct boot_sector *b, int lss)
{ {
struct info_sector i; struct info_sector i;
if (!b->info_sector) { if (!b->info_sector) {
printf( "No FSINFO sector\n" ); printf("No FSINFO sector\n");
if (interactive) if (interactive)
printf( "1) Create one\n2) Do without FSINFO\n" ); printf("1) Create one\n2) Do without FSINFO\n");
else printf( " Not automatically creating it.\n" ); else
if (interactive && get_key("12","?") == '1') { printf(" Not automatically creating it.\n");
if (interactive && get_key("12", "?") == '1') {
/* search for a free reserved sector (not boot sector and not /* search for a free reserved sector (not boot sector and not
* backup boot sector) */ * backup boot sector) */
__u32 s; __u32 s;
for( s = 1; s < CF_LE_W(b->reserved); ++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)) { if (s > 0 && s < CF_LE_W(b->reserved)) {
init_fsinfo(&i); init_fsinfo(&i);
fs_write((loff_t)s*lss,sizeof(i),&i); fs_write((loff_t) s * lss, sizeof(i), &i);
b->info_sector = CT_LE_W(s); b->info_sector = CT_LE_W(s);
fs_write((loff_t)offsetof(struct boot_sector,info_sector), fs_write((loff_t) offsetof(struct boot_sector, info_sector),
sizeof(b->info_sector),&b->info_sector); sizeof(b->info_sector), &b->info_sector);
if (fs->backupboot_start) if (fs->backupboot_start)
fs_write(fs->backupboot_start+ fs_write(fs->backupboot_start +
offsetof(struct boot_sector,info_sector), offsetof(struct boot_sector, info_sector),
sizeof(b->info_sector),&b->info_sector); sizeof(b->info_sector), &b->info_sector);
} } else {
else { printf("No free reserved sector found -- "
printf( "No free reserved sector found -- " "no space for FSINFO sector!\n");
"no space for FSINFO sector!\n" );
return; return;
} }
} } else
else return; return;
} }
fs->fsinfo_start = CF_LE_W(b->info_sector)*lss; fs->fsinfo_start = CF_LE_W(b->info_sector) * lss;
fs_read(fs->fsinfo_start,sizeof(i),&i); fs_read(fs->fsinfo_start, sizeof(i), &i);
if (i.magic != CT_LE_L(0x41615252) || if (i.magic != CT_LE_L(0x41615252) ||
i.signature != CT_LE_L(0x61417272) || i.signature != CT_LE_L(0x61417272) || i.boot_sign != CT_LE_W(0xaa55)) {
i.boot_sign != CT_LE_W(0xaa55)) { printf("FSINFO sector has bad magic number(s):\n");
printf( "FSINFO sector has bad magic number(s):\n" );
if (i.magic != CT_LE_L(0x41615252)) if (i.magic != CT_LE_L(0x41615252))
printf( " Offset %llu: 0x%08x != expected 0x%08x\n", printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
(unsigned long long)offsetof(struct info_sector,magic), (unsigned long long)offsetof(struct info_sector, magic),
CF_LE_L(i.magic),0x41615252); CF_LE_L(i.magic), 0x41615252);
if (i.signature != CT_LE_L(0x61417272)) if (i.signature != CT_LE_L(0x61417272))
printf( " Offset %llu: 0x%08x != expected 0x%08x\n", printf(" Offset %llu: 0x%08x != expected 0x%08x\n",
(unsigned long long)offsetof(struct info_sector,signature), (unsigned long long)offsetof(struct info_sector, signature),
CF_LE_L(i.signature),0x61417272); CF_LE_L(i.signature), 0x61417272);
if (i.boot_sign != CT_LE_W(0xaa55)) if (i.boot_sign != CT_LE_W(0xaa55))
printf( " Offset %llu: 0x%04x != expected 0x%04x\n", printf(" Offset %llu: 0x%04x != expected 0x%04x\n",
(unsigned long long)offsetof(struct info_sector,boot_sign), (unsigned long long)offsetof(struct info_sector, boot_sign),
CF_LE_W(i.boot_sign),0xaa55); CF_LE_W(i.boot_sign), 0xaa55);
if (interactive) if (interactive)
printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" ); printf("1) Correct\n2) Don't correct (FSINFO invalid then)\n");
else printf( " Auto-correcting it.\n" ); else
if (!interactive || get_key("12","?") == '1') { printf(" Auto-correcting it.\n");
if (!interactive || get_key("12", "?") == '1') {
init_fsinfo(&i); init_fsinfo(&i);
fs_write(fs->fsinfo_start,sizeof(i),&i); fs_write(fs->fsinfo_start, sizeof(i), &i);
} } else
else fs->fsinfo_start = 0; fs->fsinfo_start = 0;
} }
if (fs->fsinfo_start) if (fs->fsinfo_start)
fs->free_clusters = CF_LE_L(i.free_clusters); fs->free_clusters = CF_LE_L(i.free_clusters);
} }
void read_boot(DOS_FS *fs) void read_boot(DOS_FS * fs)
{ {
struct boot_sector b; struct boot_sector b;
unsigned total_sectors; unsigned total_sectors;
@ -300,38 +298,42 @@ void read_boot(DOS_FS *fs)
unsigned fat_length; unsigned fat_length;
loff_t data_size; loff_t data_size;
fs_read(0,sizeof(b),&b); fs_read(0, sizeof(b), &b);
logical_sector_size = GET_UNALIGNED_W(b.sector_size); 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 */ /* This was moved up because it's the first thing that will fail */
/* if the platform needs special handling of unaligned multibyte accesses */ /* if the platform needs special handling of unaligned multibyte accesses */
/* but such handling isn't being provided. See GET_UNALIGNED_W() above. */ /* but such handling isn't being provided. See GET_UNALIGNED_W() above. */
if (logical_sector_size & (SECTOR_SIZE-1)) if (logical_sector_size & (SECTOR_SIZE - 1))
die("Logical sector size (%d bytes) is not a multiple of the physical " die("Logical sector size (%d bytes) is not a multiple of the physical "
"sector size.",logical_sector_size); "sector size.", logical_sector_size);
fs->cluster_size = b.cluster_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) if (b.fats != 2 && b.fats != 1)
die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats); die("Currently, only 1 or 2 FATs are supported, not %d.\n", b.fats);
fs->nfats = b.fats; fs->nfats = b.fats;
sectors = GET_UNALIGNED_W(b.sectors); sectors = GET_UNALIGNED_W(b.sectors);
total_sectors = sectors ? sectors : CF_LE_L(b.total_sect); 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 */ /* Can't access last odd sector anyway, so round down */
fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size, fs_test((loff_t) ((total_sectors & ~1) - 1) * (loff_t) logical_sector_size,
logical_sector_size); logical_sector_size);
fat_length = CF_LE_W(b.fat_length) ? fat_length = CF_LE_W(b.fat_length) ?
CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length); CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length);
fs->fat_start = (loff_t)CF_LE_W(b.reserved)*logical_sector_size; fs->fat_start = (loff_t) CF_LE_W(b.reserved) * logical_sector_size;
fs->root_start = ((loff_t)CF_LE_W(b.reserved)+b.fats*fat_length)* fs->root_start = ((loff_t) CF_LE_W(b.reserved) + b.fats * fat_length) *
logical_sector_size; logical_sector_size;
fs->root_entries = GET_UNALIGNED_W(b.dir_entries); fs->root_entries = GET_UNALIGNED_W(b.dir_entries);
fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries << fs->data_start = fs->root_start + ROUND_TO_MULTIPLE(fs->root_entries <<
MSDOS_DIR_BITS,logical_sector_size); MSDOS_DIR_BITS,
data_size = (loff_t)total_sectors*logical_sector_size-fs->data_start; logical_sector_size);
fs->clusters = data_size/fs->cluster_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 */ fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
fs->fsinfo_start = 0; /* no FSINFO structure */ fs->fsinfo_start = 0; /* no FSINFO structure */
fs->free_clusters = -1; /* unknown */ fs->free_clusters = -1; /* unknown */
@ -344,14 +346,14 @@ void read_boot(DOS_FS *fs)
* (root_entries != 0), we handle the root dir the old way. Give a * (root_entries != 0), we handle the root dir the old way. Give a
* warning, but convertig to a root dir in a cluster chain seems * warning, but convertig to a root dir in a cluster chain seems
* to complex for now... */ * to complex for now... */
printf( "Warning: FAT32 root dir not in cluster chain! " printf("Warning: FAT32 root dir not in cluster chain! "
"Compatibility mode...\n" ); "Compatibility mode...\n");
else if (!fs->root_cluster && !fs->root_entries) else if (!fs->root_cluster && !fs->root_entries)
die("No root directory!"); die("No root directory!");
else if (fs->root_cluster && fs->root_entries) else if (fs->root_cluster && fs->root_entries)
printf( "Warning: FAT32 root dir is in a cluster chain, but " printf("Warning: FAT32 root dir is in a cluster chain, but "
"a separate root dir\n" "a separate root dir\n"
" area is defined. Cannot fix this easily.\n" ); " area is defined. Cannot fix this easily.\n");
if (fs->clusters < FAT16_THRESHOLD) if (fs->clusters < FAT16_THRESHOLD)
printf("Warning: Filesystem is FAT32 according to fat_length " printf("Warning: Filesystem is FAT32 according to fat_length "
"and fat32_length fields,\n" "and fat32_length fields,\n"
@ -360,26 +362,23 @@ void read_boot(DOS_FS *fs)
" This may lead to problems on some systems.\n", " This may lead to problems on some systems.\n",
fs->clusters, FAT16_THRESHOLD); fs->clusters, FAT16_THRESHOLD);
fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size; fs->backupboot_start = CF_LE_W(b.backup_boot) * logical_sector_size;
check_backup_boot(fs,&b,logical_sector_size); check_backup_boot(fs, &b, logical_sector_size);
read_fsinfo(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 /* On real MS-DOS, a 16 bit FAT is used whenever there would be too
* much clusers otherwise. */ * much clusers otherwise. */
fs->fat_bits = (fs->clusters >= FAT12_THRESHOLD) ? 16 : 12; fs->fat_bits = (fs->clusters >= FAT12_THRESHOLD) ? 16 : 12;
if (fs->clusters >= FAT16_THRESHOLD) if (fs->clusters >= FAT16_THRESHOLD)
die("Too many clusters (%lu) for FAT16 filesystem.", die("Too many clusters (%lu) for FAT16 filesystem.", fs->clusters);
fs->clusters); } else {
}
else {
/* On Atari, things are more difficult: GEMDOS always uses 12bit FATs /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs
* on floppies, and always 16 bit on harddisks. */ * on floppies, and always 16 bit on harddisks. */
fs->fat_bits = 16; /* assume 16 bit FAT for now */ fs->fat_bits = 16; /* assume 16 bit FAT for now */
/* If more clusters than fat entries in 16-bit fat, we assume /* If more clusters than fat entries in 16-bit fat, we assume
* it's a real MSDOS FS with 12-bit fat. */ * it's a real MSDOS FS with 12-bit fat. */
if (fs->clusters+2 > fat_length*logical_sector_size*8/16 || if (fs->clusters + 2 > fat_length * logical_sector_size * 8 / 16 ||
/* if it's a floppy disk --> 12bit fat */ /* if it's a floppy disk --> 12bit fat */
device_no == 2 || device_no == 2 ||
/* if it's a ramdisk or loopback device and has one of the usual /* if it's a ramdisk or loopback device and has one of the usual
@ -391,9 +390,9 @@ void read_boot(DOS_FS *fs)
} }
/* On FAT32, the high 4 bits of a FAT entry are reserved */ /* On FAT32, the high 4 bits of a FAT entry are reserved */
fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits; fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits;
fs->fat_size = fat_length*logical_sector_size; fs->fat_size = fat_length * logical_sector_size;
fs->label = calloc(12, sizeof (__u8)); fs->label = calloc(12, sizeof(__u8));
if (fs->fat_bits == 12 || fs->fat_bits == 16) { if (fs->fat_bits == 12 || fs->fat_bits == 16) {
struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b; struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
if (b16->extended_sig == 0x29) if (b16->extended_sig == 0x29)
@ -407,26 +406,29 @@ void read_boot(DOS_FS *fs)
fs->label = NULL; 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.", 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) if (!fs->root_entries && !fs->root_cluster)
die("Root directory has zero size."); die("Root directory has zero size.");
if (fs->root_entries & (MSDOS_DPS-1)) if (fs->root_entries & (MSDOS_DPS - 1))
die("Root directory (%d entries) doesn't span an integral number of " die("Root directory (%d entries) doesn't span an integral number of "
"sectors.",fs->root_entries); "sectors.", fs->root_entries);
if (logical_sector_size & (SECTOR_SIZE-1)) if (logical_sector_size & (SECTOR_SIZE - 1))
die("Logical sector size (%d bytes) is not a multiple of the physical " die("Logical sector size (%d bytes) is not a multiple of the physical "
"sector size.",logical_sector_size); "sector size.", logical_sector_size);
#if 0 /* linux kernel doesn't check that either */ #if 0 /* linux kernel doesn't check that either */
/* ++roman: On Atari, these two fields are often left uninitialized */ /* ++roman: On Atari, these two fields are often left uninitialized */
if (!atari_format && (!b.secs_track || !b.heads)) if (!atari_format && (!b.secs_track || !b.heads))
die("Invalid disk format in boot sector."); die("Invalid disk format in boot sector.");
#endif #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) static void write_boot_label(DOS_FS * fs, char *label)
{ {
struct boot_sector b; struct boot_sector b;
struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b; struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
@ -436,7 +438,8 @@ static void write_boot_label(DOS_FS *fs, char *label)
if (b16->extended_sig != 0x29) { if (b16->extended_sig != 0x29) {
b16->extended_sig = 0x29; b16->extended_sig = 0x29;
b16->serial = 0; 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); memmove(b16->label, label, 11);
} else if (fs->fat_bits == 32) { } else if (fs->fat_bits == 32) {
@ -452,7 +455,7 @@ static void write_boot_label(DOS_FS *fs, char *label)
fs_write(fs->backupboot_start, sizeof(b), &b); fs_write(fs->backupboot_start, sizeof(b), &b);
} }
static loff_t find_volume_de(DOS_FS *fs, DIR_ENT *de) static loff_t find_volume_de(DOS_FS * fs, DIR_ENT * de)
{ {
unsigned long cluster; unsigned long cluster;
loff_t offset; loff_t offset;
@ -482,7 +485,7 @@ static loff_t find_volume_de(DOS_FS *fs, DIR_ENT *de)
return 0; return 0;
} }
static void write_volume_label(DOS_FS *fs, char *label) static void write_volume_label(DOS_FS * fs, char *label)
{ {
time_t now = time(NULL); time_t now = time(NULL);
struct tm *mtime = localtime(&now); struct tm *mtime = localtime(&now);
@ -498,12 +501,12 @@ static void write_volume_label(DOS_FS *fs, char *label)
(mtime->tm_min << 5) + (mtime->tm_min << 5) +
(mtime->tm_hour << 11))); (mtime->tm_hour << 11)));
de.date = CT_LE_W((unsigned short)(mtime->tm_mday + de.date = CT_LE_W((unsigned short)(mtime->tm_mday +
((mtime->tm_mon+1) << 5) + ((mtime->tm_mon + 1) << 5) +
((mtime->tm_year-80) << 9))); ((mtime->tm_year - 80) << 9)));
fs_write(offset, sizeof(DIR_ENT), &de); fs_write(offset, sizeof(DIR_ENT), &de);
} }
void write_label(DOS_FS *fs, char *label) void write_label(DOS_FS * fs, char *label)
{ {
int l = strlen(label); int l = strlen(label);

View File

@ -19,12 +19,11 @@
can be found in /usr/share/common-licenses/GPL-3 file. can be found in /usr/share/common-licenses/GPL-3 file.
*/ */
#ifndef _BOOT_H #ifndef _BOOT_H
#define _BOOT_H #define _BOOT_H
void read_boot(DOS_FS *fs); void read_boot(DOS_FS * fs);
void write_label(DOS_FS *fs, char *label); void write_label(DOS_FS * fs, char *label);
/* Reads the boot sector from the currently open device and initializes *FS */ /* Reads the boot sector from the currently open device and initializes *FS */

File diff suppressed because it is too large Load Diff

View File

@ -19,11 +19,10 @@
can be found in /usr/share/common-licenses/GPL-3 file. can be found in /usr/share/common-licenses/GPL-3 file.
*/ */
#ifndef _CHECK_H #ifndef _CHECK_H
#define _CHECK_H #define _CHECK_H
loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern); loff_t alloc_rootdir_entry(DOS_FS * fs, DIR_ENT * de, const char *pattern);
/* Allocate a free slot in the root directory for a new file. The file name is /* Allocate a free slot in the root directory for a new file. The file name is
constructed after 'pattern', which must include a %d type format for printf constructed after 'pattern', which must include a %d type format for printf
@ -31,7 +30,7 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern);
the 'de' structure, the rest of *de is cleared. The offset returned is to the 'de' structure, the rest of *de is cleared. The offset returned is to
where in the filesystem the entry belongs. */ where in the filesystem the entry belongs. */
int scan_root(DOS_FS *fs); int scan_root(DOS_FS * fs);
/* Scans the root directory and recurses into all subdirectories. See check.c /* Scans the root directory and recurses into all subdirectories. See check.c
for all the details. Returns a non-zero integer if the file system has to for all the details. Returns a non-zero integer if the file system has to

View File

@ -23,7 +23,6 @@
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -32,48 +31,44 @@
#include "common.h" #include "common.h"
typedef struct _link { typedef struct _link {
void *data; void *data;
struct _link *next; struct _link *next;
} LINK; } LINK;
void die(char *msg, ...)
void die(char *msg,...)
{ {
va_list args; va_list args;
va_start(args,msg); va_start(args, msg);
vfprintf(stderr,msg,args); vfprintf(stderr, msg, args);
va_end(args); va_end(args);
fprintf(stderr,"\n"); fprintf(stderr, "\n");
exit(1); exit(1);
} }
void pdie(char *msg, ...)
void pdie(char *msg,...)
{ {
va_list args; va_list args;
va_start(args,msg); va_start(args, msg);
vfprintf(stderr,msg,args); vfprintf(stderr, msg, args);
va_end(args); va_end(args);
fprintf(stderr,":%s\n",strerror(errno)); fprintf(stderr, ":%s\n", strerror(errno));
exit(1); exit(1);
} }
void *alloc(int size) void *alloc(int size)
{ {
void *this; void *this;
if ((this = malloc(size))) return this; if ((this = malloc(size)))
return this;
pdie("malloc"); pdie("malloc");
return NULL; /* for GCC */ return NULL; /* for GCC */
} }
void *qalloc(void **root, int size)
void *qalloc(void **root,int size)
{ {
LINK *link; LINK *link;
@ -83,39 +78,41 @@ void *qalloc(void **root,int size)
return link->data = alloc(size); return link->data = alloc(size);
} }
void qfree(void **root) void qfree(void **root)
{ {
LINK *this; LINK *this;
while (*root) { while (*root) {
this = (LINK *) *root; this = (LINK *) * root;
*root = this->next; *root = this->next;
free(this->data); free(this->data);
free(this); free(this);
} }
} }
int min(int a, int b)
int min(int a,int b)
{ {
return a < b ? a : b; return a < b ? a : b;
} }
char get_key(char *valid, char *prompt)
char get_key(char *valid,char *prompt)
{ {
int ch,okay; int ch, okay;
while (1) { while (1) {
if (prompt) printf("%s ",prompt); if (prompt)
printf("%s ", prompt);
fflush(stdout); fflush(stdout);
while (ch = getchar(), ch == ' ' || ch == '\t'); while (ch = getchar(), ch == ' ' || ch == '\t') ;
if (ch == EOF) exit(1); if (ch == EOF)
if (!strchr(valid,okay = ch)) okay = 0; exit(1);
while (ch = getchar(), ch != '\n' && ch != EOF); if (!strchr(valid, okay = ch))
if (ch == EOF) exit(1); okay = 0;
if (okay) return okay; while (ch = getchar(), ch != '\n' && ch != EOF) ;
if (ch == EOF)
exit(1);
if (okay)
return okay;
printf("Invalid input.\n"); printf("Invalid input.\n");
} }
} }

View File

@ -19,16 +19,16 @@
can be found in /usr/share/common-licenses/GPL-3 file. can be found in /usr/share/common-licenses/GPL-3 file.
*/ */
# include <asm/types.h> #include <asm/types.h>
#ifndef _COMMON_H #ifndef _COMMON_H
#define _COMMON_H #define _COMMON_H
void die(char *msg,...) __attribute((noreturn)); void die(char *msg, ...) __attribute((noreturn));
/* Displays a prinf-style message and terminates the program. */ /* Displays a prinf-style message and terminates the program. */
void pdie(char *msg,...) __attribute((noreturn)); void pdie(char *msg, ...) __attribute((noreturn));
/* Like die, but appends an error message according to the state of errno. */ /* Like die, but appends an error message according to the state of errno. */
@ -37,7 +37,7 @@ void *alloc(int size);
/* mallocs SIZE bytes and returns a pointer to the data. Terminates the program /* mallocs SIZE bytes and returns a pointer to the data. Terminates the program
if malloc fails. */ if malloc fails. */
void *qalloc(void **root,int size); void *qalloc(void **root, int size);
/* Like alloc, but registers the data area in a list described by ROOT. */ /* Like alloc, but registers the data area in a list described by ROOT. */
@ -45,11 +45,11 @@ void qfree(void **root);
/* Deallocates all qalloc'ed data areas described by ROOT. */ /* Deallocates all qalloc'ed data areas described by ROOT. */
int min(int a,int b); int min(int a, int b);
/* Returns the smaller integer value of a and b. */ /* Returns the smaller integer value of a and b. */
char get_key(char *valid,char *prompt); char get_key(char *valid, char *prompt);
/* Displays PROMPT and waits for user input. Only characters in VALID are /* Displays PROMPT and waits for user input. Only characters in VALID are
accepted. Terminates the program on EOF. Returns the character. */ accepted. Terminates the program on EOF. Returns the character. */

View File

@ -23,7 +23,6 @@
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include "version.h" #include "version.h"
#include <stdio.h> #include <stdio.h>
@ -41,69 +40,66 @@
#include "file.h" #include "file.h"
#include "check.h" #include "check.h"
int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0;
int interactive = 0,rw = 0,list = 0,test = 0,verbose = 0,write_immed = 0;
int atari_format = 0; int atari_format = 0;
unsigned n_files = 0; unsigned n_files = 0;
void *mem_queue = NULL; void *mem_queue = NULL;
static void usage(char *name) static void usage(char *name)
{ {
fprintf(stderr,"usage: %s [-aAflrtvVwy] [-d path -d ...] " fprintf(stderr, "usage: %s [-aAflrtvVwy] [-d path -d ...] "
"[-u path -u ...]\n%15sdevice\n",name,""); "[-u path -u ...]\n%15sdevice\n", name, "");
fprintf(stderr," -a automatically repair the file system\n"); fprintf(stderr, " -a automatically repair the file system\n");
fprintf(stderr," -A toggle Atari file system format\n"); fprintf(stderr, " -A toggle Atari file system format\n");
fprintf(stderr," -d path drop that file\n"); fprintf(stderr, " -d path drop that file\n");
fprintf(stderr," -f salvage unused chains to files\n"); fprintf(stderr, " -f salvage unused chains to files\n");
fprintf(stderr," -l list path names\n"); fprintf(stderr, " -l list path names\n");
fprintf(stderr," -n no-op, check non-interactively without changing\n"); fprintf(stderr,
fprintf(stderr," -p same as -a, for compat with other *fsck\n"); " -n no-op, check non-interactively without changing\n");
fprintf(stderr," -r interactively repair the file system\n"); fprintf(stderr, " -p same as -a, for compat with other *fsck\n");
fprintf(stderr," -t test for bad clusters\n"); fprintf(stderr, " -r interactively repair the file system\n");
fprintf(stderr," -u path try to undelete that (non-directory) file\n"); fprintf(stderr, " -t test for bad clusters\n");
fprintf(stderr," -v verbose mode\n"); fprintf(stderr, " -u path try to undelete that (non-directory) file\n");
fprintf(stderr," -V perform a verification pass\n"); fprintf(stderr, " -v verbose mode\n");
fprintf(stderr," -w write changes to disk immediately\n"); fprintf(stderr, " -V perform a verification pass\n");
fprintf(stderr," -y same as -a, for compat with other *fsck\n"); fprintf(stderr, " -w write changes to disk immediately\n");
fprintf(stderr, " -y same as -a, for compat with other *fsck\n");
exit(2); exit(2);
} }
/* /*
* ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
* of MS-DOS filesystem by default. * of MS-DOS filesystem by default.
*/ */
static void check_atari( void ) static void check_atari(void)
{ {
#ifdef __mc68000__ #ifdef __mc68000__
FILE *f; FILE *f;
char line[128], *p; char line[128], *p;
if (!(f = fopen( "/proc/hardware", "r" ))) { if (!(f = fopen("/proc/hardware", "r"))) {
perror( "/proc/hardware" ); perror("/proc/hardware");
return; return;
} }
while( fgets( line, sizeof(line), f ) ) { while (fgets(line, sizeof(line), f)) {
if (strncmp( line, "Model:", 6 ) == 0) { if (strncmp(line, "Model:", 6) == 0) {
p = line + 6; p = line + 6;
p += strspn( p, " \t" ); p += strspn(p, " \t");
if (strncmp( p, "Atari ", 6 ) == 0) if (strncmp(p, "Atari ", 6) == 0)
atari_format = 1; atari_format = 1;
break; break;
} }
} }
fclose( f ); fclose(f);
#endif #endif
} }
int main(int argc, char **argv)
int main(int argc,char **argv)
{ {
DOS_FS fs; DOS_FS fs;
int salvage_files,verify,c; int salvage_files, verify, c;
unsigned n_files_check=0, n_files_verify=0; unsigned n_files_check = 0, n_files_verify = 0;
unsigned long free_clusters; unsigned long free_clusters;
memset(&fs, 0, sizeof(fs)); memset(&fs, 0, sizeof(fs));
@ -111,7 +107,7 @@ int main(int argc,char **argv)
interactive = 1; interactive = 1;
check_atari(); check_atari();
while ((c = getopt(argc,argv,"Aad:flnprtu:vVwy")) != EOF) while ((c = getopt(argc, argv, "Aad:flnprtu:vVwy")) != EOF)
switch (c) { switch (c) {
case 'A': /* toggle Atari format */ case 'A': /* toggle Atari format */
atari_format = !atari_format; atari_format = !atari_format;
@ -124,7 +120,7 @@ int main(int argc,char **argv)
salvage_files = 1; salvage_files = 1;
break; break;
case 'd': case 'd':
file_add(optarg,fdt_drop); file_add(optarg, fdt_drop);
break; break;
case 'f': case 'f':
salvage_files = 1; salvage_files = 1;
@ -144,7 +140,7 @@ int main(int argc,char **argv)
test = 1; test = 1;
break; break;
case 'u': case 'u':
file_add(optarg,fdt_undelete); file_add(optarg, fdt_undelete);
break; break;
case 'v': case 'v':
verbose = 1; verbose = 1;
@ -160,19 +156,25 @@ int main(int argc,char **argv)
usage(argv[0]); usage(argv[0]);
} }
if ((test || write_immed) && !rw) { if ((test || write_immed) && !rw) {
fprintf(stderr,"-t and -w require -a or -r\n"); fprintf(stderr, "-t and -w require -a or -r\n");
exit(2); exit(2);
} }
if (optind != argc-1) usage(argv[0]); if (optind != argc - 1)
usage(argv[0]);
printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" ); printf("dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n");
fs_open(argv[optind],rw); fs_open(argv[optind], rw);
read_boot(&fs); read_boot(&fs);
if (verify) printf("Starting check/repair pass.\n"); if (verify)
while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); printf("Starting check/repair pass.\n");
if (test) fix_bad(&fs); while (read_fat(&fs), scan_root(&fs))
if (salvage_files) reclaim_file(&fs); qfree(&mem_queue);
else reclaim_free(&fs); if (test)
fix_bad(&fs);
if (salvage_files)
reclaim_file(&fs);
else
reclaim_free(&fs);
free_clusters = update_free(&fs); free_clusters = update_free(&fs);
file_unused(); file_unused();
qfree(&mem_queue); qfree(&mem_queue);
@ -190,15 +192,15 @@ int main(int argc,char **argv)
if (fs_changed()) { if (fs_changed()) {
if (rw) { if (rw) {
if (interactive) if (interactive)
rw = get_key("yn","Perform changes ? (y/n)") == 'y'; rw = get_key("yn", "Perform changes ? (y/n)") == 'y';
else printf("Performing changes.\n");
}
else else
printf("Performing changes.\n");
} else
printf("Leaving file system unchanged.\n"); printf("Leaving file system unchanged.\n");
} }
printf( "%s: %u files, %lu/%lu clusters\n", argv[optind], printf("%s: %u files, %lu/%lu clusters\n", argv[optind],
n_files, fs.clusters - free_clusters, fs.clusters ); n_files, fs.clusters - free_clusters, fs.clusters);
return fs_close(rw) ? 1 : 0; return fs_close(rw) ? 1 : 0;
} }

View File

@ -23,17 +23,16 @@
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#ifndef _DOSFSCK_H #ifndef _DOSFSCK_H
#define _DOSFSCK_H #define _DOSFSCK_H
#include <sys/types.h> #include <sys/types.h>
#define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */ #define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */
#define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h>*/ #define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h> */
#define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */ #define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
# include <asm/types.h> #include <asm/types.h>
# include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/msdos_fs.h> #include <linux/msdos_fs.h>
@ -139,7 +138,7 @@ struct info_sector {
}; };
typedef struct { typedef struct {
__u8 name[8],ext[3]; /* name and extension */ __u8 name[8], ext[3]; /* name and extension */
__u8 attr; /* attribute bits */ __u8 attr; /* attribute bits */
__u8 lcase; /* Case for base and extension */ __u8 lcase; /* Case for base and extension */
__u8 ctime_ms; /* Creation time, milliseconds */ __u8 ctime_ms; /* Creation time, milliseconds */
@ -147,7 +146,7 @@ typedef struct {
__u16 cdate; /* Creation date */ __u16 cdate; /* Creation date */
__u16 adate; /* Last access date */ __u16 adate; /* Last access date */
__u16 starthi; /* High 16 bits of cluster in FAT32 */ __u16 starthi; /* High 16 bits of cluster in FAT32 */
__u16 time,date,start;/* time, date and first cluster */ __u16 time, date, start; /* time, date and first cluster */
__u32 size; /* file size (in bytes) */ __u32 size; /* file size (in bytes) */
} __attribute__ ((packed)) DIR_ENT; } __attribute__ ((packed)) DIR_ENT;
@ -190,7 +189,7 @@ typedef struct {
#define offsetof(t,e) ((int)&(((t *)0)->e)) #define offsetof(t,e) ((int)&(((t *)0)->e))
#endif #endif
extern int interactive,rw,list,verbose,test,write_immed; extern int interactive, rw, list, verbose, test, write_immed;
extern int atari_format; extern int atari_format;
extern unsigned n_files; extern unsigned n_files;
extern void *mem_queue; extern void *mem_queue;

View File

@ -38,19 +38,17 @@
#include "file.h" #include "file.h"
#include "check.h" #include "check.h"
int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0;
int interactive = 0,rw = 0,list = 0,test = 0,verbose = 0,write_immed = 0;
int atari_format = 0; int atari_format = 0;
unsigned n_files = 0; unsigned n_files = 0;
void *mem_queue = NULL; void *mem_queue = NULL;
static void usage(int error) static void usage(int error)
{ {
FILE *f = error ? stderr : stdout; FILE *f = error ? stderr : stdout;
int status = error ? 1 : 0; int status = error ? 1 : 0;
fprintf(f,"usage: dosfslabel device [label]\n"); fprintf(f, "usage: dosfslabel device [label]\n");
exit(status); exit(status);
} }
@ -58,31 +56,30 @@ static void usage(int error)
* ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant
* of MS-DOS filesystem by default. * of MS-DOS filesystem by default.
*/ */
static void check_atari( void ) static void check_atari(void)
{ {
#ifdef __mc68000__ #ifdef __mc68000__
FILE *f; FILE *f;
char line[128], *p; char line[128], *p;
if (!(f = fopen( "/proc/hardware", "r" ))) { if (!(f = fopen("/proc/hardware", "r"))) {
perror( "/proc/hardware" ); perror("/proc/hardware");
return; return;
} }
while( fgets( line, sizeof(line), f ) ) { while (fgets(line, sizeof(line), f)) {
if (strncmp( line, "Model:", 6 ) == 0) { if (strncmp(line, "Model:", 6) == 0) {
p = line + 6; p = line + 6;
p += strspn( p, " \t" ); p += strspn(p, " \t");
if (strncmp( p, "Atari ", 6 ) == 0) if (strncmp(p, "Atari ", 6) == 0)
atari_format = 1; atari_format = 1;
break; break;
} }
} }
fclose( f ); fclose(f);
#endif #endif
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
DOS_FS fs; DOS_FS fs;
@ -99,7 +96,7 @@ int main(int argc, char *argv[])
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
usage(0); usage(0);
else if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { else if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
printf( "dosfslabel " VERSION ", " VERSION_DATE ", FAT32, LFN\n" ); printf("dosfslabel " VERSION ", " VERSION_DATE ", FAT32, LFN\n");
exit(0); exit(0);
} }

231
src/fat.c
View File

@ -23,7 +23,6 @@
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -35,7 +34,6 @@
#include "check.h" #include "check.h"
#include "fat.h" #include "fat.h"
/** /**
* Fetch the FAT entry for a specified cluster. * Fetch the FAT entry for a specified cluster.
* *
@ -44,34 +42,33 @@
* @param[in] cluster Cluster of interest * @param[in] cluster Cluster of interest
* @param[in] fs Information from the FAT boot sectors (bits per FAT entry) * @param[in] fs Information from the FAT boot sectors (bits per FAT entry)
*/ */
void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs) void get_fat(FAT_ENTRY * entry, void *fat, unsigned long cluster, DOS_FS * fs)
{ {
unsigned char *ptr; unsigned char *ptr;
switch(fs->fat_bits) { switch (fs->fat_bits) {
case 12: case 12:
ptr = &((unsigned char *) fat)[cluster*3/2]; ptr = &((unsigned char *)fat)[cluster * 3 / 2];
entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) : entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) :
(ptr[0] | ptr[1] << 8)); (ptr[0] | ptr[1] << 8));
break; break;
case 16: case 16:
entry->value = CF_LE_W(((unsigned short *) fat)[cluster]); entry->value = CF_LE_W(((unsigned short *)fat)[cluster]);
break; break;
case 32: case 32:
/* According to M$, the high 4 bits of a FAT32 entry are reserved and /* According to M$, the high 4 bits of a FAT32 entry are reserved and
* are not part of the cluster number. So we cut them off. */ * are not part of the cluster number. So we cut them off. */
{ {
unsigned long e = CF_LE_L(((unsigned int *) fat)[cluster]); unsigned long e = CF_LE_L(((unsigned int *)fat)[cluster]);
entry->value = e & 0xfffffff; entry->value = e & 0xfffffff;
entry->reserved = e >> 28; entry->reserved = e >> 28;
} }
break; break;
default: default:
die("Bad FAT entry size: %d bits.",fs->fat_bits); die("Bad FAT entry size: %d bits.", fs->fat_bits);
} }
} }
/** /**
* Build a bookkeeping structure from the partition's FAT table. * 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, * If the partition has multiple FATs and they don't agree, try to pick a winner,
@ -80,12 +77,12 @@ void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs)
* *
* @param[inout] fs Information about the filesystem * @param[inout] fs Information about the filesystem
*/ */
void read_fat(DOS_FS *fs) void read_fat(DOS_FS * fs)
{ {
int eff_size; int eff_size;
unsigned long i; unsigned long i;
void *first,*second = NULL; void *first, *second = NULL;
int first_ok,second_ok; int first_ok, second_ok;
unsigned long total_num_clusters; unsigned long total_num_clusters;
/* Clean up from previous pass */ /* Clean up from previous pass */
@ -95,43 +92,42 @@ void read_fat(DOS_FS *fs)
fs->cluster_owner = NULL; fs->cluster_owner = NULL;
total_num_clusters = fs->clusters + 2UL; total_num_clusters = fs->clusters + 2UL;
eff_size = (total_num_clusters*fs->fat_bits+7)/8ULL; eff_size = (total_num_clusters * fs->fat_bits + 7) / 8ULL;
first = alloc(eff_size); first = alloc(eff_size);
fs_read(fs->fat_start,eff_size,first); fs_read(fs->fat_start, eff_size, first);
if (fs->nfats > 1) { if (fs->nfats > 1) {
second = alloc(eff_size); second = alloc(eff_size);
fs_read(fs->fat_start+fs->fat_size,eff_size,second); fs_read(fs->fat_start + fs->fat_size, eff_size, second);
} }
if (second && memcmp(first,second,eff_size) != 0) { if (second && memcmp(first, second, eff_size) != 0) {
FAT_ENTRY first_media, second_media; FAT_ENTRY first_media, second_media;
get_fat(&first_media,first,0,fs); get_fat(&first_media, first, 0, fs);
get_fat(&second_media,second,0,fs); get_fat(&second_media, second, 0, fs);
first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs);
if (first_ok && !second_ok) { if (first_ok && !second_ok) {
printf("FATs differ - using first FAT.\n"); printf("FATs differ - using first FAT.\n");
fs_write(fs->fat_start+fs->fat_size,eff_size,first); fs_write(fs->fat_start + fs->fat_size, eff_size, first);
} }
if (!first_ok && second_ok) { if (!first_ok && second_ok) {
printf("FATs differ - using second FAT.\n"); printf("FATs differ - using second FAT.\n");
fs_write(fs->fat_start,eff_size,second); fs_write(fs->fat_start, eff_size, second);
memcpy(first,second,eff_size); memcpy(first, second, eff_size);
} }
if (first_ok && second_ok) { if (first_ok && second_ok) {
if (interactive) { if (interactive) {
printf("FATs differ but appear to be intact. Use which FAT ?\n" printf("FATs differ but appear to be intact. Use which FAT ?\n"
"1) Use first FAT\n2) Use second FAT\n"); "1) Use first FAT\n2) Use second FAT\n");
if (get_key("12","?") == '1') { if (get_key("12", "?") == '1') {
fs_write(fs->fat_start+fs->fat_size,eff_size,first); fs_write(fs->fat_start + fs->fat_size, eff_size, first);
} else { } else {
fs_write(fs->fat_start,eff_size,second); fs_write(fs->fat_start, eff_size, second);
memcpy(first,second,eff_size); memcpy(first, second, eff_size);
} }
} } else {
else {
printf("FATs differ but appear to be intact. Using first " printf("FATs differ but appear to be intact. Using first "
"FAT.\n"); "FAT.\n");
fs_write(fs->fat_start+fs->fat_size,eff_size,first); fs_write(fs->fat_start + fs->fat_size, eff_size, first);
} }
} }
if (!first_ok && !second_ok) { if (!first_ok && !second_ok) {
@ -142,30 +138,28 @@ void read_fat(DOS_FS *fs)
if (second) { if (second) {
free(second); free(second);
} }
fs->fat = (unsigned char*) first; fs->fat = (unsigned char *)first;
fs->cluster_owner = alloc(total_num_clusters * sizeof(DOS_FILE *)); fs->cluster_owner = alloc(total_num_clusters * sizeof(DOS_FILE *));
memset(fs->cluster_owner, 0, (total_num_clusters * sizeof(DOS_FILE *))); memset(fs->cluster_owner, 0, (total_num_clusters * sizeof(DOS_FILE *)));
/* Truncate any cluster chains that link to something out of range */ /* Truncate any cluster chains that link to something out of range */
for (i = 2; i < fs->clusters+2; i++) { for (i = 2; i < fs->clusters + 2; i++) {
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs); get_fat(&curEntry, fs->fat, i, fs);
if (curEntry.value == 1) { if (curEntry.value == 1) {
printf("Cluster %ld out of range (1). Setting to EOF.\n", printf("Cluster %ld out of range (1). Setting to EOF.\n", i - 2);
i-2);
set_fat(fs, i, -1); set_fat(fs, i, -1);
} }
if (curEntry.value >= fs->clusters+2 && if (curEntry.value >= fs->clusters + 2 &&
(curEntry.value < FAT_MIN_BAD(fs))) { (curEntry.value < FAT_MIN_BAD(fs))) {
printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n", printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n",
i-2, curEntry.value, fs->clusters+2-1); i - 2, curEntry.value, fs->clusters + 2 - 1);
set_fat(fs,i,-1); set_fat(fs, i, -1);
} }
} }
} }
/** /**
* Update the FAT entry for a specified cluster * Update the FAT entry for a specified cluster
* (i.e., change the cluster it links to). * (i.e., change the cluster it links to).
@ -179,7 +173,7 @@ void read_fat(DOS_FS *fs)
* -1 == end-of-chain * -1 == end-of-chain
* -2 == bad cluster * -2 == bad cluster
*/ */
void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new) void set_fat(DOS_FS * fs, unsigned long cluster, unsigned long new)
{ {
unsigned char *data = NULL; unsigned char *data = NULL;
int size; int size;
@ -189,29 +183,28 @@ void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new)
new = FAT_EOF(fs); new = FAT_EOF(fs);
else if ((long)new == -2) else if ((long)new == -2)
new = FAT_BAD(fs); new = FAT_BAD(fs);
switch( fs->fat_bits ) { switch (fs->fat_bits) {
case 12: case 12:
data = fs->fat + cluster*3/2; data = fs->fat + cluster * 3 / 2;
offs = fs->fat_start+cluster*3/2; offs = fs->fat_start + cluster * 3 / 2;
if (cluster & 1) { if (cluster & 1) {
FAT_ENTRY prevEntry; FAT_ENTRY prevEntry;
get_fat(&prevEntry, fs->fat, cluster-1, fs); get_fat(&prevEntry, fs->fat, cluster - 1, fs);
data[0] = ((new & 0xf) << 4) | (prevEntry.value >> 8); data[0] = ((new & 0xf) << 4) | (prevEntry.value >> 8);
data[1] = new >> 4; data[1] = new >> 4;
} } else {
else {
FAT_ENTRY subseqEntry; FAT_ENTRY subseqEntry;
get_fat(&subseqEntry, fs->fat, cluster+1, fs); get_fat(&subseqEntry, fs->fat, cluster + 1, fs);
data[0] = new & 0xff; data[0] = new & 0xff;
data[1] = (new >> 8) | (cluster == fs->clusters-1 ? 0 : data[1] = (new >> 8) | (cluster == fs->clusters - 1 ? 0 :
(0xff & subseqEntry.value) << 4); (0xff & subseqEntry.value) << 4);
} }
size = 2; size = 2;
break; break;
case 16: case 16:
data = fs->fat + cluster*2; data = fs->fat + cluster * 2;
offs = fs->fat_start+cluster*2; offs = fs->fat_start + cluster * 2;
*(unsigned short *) data = CT_LE_W(new); *(unsigned short *)data = CT_LE_W(new);
size = 2; size = 2;
break; break;
case 32: case 32:
@ -219,26 +212,25 @@ void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new)
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, cluster, fs); get_fat(&curEntry, fs->fat, cluster, fs);
data = fs->fat + cluster*4; data = fs->fat + cluster * 4;
offs = fs->fat_start+cluster*4; offs = fs->fat_start + cluster * 4;
/* According to M$, the high 4 bits of a FAT32 entry are reserved and /* According to M$, the high 4 bits of a FAT32 entry are reserved and
* are not part of the cluster number. So we never touch them. */ * are not part of the cluster number. So we never touch them. */
*(unsigned long *) data = CT_LE_L( (new & 0xfffffff) | *(unsigned long *)data = CT_LE_L((new & 0xfffffff) |
(curEntry.reserved << 28) ); (curEntry.reserved << 28));
size = 4; size = 4;
} }
break; break;
default: default:
die("Bad FAT entry size: %d bits.",fs->fat_bits); die("Bad FAT entry size: %d bits.", fs->fat_bits);
} }
fs_write(offs,size,data); fs_write(offs, size, data);
if (fs->nfats > 1) { if (fs->nfats > 1) {
fs_write(offs+fs->fat_size,size,data); fs_write(offs + fs->fat_size, size, data);
} }
} }
int bad_cluster(DOS_FS * fs, unsigned long cluster)
int bad_cluster(DOS_FS *fs,unsigned long cluster)
{ {
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, cluster, fs); get_fat(&curEntry, fs->fat, cluster, fs);
@ -246,7 +238,6 @@ int bad_cluster(DOS_FS *fs,unsigned long cluster)
return FAT_IS_BAD(fs, curEntry.value); return FAT_IS_BAD(fs, curEntry.value);
} }
/** /**
* Get the cluster to which the specified cluster is linked. * Get the cluster to which the specified cluster is linked.
* If the linked cluster is marked bad, abort. * If the linked cluster is marked bad, abort.
@ -257,7 +248,7 @@ int bad_cluster(DOS_FS *fs,unsigned long cluster)
* @return -1 'cluster' is at the end of the chain * @return -1 'cluster' is at the end of the chain
* @return Other values Next cluster in this chain * @return Other values Next cluster in this chain
*/ */
unsigned long next_cluster(DOS_FS *fs,unsigned long cluster) unsigned long next_cluster(DOS_FS * fs, unsigned long cluster)
{ {
unsigned long value; unsigned long value;
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
@ -265,18 +256,17 @@ unsigned long next_cluster(DOS_FS *fs,unsigned long cluster)
get_fat(&curEntry, fs->fat, cluster, fs); get_fat(&curEntry, fs->fat, cluster, fs);
value = curEntry.value; value = curEntry.value;
if (FAT_IS_BAD(fs,value)) if (FAT_IS_BAD(fs, value))
die("Internal error: next_cluster on bad cluster"); die("Internal error: next_cluster on bad cluster");
return FAT_IS_EOF(fs,value) ? -1 : value; return FAT_IS_EOF(fs, value) ? -1 : value;
} }
loff_t cluster_start(DOS_FS * fs, unsigned long cluster)
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 * Update internal bookkeeping to show that the specified cluster belongs
* to the specified dentry. * to the specified dentry.
@ -286,18 +276,18 @@ loff_t cluster_start(DOS_FS *fs,unsigned long cluster)
* @param[in] owner Information on dentry that owns this cluster * @param[in] owner Information on dentry that owns this cluster
* (may be NULL) * (may be NULL)
*/ */
void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner) void set_owner(DOS_FS * fs, unsigned long cluster, DOS_FILE * owner)
{ {
if (fs->cluster_owner == NULL) if (fs->cluster_owner == NULL)
die("Internal error: attempt to set owner in non-existent table"); 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"); die("Internal error: attempt to change file owner");
fs->cluster_owner[cluster] = owner; fs->cluster_owner[cluster] = owner;
} }
DOS_FILE *get_owner(DOS_FS * fs, unsigned long cluster)
DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster)
{ {
if (fs->cluster_owner == NULL) if (fs->cluster_owner == NULL)
return NULL; return NULL;
@ -305,27 +295,25 @@ DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster)
return fs->cluster_owner[cluster]; return fs->cluster_owner[cluster];
} }
void fix_bad(DOS_FS * fs)
void fix_bad(DOS_FS *fs)
{ {
unsigned long i; unsigned long i;
if (verbose) if (verbose)
printf("Checking for bad clusters.\n"); printf("Checking for bad clusters.\n");
for (i = 2; i < fs->clusters+2; i++) { for (i = 2; i < fs->clusters + 2; i++) {
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs); get_fat(&curEntry, fs->fat, i, fs);
if (!get_owner(fs,i) && !FAT_IS_BAD(fs, curEntry.value)) if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
if (!fs_test(cluster_start(fs,i),fs->cluster_size)) { if (!fs_test(cluster_start(fs, i), fs->cluster_size)) {
printf("Cluster %lu is unreadable.\n",i); printf("Cluster %lu is unreadable.\n", i);
set_fat(fs,i,-2); set_fat(fs, i, -2);
} }
} }
} }
void reclaim_free(DOS_FS * fs)
void reclaim_free(DOS_FS *fs)
{ {
int reclaimed; int reclaimed;
unsigned long i; unsigned long i;
@ -333,22 +321,22 @@ void reclaim_free(DOS_FS *fs)
if (verbose) if (verbose)
printf("Checking for unused clusters.\n"); printf("Checking for unused clusters.\n");
reclaimed = 0; reclaimed = 0;
for (i = 2; i < fs->clusters+2; i++) { for (i = 2; i < fs->clusters + 2; i++) {
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs); get_fat(&curEntry, fs->fat, i, fs);
if (!get_owner(fs,i) && curEntry.value && if (!get_owner(fs, i) && curEntry.value &&
!FAT_IS_BAD(fs, curEntry.value)) { !FAT_IS_BAD(fs, curEntry.value)) {
set_fat(fs,i,0); set_fat(fs, i, 0);
reclaimed++; reclaimed++;
} }
} }
if (reclaimed) if (reclaimed)
printf("Reclaimed %d unused cluster%s (%llu bytes).\n",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). * Assign the specified owner to all orphan chains (except cycles).
* Break cross-links between orphan chains. * Break cross-links between orphan chains.
@ -359,16 +347,16 @@ void reclaim_free(DOS_FS *fs)
* clusters link to it. * clusters link to it.
* @param[in] start_cluster Where to start scanning for orphans * @param[in] start_cluster Where to start scanning for orphans
*/ */
static void tag_free(DOS_FS *fs, DOS_FILE *owner, unsigned long *num_refs, static void tag_free(DOS_FS * fs, DOS_FILE * owner, unsigned long *num_refs,
unsigned long start_cluster) unsigned long start_cluster)
{ {
int prev; int prev;
unsigned long i,walk; unsigned long i, walk;
if (start_cluster == 0) if (start_cluster == 0)
start_cluster = 2; start_cluster = 2;
for (i = start_cluster; i < fs->clusters+2; i++) { for (i = start_cluster; i < fs->clusters + 2; i++) {
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs); get_fat(&curEntry, fs->fat, i, fs);
@ -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]) { !get_owner(fs, i) && !num_refs[i]) {
prev = 0; prev = 0;
/* Walk the chain, claiming ownership as we go */ /* Walk the chain, claiming ownership as we go */
for (walk = i; walk != -1; for (walk = i; walk != -1; walk = next_cluster(fs, walk)) {
walk = next_cluster(fs,walk)) {
if (!get_owner(fs, walk)) { if (!get_owner(fs, walk)) {
set_owner(fs, walk, owner); set_owner(fs, walk, owner);
} else { } else {
@ -386,7 +373,7 @@ static void tag_free(DOS_FS *fs, DOS_FILE *owner, unsigned long *num_refs,
* or a cycle with a tail. * or a cycle with a tail.
* Terminate this orphan chain (break the link) * Terminate this orphan chain (break the link)
*/ */
set_fat(fs,prev,-1); set_fat(fs, prev, -1);
/* This is not necessary because 'walk' is owned and thus /* This is not necessary because 'walk' is owned and thus
* will never become the head of a chain (the only case * will never become the head of a chain (the only case
@ -408,12 +395,12 @@ static void tag_free(DOS_FS *fs, DOS_FILE *owner, unsigned long *num_refs,
* *
* @param[in,out] fs Information about the filesystem * @param[in,out] fs Information about the filesystem
*/ */
void reclaim_file(DOS_FS *fs) void reclaim_file(DOS_FS * fs)
{ {
DOS_FILE orphan; DOS_FILE orphan;
int reclaimed,files; int reclaimed, files;
int changed = 0; int changed = 0;
unsigned long i,next,walk; unsigned long i, next, walk;
unsigned long *num_refs = NULL; /* Only for orphaned clusters */ unsigned long *num_refs = NULL; /* Only for orphaned clusters */
unsigned long total_num_clusters; unsigned long total_num_clusters;
@ -433,7 +420,7 @@ void reclaim_file(DOS_FS *fs)
get_fat(&curEntry, fs->fat, i, fs); get_fat(&curEntry, fs->fat, i, fs);
next = curEntry.value; next = curEntry.value;
if (!get_owner(fs,i) && next && next < fs->clusters+2) { if (!get_owner(fs, i) && next && next < fs->clusters + 2) {
/* Cluster is linked, but not owned (orphan) */ /* Cluster is linked, but not owned (orphan) */
FAT_ENTRY nextEntry; FAT_ENTRY nextEntry;
get_fat(&nextEntry, fs->fat, next, fs); get_fat(&nextEntry, fs->fat, next, fs);
@ -441,8 +428,9 @@ void reclaim_file(DOS_FS *fs)
/* Mark it end-of-chain if it links into an owned cluster, /* Mark it end-of-chain if it links into an owned cluster,
* a free cluster, or a bad cluster. * a free cluster, or a bad cluster.
*/ */
if (get_owner(fs,next) || !nextEntry.value || 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 else
num_refs[next]++; num_refs[next]++;
} }
@ -464,9 +452,9 @@ void reclaim_file(DOS_FS *fs)
!get_owner(fs, i)) { !get_owner(fs, i)) {
if (!num_refs[curEntry.value]--) if (!num_refs[curEntry.value]--)
die("Internal error: num_refs going below zero"); die("Internal error: num_refs going below zero");
set_fat(fs,i,-1); set_fat(fs, i, -1);
changed = curEntry.value; changed = curEntry.value;
printf("Broke cycle at cluster %lu in free chain.\n",i); printf("Broke cycle at cluster %lu in free chain.\n", i);
/* If we've created a new chain head, /* If we've created a new chain head,
* tag_free() can claim it * tag_free() can claim it
@ -486,37 +474,37 @@ void reclaim_file(DOS_FS *fs)
DIR_ENT de; DIR_ENT de;
loff_t offset; loff_t offset;
files++; files++;
offset = alloc_rootdir_entry(fs,&de,"FSCK%04dREC"); offset = alloc_rootdir_entry(fs, &de, "FSCK%04dREC");
de.start = CT_LE_W(i&0xffff); de.start = CT_LE_W(i & 0xffff);
if (fs->fat_bits == 32) if (fs->fat_bits == 32)
de.starthi = CT_LE_W(i>>16); de.starthi = CT_LE_W(i >> 16);
for (walk = i; walk > 0 && walk != -1; for (walk = i; walk > 0 && walk != -1;
walk = next_cluster(fs,walk)) { walk = next_cluster(fs, walk)) {
de.size = CT_LE_L(CF_LE_L(de.size)+fs->cluster_size); de.size = CT_LE_L(CF_LE_L(de.size) + fs->cluster_size);
reclaimed++; reclaimed++;
} }
fs_write(offset,sizeof(DIR_ENT),&de); fs_write(offset, sizeof(DIR_ENT), &de);
} }
if (reclaimed) if (reclaimed)
printf("Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n", 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"); files == 1 ? "" : "s");
free(num_refs); free(num_refs);
} }
unsigned long update_free(DOS_FS * fs)
unsigned long update_free(DOS_FS *fs)
{ {
unsigned long i; unsigned long i;
unsigned long free = 0; unsigned long free = 0;
int do_set = 0; int do_set = 0;
for (i = 2; i < fs->clusters+2; i++) { for (i = 2; i < fs->clusters + 2; i++) {
FAT_ENTRY curEntry; FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs); get_fat(&curEntry, fs->fat, i, fs);
if (!get_owner(fs,i) && !FAT_IS_BAD(fs, curEntry.value)) if (!get_owner(fs, i) && !FAT_IS_BAD(fs, curEntry.value))
++free; ++free;
} }
@ -527,22 +515,23 @@ unsigned long update_free(DOS_FS *fs)
printf("Checking free cluster summary.\n"); printf("Checking free cluster summary.\n");
if (fs->free_clusters != 0xFFFFFFFF) { if (fs->free_clusters != 0xFFFFFFFF) {
if (free != fs->free_clusters) { if (free != fs->free_clusters) {
printf( "Free cluster summary wrong (%ld vs. really %ld)\n", printf("Free cluster summary wrong (%ld vs. really %ld)\n",
fs->free_clusters,free); fs->free_clusters, free);
if (interactive) if (interactive)
printf( "1) Correct\n2) Don't correct\n" ); printf("1) Correct\n2) Don't correct\n");
else printf( " Auto-correcting.\n" ); else
if (!interactive || get_key("12","?") == '1') printf(" Auto-correcting.\n");
if (!interactive || get_key("12", "?") == '1')
do_set = 1; do_set = 1;
} }
} } else {
else { printf("Free cluster summary uninitialized (should be %ld)\n", free);
printf( "Free cluster summary uninitialized (should be %ld)\n", free );
if (rw) { if (rw) {
if (interactive) if (interactive)
printf( "1) Set it\n2) Leave it uninitialized\n" ); printf("1) Set it\n2) Leave it uninitialized\n");
else printf( " Auto-setting.\n" ); else
if (!interactive || get_key("12","?") == '1') printf(" Auto-setting.\n");
if (!interactive || get_key("12", "?") == '1')
do_set = 1; do_set = 1;
} }
} }
@ -550,7 +539,7 @@ unsigned long update_free(DOS_FS *fs)
if (do_set) { if (do_set) {
unsigned long le_free = CT_LE_L(free); unsigned long le_free = CT_LE_L(free);
fs->free_clusters = free; fs->free_clusters = free;
fs_write(fs->fsinfo_start+offsetof(struct info_sector,free_clusters), fs_write(fs->fsinfo_start + offsetof(struct info_sector, free_clusters),
sizeof(le_free), &le_free); sizeof(le_free), &le_free);
} }

View File

@ -19,66 +19,65 @@
can be found in /usr/share/common-licenses/GPL-3 file. can be found in /usr/share/common-licenses/GPL-3 file.
*/ */
#ifndef _FAT_H #ifndef _FAT_H
#define _FAT_H #define _FAT_H
void read_fat(DOS_FS *fs); void read_fat(DOS_FS * fs);
/* Loads the FAT of the file system described by FS. Initializes the FAT, /* Loads the FAT of the file system described by FS. Initializes the FAT,
replaces broken FATs and rejects invalid cluster entries. */ replaces broken FATs and rejects invalid cluster entries. */
void get_fat(FAT_ENTRY *entry, void *fat, unsigned long cluster, DOS_FS *fs); void get_fat(FAT_ENTRY * entry, void *fat, unsigned long cluster, DOS_FS * fs);
/* Retrieve the FAT entry (next chained cluster) for CLUSTER. */ /* Retrieve the FAT entry (next chained cluster) for CLUSTER. */
void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new); void set_fat(DOS_FS * fs, unsigned long cluster, unsigned long new);
/* Changes the value of the CLUSTERth cluster of the FAT of FS to NEW. Special /* Changes the value of the CLUSTERth cluster of the FAT of FS to NEW. Special
values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or
0xfff7) */ 0xfff7) */
int bad_cluster(DOS_FS *fs,unsigned long cluster); int bad_cluster(DOS_FS * fs, unsigned long cluster);
/* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero /* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero
otherwise. */ otherwise. */
unsigned long next_cluster(DOS_FS *fs,unsigned long cluster); unsigned long next_cluster(DOS_FS * fs, unsigned long cluster);
/* Returns the number of the cluster following CLUSTER, or -1 if this is the /* Returns the number of the cluster following CLUSTER, or -1 if this is the
last cluster of the respective cluster chain. CLUSTER must not be a bad last cluster of the respective cluster chain. CLUSTER must not be a bad
cluster. */ cluster. */
loff_t cluster_start(DOS_FS *fs,unsigned long cluster); loff_t cluster_start(DOS_FS * fs, unsigned long cluster);
/* Returns the byte offset of CLUSTER, relative to the respective device. */ /* Returns the byte offset of CLUSTER, relative to the respective device. */
void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner); void set_owner(DOS_FS * fs, unsigned long cluster, DOS_FILE * owner);
/* Sets the owner pointer of the respective cluster to OWNER. If OWNER was NULL /* Sets the owner pointer of the respective cluster to OWNER. If OWNER was NULL
before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is
accepted as the new value. */ accepted as the new value. */
DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster); DOS_FILE *get_owner(DOS_FS * fs, unsigned long cluster);
/* Returns the owner of the repective cluster or NULL if the cluster has no /* Returns the owner of the repective cluster or NULL if the cluster has no
owner. */ owner. */
void fix_bad(DOS_FS *fs); void fix_bad(DOS_FS * fs);
/* Scans the disk for currently unused bad clusters and marks them as bad. */ /* Scans the disk for currently unused bad clusters and marks them as bad. */
void reclaim_free(DOS_FS *fs); void reclaim_free(DOS_FS * fs);
/* Marks all allocated, but unused clusters as free. */ /* Marks all allocated, but unused clusters as free. */
void reclaim_file(DOS_FS *fs); void reclaim_file(DOS_FS * fs);
/* Scans the FAT for chains of allocated, but unused clusters and creates files /* Scans the FAT for chains of allocated, but unused clusters and creates files
for them in the root directory. Also tries to fix all inconsistencies (e.g. for them in the root directory. Also tries to fix all inconsistencies (e.g.
loops, shared clusters, etc.) in the process. */ loops, shared clusters, etc.) in the process. */
unsigned long update_free(DOS_FS *fs); unsigned long update_free(DOS_FS * fs);
/* Updates free cluster count in FSINFO sector. */ /* Updates free cluster count in FSINFO sector. */

View File

@ -23,7 +23,6 @@
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -31,32 +30,30 @@
#include <unistd.h> #include <unistd.h>
#define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */ #define _LINUX_STAT_H /* hack to avoid inclusion of <linux/stat.h> */
#define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h>*/ #define _LINUX_STRING_H_ /* hack to avoid inclusion of <linux/string.h> */
#define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */ #define _LINUX_FS_H /* hack to avoid inclusion of <linux/fs.h> */
# include <asm/types.h> #include <asm/types.h>
#include <linux/msdos_fs.h> #include <linux/msdos_fs.h>
#include "common.h" #include "common.h"
#include "file.h" #include "file.h"
FDSC *fp_root = NULL; FDSC *fp_root = NULL;
static void put_char(char **p, unsigned char c)
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 { else {
*(*p)++ = '\\'; *(*p)++ = '\\';
*(*p)++ = '0'+(c >> 6); *(*p)++ = '0' + (c >> 6);
*(*p)++ = '0'+((c >> 3) & 7); *(*p)++ = '0' + ((c >> 3) & 7);
*(*p)++ = '0'+(c & 7); *(*p)++ = '0' + (c & 7);
} }
} }
/** /**
* Construct the "pretty-printed" representation of the name in a short directory entry. * Construct the "pretty-printed" representation of the name in a short directory entry.
* *
@ -67,39 +64,40 @@ static void put_char(char **p,unsigned char c)
*/ */
char *file_name(unsigned char *fixed) char *file_name(unsigned char *fixed)
{ {
static char path[MSDOS_NAME*4+2]; static char path[MSDOS_NAME * 4 + 2];
char *p; char *p;
int i,j; int i, j;
p = path; p = path;
for (i = j = 0; i < 8; i++) for (i = j = 0; i < 8; i++)
if (fixed[i] != ' ') { if (fixed[i] != ' ') {
while (j++ < i) *p++ = ' '; while (j++ < i)
put_char(&p,fixed[i]); *p++ = ' ';
put_char(&p, fixed[i]);
} }
if (strncmp(fixed+8," ",3)) { if (strncmp(fixed + 8, " ", 3)) {
*p++ = '.'; *p++ = '.';
for (i = j = 0; i < 3; i++) for (i = j = 0; i < 3; i++)
if (fixed[i+8] != ' ') { if (fixed[i + 8] != ' ') {
while (j++ < i) *p++ = ' '; while (j++ < i)
put_char(&p,fixed[i+8]); *p++ = ' ';
put_char(&p, fixed[i + 8]);
} }
} }
*p = 0; *p = 0;
return path; return path;
} }
int file_cvt(unsigned char *name, unsigned char *fixed)
int file_cvt(unsigned char *name,unsigned char *fixed)
{ {
unsigned char c; unsigned char c;
int size,ext,cnt; int size, ext, cnt;
size = 8; size = 8;
ext = 0; ext = 0;
while (*name) { while (*name) {
c = *name; c = *name;
if (c < ' ' || c > 0x7e || strchr("*?<>|\"/",c)) { if (c < ' ' || c > 0x7e || strchr("*?<>|\"/", c)) {
printf("Invalid character in name. Use \\ooo for special " printf("Invalid character in name. Use \\ooo for special "
"characters.\n"); "characters.\n");
return 0; return 0;
@ -109,7 +107,8 @@ int file_cvt(unsigned char *name,unsigned char *fixed)
printf("Duplicate dots in name.\n"); printf("Duplicate dots in name.\n");
return 0; return 0;
} }
while (size--) *fixed++ = ' '; while (size--)
*fixed++ = ' ';
size = 3; size = 3;
ext = 1; ext = 1;
name++; name++;
@ -122,7 +121,7 @@ int file_cvt(unsigned char *name,unsigned char *fixed)
printf("Invalid octal character.\n"); printf("Invalid octal character.\n");
return 0; return 0;
} }
c = c*8+*name++-'0'; c = c * 8 + *name++ - '0';
} }
if (cnt < 4) { if (cnt < 4) {
printf("Expected three octal digits.\n"); printf("Expected three octal digits.\n");
@ -130,113 +129,128 @@ int file_cvt(unsigned char *name,unsigned char *fixed)
} }
name += 3; name += 3;
} }
if (islower(c)) c = toupper(c); if (islower(c))
c = toupper(c);
if (size) { if (size) {
*fixed++ = c; *fixed++ = c;
size--; size--;
} }
name++; name++;
} }
if (*name || size == 8) return 0; if (*name || size == 8)
return 0;
if (!ext) { if (!ext) {
while (size--) *fixed++ = ' '; while (size--)
*fixed++ = ' ';
size = 3; size = 3;
} }
while (size--) *fixed++ = ' '; while (size--)
*fixed++ = ' ';
return 1; return 1;
} }
void file_add(char *path, FD_TYPE type)
void file_add(char *path,FD_TYPE type)
{ {
FDSC **current,*walk; FDSC **current, *walk;
char name[MSDOS_NAME]; char name[MSDOS_NAME];
char *here; char *here;
current = &fp_root; current = &fp_root;
if (*path != '/') die("%s: Absolute path required.",path); if (*path != '/')
die("%s: Absolute path required.", path);
path++; path++;
while (1) { while (1) {
if ((here = strchr(path,'/'))) *here = 0; if ((here = strchr(path, '/')))
if (!file_cvt(path,name)) exit(2); *here = 0;
if (!file_cvt(path, name))
exit(2);
for (walk = *current; walk; walk = walk->next) for (walk = *current; walk; walk = walk->next)
if (!here && (!strncmp(name,walk->name,MSDOS_NAME) || (type == if (!here && (!strncmp(name, walk->name, MSDOS_NAME) || (type ==
fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1)))) fdt_undelete
die("Ambiguous name: \"%s\"",path); &&
else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break; !strncmp
(name + 1,
walk->
name + 1,
MSDOS_NAME
- 1))))
die("Ambiguous name: \"%s\"", path);
else if (here && !strncmp(name, walk->name, MSDOS_NAME))
break;
if (!walk) { if (!walk) {
walk = alloc(sizeof(FDSC)); walk = alloc(sizeof(FDSC));
strncpy(walk->name,name,MSDOS_NAME); strncpy(walk->name, name, MSDOS_NAME);
walk->type = here ? fdt_none : type; walk->type = here ? fdt_none : type;
walk->first = NULL; walk->first = NULL;
walk->next = *current; walk->next = *current;
*current = walk; *current = walk;
} }
current = &walk->first; current = &walk->first;
if (!here) break; if (!here)
break;
*here = '/'; *here = '/';
path = here+1; path = here + 1;
} }
} }
FDSC **file_cd(FDSC ** curr, char *fixed)
FDSC **file_cd(FDSC **curr,char *fixed)
{ {
FDSC **walk; FDSC **walk;
if (!curr || !*curr) return NULL; if (!curr || !*curr)
return NULL;
for (walk = curr; *walk; walk = &(*walk)->next) for (walk = curr; *walk; walk = &(*walk)->next)
if (!strncmp((*walk)->name,fixed,MSDOS_NAME) && (*walk)->first) if (!strncmp((*walk)->name, fixed, MSDOS_NAME) && (*walk)->first)
return &(*walk)->first; return &(*walk)->first;
return NULL; return NULL;
} }
static FDSC **file_find(FDSC ** dir, char *fixed)
static FDSC **file_find(FDSC **dir,char *fixed)
{ {
if (!dir || !*dir) return NULL; if (!dir || !*dir)
if (*(unsigned char *) fixed == DELETED_FLAG) { return NULL;
if (*(unsigned char *)fixed == DELETED_FLAG) {
while (*dir) { 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; return dir;
dir = &(*dir)->next; dir = &(*dir)->next;
} }
return NULL; return NULL;
} }
while (*dir) { while (*dir) {
if (!strncmp((*dir)->name,fixed,MSDOS_NAME) && !(*dir)->first) if (!strncmp((*dir)->name, fixed, MSDOS_NAME) && !(*dir)->first)
return dir; return dir;
dir = &(*dir)->next; dir = &(*dir)->next;
} }
return NULL; return NULL;
} }
/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no /* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no
such file exists or if CURR is NULL. */ such file exists or if CURR is NULL. */
FD_TYPE file_type(FDSC **curr,char *fixed) FD_TYPE file_type(FDSC ** curr, char *fixed)
{ {
FDSC **this; FDSC **this;
if ((this = file_find(curr,fixed))) return (*this)->type; if ((this = file_find(curr, fixed)))
return (*this)->type;
return fdt_none; return fdt_none;
} }
void file_modify(FDSC ** curr, char *fixed)
void file_modify(FDSC **curr,char *fixed)
{ {
FDSC **this,*next; FDSC **this, *next;
if (!(this = file_find(curr,fixed))) if (!(this = file_find(curr, fixed)))
die("Internal error: file_find failed"); die("Internal error: file_find failed");
switch ((*this)->type) { switch ((*this)->type) {
case fdt_drop: case fdt_drop:
printf("Dropping %s\n",file_name(fixed)); printf("Dropping %s\n", file_name(fixed));
*(unsigned char *) fixed = DELETED_FLAG; *(unsigned char *)fixed = DELETED_FLAG;
break; break;
case fdt_undelete: case fdt_undelete:
*fixed = *(*this)->name; *fixed = *(*this)->name;
printf("Undeleting %s\n",file_name(fixed)); printf("Undeleting %s\n", file_name(fixed));
break; break;
default: default:
die("Internal error: file_modify"); die("Internal error: file_modify");
@ -246,23 +260,22 @@ void file_modify(FDSC **curr,char *fixed)
*this = next; *this = next;
} }
static void report_unused(FDSC * this)
static void report_unused(FDSC *this)
{ {
FDSC *next; FDSC *next;
while (this) { while (this) {
next = this->next; next = this->next;
if (this->first) report_unused(this->first); if (this->first)
report_unused(this->first);
else if (this->type != fdt_none) else if (this->type != fdt_none)
printf("Warning: did not %s file %s\n",this->type == fdt_drop ? printf("Warning: did not %s file %s\n", this->type == fdt_drop ?
"drop" : "undelete",file_name(this->name)); "drop" : "undelete", file_name(this->name));
free(this); free(this);
this = next; this = next;
} }
} }
void file_unused(void) void file_unused(void)
{ {
report_unused(fp_root); report_unused(fp_root);

View File

@ -19,11 +19,10 @@
can be found in /usr/share/common-licenses/GPL-3 file. can be found in /usr/share/common-licenses/GPL-3 file.
*/ */
#ifndef _FILE_H #ifndef _FILE_H
#define _FILE_H #define _FILE_H
typedef enum { fdt_none,fdt_drop,fdt_undelete } FD_TYPE; typedef enum { fdt_none, fdt_drop, fdt_undelete } FD_TYPE;
typedef struct _fptr { typedef struct _fptr {
char name[MSDOS_NAME]; char name[MSDOS_NAME];
@ -32,36 +31,34 @@ typedef struct _fptr {
struct _fptr *next; /* next file in directory */ struct _fptr *next; /* next file in directory */
} FDSC; } FDSC;
extern FDSC *fp_root; extern FDSC *fp_root;
char *file_name(unsigned char *fixed); char *file_name(unsigned char *fixed);
/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file /* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file
name. */ name. */
int file_cvt(unsigned char *name,unsigned char *fixed); int file_cvt(unsigned char *name, unsigned char *fixed);
/* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a /* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a
non-zero integer on success, zero on failure. */ non-zero integer on success, zero on failure. */
void file_add(char *path,FD_TYPE type); void file_add(char *path, FD_TYPE type);
/* Define special attributes for a path. TYPE can be either FDT_DROP or /* Define special attributes for a path. TYPE can be either FDT_DROP or
FDT_UNDELETE. */ FDT_UNDELETE. */
FDSC **file_cd(FDSC **curr,char *fixed); FDSC **file_cd(FDSC ** curr, char *fixed);
/* Returns a pointer to the directory descriptor of the subdirectory FIXED of /* Returns a pointer to the directory descriptor of the subdirectory FIXED of
CURR, or NULL if no such subdirectory exists. */ CURR, or NULL if no such subdirectory exists. */
FD_TYPE file_type(FDSC **curr,char *fixed); FD_TYPE file_type(FDSC ** curr, char *fixed);
/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no /* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no
such file exists or if CURR is NULL. */ such file exists or if CURR is NULL. */
void file_modify(FDSC **curr,char *fixed); void file_modify(FDSC ** curr, char *fixed);
/* Performs the necessary operation on the entry of CURR that is named FIXED. */ /* Performs the necessary operation on the entry of CURR that is named FIXED. */

118
src/io.c
View File

@ -45,7 +45,6 @@
#include "common.h" #include "common.h"
#include "io.h" #include "io.h"
typedef struct _change { typedef struct _change {
void *data; void *data;
loff_t pos; loff_t pos;
@ -53,20 +52,20 @@ typedef struct _change {
struct _change *next; struct _change *next;
} CHANGE; } CHANGE;
static CHANGE *changes, *last;
static CHANGE *changes,*last; static int fd, did_change = 0;
static int fd,did_change = 0;
unsigned device_no; unsigned device_no;
#ifdef __DJGPP__ #ifdef __DJGPP__
#include "volume.h" /* DOS lowlevel disk access functions */ #include "volume.h" /* DOS lowlevel disk access functions */
loff_t llseek(int fd, loff_t offset, int whence) 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); return VolumeSeek(offset);
} }
#define open OpenVolume #define open OpenVolume
#define close CloseVolume #define close CloseVolume
#define read(a,b,c) ReadVolume(b,c) #define read(a,b,c) ReadVolume(b,c)
@ -74,15 +73,15 @@ loff_t llseek(int fd, loff_t offset, int whence)
#else #else
loff_t llseek(int fd, loff_t offset, int whence) loff_t llseek(int fd, loff_t offset, int whence)
{ {
return (loff_t) lseek64(fd, (off64_t)offset, whence); return (loff_t) lseek64(fd, (off64_t) offset, whence);
} }
#endif #endif
void fs_open(char *path,int rw) void fs_open(char *path, int rw)
{ {
struct stat stbuf; struct stat stbuf;
if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0) { if ((fd = open(path, rw ? O_RDWR : O_RDONLY)) < 0) {
perror("open"); perror("open");
exit(6); exit(6);
} }
@ -90,16 +89,15 @@ void fs_open(char *path,int rw)
did_change = 0; did_change = 0;
#ifndef _DJGPP_ #ifndef _DJGPP_
if (fstat(fd,&stbuf) < 0) if (fstat(fd, &stbuf) < 0)
pdie("fstat %s",path); pdie("fstat %s", path);
device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0; device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;
#else #else
if (IsWorkingOnImageFile()) { if (IsWorkingOnImageFile()) {
if (fstat(GetVolumeHandle(),&stbuf) < 0) if (fstat(GetVolumeHandle(), &stbuf) < 0)
pdie("fstat image %s",path); pdie("fstat image %s", path);
device_no = 0; device_no = 0;
} } else {
else {
/* return 2 for floppy, 1 for ramdisk, 7 for loopback */ /* return 2 for floppy, 1 for ramdisk, 7 for loopback */
/* used by boot.c in Atari mode: floppy always FAT12, */ /* used by boot.c in Atari mode: floppy always FAT12, */
/* loopback / ramdisk only FAT12 if usual floppy size, */ /* loopback / ramdisk only FAT12 if usual floppy size, */
@ -110,7 +108,6 @@ void fs_open(char *path,int rw)
#endif #endif
} }
/** /**
* Read data from the partition, accounting for any pending updates that are * Read data from the partition, accounting for any pending updates that are
* queued for writing. * queued for writing.
@ -120,61 +117,72 @@ void fs_open(char *path,int rw)
* @param[in] size Number of bytes to read * @param[in] size Number of bytes to read
* @param[out] data Where to put the data read * @param[out] data Where to put the data read
*/ */
void fs_read(loff_t pos,int size,void *data) void fs_read(loff_t pos, int size, void *data)
{ {
CHANGE *walk; CHANGE *walk;
int got; int got;
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); if (llseek(fd, pos, 0) != pos)
if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos); pdie("Seek to %lld", pos);
if (got != size) die("Got %d bytes instead of %d at %lld",got,size,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) { for (walk = changes; walk; walk = walk->next) {
if (walk->pos < pos+size && walk->pos+walk->size > pos) { if (walk->pos < pos + size && walk->pos + walk->size > pos) {
if (walk->pos < pos) if (walk->pos < pos)
memcpy(data,(char *) walk->data+pos-walk->pos,min(size, memcpy(data, (char *)walk->data + pos - walk->pos, min(size,
walk->size-pos+walk->pos)); walk->
else memcpy((char *) data+walk->pos-pos,walk->data,min(walk->size, size -
size+pos-walk->pos)); 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)
int fs_test(loff_t pos,int size)
{ {
void *scratch; void *scratch;
int okay; 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); scratch = alloc(size);
okay = read(fd,scratch,size) == size; okay = read(fd, scratch, size) == size;
free(scratch); free(scratch);
return okay; return okay;
} }
void fs_write(loff_t pos, int size, void *data)
void fs_write(loff_t pos,int size,void *data)
{ {
CHANGE *new; CHANGE *new;
int did; int did;
if (write_immed) { if (write_immed) {
did_change = 1; did_change = 1;
if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); if (llseek(fd, pos, 0) != pos)
if ((did = write(fd,data,size)) == size) return; pdie("Seek to %lld", pos);
if (did < 0) pdie("Write %d bytes at %lld",size,pos); if ((did = write(fd, data, size)) == size)
die("Wrote %d bytes instead of %d at %lld",did,size,pos); 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 = alloc(sizeof(CHANGE));
new->pos = pos; new->pos = pos;
memcpy(new->data = alloc(new->size = size),data,size); memcpy(new->data = alloc(new->size = size), data, size);
new->next = NULL; new->next = NULL;
if (last) last->next = new; if (last)
else changes = new; last->next = new;
else
changes = new;
last = new; last = new;
} }
static void fs_flush(void) static void fs_flush(void)
{ {
CHANGE *this; CHANGE *this;
@ -183,40 +191,42 @@ static void fs_flush(void)
while (changes) { while (changes) {
this = changes; this = changes;
changes = changes->next; changes = changes->next;
if (llseek(fd,this->pos,0) != this->pos) if (llseek(fd, this->pos, 0) != this->pos)
fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n", fprintf(stderr,
(long long)this->pos,strerror(errno),this->size); "Seek to %lld failed: %s\n Did not write %d bytes.\n",
else if ((size = write(fd,this->data,this->size)) < 0) (long long)this->pos, strerror(errno), this->size);
fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size, else if ((size = write(fd, this->data, this->size)) < 0)
(long long)this->pos,strerror(errno)); fprintf(stderr, "Writing %d bytes at %lld failed: %s\n", this->size,
(long long)this->pos, strerror(errno));
else if (size != this->size) else if (size != this->size)
fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld." fprintf(stderr, "Wrote %d bytes instead of %d bytes at %lld."
"\n",size,this->size,(long long)this->pos); "\n", size, this->size, (long long)this->pos);
free(this->data); free(this->data);
free(this); free(this);
} }
} }
int fs_close(int write) int fs_close(int write)
{ {
CHANGE *next; CHANGE *next;
int changed; int changed;
changed = !!changes; changed = ! !changes;
if (write) fs_flush(); if (write)
else while (changes) { fs_flush();
else
while (changes) {
next = changes->next; next = changes->next;
free(changes->data); free(changes->data);
free(changes); free(changes);
changes = next; changes = next;
} }
if (close(fd) < 0) pdie("closing file system"); if (close(fd) < 0)
pdie("closing file system");
return changed || did_change; return changed || did_change;
} }
int fs_changed(void) int fs_changed(void)
{ {
return !!changes || did_change; return ! !changes || did_change;
} }

View File

@ -23,7 +23,6 @@
/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
* by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
#ifndef _IO_H #ifndef _IO_H
#define _IO_H #define _IO_H
@ -33,22 +32,22 @@ loff_t llseek(int fd, loff_t offset, int whence);
/* lseek() analogue for large offsets. */ /* lseek() analogue for large offsets. */
void fs_open(char *path,int rw); void fs_open(char *path, int rw);
/* Opens the file system PATH. If RW is zero, the file system is opened /* Opens the file system PATH. If RW is zero, the file system is opened
read-only, otherwise, it is opened read-write. */ read-only, otherwise, it is opened read-write. */
void fs_read(loff_t pos,int size,void *data); void fs_read(loff_t pos, int size, void *data);
/* Reads SIZE bytes starting at POS into DATA. Performs all applicable /* Reads SIZE bytes starting at POS into DATA. Performs all applicable
changes. */ changes. */
int fs_test(loff_t pos,int size); int fs_test(loff_t pos, int size);
/* Returns a non-zero integer if SIZE bytes starting at POS can be read without /* Returns a non-zero integer if SIZE bytes starting at POS can be read without
errors. Otherwise, it returns zero. */ errors. Otherwise, it returns zero. */
void fs_write(loff_t pos,int size,void *data); void fs_write(loff_t pos, int size, void *data);
/* If write_immed is non-zero, SIZE bytes are written from DATA to the disk, /* If write_immed is non-zero, SIZE bytes are written from DATA to the disk,
starting at POS. If write_immed is zero, the change is added to a list in starting at POS. If write_immed is zero, the change is added to a list in

279
src/lfn.c
View File

@ -88,22 +88,23 @@ static unsigned char fat_uni2esc[64] = {
/* This function converts an unicode string to a normal ASCII string, assuming /* This function converts an unicode string to a normal ASCII string, assuming
* ISO-8859-1 charset. Characters not in 8859-1 are converted to the same * ISO-8859-1 charset. Characters not in 8859-1 are converted to the same
* escape notation as used by the kernel, i.e. the uuencode-like ":xxx" */ * escape notation as used by the kernel, i.e. the uuencode-like ":xxx" */
static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q ) static char *cnv_unicode(const unsigned char *uni, int maxlen, int use_q)
{ {
const unsigned char *up; const unsigned char *up;
unsigned char *out, *cp; unsigned char *out, *cp;
int len, val; 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]);
if (UNICODE_CONVERTABLE(up[0],up[1])) up += 2) {
if (UNICODE_CONVERTABLE(up[0], up[1]))
++len; ++len;
else else
len += 4; len += 4;
} }
cp = out = use_q ? qalloc( &mem_queue, len+1 ) : alloc( len+1 ); cp = out = use_q ? qalloc(&mem_queue, len + 1) : alloc(len + 1);
for( up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ) { for (up = uni; (up - uni) / 2 < maxlen && (up[0] || up[1]); up += 2) {
if (UNICODE_CONVERTABLE(up[0],up[1])) if (UNICODE_CONVERTABLE(up[0], up[1]))
*cp++ = up[0]; *cp++ = up[0];
else { else {
/* here the same escape notation is used as in the Linux kernel */ /* here the same escape notation is used as in the Linux kernel */
@ -119,19 +120,17 @@ static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q )
} }
*cp = 0; *cp = 0;
return( out ); return (out);
} }
static void copy_lfn_part(char *dst, LFN_ENT * lfn)
static void copy_lfn_part( char *dst, LFN_ENT *lfn )
{ {
memcpy( dst, lfn->name0_4, 10 ); memcpy(dst, lfn->name0_4, 10);
memcpy( dst+10, lfn->name5_10, 12 ); memcpy(dst + 10, lfn->name5_10, 12);
memcpy( dst+22, lfn->name11_12, 4 ); memcpy(dst + 22, lfn->name11_12, 4);
} }
static void clear_lfn_slots(int start, int end)
static void clear_lfn_slots( int start, int end )
{ {
int i; int i;
LFN_ENT empty; LFN_ENT empty;
@ -140,11 +139,11 @@ static void clear_lfn_slots( int start, int end )
* This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading
* a directory at the first zero entry... * a directory at the first zero entry...
*/ */
memset( &empty, 0, sizeof(empty) ); memset(&empty, 0, sizeof(empty));
empty.id = DELETED_FLAG; empty.id = DELETED_FLAG;
for( i = start; i <= end; ++i ) { for (i = start; i <= end; ++i) {
fs_write( lfn_offsets[i], sizeof(LFN_ENT), &empty ); fs_write(lfn_offsets[i], sizeof(LFN_ENT), &empty);
} }
} }
@ -153,34 +152,34 @@ void lfn_fix_checksum(loff_t from, loff_t to, const char *short_name)
int i; int i;
__u8 sum; __u8 sum;
for (sum = 0, i = 0; i < 11; i++) for (sum = 0, i = 0; i < 11; i++)
sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + short_name[i]; sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + short_name[i];
for( ; from < to; from += sizeof(LFN_ENT) ) { for (; from < to; from += sizeof(LFN_ENT)) {
fs_write( from + offsetof(LFN_ENT,alias_checksum), sizeof(sum), &sum ); fs_write(from + offsetof(LFN_ENT, alias_checksum), sizeof(sum), &sum);
} }
} }
void lfn_reset( void ) void lfn_reset(void)
{ {
if (lfn_unicode) if (lfn_unicode)
free( lfn_unicode ); free(lfn_unicode);
lfn_unicode = NULL; lfn_unicode = NULL;
if (lfn_offsets) if (lfn_offsets)
free( lfn_offsets ); free(lfn_offsets);
lfn_offsets = NULL; lfn_offsets = NULL;
lfn_slot = -1; lfn_slot = -1;
} }
/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part /* This function is only called with de->attr == VFAT_LN_ATTR. It stores part
* of the long name. */ * of the long name. */
void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ) void lfn_add_slot(DIR_ENT * de, loff_t dir_offset)
{ {
LFN_ENT *lfn = (LFN_ENT *)de; LFN_ENT *lfn = (LFN_ENT *) de;
int slot = lfn->id & LFN_ID_SLOTMASK; int slot = lfn->id & LFN_ID_SLOTMASK;
unsigned offset; unsigned offset;
if (lfn_slot == 0) lfn_check_orphaned(); if (lfn_slot == 0)
lfn_check_orphaned();
if (de->attr != VFAT_LN_ATTR) if (de->attr != VFAT_LN_ATTR)
die("lfn_add_slot called with non-LFN directory entry"); die("lfn_add_slot called with non-LFN directory entry");
@ -196,65 +195,63 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
* checksum ok: clear start bit */ * checksum ok: clear start bit */
/* XXX: Should delay that until next LFN known (then can better /* XXX: Should delay that until next LFN known (then can better
* display the name) */ * display the name) */
printf( "A new long file name starts within an old one.\n" ); printf("A new long file name starts within an old one.\n");
if (slot == lfn_slot && if (slot == lfn_slot && lfn->alias_checksum == lfn_checksum) {
lfn->alias_checksum == lfn_checksum) {
char *part1 = CNV_THIS_PART(lfn); char *part1 = CNV_THIS_PART(lfn);
char *part2 = CNV_PARTS_SO_FAR(); char *part2 = CNV_PARTS_SO_FAR();
printf( " It could be that the LFN start bit is wrong here\n" printf(" It could be that the LFN start bit is wrong here\n"
" if \"%s\" seems to match \"%s\".\n", part1, part2 ); " if \"%s\" seems to match \"%s\".\n", part1, part2);
free( part1 ); free(part1);
free( part2 ); free(part2);
can_clear = 1; can_clear = 1;
} }
if (interactive) { if (interactive) {
printf( "1: Delete previous LFN\n2: Leave it as it is.\n" ); printf("1: Delete previous LFN\n2: Leave it as it is.\n");
if (can_clear) if (can_clear)
printf( "3: Clear start bit and concatenate LFNs\n" ); printf("3: Clear start bit and concatenate LFNs\n");
} } else
else printf( " Not auto-correcting this.\n" ); printf(" Not auto-correcting this.\n");
if (interactive) { if (interactive) {
switch( get_key( can_clear ? "123" : "12", "?" )) { switch (get_key(can_clear ? "123" : "12", "?")) {
case '1': case '1':
clear_lfn_slots( 0, lfn_parts-1 ); clear_lfn_slots(0, lfn_parts - 1);
lfn_reset(); lfn_reset();
break; break;
case '2': case '2':
break; break;
case '3': case '3':
lfn->id &= ~LFN_ID_START; lfn->id &= ~LFN_ID_START;
fs_write( dir_offset+offsetof(LFN_ENT,id), fs_write(dir_offset + offsetof(LFN_ENT, id),
sizeof(lfn->id), &lfn->id ); sizeof(lfn->id), &lfn->id);
break; break;
} }
} }
} }
lfn_slot = slot; lfn_slot = slot;
lfn_checksum = lfn->alias_checksum; lfn_checksum = lfn->alias_checksum;
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); lfn_unicode = alloc((lfn_slot * CHARS_PER_LFN + 1) * 2);
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); lfn_offsets = alloc(lfn_slot * sizeof(loff_t));
lfn_parts = 0; 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 */ /* No LFN in progress, but slot found; start bit missing */
/* Causes: 1) start bit got lost, 2) Previous slot with start bit got /* Causes: 1) start bit got lost, 2) Previous slot with start bit got
* lost */ * lost */
/* Fixes: 1) delete LFN, 2) set start bit */ /* Fixes: 1) delete LFN, 2) set start bit */
char *part = CNV_THIS_PART(lfn); char *part = CNV_THIS_PART(lfn);
printf( "Long filename fragment \"%s\" found outside a LFN " printf("Long filename fragment \"%s\" found outside a LFN "
"sequence.\n (Maybe the start bit is missing on the " "sequence.\n (Maybe the start bit is missing on the "
"last fragment)\n", part ); "last fragment)\n", part);
if (interactive) { if (interactive) {
printf( "1: Delete fragment\n2: Leave it as it is.\n" printf("1: Delete fragment\n2: Leave it as it is.\n"
"3: Set start bit\n" ); "3: Set start bit\n");
} } else
else printf( " Not auto-correcting this.\n" ); printf(" Not auto-correcting this.\n");
switch( interactive ? get_key( "123", "?" ) : '2') { switch (interactive ? get_key("123", "?") : '2') {
case '1': case '1':
if (!lfn_offsets) if (!lfn_offsets)
lfn_offsets = alloc( sizeof(loff_t) ); lfn_offsets = alloc(sizeof(loff_t));
lfn_offsets[0] = dir_offset; lfn_offsets[0] = dir_offset;
clear_lfn_slots( 0, 0 ); clear_lfn_slots(0, 0);
lfn_reset(); lfn_reset();
return; return;
case '2': case '2':
@ -262,49 +259,48 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
return; return;
case '3': case '3':
lfn->id |= LFN_ID_START; lfn->id |= LFN_ID_START;
fs_write( dir_offset+offsetof(LFN_ENT,id), fs_write(dir_offset + offsetof(LFN_ENT, id),
sizeof(lfn->id), &lfn->id ); sizeof(lfn->id), &lfn->id);
lfn_slot = slot; lfn_slot = slot;
lfn_checksum = lfn->alias_checksum; lfn_checksum = lfn->alias_checksum;
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); lfn_unicode = alloc((lfn_slot * CHARS_PER_LFN + 1) * 2);
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); lfn_offsets = alloc(lfn_slot * sizeof(loff_t));
lfn_parts = 0; lfn_parts = 0;
break; break;
} }
} } else if (slot != lfn_slot) {
else if (slot != lfn_slot) {
/* wrong sequence number */ /* wrong sequence number */
/* Causes: 1) seq-no destroyed */ /* Causes: 1) seq-no destroyed */
/* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts /* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts
* are ok?, maybe only if checksum is ok?) (Attention: space * are ok?, maybe only if checksum is ok?) (Attention: space
* for name was allocated before!) */ * for name was allocated before!) */
int can_fix = 0; int can_fix = 0;
printf( "Unexpected long filename sequence number " printf("Unexpected long filename sequence number "
"(%d vs. expected %d).\n", "(%d vs. expected %d).\n", slot, lfn_slot);
slot, lfn_slot );
if (lfn->alias_checksum == lfn_checksum && lfn_slot > 0) { if (lfn->alias_checksum == lfn_checksum && lfn_slot > 0) {
char *part1 = CNV_THIS_PART(lfn); char *part1 = CNV_THIS_PART(lfn);
char *part2 = CNV_PARTS_SO_FAR(); char *part2 = CNV_PARTS_SO_FAR();
printf( " It could be that just the number is wrong\n" printf(" It could be that just the number is wrong\n"
" if \"%s\" seems to match \"%s\".\n", part1, part2 ); " if \"%s\" seems to match \"%s\".\n", part1, part2);
free( part1 ); free(part1);
free( part2 ); free(part2);
can_fix = 1; can_fix = 1;
} }
if (interactive) { 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) if (can_fix)
printf( "3: Correct sequence number\n" ); printf("3: Correct sequence number\n");
} } else
else printf( " Not auto-correcting this.\n" ); printf(" Not auto-correcting this.\n");
switch( interactive ? get_key( can_fix ? "123" : "12", "?" ) : '2') { switch (interactive ? get_key(can_fix ? "123" : "12", "?") : '2') {
case '1': case '1':
if (!lfn_offsets) { if (!lfn_offsets) {
lfn_offsets = alloc( sizeof(loff_t) ); lfn_offsets = alloc(sizeof(loff_t));
lfn_parts = 0; lfn_parts = 0;
} }
lfn_offsets[lfn_parts++] = dir_offset; lfn_offsets[lfn_parts++] = dir_offset;
clear_lfn_slots( 0, lfn_parts-1 ); clear_lfn_slots(0, lfn_parts - 1);
lfn_reset(); lfn_reset();
return; return;
case '2': case '2':
@ -312,8 +308,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
return; return;
case '3': case '3':
lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot; lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot;
fs_write( dir_offset+offsetof(LFN_ENT,id), fs_write(dir_offset + offsetof(LFN_ENT, id),
sizeof(lfn->id), &lfn->id ); sizeof(lfn->id), &lfn->id);
break; break;
} }
} }
@ -322,27 +318,27 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
/* checksum mismatch */ /* checksum mismatch */
/* Causes: 1) checksum field here destroyed */ /* Causes: 1) checksum field here destroyed */
/* Fixes: 1) delete LFN, 2) fix checksum */ /* Fixes: 1) delete LFN, 2) fix checksum */
printf( "Checksum in long filename part wrong " printf("Checksum in long filename part wrong "
"(%02x vs. expected %02x).\n", "(%02x vs. expected %02x).\n",
lfn->alias_checksum, lfn_checksum ); lfn->alias_checksum, lfn_checksum);
if (interactive) { if (interactive) {
printf( "1: Delete LFN\n2: Leave it as it is.\n" printf("1: Delete LFN\n2: Leave it as it is.\n"
"3: Correct checksum\n" ); "3: Correct checksum\n");
} } else
else printf( " Not auto-correcting this.\n" ); printf(" Not auto-correcting this.\n");
if (interactive) { if (interactive) {
switch( get_key( "123", "?" )) { switch (get_key("123", "?")) {
case '1': case '1':
lfn_offsets[lfn_parts++] = dir_offset; lfn_offsets[lfn_parts++] = dir_offset;
clear_lfn_slots( 0, lfn_parts-1 ); clear_lfn_slots(0, lfn_parts - 1);
lfn_reset(); lfn_reset();
return; return;
case '2': case '2':
break; break;
case '3': case '3':
lfn->alias_checksum = lfn_checksum; lfn->alias_checksum = lfn_checksum;
fs_write( dir_offset+offsetof(LFN_ENT,alias_checksum), fs_write(dir_offset + offsetof(LFN_ENT, alias_checksum),
sizeof(lfn->alias_checksum), &lfn->alias_checksum ); sizeof(lfn->alias_checksum), &lfn->alias_checksum);
break; break;
} }
} }
@ -350,43 +346,44 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
if (lfn_slot != -1) { if (lfn_slot != -1) {
lfn_slot--; lfn_slot--;
offset = lfn_slot * CHARS_PER_LFN*2; offset = lfn_slot * CHARS_PER_LFN * 2;
copy_lfn_part( lfn_unicode+offset, lfn ); copy_lfn_part(lfn_unicode + offset, lfn);
if (lfn->id & LFN_ID_START) if (lfn->id & LFN_ID_START)
lfn_unicode[offset+26] = lfn_unicode[offset+27] = 0; lfn_unicode[offset + 26] = lfn_unicode[offset + 27] = 0;
lfn_offsets[lfn_parts++] = dir_offset; lfn_offsets[lfn_parts++] = dir_offset;
} }
if (lfn->reserved != 0) { if (lfn->reserved != 0) {
printf( "Reserved field in VFAT long filename slot is not 0 " printf("Reserved field in VFAT long filename slot is not 0 "
"(but 0x%02x).\n", lfn->reserved ); "(but 0x%02x).\n", lfn->reserved);
if (interactive) if (interactive)
printf( "1: Fix.\n2: Leave it.\n" ); printf("1: Fix.\n2: Leave it.\n");
else printf( "Auto-setting to 0.\n" ); else
if (!interactive || get_key("12","?") == '1') { printf("Auto-setting to 0.\n");
if (!interactive || get_key("12", "?") == '1') {
lfn->reserved = 0; lfn->reserved = 0;
fs_write( dir_offset+offsetof(LFN_ENT,reserved), fs_write(dir_offset + offsetof(LFN_ENT, reserved),
sizeof(lfn->reserved), &lfn->reserved ); sizeof(lfn->reserved), &lfn->reserved);
} }
} }
if (lfn->start != CT_LE_W(0)) { if (lfn->start != CT_LE_W(0)) {
printf( "Start cluster field in VFAT long filename slot is not 0 " printf("Start cluster field in VFAT long filename slot is not 0 "
"(but 0x%04x).\n", lfn->start ); "(but 0x%04x).\n", lfn->start);
if (interactive) if (interactive)
printf( "1: Fix.\n2: Leave it.\n" ); printf("1: Fix.\n2: Leave it.\n");
else printf( "Auto-setting to 0.\n" ); else
if (!interactive || get_key("12","?") == '1') { printf("Auto-setting to 0.\n");
if (!interactive || get_key("12", "?") == '1') {
lfn->start = CT_LE_W(0); lfn->start = CT_LE_W(0);
fs_write( dir_offset+offsetof(LFN_ENT,start), fs_write(dir_offset + offsetof(LFN_ENT, start),
sizeof(lfn->start),&lfn->start ); sizeof(lfn->start), &lfn->start);
} }
} }
} }
/* This function is always called when de->attr != VFAT_LN_ATTR is found, to /* This function is always called when de->attr != VFAT_LN_ATTR is found, to
* retrieve the previously constructed LFN. */ * retrieve the previously constructed LFN. */
char *lfn_get( DIR_ENT *de, loff_t *lfn_offset ) char *lfn_get(DIR_ENT * de, loff_t * lfn_offset)
{ {
char *lfn; char *lfn;
__u8 sum; __u8 sum;
@ -398,7 +395,7 @@ char *lfn_get( DIR_ENT *de, loff_t *lfn_offset )
#if 0 #if 0
if (de->lcase) if (de->lcase)
printf( "lcase=%02x\n",de->lcase ); printf("lcase=%02x\n", de->lcase);
#endif #endif
if (lfn_slot == -1) if (lfn_slot == -1)
@ -413,67 +410,66 @@ char *lfn_get( DIR_ENT *de, loff_t *lfn_offset )
* 3) renumber entries and truncate name */ * 3) renumber entries and truncate name */
char *long_name = CNV_PARTS_SO_FAR(); char *long_name = CNV_PARTS_SO_FAR();
char *short_name = file_name(de->name); char *short_name = file_name(de->name);
printf( "Unfinished long file name \"%s\".\n" printf("Unfinished long file name \"%s\".\n"
" (Start may have been overwritten by %s)\n", " (Start may have been overwritten by %s)\n",
long_name, short_name ); long_name, short_name);
free( long_name ); free(long_name);
if (interactive) { if (interactive) {
printf( "1: Delete LFN\n2: Leave it as it is.\n" printf("1: Delete LFN\n2: Leave it as it is.\n"
"3: Fix numbering (truncates long name and attaches " "3: Fix numbering (truncates long name and attaches "
"it to short name %s)\n", short_name ); "it to short name %s)\n", short_name);
} } else
else printf( " Not auto-correcting this.\n" ); printf(" Not auto-correcting this.\n");
switch( interactive ? get_key( "123", "?" ) : '2') { switch (interactive ? get_key("123", "?") : '2') {
case '1': case '1':
clear_lfn_slots( 0, lfn_parts-1 ); clear_lfn_slots(0, lfn_parts - 1);
lfn_reset(); lfn_reset();
return NULL; return NULL;
case '2': case '2':
lfn_reset(); lfn_reset();
return NULL; return NULL;
case '3': case '3':
for( i = 0; i < lfn_parts; ++i ) { for (i = 0; i < lfn_parts; ++i) {
__u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0); __u8 id = (lfn_parts - i) | (i == 0 ? LFN_ID_START : 0);
fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id), fs_write(lfn_offsets[i] + offsetof(LFN_ENT, id),
sizeof(id), &id ); sizeof(id), &id);
} }
memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2, memmove(lfn_unicode, lfn_unicode + lfn_slot * CHARS_PER_LFN * 2,
lfn_parts*CHARS_PER_LFN*2 ); lfn_parts * CHARS_PER_LFN * 2);
break; break;
} }
} }
for (sum = 0, i = 0; i < 11; i++) for (sum = 0, i = 0; i < 11; i++)
sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i]; sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + de->name[i];
if (sum != lfn_checksum) { if (sum != lfn_checksum) {
/* checksum doesn't match, long name doesn't apply to this alias */ /* checksum doesn't match, long name doesn't apply to this alias */
/* Causes: 1) alias renamed */ /* Causes: 1) alias renamed */
/* Fixes: 1) Fix checksum in LFN entries */ /* Fixes: 1) Fix checksum in LFN entries */
char *long_name = CNV_PARTS_SO_FAR(); char *long_name = CNV_PARTS_SO_FAR();
char *short_name = file_name(de->name); char *short_name = file_name(de->name);
printf( "Wrong checksum for long file name \"%s\".\n" printf("Wrong checksum for long file name \"%s\".\n"
" (Short name %s may have changed without updating the long name)\n", " (Short name %s may have changed without updating the long name)\n",
long_name, short_name ); long_name, short_name);
free( long_name ); free(long_name);
if (interactive) { if (interactive) {
printf( "1: Delete LFN\n2: Leave it as it is.\n" printf("1: Delete LFN\n2: Leave it as it is.\n"
"3: Fix checksum (attaches to short name %s)\n", "3: Fix checksum (attaches to short name %s)\n", short_name);
short_name ); } else
} printf(" Not auto-correcting this.\n");
else printf( " Not auto-correcting this.\n" );
if (interactive) { if (interactive) {
switch( get_key( "123", "?" )) { switch (get_key("123", "?")) {
case '1': case '1':
clear_lfn_slots( 0, lfn_parts-1 ); clear_lfn_slots(0, lfn_parts - 1);
lfn_reset(); lfn_reset();
return NULL; return NULL;
case '2': case '2':
lfn_reset(); lfn_reset();
return NULL; return NULL;
case '3': case '3':
for( i = 0; i < lfn_parts; ++i ) { for (i = 0; i < lfn_parts; ++i) {
fs_write( lfn_offsets[i]+offsetof(LFN_ENT,alias_checksum), fs_write(lfn_offsets[i] + offsetof(LFN_ENT, alias_checksum),
sizeof(sum), &sum ); sizeof(sum), &sum);
} }
break; break;
} }
@ -481,9 +477,9 @@ char *lfn_get( DIR_ENT *de, loff_t *lfn_offset )
} }
*lfn_offset = lfn_offsets[0]; *lfn_offset = lfn_offsets[0];
lfn = cnv_unicode( lfn_unicode, UNTIL_0, 1 ); lfn = cnv_unicode(lfn_unicode, UNTIL_0, 1);
lfn_reset(); lfn_reset();
return( lfn ); return (lfn);
} }
void lfn_check_orphaned(void) void lfn_check_orphaned(void)
@ -496,9 +492,10 @@ void lfn_check_orphaned(void)
long_name = CNV_PARTS_SO_FAR(); long_name = CNV_PARTS_SO_FAR();
printf("Orphaned long file name part \"%s\"\n", long_name); printf("Orphaned long file name part \"%s\"\n", long_name);
if (interactive) if (interactive)
printf( "1: Delete.\n2: Leave it.\n" ); printf("1: Delete.\n2: Leave it.\n");
else printf( " Auto-deleting.\n" ); else
if (!interactive || get_key("12","?") == '1') { printf(" Auto-deleting.\n");
if (!interactive || get_key("12", "?") == '1') {
clear_lfn_slots(0, lfn_parts - 1); clear_lfn_slots(0, lfn_parts - 1);
} }
lfn_reset(); lfn_reset();

View File

@ -22,13 +22,13 @@
#ifndef _LFN_H #ifndef _LFN_H
#define _LFN_H #define _LFN_H
void lfn_reset( void ); void lfn_reset(void);
/* Reset the state of the LFN parser. */ /* Reset the state of the LFN parser. */
void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ); void lfn_add_slot(DIR_ENT * de, loff_t dir_offset);
/* Process a dir slot that is a VFAT LFN entry. */ /* Process a dir slot that is a VFAT LFN entry. */
char *lfn_get( DIR_ENT *de, loff_t *lfn_offset ); char *lfn_get(DIR_ENT * de, loff_t * lfn_offset);
/* Retrieve the long name for the proper dir entry. */ /* Retrieve the long name for the proper dir entry. */
void lfn_check_orphaned(void); void lfn_check_orphaned(void);

File diff suppressed because it is too large Load Diff