From 62e33ea5fff23409b6695e0b83fe9e66a095060c Mon Sep 17 00:00:00 2001 From: Steven Edwards Date: Fri, 29 Jul 2005 23:03:42 +0000 Subject: [PATCH] dos line endings svn path=/trunk/; revision=16887 --- rosapps/sysutils/dosfsck/boot.c | 740 +++++------ rosapps/sysutils/dosfsck/boot.h | 26 +- rosapps/sysutils/dosfsck/byteorder.h | 118 +- rosapps/sysutils/dosfsck/byteswap.h | 80 +- rosapps/sysutils/dosfsck/byteswap1.h | 266 ++-- rosapps/sysutils/dosfsck/check.c | 1722 +++++++++++++------------- rosapps/sysutils/dosfsck/check.h | 46 +- rosapps/sysutils/dosfsck/common.c | 214 ++-- rosapps/sysutils/dosfsck/common.h | 78 +- rosapps/sysutils/dosfsck/compiler.h | 316 ++--- rosapps/sysutils/dosfsck/dosfsck.c | 366 +++--- rosapps/sysutils/dosfsck/dosfsck.h | 350 +++--- rosapps/sysutils/dosfsck/fat.c | 722 +++++------ rosapps/sysutils/dosfsck/fat.h | 128 +- rosapps/sysutils/dosfsck/file.c | 502 ++++---- rosapps/sysutils/dosfsck/file.h | 110 +- rosapps/sysutils/dosfsck/getopt.c | 126 +- rosapps/sysutils/dosfsck/io.c | 378 +++--- rosapps/sysutils/dosfsck/io.h | 108 +- rosapps/sysutils/dosfsck/lfn.c | 952 +++++++------- rosapps/sysutils/dosfsck/lfn.h | 40 +- rosapps/sysutils/dosfsck/msdos_fs.h | 364 +++--- rosapps/sysutils/dosfsck/swab.h | 384 +++--- rosapps/sysutils/dosfsck/version.h | 16 +- rosapps/sysutils/dosfsck/vfat.h | 1488 +++++++++++----------- 25 files changed, 4820 insertions(+), 4820 deletions(-) diff --git a/rosapps/sysutils/dosfsck/boot.c b/rosapps/sysutils/dosfsck/boot.c index dac2d2c4504..cddbac3e1e0 100644 --- a/rosapps/sysutils/dosfsck/boot.c +++ b/rosapps/sysutils/dosfsck/boot.c @@ -1,370 +1,370 @@ -/* boot.c - Read and analyze ia PC/MS-DOS boot sector */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - -#include -#include -#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "boot.h" - - -#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) - /* don't divide by zero */ - -static struct { - __u8 media; - char *descr; -} mediabytes[] = { - { 0xf0, "5.25\" or 3.5\" HD floppy" }, - { 0xf8, "hard disk" }, - { 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or " - "5.25\" 1.2M floppy 2s/80tr/15sec" }, - { 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" }, - { 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" }, - { 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" }, - { 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" }, - { 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" }, - { 0xff, "5.25\" 320k floppy 2s/40tr/8sec" }, -}; - -#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__ -/* Unaligned fields must first be copied byte-wise */ -#define GET_UNALIGNED_W(f) \ - ({ \ - unsigned short __v; \ - memcpy( &__v, &f, sizeof(__v) ); \ - CF_LE_W( *(unsigned short *)&f ); \ - }) -#else -#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f ) -#endif - - -static char *get_media_descr( unsigned char media ) -{ - int i; - - for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) { - if (mediabytes[i].media == media) - return( mediabytes[i].descr ); - } - return( "undefined" ); -} - -static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss) -{ - unsigned short sectors; - - printf("Boot sector contents:\n"); - if (!atari_format) { - char id[9]; - strncpy(id,b->system_id,8); - id[8] = 0; - printf("System ID \"%s\"\n",id); - } - else { - /* On Atari, a 24 bit serial number is stored at offset 8 of the boot - * sector */ - printf("Serial number 0x%x\n", - b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16)); - } - 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 cluster\n",fs->cluster_size); - printf("%10d reserved sector%s\n",CF_LE_W(b->reserved), - CF_LE_W(b->reserved) == 1 ? "" : "s"); - printf("First FAT starts at byte %llu (sector %llu)\n", - (__u64)fs->fat_start, - (__u64)fs->fat_start/lss); - printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits); - printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size, - fs->fat_size/lss); - if (!fs->root_cluster) { - printf("Root directory starts at byte %llu (sector %llu)\n", - (__u64)fs->root_start, - (__u64)fs->root_start/lss); - printf("%10d root directory entries\n",fs->root_entries); - } - else { - printf( "Root directory start at cluster %lu (arbitrary size)\n", - fs->root_cluster); - } - printf("Data area starts at byte %llu (sector %llu)\n", - (__u64)fs->data_start, - (__u64)fs->data_start/lss); - printf("%10lu data clusters (%llu bytes)\n",fs->clusters, - (__u64)fs->clusters*fs->cluster_size); - printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track), - CF_LE_W(b->heads)); - printf("%10u hidden sectors\n", - atari_format ? - /* On Atari, the hidden field is only 16 bit wide and unused */ - (((unsigned char *)&b->hidden)[0] | - ((unsigned char *)&b->hidden)[1] << 8) : - CF_LE_L(b->hidden)); - sectors = GET_UNALIGNED_W( b->sectors ); - 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) -{ - struct boot_sector b2; - - if (!fs->backupboot_start) { - printf( "There is no backup boot sector.\n" ); - if (CF_LE_W(b->reserved) < 3) { - printf( "And there is no space for creating one!\n" ); - return; - } - if (interactive) - printf( "1) Create one\n2) Do without a backup\n" ); - else printf( " Auto-creating backup boot block.\n" ); - if (!interactive || get_key("12","?") == '1') { - int bbs; - /* The usual place for the backup boot sector is sector 6. Choose - * that or the last reserved sector. */ - if (CF_LE_W(b->reserved) >= 7 && CF_LE_W(b->info_sector) != 6) - bbs = 6; - else { - bbs = CF_LE_W(b->reserved) - 1; - if (bbs == CF_LE_W(b->info_sector)) - --bbs; /* this is never 0, as we checked reserved >= 3! */ - } - fs->backupboot_start = bbs*lss; - b->backup_boot = CT_LE_W(bbs); - fs_write(fs->backupboot_start,sizeof(*b),b); - fs_write((off_t)offsetof(struct boot_sector,backup_boot), - sizeof(b->backup_boot),&b->backup_boot); - printf( "Created backup of boot sector in sector %d\n", bbs ); - return; - } - else return; - } - - fs_read(fs->backupboot_start,sizeof(b2),&b2); - if (memcmp(b,&b2,sizeof(b2)) != 0) { - /* there are any differences */ - __u8 *p, *q; - int i, pos, first = 1; - char buf[20]; - - printf( "There are differences between boot sector and its backup.\n" ); - printf( "Differences: (offset:original/backup)\n " ); - pos = 2; - for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2); - ++p, ++q, ++i ) { - if (*p != *q) { - sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ", - (unsigned)(p-(__u8 *)b), *p, *q ); - if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2; - printf( "%s", buf ); - pos += strlen(buf); - first = 0; - } - } - printf( "\n" ); - - if (interactive) - printf( "1) Copy original to backup\n" - "2) Copy backup to original\n" - "3) No action\n" ); - else printf( " Not automatically fixing this.\n" ); - switch (interactive ? get_key("123","?") : '3') { - case '1': - fs_write(fs->backupboot_start,sizeof(*b),b); - break; - case '2': - fs_write(0,sizeof(b2),&b2); - break; - default: - break; - } - } -} - -static void init_fsinfo(struct info_sector *i) -{ - i->magic = CT_LE_L(0x41615252); - i->signature = CT_LE_L(0x61417272); - i->free_clusters = CT_LE_L(-1); - i->next_cluster = CT_LE_L(2); - i->boot_sign = CT_LE_W(0xaa55); -} - -static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss) -{ - struct info_sector i; - - if (!b->info_sector) { - printf( "No FSINFO sector\n" ); - if (interactive) - printf( "1) Create one\n2) Do without FSINFO\n" ); - else printf( " Not automatically creating it.\n" ); - if (interactive && get_key("12","?") == '1') { - /* search for a free reserved sector (not boot sector and not - * backup boot sector) */ - __u32 s; - for( s = 1; s < CF_LE_W(b->reserved); ++s ) - if (s != CF_LE_W(b->backup_boot)) break; - if (s > 0 && s < CF_LE_W(b->reserved)) { - init_fsinfo(&i); - fs_write((off_t)s*lss,sizeof(i),&i); - b->info_sector = CT_LE_W(s); - fs_write((off_t)offsetof(struct boot_sector,info_sector), - sizeof(b->info_sector),&b->info_sector); - if (fs->backupboot_start) - fs_write(fs->backupboot_start+ - offsetof(struct boot_sector,info_sector), - sizeof(b->info_sector),&b->info_sector); - } - else { - printf( "No free reserved sector found -- " - "no space for FSINFO sector!\n" ); - return; - } - } - else return; - } - - fs->fsinfo_start = CF_LE_W(b->info_sector)*lss; - fs_read(fs->fsinfo_start,sizeof(i),&i); - - if (i.magic != CT_LE_L(0x41615252) || - i.signature != CT_LE_L(0x61417272) || - i.boot_sign != CT_LE_W(0xaa55)) { - printf( "FSINFO sector has bad magic number(s):\n" ); - if (i.magic != CT_LE_L(0x41615252)) - printf( " Offset %llu: 0x%08x != expected 0x%08x\n", - (__u64)offsetof(struct info_sector,magic), - CF_LE_L(i.magic),0x41615252); - if (i.signature != CT_LE_L(0x61417272)) - printf( " Offset %llu: 0x%08x != expected 0x%08x\n", - (__u64)offsetof(struct info_sector,signature), - CF_LE_L(i.signature),0x61417272); - if (i.boot_sign != CT_LE_W(0xaa55)) - printf( " Offset %llu: 0x%04x != expected 0x%04x\n", - (__u64)offsetof(struct info_sector,boot_sign), - CF_LE_W(i.boot_sign),0xaa55); - if (interactive) - printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" ); - else printf( " Auto-correcting it.\n" ); - if (!interactive || get_key("12","?") == '1') { - init_fsinfo(&i); - fs_write(fs->fsinfo_start,sizeof(i),&i); - } - else fs->fsinfo_start = 0; - } - - if (fs->fsinfo_start) - fs->free_clusters = CF_LE_L(i.free_clusters); -} - -void read_boot(DOS_FS *fs) -{ - struct boot_sector b; - unsigned total_sectors; - unsigned short logical_sector_size, sectors; - unsigned fat_length; - loff_t data_size; - - fs_read(0,sizeof(b),&b); - logical_sector_size = GET_UNALIGNED_W(b.sector_size); - if (!logical_sector_size) die("Logical sector size is zero."); - fs->cluster_size = b.cluster_size*logical_sector_size; - if (!fs->cluster_size) die("Cluster size is zero."); - if (b.fats != 2 && b.fats != 1) - die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats); - fs->nfats = b.fats; - sectors = GET_UNALIGNED_W(b.sectors); - total_sectors = sectors ? sectors : CF_LE_L(b.total_sect); - if (verbose) printf("Checking we can access the last sector of the filesystem\n"); - /* Can't access last odd sector anyway, so round down */ - fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size, - logical_sector_size); - fat_length = CF_LE_W(b.fat_length) ? - CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length); - fs->fat_start = (off_t)CF_LE_W(b.reserved)*logical_sector_size; - fs->root_start = ((off_t)CF_LE_W(b.reserved)+b.fats*fat_length)* - logical_sector_size; - fs->root_entries = GET_UNALIGNED_W(b.dir_entries); - fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries << - MSDOS_DIR_BITS,logical_sector_size); - 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->fsinfo_start = 0; /* no FSINFO structure */ - fs->free_clusters = -1; /* unknown */ - if (!b.fat_length && b.fat32_length) { - fs->fat_bits = 32; - fs->root_cluster = CF_LE_L(b.root_cluster); - if (!fs->root_cluster && fs->root_entries) - /* M$ hasn't specified this, but it looks reasonable: If - * root_cluster is 0 but there is a separate root dir - * (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 - * to complex for now... */ - printf( "Warning: FAT32 root dir not in cluster chain! " - "Compability mode...\n" ); - else if (!fs->root_cluster && !fs->root_entries) - die("No root directory!"); - else if (fs->root_cluster && fs->root_entries) - printf( "Warning: FAT32 root dir is in a cluster chain, but " - "a separate root dir\n" - " area is defined. Cannot fix this easily.\n" ); - - fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size; - check_backup_boot(fs,&b,logical_sector_size); - - read_fsinfo(fs,&b,logical_sector_size); - } - else if (!atari_format) { - /* On real MS-DOS, a 16 bit FAT is used whenever there would be too - * much clusers otherwise. */ - fs->fat_bits = (fs->clusters > MSDOS_FAT12) ? 16 : 12; - } - else { - /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs - * on floppies, and always 16 bit on harddisks. */ - fs->fat_bits = 16; /* assume 16 bit FAT for now */ - /* If more clusters than fat entries in 16-bit fat, we assume - * it's a real MSDOS FS with 12-bit fat. */ - if (fs->clusters+2 > fat_length*logical_sector_size*8/16 || - /* if it's a floppy disk --> 12bit fat */ - device_no == 2 || - /* if it's a ramdisk or loopback device and has one of the usual - * floppy sizes -> 12bit FAT */ - ((device_no == 1 || device_no == 7) && - (total_sectors == 720 || total_sectors == 1440 || - total_sectors == 2880))) - fs->fat_bits = 12; - } - /* 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->fat_size = fat_length*logical_sector_size; - if (fs->clusters > ((__u64)fs->fat_size*8/fs->fat_bits)-2) - die("File system has %d clusters but only space for %d FAT entries.", - fs->clusters,((__u64)fs->fat_size*8/fs->fat_bits)-2); - if (!fs->root_entries && !fs->root_cluster) - die("Root directory has zero size."); - if (fs->root_entries & (MSDOS_DPS-1)) - die("Root directory (%d entries) doesn't span an integral number of " - "sectors.",fs->root_entries); - if (logical_sector_size & (SECTOR_SIZE-1)) - die("Logical sector size (%d bytes) is not a multiple of the physical " - "sector size.",logical_sector_size); - /* ++roman: On Atari, these two fields are often left uninitialized */ - if (!atari_format && (!b.secs_track || !b.heads)) - die("Invalid disk format in boot sector."); - if (verbose) dump_boot(fs,&b,logical_sector_size); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* boot.c - Read and analyze ia PC/MS-DOS boot sector */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + +#include +#include +#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "boot.h" + + +#define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) + /* don't divide by zero */ + +static struct { + __u8 media; + char *descr; +} mediabytes[] = { + { 0xf0, "5.25\" or 3.5\" HD floppy" }, + { 0xf8, "hard disk" }, + { 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or " + "5.25\" 1.2M floppy 2s/80tr/15sec" }, + { 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" }, + { 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" }, + { 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" }, + { 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" }, + { 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" }, + { 0xff, "5.25\" 320k floppy 2s/40tr/8sec" }, +}; + +#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__ +/* Unaligned fields must first be copied byte-wise */ +#define GET_UNALIGNED_W(f) \ + ({ \ + unsigned short __v; \ + memcpy( &__v, &f, sizeof(__v) ); \ + CF_LE_W( *(unsigned short *)&f ); \ + }) +#else +#define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f ) +#endif + + +static char *get_media_descr( unsigned char media ) +{ + int i; + + for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) { + if (mediabytes[i].media == media) + return( mediabytes[i].descr ); + } + return( "undefined" ); +} + +static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss) +{ + unsigned short sectors; + + printf("Boot sector contents:\n"); + if (!atari_format) { + char id[9]; + strncpy(id,b->system_id,8); + id[8] = 0; + printf("System ID \"%s\"\n",id); + } + else { + /* On Atari, a 24 bit serial number is stored at offset 8 of the boot + * sector */ + printf("Serial number 0x%x\n", + b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16)); + } + 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 cluster\n",fs->cluster_size); + printf("%10d reserved sector%s\n",CF_LE_W(b->reserved), + CF_LE_W(b->reserved) == 1 ? "" : "s"); + printf("First FAT starts at byte %llu (sector %llu)\n", + (__u64)fs->fat_start, + (__u64)fs->fat_start/lss); + printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits); + printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size, + fs->fat_size/lss); + if (!fs->root_cluster) { + printf("Root directory starts at byte %llu (sector %llu)\n", + (__u64)fs->root_start, + (__u64)fs->root_start/lss); + printf("%10d root directory entries\n",fs->root_entries); + } + else { + printf( "Root directory start at cluster %lu (arbitrary size)\n", + fs->root_cluster); + } + printf("Data area starts at byte %llu (sector %llu)\n", + (__u64)fs->data_start, + (__u64)fs->data_start/lss); + printf("%10lu data clusters (%llu bytes)\n",fs->clusters, + (__u64)fs->clusters*fs->cluster_size); + printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track), + CF_LE_W(b->heads)); + printf("%10u hidden sectors\n", + atari_format ? + /* On Atari, the hidden field is only 16 bit wide and unused */ + (((unsigned char *)&b->hidden)[0] | + ((unsigned char *)&b->hidden)[1] << 8) : + CF_LE_L(b->hidden)); + sectors = GET_UNALIGNED_W( b->sectors ); + 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) +{ + struct boot_sector b2; + + if (!fs->backupboot_start) { + printf( "There is no backup boot sector.\n" ); + if (CF_LE_W(b->reserved) < 3) { + printf( "And there is no space for creating one!\n" ); + return; + } + if (interactive) + printf( "1) Create one\n2) Do without a backup\n" ); + else printf( " Auto-creating backup boot block.\n" ); + if (!interactive || get_key("12","?") == '1') { + int bbs; + /* The usual place for the backup boot sector is sector 6. Choose + * that or the last reserved sector. */ + if (CF_LE_W(b->reserved) >= 7 && CF_LE_W(b->info_sector) != 6) + bbs = 6; + else { + bbs = CF_LE_W(b->reserved) - 1; + if (bbs == CF_LE_W(b->info_sector)) + --bbs; /* this is never 0, as we checked reserved >= 3! */ + } + fs->backupboot_start = bbs*lss; + b->backup_boot = CT_LE_W(bbs); + fs_write(fs->backupboot_start,sizeof(*b),b); + fs_write((off_t)offsetof(struct boot_sector,backup_boot), + sizeof(b->backup_boot),&b->backup_boot); + printf( "Created backup of boot sector in sector %d\n", bbs ); + return; + } + else return; + } + + fs_read(fs->backupboot_start,sizeof(b2),&b2); + if (memcmp(b,&b2,sizeof(b2)) != 0) { + /* there are any differences */ + __u8 *p, *q; + int i, pos, first = 1; + char buf[20]; + + printf( "There are differences between boot sector and its backup.\n" ); + printf( "Differences: (offset:original/backup)\n " ); + pos = 2; + for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2); + ++p, ++q, ++i ) { + if (*p != *q) { + sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ", + (unsigned)(p-(__u8 *)b), *p, *q ); + if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2; + printf( "%s", buf ); + pos += strlen(buf); + first = 0; + } + } + printf( "\n" ); + + if (interactive) + printf( "1) Copy original to backup\n" + "2) Copy backup to original\n" + "3) No action\n" ); + else printf( " Not automatically fixing this.\n" ); + switch (interactive ? get_key("123","?") : '3') { + case '1': + fs_write(fs->backupboot_start,sizeof(*b),b); + break; + case '2': + fs_write(0,sizeof(b2),&b2); + break; + default: + break; + } + } +} + +static void init_fsinfo(struct info_sector *i) +{ + i->magic = CT_LE_L(0x41615252); + i->signature = CT_LE_L(0x61417272); + i->free_clusters = CT_LE_L(-1); + i->next_cluster = CT_LE_L(2); + i->boot_sign = CT_LE_W(0xaa55); +} + +static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss) +{ + struct info_sector i; + + if (!b->info_sector) { + printf( "No FSINFO sector\n" ); + if (interactive) + printf( "1) Create one\n2) Do without FSINFO\n" ); + else printf( " Not automatically creating it.\n" ); + if (interactive && get_key("12","?") == '1') { + /* search for a free reserved sector (not boot sector and not + * backup boot sector) */ + __u32 s; + for( s = 1; s < CF_LE_W(b->reserved); ++s ) + if (s != CF_LE_W(b->backup_boot)) break; + if (s > 0 && s < CF_LE_W(b->reserved)) { + init_fsinfo(&i); + fs_write((off_t)s*lss,sizeof(i),&i); + b->info_sector = CT_LE_W(s); + fs_write((off_t)offsetof(struct boot_sector,info_sector), + sizeof(b->info_sector),&b->info_sector); + if (fs->backupboot_start) + fs_write(fs->backupboot_start+ + offsetof(struct boot_sector,info_sector), + sizeof(b->info_sector),&b->info_sector); + } + else { + printf( "No free reserved sector found -- " + "no space for FSINFO sector!\n" ); + return; + } + } + else return; + } + + fs->fsinfo_start = CF_LE_W(b->info_sector)*lss; + fs_read(fs->fsinfo_start,sizeof(i),&i); + + if (i.magic != CT_LE_L(0x41615252) || + i.signature != CT_LE_L(0x61417272) || + i.boot_sign != CT_LE_W(0xaa55)) { + printf( "FSINFO sector has bad magic number(s):\n" ); + if (i.magic != CT_LE_L(0x41615252)) + printf( " Offset %llu: 0x%08x != expected 0x%08x\n", + (__u64)offsetof(struct info_sector,magic), + CF_LE_L(i.magic),0x41615252); + if (i.signature != CT_LE_L(0x61417272)) + printf( " Offset %llu: 0x%08x != expected 0x%08x\n", + (__u64)offsetof(struct info_sector,signature), + CF_LE_L(i.signature),0x61417272); + if (i.boot_sign != CT_LE_W(0xaa55)) + printf( " Offset %llu: 0x%04x != expected 0x%04x\n", + (__u64)offsetof(struct info_sector,boot_sign), + CF_LE_W(i.boot_sign),0xaa55); + if (interactive) + printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" ); + else printf( " Auto-correcting it.\n" ); + if (!interactive || get_key("12","?") == '1') { + init_fsinfo(&i); + fs_write(fs->fsinfo_start,sizeof(i),&i); + } + else fs->fsinfo_start = 0; + } + + if (fs->fsinfo_start) + fs->free_clusters = CF_LE_L(i.free_clusters); +} + +void read_boot(DOS_FS *fs) +{ + struct boot_sector b; + unsigned total_sectors; + unsigned short logical_sector_size, sectors; + unsigned fat_length; + loff_t data_size; + + fs_read(0,sizeof(b),&b); + logical_sector_size = GET_UNALIGNED_W(b.sector_size); + if (!logical_sector_size) die("Logical sector size is zero."); + fs->cluster_size = b.cluster_size*logical_sector_size; + if (!fs->cluster_size) die("Cluster size is zero."); + if (b.fats != 2 && b.fats != 1) + die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats); + fs->nfats = b.fats; + sectors = GET_UNALIGNED_W(b.sectors); + total_sectors = sectors ? sectors : CF_LE_L(b.total_sect); + if (verbose) printf("Checking we can access the last sector of the filesystem\n"); + /* Can't access last odd sector anyway, so round down */ + fs_test((loff_t)((total_sectors & ~1)-1)*(loff_t)logical_sector_size, + logical_sector_size); + fat_length = CF_LE_W(b.fat_length) ? + CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length); + fs->fat_start = (off_t)CF_LE_W(b.reserved)*logical_sector_size; + fs->root_start = ((off_t)CF_LE_W(b.reserved)+b.fats*fat_length)* + logical_sector_size; + fs->root_entries = GET_UNALIGNED_W(b.dir_entries); + fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries << + MSDOS_DIR_BITS,logical_sector_size); + 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->fsinfo_start = 0; /* no FSINFO structure */ + fs->free_clusters = -1; /* unknown */ + if (!b.fat_length && b.fat32_length) { + fs->fat_bits = 32; + fs->root_cluster = CF_LE_L(b.root_cluster); + if (!fs->root_cluster && fs->root_entries) + /* M$ hasn't specified this, but it looks reasonable: If + * root_cluster is 0 but there is a separate root dir + * (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 + * to complex for now... */ + printf( "Warning: FAT32 root dir not in cluster chain! " + "Compability mode...\n" ); + else if (!fs->root_cluster && !fs->root_entries) + die("No root directory!"); + else if (fs->root_cluster && fs->root_entries) + printf( "Warning: FAT32 root dir is in a cluster chain, but " + "a separate root dir\n" + " area is defined. Cannot fix this easily.\n" ); + + fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size; + check_backup_boot(fs,&b,logical_sector_size); + + read_fsinfo(fs,&b,logical_sector_size); + } + else if (!atari_format) { + /* On real MS-DOS, a 16 bit FAT is used whenever there would be too + * much clusers otherwise. */ + fs->fat_bits = (fs->clusters > MSDOS_FAT12) ? 16 : 12; + } + else { + /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs + * on floppies, and always 16 bit on harddisks. */ + fs->fat_bits = 16; /* assume 16 bit FAT for now */ + /* If more clusters than fat entries in 16-bit fat, we assume + * it's a real MSDOS FS with 12-bit fat. */ + if (fs->clusters+2 > fat_length*logical_sector_size*8/16 || + /* if it's a floppy disk --> 12bit fat */ + device_no == 2 || + /* if it's a ramdisk or loopback device and has one of the usual + * floppy sizes -> 12bit FAT */ + ((device_no == 1 || device_no == 7) && + (total_sectors == 720 || total_sectors == 1440 || + total_sectors == 2880))) + fs->fat_bits = 12; + } + /* 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->fat_size = fat_length*logical_sector_size; + if (fs->clusters > ((__u64)fs->fat_size*8/fs->fat_bits)-2) + die("File system has %d clusters but only space for %d FAT entries.", + fs->clusters,((__u64)fs->fat_size*8/fs->fat_bits)-2); + if (!fs->root_entries && !fs->root_cluster) + die("Root directory has zero size."); + if (fs->root_entries & (MSDOS_DPS-1)) + die("Root directory (%d entries) doesn't span an integral number of " + "sectors.",fs->root_entries); + if (logical_sector_size & (SECTOR_SIZE-1)) + die("Logical sector size (%d bytes) is not a multiple of the physical " + "sector size.",logical_sector_size); + /* ++roman: On Atari, these two fields are often left uninitialized */ + if (!atari_format && (!b.secs_track || !b.heads)) + die("Invalid disk format in boot sector."); + if (verbose) dump_boot(fs,&b,logical_sector_size); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/boot.h b/rosapps/sysutils/dosfsck/boot.h index 0540c701662..63cbcf01995 100644 --- a/rosapps/sysutils/dosfsck/boot.h +++ b/rosapps/sysutils/dosfsck/boot.h @@ -1,13 +1,13 @@ -/* boot.h - Read and analyze ia PC/MS-DOS boot sector */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _BOOT_H -#define _BOOT_H - -void read_boot(DOS_FS *fs); - -/* Reads the boot sector from the currently open device and initializes *FS */ - -#endif +/* boot.h - Read and analyze ia PC/MS-DOS boot sector */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _BOOT_H +#define _BOOT_H + +void read_boot(DOS_FS *fs); + +/* Reads the boot sector from the currently open device and initializes *FS */ + +#endif diff --git a/rosapps/sysutils/dosfsck/byteorder.h b/rosapps/sysutils/dosfsck/byteorder.h index 07ab6ebfaac..15b87c09e18 100644 --- a/rosapps/sysutils/dosfsck/byteorder.h +++ b/rosapps/sysutils/dosfsck/byteorder.h @@ -1,59 +1,59 @@ -#ifndef _I386_BYTEORDER_H -#define _I386_BYTEORDER_H - -//#include "types.h" -#include "compiler.h" - -#ifdef __GNUC__ - -/* For avoiding bswap on i386 */ -//#ifdef __KERNEL__ -//#include -//#endif - -static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) -{ -#ifdef CONFIG_X86_BSWAP - __asm__("bswap %0" : "=r" (x) : "0" (x)); -#else - __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ - "rorl $16,%0\n\t" /* swap words */ - "xchgb %b0,%h0" /* swap higher bytes */ - :"=q" (x) - : "0" (x)); -#endif - return x; -} - -static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val) -{ - union { - struct { __u32 a,b; } s; - __u64 u; - } v; - v.u = val; -#ifdef CONFIG_X86_BSWAP - asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1" - : "=r" (v.s.a), "=r" (v.s.b) - : "0" (v.s.a), "1" (v.s.b)); -#else - v.s.a = ___arch__swab32(v.s.a); - v.s.b = ___arch__swab32(v.s.b); - asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b)); -#endif - return v.u; -} - -/* Do not define swab16. Gcc is smart enough to recognize "C" version and - convert it into rotation or exhange. */ - -#define __arch__swab64(x) ___arch__swab64(x) -#define __arch__swab32(x) ___arch__swab32(x) - -#define __BYTEORDER_HAS_U64__ - -#endif /* __GNUC__ */ - -//#include "little_endian.h" - -#endif /* _I386_BYTEORDER_H */ +#ifndef _I386_BYTEORDER_H +#define _I386_BYTEORDER_H + +//#include "types.h" +#include "compiler.h" + +#ifdef __GNUC__ + +/* For avoiding bswap on i386 */ +//#ifdef __KERNEL__ +//#include +//#endif + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +{ +#ifdef CONFIG_X86_BSWAP + __asm__("bswap %0" : "=r" (x) : "0" (x)); +#else + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ + "rorl $16,%0\n\t" /* swap words */ + "xchgb %b0,%h0" /* swap higher bytes */ + :"=q" (x) + : "0" (x)); +#endif + return x; +} + +static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val) +{ + union { + struct { __u32 a,b; } s; + __u64 u; + } v; + v.u = val; +#ifdef CONFIG_X86_BSWAP + asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1" + : "=r" (v.s.a), "=r" (v.s.b) + : "0" (v.s.a), "1" (v.s.b)); +#else + v.s.a = ___arch__swab32(v.s.a); + v.s.b = ___arch__swab32(v.s.b); + asm("xchgl %0,%1" : "=r" (v.s.a), "=r" (v.s.b) : "0" (v.s.a), "1" (v.s.b)); +#endif + return v.u; +} + +/* Do not define swab16. Gcc is smart enough to recognize "C" version and + convert it into rotation or exhange. */ + +#define __arch__swab64(x) ___arch__swab64(x) +#define __arch__swab32(x) ___arch__swab32(x) + +#define __BYTEORDER_HAS_U64__ + +#endif /* __GNUC__ */ + +//#include "little_endian.h" + +#endif /* _I386_BYTEORDER_H */ diff --git a/rosapps/sysutils/dosfsck/byteswap.h b/rosapps/sysutils/dosfsck/byteswap.h index 0cf37c16848..4a09eb6d68f 100644 --- a/rosapps/sysutils/dosfsck/byteswap.h +++ b/rosapps/sysutils/dosfsck/byteswap.h @@ -1,40 +1,40 @@ -/* Copyright (C) 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _BYTESWAP_H -#define _BYTESWAP_H 1 - -/* Get the machine specific, optimized definitions. */ -#include "byteswap1.h" - - -/* The following definitions must all be macros since otherwise some - of the possible optimizations are not possible. */ - -/* Return a value with all bytes in the 16 bit argument swapped. */ -#define bswap_16(x) __bswap_16 (x) - -/* Return a value with all bytes in the 32 bit argument swapped. */ -#define bswap_32(x) __bswap_32 (x) - -#if defined __GNUC__ && __GNUC__ >= 2 -/* Return a value with all bytes in the 64 bit argument swapped. */ -# define bswap_64(x) __bswap_64 (x) -#endif - -#endif /* byteswap.h */ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H 1 + +/* Get the machine specific, optimized definitions. */ +#include "byteswap1.h" + + +/* The following definitions must all be macros since otherwise some + of the possible optimizations are not possible. */ + +/* Return a value with all bytes in the 16 bit argument swapped. */ +#define bswap_16(x) __bswap_16 (x) + +/* Return a value with all bytes in the 32 bit argument swapped. */ +#define bswap_32(x) __bswap_32 (x) + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Return a value with all bytes in the 64 bit argument swapped. */ +# define bswap_64(x) __bswap_64 (x) +#endif + +#endif /* byteswap.h */ diff --git a/rosapps/sysutils/dosfsck/byteswap1.h b/rosapps/sysutils/dosfsck/byteswap1.h index 33af2088883..1e5d4666134 100644 --- a/rosapps/sysutils/dosfsck/byteswap1.h +++ b/rosapps/sysutils/dosfsck/byteswap1.h @@ -1,133 +1,133 @@ -/* Macros to swap the order of bytes in integer values. - Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#if !defined _BYTESWAP_H && !defined _NETINET_IN_H -# error "Never use directly; include instead." -#endif - -#ifndef _BITS_BYTESWAP_H -#define _BITS_BYTESWAP_H 1 - -/* Swap bytes in 16 bit value. */ -#define __bswap_constant_16(x) \ - ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) - -#ifdef __GNUC__ -# if __GNUC__ >= 2 -# define __bswap_16(x) \ - (__extension__ \ - ({ register unsigned short int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_16 (__x); \ - else \ - __asm__ ("rorw $8, %w0" \ - : "=r" (__v) \ - : "0" (__x) \ - : "cc"); \ - __v; })) -# else -/* This is better than nothing. */ -# define __bswap_16(x) \ - (__extension__ \ - ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) -# endif -#else -static __inline unsigned short int -__bswap_16 (unsigned short int __bsx) -{ - return __bswap_constant_16 (__bsx); -} -#endif - -/* Swap bytes in 32 bit value. */ -#define __bswap_constant_32(x) \ - ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) - -#ifdef __GNUC__ -# if __GNUC__ >= 2 -/* To swap the bytes in a word the i486 processors and up provide the - `bswap' opcode. On i386 we have to use three instructions. */ -# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ - && !defined __pentium4__ -# define __bswap_32(x) \ - (__extension__ \ - ({ register unsigned int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_32 (__x); \ - else \ - __asm__ ("rorw $8, %w0;" \ - "rorl $16, %0;" \ - "rorw $8, %w0" \ - : "=r" (__v) \ - : "0" (__x) \ - : "cc"); \ - __v; })) -# else -# define __bswap_32(x) \ - (__extension__ \ - ({ register unsigned int __v, __x = (x); \ - if (__builtin_constant_p (__x)) \ - __v = __bswap_constant_32 (__x); \ - else \ - __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ - __v; })) -# endif -# else -# define __bswap_32(x) \ - (__extension__ \ - ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) -# endif -#else -static __inline unsigned int -__bswap_32 (unsigned int __bsx) -{ - return __bswap_constant_32 (__bsx); -} -#endif - - -#if defined __GNUC__ && __GNUC__ >= 2 -/* Swap bytes in 64 bit value. */ -#define __bswap_constant_64(x) \ - ((((x) & 0xff00000000000000ull) >> 56) \ - | (((x) & 0x00ff000000000000ull) >> 40) \ - | (((x) & 0x0000ff0000000000ull) >> 24) \ - | (((x) & 0x000000ff00000000ull) >> 8) \ - | (((x) & 0x00000000ff000000ull) << 8) \ - | (((x) & 0x0000000000ff0000ull) << 24) \ - | (((x) & 0x000000000000ff00ull) << 40) \ - | (((x) & 0x00000000000000ffull) << 56)) - -# define __bswap_64(x) \ - (__extension__ \ - ({ union { __extension__ unsigned long long int __ll; \ - unsigned long int __l[2]; } __w, __r; \ - if (__builtin_constant_p (x)) \ - __r.__ll = __bswap_constant_64 (x); \ - else \ - { \ - __w.__ll = (x); \ - __r.__l[0] = __bswap_32 (__w.__l[1]); \ - __r.__l[1] = __bswap_32 (__w.__l[0]); \ - } \ - __r.__ll; })) -#endif - -#endif /* _BITS_BYTESWAP_H */ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else +/* This is better than nothing. */ +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) +# endif +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +/* To swap the bytes in a word the i486 processors and up provide the + `bswap' opcode. On i386 we have to use three instructions. */ +# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ + && !defined __pentium4__ +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ + __v; })) +# endif +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) +# endif +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +#define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned long int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/rosapps/sysutils/dosfsck/check.c b/rosapps/sysutils/dosfsck/check.c index a7c384aba34..425bd208461 100644 --- a/rosapps/sysutils/dosfsck/check.c +++ b/rosapps/sysutils/dosfsck/check.c @@ -1,867 +1,867 @@ -/* check.c - Check and repair a PC/MS-DOS file system */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -#include +/* check.c - Check and repair a PC/MS-DOS file system */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +#include #include -#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "fat.h" -#include "file.h" -#include "lfn.h" -#include "check.h" - - -static DOS_FILE *root; - -/* get start field of a dir entry */ -#define FSTART(p,fs) \ - ((unsigned long)CF_LE_W(p->dir_ent.start) | \ - (fs->fat_bits == 32 ? CF_LE_W(p->dir_ent.starthi) << 16 : 0)) - -#define MODIFY(p,i,v) \ - do { \ - if (p->offset) { \ - p->dir_ent.i = v; \ - fs_write(p->offset+offsetof(DIR_ENT,i), \ - sizeof(p->dir_ent.i),&p->dir_ent.i); \ - } \ - } while(0) - -#define MODIFY_START(p,v,fs) \ - do { \ - unsigned long __v = (v); \ - if (!p->offset) { \ - /* writing to fake entry for FAT32 root dir */ \ - if (!__v) die("Oops, deleting FAT32 root dir!"); \ - fs->root_cluster = __v; \ - p->dir_ent.start = CT_LE_W(__v&0xffff); \ - p->dir_ent.starthi = CT_LE_W(__v>>16); \ - __v = CT_LE_L(__v); \ - fs_write((loff_t)offsetof(struct boot_sector,root_cluster), \ - sizeof(((struct boot_sector *)0)->root_cluster), \ - &__v); \ - } \ - else { \ - MODIFY(p,start,CT_LE_W((__v)&0xffff)); \ - if (fs->fat_bits == 32) \ - MODIFY(p,starthi,CT_LE_W((__v)>>16)); \ - } \ - } while(0) - - -loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern) -{ - static int curr_num = 0; - loff_t offset; - - if (fs->root_cluster) { - DIR_ENT d2; - int i = 0, got = 0; - unsigned long clu_num, prev = 0; - loff_t offset2; - - clu_num = fs->root_cluster; - offset = cluster_start(fs,clu_num); - while (clu_num > 0 && clu_num != -1) { - fs_read(offset,sizeof(DIR_ENT),&d2); - if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) { - got = 1; - break; - } - i += sizeof(DIR_ENT); - offset += sizeof(DIR_ENT); - if ((i % fs->cluster_size) == 0) { - prev = clu_num; - if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) - break; - offset = cluster_start(fs,clu_num); - } - } - if (!got) { - /* no free slot, need to extend root dir: alloc next free cluster - * after previous one */ - if (!prev) - die("Root directory has no cluster allocated!"); - for (clu_num = prev+1; clu_num != prev; clu_num++) { - if (clu_num >= fs->clusters+2) clu_num = 2; - if (!fs->fat[clu_num].value) - break; - } - if (clu_num == prev) - die("Root directory full and no free cluster"); - set_fat(fs,prev,clu_num); - set_fat(fs,clu_num,-1); - set_owner(fs, clu_num, get_owner(fs, fs->root_cluster)); - /* clear new cluster */ - memset( &d2, 0, sizeof(d2) ); - offset = cluster_start(fs,clu_num); - for( i = 0; i < (int)fs->cluster_size; i += sizeof(DIR_ENT) ) - fs_write( offset+i, sizeof(d2), &d2 ); - } - memset(de,0,sizeof(DIR_ENT)); - while (1) { - sprintf(de->name,pattern,curr_num); - clu_num = fs->root_cluster; - i = 0; - offset2 = cluster_start(fs,clu_num); - while (clu_num > 0 && clu_num != -1) { - fs_read(offset2,sizeof(DIR_ENT),&d2); - if (offset2 != offset && - !strncmp(d2.name,de->name,MSDOS_NAME)) - break; - i += sizeof(DIR_ENT); - offset2 += sizeof(DIR_ENT); - if ((i % fs->cluster_size) == 0) { - if ((clu_num = next_cluster(fs,clu_num)) == 0 || - clu_num == -1) - break; - offset2 = cluster_start(fs,clu_num); - } - } - if (clu_num == 0 || clu_num == -1) - break; - if (++curr_num >= 10000) die("Unable to create unique name"); - } - } - else { - DIR_ENT *root; - int next_free = 0, scan; - - root = alloc(fs->root_entries*sizeof(DIR_ENT)); - fs_read(fs->root_start,fs->root_entries*sizeof(DIR_ENT),root); - - while (next_free < (int)fs->root_entries) - if (IS_FREE(root[next_free].name) && - root[next_free].attr != VFAT_LN_ATTR) - break; - else next_free++; - if (next_free == (int)fs->root_entries) - die("Root directory is full."); - offset = fs->root_start+next_free*sizeof(DIR_ENT); - memset(de,0,sizeof(DIR_ENT)); - while (1) { - sprintf(de->name,pattern,curr_num); - for (scan = 0; scan < (int)fs->root_entries; scan++) - if (scan != next_free && - !strncmp(root[scan].name,de->name,MSDOS_NAME)) - break; - if (scan == (int)fs->root_entries) break; - if (++curr_num >= 10000) die("Unable to create unique name"); - } - free(root); - } - ++n_files; - return offset; -} - - -static char *path_name(DOS_FILE *file) -{ +#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "fat.h" +#include "file.h" +#include "lfn.h" +#include "check.h" + + +static DOS_FILE *root; + +/* get start field of a dir entry */ +#define FSTART(p,fs) \ + ((unsigned long)CF_LE_W(p->dir_ent.start) | \ + (fs->fat_bits == 32 ? CF_LE_W(p->dir_ent.starthi) << 16 : 0)) + +#define MODIFY(p,i,v) \ + do { \ + if (p->offset) { \ + p->dir_ent.i = v; \ + fs_write(p->offset+offsetof(DIR_ENT,i), \ + sizeof(p->dir_ent.i),&p->dir_ent.i); \ + } \ + } while(0) + +#define MODIFY_START(p,v,fs) \ + do { \ + unsigned long __v = (v); \ + if (!p->offset) { \ + /* writing to fake entry for FAT32 root dir */ \ + if (!__v) die("Oops, deleting FAT32 root dir!"); \ + fs->root_cluster = __v; \ + p->dir_ent.start = CT_LE_W(__v&0xffff); \ + p->dir_ent.starthi = CT_LE_W(__v>>16); \ + __v = CT_LE_L(__v); \ + fs_write((loff_t)offsetof(struct boot_sector,root_cluster), \ + sizeof(((struct boot_sector *)0)->root_cluster), \ + &__v); \ + } \ + else { \ + MODIFY(p,start,CT_LE_W((__v)&0xffff)); \ + if (fs->fat_bits == 32) \ + MODIFY(p,starthi,CT_LE_W((__v)>>16)); \ + } \ + } while(0) + + +loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern) +{ + static int curr_num = 0; + loff_t offset; + + if (fs->root_cluster) { + DIR_ENT d2; + int i = 0, got = 0; + unsigned long clu_num, prev = 0; + loff_t offset2; + + clu_num = fs->root_cluster; + offset = cluster_start(fs,clu_num); + while (clu_num > 0 && clu_num != -1) { + fs_read(offset,sizeof(DIR_ENT),&d2); + if (IS_FREE(d2.name) && d2.attr != VFAT_LN_ATTR) { + got = 1; + break; + } + i += sizeof(DIR_ENT); + offset += sizeof(DIR_ENT); + if ((i % fs->cluster_size) == 0) { + prev = clu_num; + if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) + break; + offset = cluster_start(fs,clu_num); + } + } + if (!got) { + /* no free slot, need to extend root dir: alloc next free cluster + * after previous one */ + if (!prev) + die("Root directory has no cluster allocated!"); + for (clu_num = prev+1; clu_num != prev; clu_num++) { + if (clu_num >= fs->clusters+2) clu_num = 2; + if (!fs->fat[clu_num].value) + break; + } + if (clu_num == prev) + die("Root directory full and no free cluster"); + set_fat(fs,prev,clu_num); + set_fat(fs,clu_num,-1); + set_owner(fs, clu_num, get_owner(fs, fs->root_cluster)); + /* clear new cluster */ + memset( &d2, 0, sizeof(d2) ); + offset = cluster_start(fs,clu_num); + for( i = 0; i < (int)fs->cluster_size; i += sizeof(DIR_ENT) ) + fs_write( offset+i, sizeof(d2), &d2 ); + } + memset(de,0,sizeof(DIR_ENT)); + while (1) { + sprintf(de->name,pattern,curr_num); + clu_num = fs->root_cluster; + i = 0; + offset2 = cluster_start(fs,clu_num); + while (clu_num > 0 && clu_num != -1) { + fs_read(offset2,sizeof(DIR_ENT),&d2); + if (offset2 != offset && + !strncmp(d2.name,de->name,MSDOS_NAME)) + break; + i += sizeof(DIR_ENT); + offset2 += sizeof(DIR_ENT); + if ((i % fs->cluster_size) == 0) { + if ((clu_num = next_cluster(fs,clu_num)) == 0 || + clu_num == -1) + break; + offset2 = cluster_start(fs,clu_num); + } + } + if (clu_num == 0 || clu_num == -1) + break; + if (++curr_num >= 10000) die("Unable to create unique name"); + } + } + else { + DIR_ENT *root; + int next_free = 0, scan; + + root = alloc(fs->root_entries*sizeof(DIR_ENT)); + fs_read(fs->root_start,fs->root_entries*sizeof(DIR_ENT),root); + + while (next_free < (int)fs->root_entries) + if (IS_FREE(root[next_free].name) && + root[next_free].attr != VFAT_LN_ATTR) + break; + else next_free++; + if (next_free == (int)fs->root_entries) + die("Root directory is full."); + offset = fs->root_start+next_free*sizeof(DIR_ENT); + memset(de,0,sizeof(DIR_ENT)); + while (1) { + sprintf(de->name,pattern,curr_num); + for (scan = 0; scan < (int)fs->root_entries; scan++) + if (scan != next_free && + !strncmp(root[scan].name,de->name,MSDOS_NAME)) + break; + if (scan == (int)fs->root_entries) break; + if (++curr_num >= 10000) die("Unable to create unique name"); + } + free(root); + } + ++n_files; + return offset; +} + + +static char *path_name(DOS_FILE *file) +{ // static char path[PATH_MAX*2]; - static char path[MAX_PATH*2]; - - if (!file) *path = 0; - else { - if (strlen(path_name(file->parent)) > MAX_PATH) - die("Path name too long."); - if (strcmp(path,"/") != 0) strcat(path,"/"); - strcpy(strrchr(path,0),file->lfn?file->lfn:file_name(file->dir_ent.name)); - } - return path; -} - - -static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; - /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ - - -/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ - -time_t date_dos2unix(unsigned short time,unsigned short date) -{ - int month,year; - time_t secs; - - month = ((date >> 5) & 15)-1; - year = date >> 9; - secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* - ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && - month < 2 ? 1 : 0)+3653); - /* days since 1.1.70 plus 80's leap day */ - return secs; -} - - -static char *file_stat(DOS_FILE *file) -{ - static char temp[100]; - struct tm *tm; - char tmp[100]; - time_t date; - - date = date_dos2unix(CF_LE_W(file->dir_ent.time),CF_LE_W(file-> - dir_ent.date)); - tm = localtime(&date); - strftime(tmp,99,"%H:%M:%S %b %d %Y",tm); - sprintf(temp," Size %u bytes, date %s",CF_LE_L(file->dir_ent.size),tmp); - return temp; -} - - -static int bad_name(unsigned char *name) -{ - int i, spc, suspicious = 0; - char *bad_chars = atari_format ? "*?\\/:" : "*?<>|\"\\/:"; - - /* Do not complain about (and auto-correct) the extended attribute files - * of OS/2. */ - if (strncmp(name,"EA DATA SF",11) == 0 || - strncmp(name,"WP ROOT SF",11) == 0) return 0; - - for (i = 0; i < 8; i++) { - if (name[i] < ' ' || name[i] == 0x7f) return 1; - if (name[i] > 0x7f) ++suspicious; - if (strchr(bad_chars,name[i])) return 1; - } - - for (i = 8; i < 11; i++) { - if (name[i] < ' ' || name[i] == 0x7f) return 1; - if (name[i] > 0x7f) ++suspicious; - if (strchr(bad_chars,name[i])) return 1; - } - - spc = 0; - for (i = 0; i < 8; i++) { - if (name[i] == ' ') - spc = 1; - else if (spc) - /* non-space after a space not allowed, space terminates the name - * part */ - return 1; - } - - spc = 0; - for (i = 8; i < 11; i++) { - if (name[i] == ' ') - spc = 1; - else if (spc) - /* non-space after a space not allowed, space terminates the name - * part */ - return 1; - } - - /* Under GEMDOS, chars >= 128 are never allowed. */ - if (atari_format && suspicious) - return 1; - - /* Only complain about too much suspicious chars in interactive mode, - * never correct them automatically. The chars are all basically ok, so we - * shouldn't auto-correct such names. */ - if (interactive && suspicious > 6) - return 1; - return 0; -} - - -static void drop_file(DOS_FS *fs,DOS_FILE *file) -{ - unsigned long cluster; - - MODIFY(file,name[0],DELETED_FLAG); - for (cluster = FSTART(file,fs); cluster > 0 && cluster < - fs->clusters+2; cluster = next_cluster(fs,cluster)) - set_owner(fs,cluster,NULL); - --n_files; -} - - -static void truncate_file(DOS_FS *fs,DOS_FILE *file,unsigned long clusters) -{ - int deleting; - unsigned long walk,next,prev; - - walk = FSTART(file,fs); - prev = 0; - if ((deleting = !clusters)) MODIFY_START(file,0,fs); - while (walk > 0 && walk != -1) { - next = next_cluster(fs,walk); - if (deleting) set_fat(fs,walk,0); - else if ((deleting = !--clusters)) set_fat(fs,walk,-1); - prev = walk; - walk = next; - } -} - - -static void auto_rename(DOS_FILE *file) -{ - DOS_FILE *first,*walk; - int number; - - if (!file->offset) return; /* cannot rename FAT32 root dir */ - first = file->parent ? file->parent->first : root; - number = 0; - while (1) { - sprintf(file->dir_ent.name,"FSCK%04d",number); - strncpy(file->dir_ent.ext,"REN",3); - for (walk = first; walk; walk = walk->next) - if (walk != file && !strncmp(walk->dir_ent.name,file->dir_ent. - name,MSDOS_NAME)) break; - if (!walk) { - fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); - return; - } - number++; - } - die("Can't generate a unique name."); -} - - -static void rename_file(DOS_FILE *file) -{ - unsigned char name[46]; - unsigned char *walk,*here; - - if (!file->offset) { - printf( "Cannot rename FAT32 root dir\n" ); - return; /* cannot rename FAT32 root dir */ - } - while (1) { - printf("New name: "); - fflush(stdout); - if (fgets(name,45,stdin)) { - if ((here = strchr(name,'\n'))) *here = 0; - for (walk = strrchr(name,0); walk >= name && (*walk == ' ' || - *walk == '\t'); walk--); - walk[1] = 0; - for (walk = name; *walk == ' ' || *walk == '\t'; walk++); - if (file_cvt(walk,file->dir_ent.name)) { - fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); - return; - } - } - } -} - - -static int handle_dot(DOS_FS *fs,DOS_FILE *file,int dots) -{ - char *name; - - name = strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME) ? ".." : "."; - if (!(file->dir_ent.attr & ATTR_DIR)) { - printf("%s\n Is a non-directory.\n",path_name(file)); - if (interactive) - printf("1) Drop it\n2) Auto-rename\n3) Rename\n" - "4) Convert to directory\n"); - else printf(" Auto-renaming it.\n"); - switch (interactive ? get_key("1234","?") : '2') { - case '1': - drop_file(fs,file); - return 1; - case '2': - auto_rename(file); - printf(" Renamed to %s\n",file_name(file->dir_ent.name)); - return 0; - case '3': - rename_file(file); - return 0; - case '4': - MODIFY(file,size,CT_LE_L(0)); - MODIFY(file,attr,file->dir_ent.attr | ATTR_DIR); - break; - } - } - if (!dots) { - printf("Root contains directory \"%s\". Dropping it.\n",name); - drop_file(fs,file); - return 1; - } - return 0; -} - - -static int check_file(DOS_FS *fs,DOS_FILE *file) -{ - DOS_FILE *owner; - int restart; - unsigned long expect,curr,this,clusters,prev,walk,clusters2; - - if (file->dir_ent.attr & ATTR_DIR) { - if (CF_LE_L(file->dir_ent.size)) { - printf("%s\n Directory has non-zero size. Fixing it.\n", - path_name(file)); - MODIFY(file,size,CT_LE_L(0)); - } - if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) { - expect = FSTART(file->parent,fs); - if (FSTART(file,fs) != expect) { - printf("%s\n Start (%ld) does not point to parent (%ld)\n", - path_name(file),FSTART(file,fs),expect); - MODIFY_START(file,expect,fs); - } - return 0; - } - if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOTDOT, - MSDOS_NAME)) { - expect = file->parent->parent ? FSTART(file->parent->parent,fs):0; - if (fs->root_cluster && expect == fs->root_cluster) - expect = 0; - if (FSTART(file,fs) != expect) { - printf("%s\n Start (%lu) does not point to .. (%lu)\n", - path_name(file),FSTART(file,fs),expect); - MODIFY_START(file,expect,fs); - } - return 0; - } - if (FSTART(file,fs)==0){ - printf ("%s\n Start does point to root directory. Deleting dir. \n", - path_name(file)); - MODIFY(file,name[0],DELETED_FLAG); - return 0; - } - } - if (FSTART(file,fs) >= fs->clusters+2) { - printf("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n", - path_name(file),FSTART(file,fs),fs->clusters+1); - if (!file->offset) - die( "Bad FAT32 root directory! (bad start cluster)\n" ); - MODIFY_START(file,0,fs); - } - clusters = prev = 0; - for (curr = FSTART(file,fs) ? FSTART(file,fs) : - -1; curr != -1; curr = next_cluster(fs,curr)) { - if (!fs->fat[curr].value || bad_cluster(fs,curr)) { - printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n", - path_name(file),fs->fat[curr].value ? "bad" : "free",curr); - if (prev) set_fat(fs,prev,-1); - else if (!file->offset) - die( "FAT32 root dir starts with a bad cluster!" ); - else MODIFY_START(file,0,fs); - break; - } - if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) <= - clusters*fs->cluster_size) { - printf("%s\n File size is %u bytes, cluster chain length is > %lu " - "bytes.\n Truncating file to %u bytes.\n",path_name(file), - CF_LE_L(file->dir_ent.size),clusters*fs->cluster_size, - CF_LE_L(file->dir_ent.size)); - truncate_file(fs,file,clusters); - break; - } - if ((owner = get_owner(fs,curr))) { - int do_trunc = 0; - printf("%s and\n",path_name(owner)); - printf("%s\n share clusters.\n",path_name(file)); - clusters2 = 0; - for (walk = FSTART(owner,fs); walk > 0 && walk != -1; walk = - next_cluster(fs,walk)) - if (walk == curr) break; - else clusters2++; - restart = file->dir_ent.attr & ATTR_DIR; - if (!owner->offset) { - printf( " Truncating second to %lu bytes because first " - "is FAT32 root dir.\n", clusters2*fs->cluster_size ); - do_trunc = 2; - } - else if (!file->offset) { - printf( " Truncating first to %lu bytes because second " - "is FAT32 root dir.\n", clusters*fs->cluster_size ); - do_trunc = 1; - } - else if (interactive) - printf("1) Truncate first to %lu bytes%s\n" - "2) Truncate second to %lu bytes\n",clusters*fs->cluster_size, - restart ? " and restart" : "",clusters2*fs->cluster_size); - else printf(" Truncating second to %lu bytes.\n",clusters2* - fs->cluster_size); - if (do_trunc != 2 && - (do_trunc == 1 || - (interactive && get_key("12","?") == '1'))) { - prev = 0; - clusters = 0; - for (this = FSTART(owner,fs); this > 0 && this != -1; this = - next_cluster(fs,this)) { - if (this == curr) { - if (prev) set_fat(fs,prev,-1); - else MODIFY_START(owner,0,fs); - MODIFY(owner,size,CT_LE_L(clusters*fs->cluster_size)); - if (restart) return 1; - while (this > 0 && this != -1) { - set_owner(fs,this,NULL); - this = next_cluster(fs,this); - } - break; - } - clusters++; - prev = this; - } - if (this != curr) - die("Internal error: didn't find cluster %d in chain" - " starting at %d",curr,FSTART(owner,fs)); - } - else { - if (prev) set_fat(fs,prev,-1); - else MODIFY_START(file,0,fs); - break; - } - } - set_owner(fs,curr,file); - clusters++; - prev = curr; - } - if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) > - clusters*fs->cluster_size) { - printf("%s\n File size is %u bytes, cluster chain length is %lu bytes." - "\n Truncating file to %lu bytes.\n",path_name(file),CF_LE_L(file-> - dir_ent.size),clusters*fs->cluster_size,clusters*fs->cluster_size); - MODIFY(file,size,CT_LE_L(clusters*fs->cluster_size)); - } - return 0; -} - - -static int check_files(DOS_FS *fs,DOS_FILE *start) -{ - while (start) { - if (check_file(fs,start)) return 1; - start = start->next; - } - return 0; -} - - -static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots) -{ - DOS_FILE *parent,**walk,**scan; - int dot,dotdot,skip,redo; - int good,bad; - - if (!*root) return 0; - parent = (*root)->parent; - good = bad = 0; - for (walk = root; *walk; walk = &(*walk)->next) - if (bad_name((*walk)->dir_ent.name)) bad++; - else good++; - if (*root && parent && good+bad > 4 && bad > good/2) { - printf("%s\n Has a large number of bad entries. (%d/%d)\n", - path_name(parent),bad,good+bad); - if (!dots) printf( " Not dropping root directory.\n" ); - else if (!interactive) printf(" Not dropping it in auto-mode.\n"); - else if (get_key("yn","Drop directory ? (y/n)") == 'y') { - truncate_file(fs,parent,0); - MODIFY(parent,name[0],DELETED_FLAG); - /* buglet: deleted directory stays in the list. */ - return 1; - } - } - dot = dotdot = redo = 0; - walk = root; - while (*walk) { - if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME) || - !strncmp((*walk)->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) { - if (handle_dot(fs,*walk,dots)) { - *walk = (*walk)->next; - continue; - } - if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) dot++; - else dotdot++; - } - if (!((*walk)->dir_ent.attr & ATTR_VOLUME) && - bad_name((*walk)->dir_ent.name)) { - printf("%s\n Bad file name.\n",path_name(*walk)); - if (interactive) - printf("1) Drop file\n2) Rename file\n3) Auto-rename\n" - "4) Keep it\n"); - else printf(" Auto-renaming it.\n"); - switch (interactive ? get_key("1234","?") : '3') { - case '1': - drop_file(fs,*walk); - walk = &(*walk)->next; - continue; - case '2': - rename_file(*walk); - redo = 1; - break; - case '3': - auto_rename(*walk); - printf(" Renamed to %s\n",file_name((*walk)->dir_ent. - name)); - break; - case '4': - break; - } - } - /* don't check for duplicates of the volume label */ - if (!((*walk)->dir_ent.attr & ATTR_VOLUME)) { - scan = &(*walk)->next; - skip = 0; - while (*scan && !skip) { - if (!((*scan)->dir_ent.attr & ATTR_VOLUME) && - !strncmp((*walk)->dir_ent.name,(*scan)->dir_ent.name,MSDOS_NAME)) { - printf("%s\n Duplicate directory entry.\n First %s\n", - path_name(*walk),file_stat(*walk)); - printf(" Second %s\n",file_stat(*scan)); - if (interactive) - printf("1) Drop first\n2) Drop second\n3) Rename first\n" - "4) Rename second\n5) Auto-rename first\n" - "6) Auto-rename second\n"); - else printf(" Auto-renaming second.\n"); - switch (interactive ? get_key("123456","?") : '6') { - case '1': - drop_file(fs,*walk); - *walk = (*walk)->next; - skip = 1; - break; - case '2': - drop_file(fs,*scan); - *scan = (*scan)->next; - continue; - case '3': - rename_file(*walk); - printf(" Renamed to %s\n",path_name(*walk)); - redo = 1; - break; - case '4': - rename_file(*scan); - printf(" Renamed to %s\n",path_name(*walk)); - redo = 1; - break; - case '5': - auto_rename(*walk); - printf(" Renamed to %s\n",file_name((*walk)->dir_ent. - name)); - break; - case '6': - auto_rename(*scan); - printf(" Renamed to %s\n",file_name((*scan)->dir_ent. - name)); - break; - } - } - scan = &(*scan)->next; - } - if (skip) continue; - } - if (!redo) walk = &(*walk)->next; - else { - walk = root; - dot = dotdot = redo = 0; - } - } - if (dots && !dot) - printf("%s\n \".\" is missing. Can't fix this yet.\n", - path_name(parent)); - if (dots && !dotdot) - printf("%s\n \"..\" is missing. Can't fix this yet.\n", - path_name(parent)); - return 0; -} - - -static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test) -{ - DOS_FILE *owner; - unsigned long walk,prev,clusters,next_clu; - - prev = clusters = 0; - for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; - walk = next_clu) { - next_clu = next_cluster(fs,walk); - if ((owner = get_owner(fs,walk))) { - if (owner == file) { - printf("%s\n Circular cluster chain. Truncating to %lu " - "cluster%s.\n",path_name(file),clusters,clusters == 1 ? "" : - "s"); - if (prev) set_fat(fs,prev,-1); - else if (!file->offset) - die( "Bad FAT32 root directory! (bad start cluster)\n" ); - else MODIFY_START(file,0,fs); - } - break; - } - if (bad_cluster(fs,walk)) break; - if (read_test) { - if (fs_test(cluster_start(fs,walk),fs->cluster_size)) { - prev = walk; - clusters++; - } - else { - printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n", - path_name(file),clusters,walk); - if (prev) set_fat(fs,prev,next_cluster(fs,walk)); - else MODIFY_START(file,next_cluster(fs,walk),fs); - set_fat(fs,walk,-2); - } - } - set_owner(fs,walk,file); - } - for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; - walk = next_cluster(fs,walk)) - if (bad_cluster(fs,walk)) break; - else if (get_owner(fs,walk) == file) set_owner(fs,walk,NULL); - else break; -} - - -static void undelete(DOS_FS *fs,DOS_FILE *file) -{ - unsigned long clusters,left,prev,walk; - - clusters = left = (CF_LE_L(file->dir_ent.size)+fs->cluster_size-1)/ - fs->cluster_size; - prev = 0; - for (walk = FSTART(file,fs); left && walk >= 2 && walk < - fs->clusters+2 && !fs->fat[walk].value; walk++) { - left--; - if (prev) set_fat(fs,prev,walk); - prev = walk; - } - if (prev) set_fat(fs,prev,-1); - else MODIFY_START(file,0,fs); - if (left) - printf("Warning: Did only undelete %lu of %lu cluster%s.\n",clusters-left, - clusters,clusters == 1 ? "" : "s"); - -} - - -static void new_dir( void ) -{ - lfn_reset(); -} - - -static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent, - loff_t offset,FDSC **cp) -{ - DOS_FILE *new; - DIR_ENT de; - FD_TYPE type; + static char path[MAX_PATH*2]; + + if (!file) *path = 0; + else { + if (strlen(path_name(file->parent)) > MAX_PATH) + die("Path name too long."); + if (strcmp(path,"/") != 0) strcat(path,"/"); + strcpy(strrchr(path,0),file->lfn?file->lfn:file_name(file->dir_ent.name)); + } + return path; +} + + +static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; + /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ + + +/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ + +time_t date_dos2unix(unsigned short time,unsigned short date) +{ + int month,year; + time_t secs; + + month = ((date >> 5) & 15)-1; + year = date >> 9; + secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* + ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && + month < 2 ? 1 : 0)+3653); + /* days since 1.1.70 plus 80's leap day */ + return secs; +} + + +static char *file_stat(DOS_FILE *file) +{ + static char temp[100]; + struct tm *tm; + char tmp[100]; + time_t date; + + date = date_dos2unix(CF_LE_W(file->dir_ent.time),CF_LE_W(file-> + dir_ent.date)); + tm = localtime(&date); + strftime(tmp,99,"%H:%M:%S %b %d %Y",tm); + sprintf(temp," Size %u bytes, date %s",CF_LE_L(file->dir_ent.size),tmp); + return temp; +} + + +static int bad_name(unsigned char *name) +{ + int i, spc, suspicious = 0; + char *bad_chars = atari_format ? "*?\\/:" : "*?<>|\"\\/:"; + + /* Do not complain about (and auto-correct) the extended attribute files + * of OS/2. */ + if (strncmp(name,"EA DATA SF",11) == 0 || + strncmp(name,"WP ROOT SF",11) == 0) return 0; + + for (i = 0; i < 8; i++) { + if (name[i] < ' ' || name[i] == 0x7f) return 1; + if (name[i] > 0x7f) ++suspicious; + if (strchr(bad_chars,name[i])) return 1; + } + + for (i = 8; i < 11; i++) { + if (name[i] < ' ' || name[i] == 0x7f) return 1; + if (name[i] > 0x7f) ++suspicious; + if (strchr(bad_chars,name[i])) return 1; + } + + spc = 0; + for (i = 0; i < 8; i++) { + if (name[i] == ' ') + spc = 1; + else if (spc) + /* non-space after a space not allowed, space terminates the name + * part */ + return 1; + } + + spc = 0; + for (i = 8; i < 11; i++) { + if (name[i] == ' ') + spc = 1; + else if (spc) + /* non-space after a space not allowed, space terminates the name + * part */ + return 1; + } + + /* Under GEMDOS, chars >= 128 are never allowed. */ + if (atari_format && suspicious) + return 1; + + /* Only complain about too much suspicious chars in interactive mode, + * never correct them automatically. The chars are all basically ok, so we + * shouldn't auto-correct such names. */ + if (interactive && suspicious > 6) + return 1; + return 0; +} + + +static void drop_file(DOS_FS *fs,DOS_FILE *file) +{ + unsigned long cluster; + + MODIFY(file,name[0],DELETED_FLAG); + for (cluster = FSTART(file,fs); cluster > 0 && cluster < + fs->clusters+2; cluster = next_cluster(fs,cluster)) + set_owner(fs,cluster,NULL); + --n_files; +} + + +static void truncate_file(DOS_FS *fs,DOS_FILE *file,unsigned long clusters) +{ + int deleting; + unsigned long walk,next,prev; + + walk = FSTART(file,fs); + prev = 0; + if ((deleting = !clusters)) MODIFY_START(file,0,fs); + while (walk > 0 && walk != -1) { + next = next_cluster(fs,walk); + if (deleting) set_fat(fs,walk,0); + else if ((deleting = !--clusters)) set_fat(fs,walk,-1); + prev = walk; + walk = next; + } +} + + +static void auto_rename(DOS_FILE *file) +{ + DOS_FILE *first,*walk; + int number; + + if (!file->offset) return; /* cannot rename FAT32 root dir */ + first = file->parent ? file->parent->first : root; + number = 0; + while (1) { + sprintf(file->dir_ent.name,"FSCK%04d",number); + strncpy(file->dir_ent.ext,"REN",3); + for (walk = first; walk; walk = walk->next) + if (walk != file && !strncmp(walk->dir_ent.name,file->dir_ent. + name,MSDOS_NAME)) break; + if (!walk) { + fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); + return; + } + number++; + } + die("Can't generate a unique name."); +} + + +static void rename_file(DOS_FILE *file) +{ + unsigned char name[46]; + unsigned char *walk,*here; + + if (!file->offset) { + printf( "Cannot rename FAT32 root dir\n" ); + return; /* cannot rename FAT32 root dir */ + } + while (1) { + printf("New name: "); + fflush(stdout); + if (fgets(name,45,stdin)) { + if ((here = strchr(name,'\n'))) *here = 0; + for (walk = strrchr(name,0); walk >= name && (*walk == ' ' || + *walk == '\t'); walk--); + walk[1] = 0; + for (walk = name; *walk == ' ' || *walk == '\t'; walk++); + if (file_cvt(walk,file->dir_ent.name)) { + fs_write(file->offset,MSDOS_NAME,file->dir_ent.name); + return; + } + } + } +} + + +static int handle_dot(DOS_FS *fs,DOS_FILE *file,int dots) +{ + char *name; + + name = strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME) ? ".." : "."; + if (!(file->dir_ent.attr & ATTR_DIR)) { + printf("%s\n Is a non-directory.\n",path_name(file)); + if (interactive) + printf("1) Drop it\n2) Auto-rename\n3) Rename\n" + "4) Convert to directory\n"); + else printf(" Auto-renaming it.\n"); + switch (interactive ? get_key("1234","?") : '2') { + case '1': + drop_file(fs,file); + return 1; + case '2': + auto_rename(file); + printf(" Renamed to %s\n",file_name(file->dir_ent.name)); + return 0; + case '3': + rename_file(file); + return 0; + case '4': + MODIFY(file,size,CT_LE_L(0)); + MODIFY(file,attr,file->dir_ent.attr | ATTR_DIR); + break; + } + } + if (!dots) { + printf("Root contains directory \"%s\". Dropping it.\n",name); + drop_file(fs,file); + return 1; + } + return 0; +} + + +static int check_file(DOS_FS *fs,DOS_FILE *file) +{ + DOS_FILE *owner; + int restart; + unsigned long expect,curr,this,clusters,prev,walk,clusters2; + + if (file->dir_ent.attr & ATTR_DIR) { + if (CF_LE_L(file->dir_ent.size)) { + printf("%s\n Directory has non-zero size. Fixing it.\n", + path_name(file)); + MODIFY(file,size,CT_LE_L(0)); + } + if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) { + expect = FSTART(file->parent,fs); + if (FSTART(file,fs) != expect) { + printf("%s\n Start (%ld) does not point to parent (%ld)\n", + path_name(file),FSTART(file,fs),expect); + MODIFY_START(file,expect,fs); + } + return 0; + } + if (file->parent && !strncmp(file->dir_ent.name,MSDOS_DOTDOT, + MSDOS_NAME)) { + expect = file->parent->parent ? FSTART(file->parent->parent,fs):0; + if (fs->root_cluster && expect == fs->root_cluster) + expect = 0; + if (FSTART(file,fs) != expect) { + printf("%s\n Start (%lu) does not point to .. (%lu)\n", + path_name(file),FSTART(file,fs),expect); + MODIFY_START(file,expect,fs); + } + return 0; + } + if (FSTART(file,fs)==0){ + printf ("%s\n Start does point to root directory. Deleting dir. \n", + path_name(file)); + MODIFY(file,name[0],DELETED_FLAG); + return 0; + } + } + if (FSTART(file,fs) >= fs->clusters+2) { + printf("%s\n Start cluster beyond limit (%lu > %lu). Truncating file.\n", + path_name(file),FSTART(file,fs),fs->clusters+1); + if (!file->offset) + die( "Bad FAT32 root directory! (bad start cluster)\n" ); + MODIFY_START(file,0,fs); + } + clusters = prev = 0; + for (curr = FSTART(file,fs) ? FSTART(file,fs) : + -1; curr != -1; curr = next_cluster(fs,curr)) { + if (!fs->fat[curr].value || bad_cluster(fs,curr)) { + printf("%s\n Contains a %s cluster (%lu). Assuming EOF.\n", + path_name(file),fs->fat[curr].value ? "bad" : "free",curr); + if (prev) set_fat(fs,prev,-1); + else if (!file->offset) + die( "FAT32 root dir starts with a bad cluster!" ); + else MODIFY_START(file,0,fs); + break; + } + if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) <= + clusters*fs->cluster_size) { + printf("%s\n File size is %u bytes, cluster chain length is > %lu " + "bytes.\n Truncating file to %u bytes.\n",path_name(file), + CF_LE_L(file->dir_ent.size),clusters*fs->cluster_size, + CF_LE_L(file->dir_ent.size)); + truncate_file(fs,file,clusters); + break; + } + if ((owner = get_owner(fs,curr))) { + int do_trunc = 0; + printf("%s and\n",path_name(owner)); + printf("%s\n share clusters.\n",path_name(file)); + clusters2 = 0; + for (walk = FSTART(owner,fs); walk > 0 && walk != -1; walk = + next_cluster(fs,walk)) + if (walk == curr) break; + else clusters2++; + restart = file->dir_ent.attr & ATTR_DIR; + if (!owner->offset) { + printf( " Truncating second to %lu bytes because first " + "is FAT32 root dir.\n", clusters2*fs->cluster_size ); + do_trunc = 2; + } + else if (!file->offset) { + printf( " Truncating first to %lu bytes because second " + "is FAT32 root dir.\n", clusters*fs->cluster_size ); + do_trunc = 1; + } + else if (interactive) + printf("1) Truncate first to %lu bytes%s\n" + "2) Truncate second to %lu bytes\n",clusters*fs->cluster_size, + restart ? " and restart" : "",clusters2*fs->cluster_size); + else printf(" Truncating second to %lu bytes.\n",clusters2* + fs->cluster_size); + if (do_trunc != 2 && + (do_trunc == 1 || + (interactive && get_key("12","?") == '1'))) { + prev = 0; + clusters = 0; + for (this = FSTART(owner,fs); this > 0 && this != -1; this = + next_cluster(fs,this)) { + if (this == curr) { + if (prev) set_fat(fs,prev,-1); + else MODIFY_START(owner,0,fs); + MODIFY(owner,size,CT_LE_L(clusters*fs->cluster_size)); + if (restart) return 1; + while (this > 0 && this != -1) { + set_owner(fs,this,NULL); + this = next_cluster(fs,this); + } + break; + } + clusters++; + prev = this; + } + if (this != curr) + die("Internal error: didn't find cluster %d in chain" + " starting at %d",curr,FSTART(owner,fs)); + } + else { + if (prev) set_fat(fs,prev,-1); + else MODIFY_START(file,0,fs); + break; + } + } + set_owner(fs,curr,file); + clusters++; + prev = curr; + } + if (!(file->dir_ent.attr & ATTR_DIR) && CF_LE_L(file->dir_ent.size) > + clusters*fs->cluster_size) { + printf("%s\n File size is %u bytes, cluster chain length is %lu bytes." + "\n Truncating file to %lu bytes.\n",path_name(file),CF_LE_L(file-> + dir_ent.size),clusters*fs->cluster_size,clusters*fs->cluster_size); + MODIFY(file,size,CT_LE_L(clusters*fs->cluster_size)); + } + return 0; +} + + +static int check_files(DOS_FS *fs,DOS_FILE *start) +{ + while (start) { + if (check_file(fs,start)) return 1; + start = start->next; + } + return 0; +} + + +static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots) +{ + DOS_FILE *parent,**walk,**scan; + int dot,dotdot,skip,redo; + int good,bad; + + if (!*root) return 0; + parent = (*root)->parent; + good = bad = 0; + for (walk = root; *walk; walk = &(*walk)->next) + if (bad_name((*walk)->dir_ent.name)) bad++; + else good++; + if (*root && parent && good+bad > 4 && bad > good/2) { + printf("%s\n Has a large number of bad entries. (%d/%d)\n", + path_name(parent),bad,good+bad); + if (!dots) printf( " Not dropping root directory.\n" ); + else if (!interactive) printf(" Not dropping it in auto-mode.\n"); + else if (get_key("yn","Drop directory ? (y/n)") == 'y') { + truncate_file(fs,parent,0); + MODIFY(parent,name[0],DELETED_FLAG); + /* buglet: deleted directory stays in the list. */ + return 1; + } + } + dot = dotdot = redo = 0; + walk = root; + while (*walk) { + if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME) || + !strncmp((*walk)->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) { + if (handle_dot(fs,*walk,dots)) { + *walk = (*walk)->next; + continue; + } + if (!strncmp((*walk)->dir_ent.name,MSDOS_DOT,MSDOS_NAME)) dot++; + else dotdot++; + } + if (!((*walk)->dir_ent.attr & ATTR_VOLUME) && + bad_name((*walk)->dir_ent.name)) { + printf("%s\n Bad file name.\n",path_name(*walk)); + if (interactive) + printf("1) Drop file\n2) Rename file\n3) Auto-rename\n" + "4) Keep it\n"); + else printf(" Auto-renaming it.\n"); + switch (interactive ? get_key("1234","?") : '3') { + case '1': + drop_file(fs,*walk); + walk = &(*walk)->next; + continue; + case '2': + rename_file(*walk); + redo = 1; + break; + case '3': + auto_rename(*walk); + printf(" Renamed to %s\n",file_name((*walk)->dir_ent. + name)); + break; + case '4': + break; + } + } + /* don't check for duplicates of the volume label */ + if (!((*walk)->dir_ent.attr & ATTR_VOLUME)) { + scan = &(*walk)->next; + skip = 0; + while (*scan && !skip) { + if (!((*scan)->dir_ent.attr & ATTR_VOLUME) && + !strncmp((*walk)->dir_ent.name,(*scan)->dir_ent.name,MSDOS_NAME)) { + printf("%s\n Duplicate directory entry.\n First %s\n", + path_name(*walk),file_stat(*walk)); + printf(" Second %s\n",file_stat(*scan)); + if (interactive) + printf("1) Drop first\n2) Drop second\n3) Rename first\n" + "4) Rename second\n5) Auto-rename first\n" + "6) Auto-rename second\n"); + else printf(" Auto-renaming second.\n"); + switch (interactive ? get_key("123456","?") : '6') { + case '1': + drop_file(fs,*walk); + *walk = (*walk)->next; + skip = 1; + break; + case '2': + drop_file(fs,*scan); + *scan = (*scan)->next; + continue; + case '3': + rename_file(*walk); + printf(" Renamed to %s\n",path_name(*walk)); + redo = 1; + break; + case '4': + rename_file(*scan); + printf(" Renamed to %s\n",path_name(*walk)); + redo = 1; + break; + case '5': + auto_rename(*walk); + printf(" Renamed to %s\n",file_name((*walk)->dir_ent. + name)); + break; + case '6': + auto_rename(*scan); + printf(" Renamed to %s\n",file_name((*scan)->dir_ent. + name)); + break; + } + } + scan = &(*scan)->next; + } + if (skip) continue; + } + if (!redo) walk = &(*walk)->next; + else { + walk = root; + dot = dotdot = redo = 0; + } + } + if (dots && !dot) + printf("%s\n \".\" is missing. Can't fix this yet.\n", + path_name(parent)); + if (dots && !dotdot) + printf("%s\n \"..\" is missing. Can't fix this yet.\n", + path_name(parent)); + return 0; +} + + +static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test) +{ + DOS_FILE *owner; + unsigned long walk,prev,clusters,next_clu; + + prev = clusters = 0; + for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; + walk = next_clu) { + next_clu = next_cluster(fs,walk); + if ((owner = get_owner(fs,walk))) { + if (owner == file) { + printf("%s\n Circular cluster chain. Truncating to %lu " + "cluster%s.\n",path_name(file),clusters,clusters == 1 ? "" : + "s"); + if (prev) set_fat(fs,prev,-1); + else if (!file->offset) + die( "Bad FAT32 root directory! (bad start cluster)\n" ); + else MODIFY_START(file,0,fs); + } + break; + } + if (bad_cluster(fs,walk)) break; + if (read_test) { + if (fs_test(cluster_start(fs,walk),fs->cluster_size)) { + prev = walk; + clusters++; + } + else { + printf("%s\n Cluster %lu (%lu) is unreadable. Skipping it.\n", + path_name(file),clusters,walk); + if (prev) set_fat(fs,prev,next_cluster(fs,walk)); + else MODIFY_START(file,next_cluster(fs,walk),fs); + set_fat(fs,walk,-2); + } + } + set_owner(fs,walk,file); + } + for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2; + walk = next_cluster(fs,walk)) + if (bad_cluster(fs,walk)) break; + else if (get_owner(fs,walk) == file) set_owner(fs,walk,NULL); + else break; +} + + +static void undelete(DOS_FS *fs,DOS_FILE *file) +{ + unsigned long clusters,left,prev,walk; + + clusters = left = (CF_LE_L(file->dir_ent.size)+fs->cluster_size-1)/ + fs->cluster_size; + prev = 0; + for (walk = FSTART(file,fs); left && walk >= 2 && walk < + fs->clusters+2 && !fs->fat[walk].value; walk++) { + left--; + if (prev) set_fat(fs,prev,walk); + prev = walk; + } + if (prev) set_fat(fs,prev,-1); + else MODIFY_START(file,0,fs); + if (left) + printf("Warning: Did only undelete %lu of %lu cluster%s.\n",clusters-left, + clusters,clusters == 1 ? "" : "s"); + +} + + +static void new_dir( void ) +{ + lfn_reset(); +} + + +static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent, + loff_t offset,FDSC **cp) +{ + DOS_FILE *new; + DIR_ENT de; + FD_TYPE type; char tmpBuffer[512]; // TMN: - - if (offset) { + + if (offset) { // fs_read(offset,sizeof(DIR_ENT),&de); fs_read(offset,sizeof(tmpBuffer),&tmpBuffer); // TMN: - memcpy(&de, tmpBuffer, sizeof(DIR_ENT)); // TMN: - } else { - memcpy(de.name," ",MSDOS_NAME); - de.attr = ATTR_DIR; - de.size = de.time = de.date = 0; - de.start = CT_LE_W(fs->root_cluster & 0xffff); - de.starthi = CT_LE_W((fs->root_cluster >> 16) & 0xffff); - } - if ((type = file_type(cp,de.name)) != fdt_none) { - if (type == fdt_undelete && (de.attr & ATTR_DIR)) - die("Can't undelete directories."); - file_modify(cp,de.name); - fs_write(offset,1,&de); - } - if (IS_FREE(de.name)) { - lfn_check_orphaned(); - return; - } - if (de.attr == VFAT_LN_ATTR) { - lfn_add_slot(&de,offset); - return; - } - new = qalloc(&mem_queue,sizeof(DOS_FILE)); - new->lfn = lfn_get(&de); - new->offset = offset; - memcpy(&new->dir_ent,&de,sizeof(de)); - new->next = new->first = NULL; - new->parent = parent; - if (type == fdt_undelete) undelete(fs,new); - **chain = new; - *chain = &new->next; - if (list) { - printf("Checking file %s",path_name(new)); - if (new->lfn) - printf(" (%s)", file_name(new->dir_ent.name) ); - printf("\n"); - } - if (offset && - strncmp(de.name,MSDOS_DOT,MSDOS_NAME) != 0 && - strncmp(de.name,MSDOS_DOTDOT,MSDOS_NAME) != 0) - ++n_files; - test_file(fs,new,test); -} - - -static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp); - - -static int scan_dir(DOS_FS *fs,DOS_FILE *this,FDSC **cp) -{ - DOS_FILE **chain; - int i; - unsigned long clu_num; - - chain = &this->first; - i = 0; - clu_num = FSTART(this,fs); - new_dir(); - while (clu_num > 0 && clu_num != -1) { - add_file(fs,&chain,this,cluster_start(fs,clu_num)+(i % fs-> - cluster_size),cp); - i += sizeof(DIR_ENT); - if (!(i % fs->cluster_size)) - if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) - break; - } - lfn_check_orphaned(); - if (check_dir(fs,&this->first,this->offset)) return 0; - if (check_files(fs,this->first)) return 1; - return subdirs(fs,this,cp); -} - - -static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp) -{ - DOS_FILE *walk; - - for (walk = parent ? parent->first : root; walk; walk = walk->next) - if (walk->dir_ent.attr & ATTR_DIR) - if (strncmp(walk->dir_ent.name,MSDOS_DOT,MSDOS_NAME) && - strncmp(walk->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) - if (scan_dir(fs,walk,file_cd(cp,walk->dir_ent.name))) return 1; - return 0; -} - - -int scan_root(DOS_FS *fs) -{ - DOS_FILE **chain; - int i; - - root = NULL; - chain = &root; - new_dir(); - if (fs->root_cluster) { - add_file(fs,&chain,NULL,0,&fp_root); - } - else { - for (i = 0; i < fs->root_entries; i++) - add_file(fs,&chain,NULL,fs->root_start+i*sizeof(DIR_ENT),&fp_root); - } - lfn_check_orphaned(); - (void) check_dir(fs,&root,0); - if (check_files(fs,root)) return 1; - return subdirs(fs,NULL,&fp_root); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ + memcpy(&de, tmpBuffer, sizeof(DIR_ENT)); // TMN: + } else { + memcpy(de.name," ",MSDOS_NAME); + de.attr = ATTR_DIR; + de.size = de.time = de.date = 0; + de.start = CT_LE_W(fs->root_cluster & 0xffff); + de.starthi = CT_LE_W((fs->root_cluster >> 16) & 0xffff); + } + if ((type = file_type(cp,de.name)) != fdt_none) { + if (type == fdt_undelete && (de.attr & ATTR_DIR)) + die("Can't undelete directories."); + file_modify(cp,de.name); + fs_write(offset,1,&de); + } + if (IS_FREE(de.name)) { + lfn_check_orphaned(); + return; + } + if (de.attr == VFAT_LN_ATTR) { + lfn_add_slot(&de,offset); + return; + } + new = qalloc(&mem_queue,sizeof(DOS_FILE)); + new->lfn = lfn_get(&de); + new->offset = offset; + memcpy(&new->dir_ent,&de,sizeof(de)); + new->next = new->first = NULL; + new->parent = parent; + if (type == fdt_undelete) undelete(fs,new); + **chain = new; + *chain = &new->next; + if (list) { + printf("Checking file %s",path_name(new)); + if (new->lfn) + printf(" (%s)", file_name(new->dir_ent.name) ); + printf("\n"); + } + if (offset && + strncmp(de.name,MSDOS_DOT,MSDOS_NAME) != 0 && + strncmp(de.name,MSDOS_DOTDOT,MSDOS_NAME) != 0) + ++n_files; + test_file(fs,new,test); +} + + +static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp); + + +static int scan_dir(DOS_FS *fs,DOS_FILE *this,FDSC **cp) +{ + DOS_FILE **chain; + int i; + unsigned long clu_num; + + chain = &this->first; + i = 0; + clu_num = FSTART(this,fs); + new_dir(); + while (clu_num > 0 && clu_num != -1) { + add_file(fs,&chain,this,cluster_start(fs,clu_num)+(i % fs-> + cluster_size),cp); + i += sizeof(DIR_ENT); + if (!(i % fs->cluster_size)) + if ((clu_num = next_cluster(fs,clu_num)) == 0 || clu_num == -1) + break; + } + lfn_check_orphaned(); + if (check_dir(fs,&this->first,this->offset)) return 0; + if (check_files(fs,this->first)) return 1; + return subdirs(fs,this,cp); +} + + +static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp) +{ + DOS_FILE *walk; + + for (walk = parent ? parent->first : root; walk; walk = walk->next) + if (walk->dir_ent.attr & ATTR_DIR) + if (strncmp(walk->dir_ent.name,MSDOS_DOT,MSDOS_NAME) && + strncmp(walk->dir_ent.name,MSDOS_DOTDOT,MSDOS_NAME)) + if (scan_dir(fs,walk,file_cd(cp,walk->dir_ent.name))) return 1; + return 0; +} + + +int scan_root(DOS_FS *fs) +{ + DOS_FILE **chain; + int i; + + root = NULL; + chain = &root; + new_dir(); + if (fs->root_cluster) { + add_file(fs,&chain,NULL,0,&fp_root); + } + else { + for (i = 0; i < fs->root_entries; i++) + add_file(fs,&chain,NULL,fs->root_start+i*sizeof(DIR_ENT),&fp_root); + } + lfn_check_orphaned(); + (void) check_dir(fs,&root,0); + if (check_files(fs,root)) return 1; + return subdirs(fs,NULL,&fp_root); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/check.h b/rosapps/sysutils/dosfsck/check.h index 38f1c686b5c..4498b7fac9c 100644 --- a/rosapps/sysutils/dosfsck/check.h +++ b/rosapps/sysutils/dosfsck/check.h @@ -1,23 +1,23 @@ -/* check.h - Check and repair a PC/MS-DOS file system */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _CHECK_H -#define _CHECK_H - -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 - constructed after 'pattern', which must include a %d type format for printf - and expand to exactly 11 characters. The name actually used is written into - the 'de' structure, the rest of *de is cleared. The offset returned is to - where in the filesystem the entry belongs. */ - -int scan_root(DOS_FS *fs); - -/* 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 - be checked again. */ - -#endif +/* check.h - Check and repair a PC/MS-DOS file system */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _CHECK_H +#define _CHECK_H + +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 + constructed after 'pattern', which must include a %d type format for printf + and expand to exactly 11 characters. The name actually used is written into + the 'de' structure, the rest of *de is cleared. The offset returned is to + where in the filesystem the entry belongs. */ + +int scan_root(DOS_FS *fs); + +/* 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 + be checked again. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/common.c b/rosapps/sysutils/dosfsck/common.c index 48a5f3384ac..cc002ea45a6 100644 --- a/rosapps/sysutils/dosfsck/common.c +++ b/rosapps/sysutils/dosfsck/common.c @@ -1,110 +1,110 @@ -/* common.c - Common functions */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -#include -#include - -#include "common.h" - - -typedef struct _link { - void *data; - struct _link *next; -} LINK; - - -void die(char *msg,...) -{ - va_list args; - - va_start(args,msg); - vfprintf(stderr,msg,args); - va_end(args); - fprintf(stderr,"\n"); - exit(1); -} - - -void pdie(char *msg,...) -{ - va_list args; - - va_start(args,msg); - vfprintf(stderr,msg,args); - va_end(args); - fprintf(stderr,":%s\n",strerror(errno)); - exit(1); -} - - -void *alloc(int size) -{ - void *this; - - if ((this = malloc(size))) return this; - pdie("malloc"); - return NULL; /* for GCC */ -} - - -void *qalloc(void **root,int size) -{ - LINK *link; - - link = alloc(sizeof(LINK)); - link->next = *root; - *root = link; - return link->data = alloc(size); -} - - -void qfree(void **root) -{ - LINK *this; - - while (*root) { - this = (LINK *) *root; - *root = this->next; - free(this->data); - free(this); - } -} - +/* common.c - Common functions */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +#include +#include + +#include "common.h" + + +typedef struct _link { + void *data; + struct _link *next; +} LINK; + + +void die(char *msg,...) +{ + va_list args; + + va_start(args,msg); + vfprintf(stderr,msg,args); + va_end(args); + fprintf(stderr,"\n"); + exit(1); +} + + +void pdie(char *msg,...) +{ + va_list args; + + va_start(args,msg); + vfprintf(stderr,msg,args); + va_end(args); + fprintf(stderr,":%s\n",strerror(errno)); + exit(1); +} + + +void *alloc(int size) +{ + void *this; + + if ((this = malloc(size))) return this; + pdie("malloc"); + return NULL; /* for GCC */ +} + + +void *qalloc(void **root,int size) +{ + LINK *link; + + link = alloc(sizeof(LINK)); + link->next = *root; + *root = link; + return link->data = alloc(size); +} + + +void qfree(void **root) +{ + LINK *this; + + while (*root) { + this = (LINK *) *root; + *root = this->next; + free(this->data); + free(this); + } +} + #ifdef min #undef min -#endif -int min(int a,int b) -{ - return a < b ? a : b; -} - - -char get_key(char *valid,char *prompt) -{ - int ch,okay; - - while (1) { - if (prompt) printf("%s ",prompt); - fflush(stdout); - while (ch = getchar(), ch == ' ' || ch == '\t'); - if (ch == EOF) exit(1); - if (!strchr(valid,okay = ch)) okay = 0; - while (ch = getchar(), ch != '\n' && ch != EOF); - if (ch == EOF) exit(1); - if (okay) return okay; - printf("Invalid input.\n"); - } -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +#endif +int min(int a,int b) +{ + return a < b ? a : b; +} + + +char get_key(char *valid,char *prompt) +{ + int ch,okay; + + while (1) { + if (prompt) printf("%s ",prompt); + fflush(stdout); + while (ch = getchar(), ch == ' ' || ch == '\t'); + if (ch == EOF) exit(1); + if (!strchr(valid,okay = ch)) okay = 0; + while (ch = getchar(), ch != '\n' && ch != EOF); + if (ch == EOF) exit(1); + if (okay) return okay; + printf("Invalid input.\n"); + } +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/common.h b/rosapps/sysutils/dosfsck/common.h index 98a46857dc8..6e9bdceed3f 100644 --- a/rosapps/sysutils/dosfsck/common.h +++ b/rosapps/sysutils/dosfsck/common.h @@ -1,42 +1,42 @@ -/* common.h - Common functions */ - -# define MSDOS_FAT12 4084 /* maximum number of clusters in a 12 bit FAT */ - -#include "version.h" - -#ifndef _COMMON_H -#define _COMMON_H +/* common.h - Common functions */ -//void die(char *msg,...) __attribute((noreturn)); +# define MSDOS_FAT12 4084 /* maximum number of clusters in a 12 bit FAT */ + +#include "version.h" + +#ifndef _COMMON_H +#define _COMMON_H + +//void die(char *msg,...) __attribute((noreturn)); __declspec(noreturn) void die(char *msg,...); - -/* Displays a prinf-style message and terminates the program. */ - -//void pdie(char *msg,...) __attribute((noreturn)); + +/* Displays a prinf-style message and terminates the program. */ + +//void pdie(char *msg,...) __attribute((noreturn)); __declspec(noreturn) void pdie(char *msg,...); - -/* Like die, but appends an error message according to the state of errno. */ - -void *alloc(int size); - -/* mallocs SIZE bytes and returns a pointer to the data. Terminates the program - if malloc fails. */ - -void *qalloc(void **root,int size); - -/* Like alloc, but registers the data area in a list described by ROOT. */ - -void qfree(void **root); - -/* Deallocates all qalloc'ed data areas described by ROOT. */ - -//int min(int a,int b); - -/* Returns the smaller integer value of a and b. */ - -char get_key(char *valid,char *prompt); - -/* Displays PROMPT and waits for user input. Only characters in VALID are - accepted. Terminates the program on EOF. Returns the character. */ - -#endif + +/* Like die, but appends an error message according to the state of errno. */ + +void *alloc(int size); + +/* mallocs SIZE bytes and returns a pointer to the data. Terminates the program + if malloc fails. */ + +void *qalloc(void **root,int size); + +/* Like alloc, but registers the data area in a list described by ROOT. */ + +void qfree(void **root); + +/* Deallocates all qalloc'ed data areas described by ROOT. */ + +//int min(int a,int b); + +/* Returns the smaller integer value of a and b. */ + +char get_key(char *valid,char *prompt); + +/* Displays PROMPT and waits for user input. Only characters in VALID are + accepted. Terminates the program on EOF. Returns the character. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/compiler.h b/rosapps/sysutils/dosfsck/compiler.h index 2d3edfe38b7..f685e93f6e0 100644 --- a/rosapps/sysutils/dosfsck/compiler.h +++ b/rosapps/sysutils/dosfsck/compiler.h @@ -1,158 +1,158 @@ -#ifndef __LINUX_COMPILER_H -#define __LINUX_COMPILER_H - -#ifndef __ASSEMBLY__ - -#ifdef __CHECKER__ -# define __user __attribute__((noderef, address_space(1))) -# define __kernel /* default address space */ -# define __safe __attribute__((safe)) -# define __force __attribute__((force)) -# define __nocast __attribute__((nocast)) -# define __iomem __attribute__((noderef, address_space(2))) -# define __acquires(x) __attribute__((context(0,1))) -# define __releases(x) __attribute__((context(1,0))) -# define __acquire(x) __context__(1) -# define __release(x) __context__(-1) -# define __cond_lock(x) ((x) ? ({ __context__(1); 1; }) : 0) -extern void __chk_user_ptr(void __user *); -extern void __chk_io_ptr(void __iomem *); -#else -# define __user -# define __kernel -# define __safe -# define __force -# define __nocast -# define __iomem -# define __chk_user_ptr(x) (void)0 -# define __chk_io_ptr(x) (void)0 -//# define __builtin_warning(x, y...) (1) -# define __acquires(x) -# define __releases(x) -# define __acquire(x) (void)0 -# define __release(x) (void)0 -# define __cond_lock(x) (x) -#endif - -#ifdef __KERNEL__ - -#if __GNUC__ > 4 -#error no compiler-gcc.h file for this gcc version -#elif __GNUC__ == 4 -# include -#elif __GNUC__ == 3 -# include -#elif __GNUC__ == 2 -# include -#else -# error Sorry, your compiler is too old/not recognized. -#endif - -/* Intel compiler defines __GNUC__. So we will overwrite implementations - * coming from above header files here - */ -#ifdef __INTEL_COMPILER -# include -#endif - -/* - * Generic compiler-dependent macros required for kernel - * build go below this comment. Actual compiler/compiler version - * specific implementations come from the above header files - */ - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - -/* Optimization barrier */ -#ifndef barrier -# define barrier() __memory_barrier() -#endif - -#ifndef RELOC_HIDE -# define RELOC_HIDE(ptr, off) \ - ({ unsigned long __ptr; \ - __ptr = (unsigned long) (ptr); \ - (typeof(ptr)) (__ptr + (off)); }) -#endif - -#endif /* __KERNEL__ */ - -#endif /* __ASSEMBLY__ */ - -/* - * Allow us to mark functions as 'deprecated' and have gcc emit a nice - * warning for each use, in hopes of speeding the functions removal. - * Usage is: - * int __deprecated foo(void) - */ -#ifndef __deprecated -# define __deprecated /* unimplemented */ -#endif - -#ifdef MODULE -#define __deprecated_for_modules __deprecated -#else -#define __deprecated_for_modules -#endif - -#ifndef __must_check -#define __must_check -#endif - -/* - * Allow us to avoid 'defined but not used' warnings on functions and data, - * as well as force them to be emitted to the assembly file. - * - * As of gcc 3.3, static functions that are not marked with attribute((used)) - * may be elided from the assembly file. As of gcc 3.3, static data not so - * marked will not be elided, but this may change in a future gcc version. - * - * In prior versions of gcc, such functions and data would be emitted, but - * would be warned about except with attribute((unused)). - */ -#ifndef __attribute_used__ -# define __attribute_used__ /* unimplemented */ -#endif - -/* - * From the GCC manual: - * - * Many functions have no effects except the return value and their - * return value depends only on the parameters and/or global - * variables. Such a function can be subject to common subexpression - * elimination and loop optimization just as an arithmetic operator - * would be. - * [...] - */ -#ifndef __attribute_pure__ -# define __attribute_pure__ /* unimplemented */ -#endif - -/* - * From the GCC manual: - * - * Many functions do not examine any values except their arguments, - * and have no effects except the return value. Basically this is - * just slightly more strict class than the `pure' attribute above, - * since function is not allowed to read global memory. - * - * Note that a function that has pointer arguments and examines the - * data pointed to must _not_ be declared `const'. Likewise, a - * function that calls a non-`const' function usually must not be - * `const'. It does not make sense for a `const' function to return - * `void'. - */ -#ifndef __attribute_const__ -# define __attribute_const__ /* unimplemented */ -#endif - -#ifndef noinline -#define noinline -#endif - -#ifndef __always_inline -#define __always_inline inline -#endif - -#endif /* __LINUX_COMPILER_H */ +#ifndef __LINUX_COMPILER_H +#define __LINUX_COMPILER_H + +#ifndef __ASSEMBLY__ + +#ifdef __CHECKER__ +# define __user __attribute__((noderef, address_space(1))) +# define __kernel /* default address space */ +# define __safe __attribute__((safe)) +# define __force __attribute__((force)) +# define __nocast __attribute__((nocast)) +# define __iomem __attribute__((noderef, address_space(2))) +# define __acquires(x) __attribute__((context(0,1))) +# define __releases(x) __attribute__((context(1,0))) +# define __acquire(x) __context__(1) +# define __release(x) __context__(-1) +# define __cond_lock(x) ((x) ? ({ __context__(1); 1; }) : 0) +extern void __chk_user_ptr(void __user *); +extern void __chk_io_ptr(void __iomem *); +#else +# define __user +# define __kernel +# define __safe +# define __force +# define __nocast +# define __iomem +# define __chk_user_ptr(x) (void)0 +# define __chk_io_ptr(x) (void)0 +//# define __builtin_warning(x, y...) (1) +# define __acquires(x) +# define __releases(x) +# define __acquire(x) (void)0 +# define __release(x) (void)0 +# define __cond_lock(x) (x) +#endif + +#ifdef __KERNEL__ + +#if __GNUC__ > 4 +#error no compiler-gcc.h file for this gcc version +#elif __GNUC__ == 4 +# include +#elif __GNUC__ == 3 +# include +#elif __GNUC__ == 2 +# include +#else +# error Sorry, your compiler is too old/not recognized. +#endif + +/* Intel compiler defines __GNUC__. So we will overwrite implementations + * coming from above header files here + */ +#ifdef __INTEL_COMPILER +# include +#endif + +/* + * Generic compiler-dependent macros required for kernel + * build go below this comment. Actual compiler/compiler version + * specific implementations come from the above header files + */ + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +/* Optimization barrier */ +#ifndef barrier +# define barrier() __memory_barrier() +#endif + +#ifndef RELOC_HIDE +# define RELOC_HIDE(ptr, off) \ + ({ unsigned long __ptr; \ + __ptr = (unsigned long) (ptr); \ + (typeof(ptr)) (__ptr + (off)); }) +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +/* + * Allow us to mark functions as 'deprecated' and have gcc emit a nice + * warning for each use, in hopes of speeding the functions removal. + * Usage is: + * int __deprecated foo(void) + */ +#ifndef __deprecated +# define __deprecated /* unimplemented */ +#endif + +#ifdef MODULE +#define __deprecated_for_modules __deprecated +#else +#define __deprecated_for_modules +#endif + +#ifndef __must_check +#define __must_check +#endif + +/* + * Allow us to avoid 'defined but not used' warnings on functions and data, + * as well as force them to be emitted to the assembly file. + * + * As of gcc 3.3, static functions that are not marked with attribute((used)) + * may be elided from the assembly file. As of gcc 3.3, static data not so + * marked will not be elided, but this may change in a future gcc version. + * + * In prior versions of gcc, such functions and data would be emitted, but + * would be warned about except with attribute((unused)). + */ +#ifndef __attribute_used__ +# define __attribute_used__ /* unimplemented */ +#endif + +/* + * From the GCC manual: + * + * Many functions have no effects except the return value and their + * return value depends only on the parameters and/or global + * variables. Such a function can be subject to common subexpression + * elimination and loop optimization just as an arithmetic operator + * would be. + * [...] + */ +#ifndef __attribute_pure__ +# define __attribute_pure__ /* unimplemented */ +#endif + +/* + * From the GCC manual: + * + * Many functions do not examine any values except their arguments, + * and have no effects except the return value. Basically this is + * just slightly more strict class than the `pure' attribute above, + * since function is not allowed to read global memory. + * + * Note that a function that has pointer arguments and examines the + * data pointed to must _not_ be declared `const'. Likewise, a + * function that calls a non-`const' function usually must not be + * `const'. It does not make sense for a `const' function to return + * `void'. + */ +#ifndef __attribute_const__ +# define __attribute_const__ /* unimplemented */ +#endif + +#ifndef noinline +#define noinline +#endif + +#ifndef __always_inline +#define __always_inline inline +#endif + +#endif /* __LINUX_COMPILER_H */ diff --git a/rosapps/sysutils/dosfsck/dosfsck.c b/rosapps/sysutils/dosfsck/dosfsck.c index 9efc5715427..40461bbc3b2 100644 --- a/rosapps/sysutils/dosfsck/dosfsck.c +++ b/rosapps/sysutils/dosfsck/dosfsck.c @@ -1,184 +1,184 @@ -/* dosfsck.c - User interface */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include "version.h" - -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "boot.h" -#include "fat.h" -#include "file.h" -#include "check.h" - - -int interactive = 0,list = 0,test = 0,verbose = 0,write_immed = 0; -int atari_format = 0; -unsigned n_files = 0; -void *mem_queue = NULL; - - -static void usage(char *name) -{ - fprintf(stderr,"usage: %s [-aAflrtvVwy] [-d path -d ...] " - "[-u path -u ...]\n%15sdevice\n",name,""); - fprintf(stderr," -a automatically repair the file system\n"); - fprintf(stderr," -A toggle Atari file system format\n"); - fprintf(stderr," -d path drop that file\n"); - fprintf(stderr," -f salvage unused chains to files\n"); - fprintf(stderr," -l list path names\n"); - fprintf(stderr," -n no-op, check non-interactively without changing\n"); - fprintf(stderr," -r interactively repair the file system\n"); - fprintf(stderr," -t test for bad clusters\n"); - fprintf(stderr," -u path try to undelete that (non-directory) file\n"); - fprintf(stderr," -v verbose mode\n"); - fprintf(stderr," -V perform a verification pass\n"); - fprintf(stderr," -w write changes to disk immediately\n"); - fprintf(stderr," -y same as -a, for compat with other *fsck\n"); - exit(2); -} - - -/* - * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant - * of MS-DOS filesystem by default. - */ -static void check_atari( void ) -{ -#ifdef __mc68000__ - FILE *f; - char line[128], *p; - - if (!(f = fopen( "/proc/hardware", "r" ))) { - perror( "/proc/hardware" ); - return; - } - - while( fgets( line, sizeof(line), f ) ) { - if (strncmp( line, "Model:", 6 ) == 0) { - p = line + 6; - p += strspn( p, " \t" ); - if (strncmp( p, "Atari ", 6 ) == 0) - atari_format = 1; - break; - } - } - fclose( f ); -#endif -} - - -int main(int argc,char **argv) -{ - DOS_FS fs; - int rw,salvage_files,verify,c; - unsigned long free_clusters; - - rw = salvage_files = verify = 0; - interactive = 1; - check_atari(); - - while ((c = getopt(argc,argv,"Aad:flnrtu:vVwy")) != EOF) - switch (c) { - case 'A': /* toggle Atari format */ - atari_format = !atari_format; - break; - case 'a': - case 'y': - rw = 1; - interactive = 0; - salvage_files = 1; - break; - case 'd': - file_add(optarg,fdt_drop); - break; - case 'f': - salvage_files = 1; - break; - case 'l': - list = 1; - break; - case 'n': - rw = 0; - interactive = 0; - break; - case 'r': - rw = 1; - interactive = 1; - break; - case 't': - test = 1; - break; - case 'u': - file_add(optarg,fdt_undelete); - break; - case 'v': - verbose = 1; - printf("dosfsck " VERSION " (" VERSION_DATE ")\n"); - break; - case 'V': - verify = 1; - break; - case 'w': - write_immed = 1; - break; - default: - usage(argv[0]); +/* dosfsck.c - User interface */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include "version.h" + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "boot.h" +#include "fat.h" +#include "file.h" +#include "check.h" + + +int interactive = 0,list = 0,test = 0,verbose = 0,write_immed = 0; +int atari_format = 0; +unsigned n_files = 0; +void *mem_queue = NULL; + + +static void usage(char *name) +{ + fprintf(stderr,"usage: %s [-aAflrtvVwy] [-d path -d ...] " + "[-u path -u ...]\n%15sdevice\n",name,""); + fprintf(stderr," -a automatically repair the file system\n"); + fprintf(stderr," -A toggle Atari file system format\n"); + fprintf(stderr," -d path drop that file\n"); + fprintf(stderr," -f salvage unused chains to files\n"); + fprintf(stderr," -l list path names\n"); + fprintf(stderr," -n no-op, check non-interactively without changing\n"); + fprintf(stderr," -r interactively repair the file system\n"); + fprintf(stderr," -t test for bad clusters\n"); + fprintf(stderr," -u path try to undelete that (non-directory) file\n"); + fprintf(stderr," -v verbose mode\n"); + fprintf(stderr," -V perform a verification pass\n"); + fprintf(stderr," -w write changes to disk immediately\n"); + fprintf(stderr," -y same as -a, for compat with other *fsck\n"); + exit(2); +} + + +/* + * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant + * of MS-DOS filesystem by default. + */ +static void check_atari( void ) +{ +#ifdef __mc68000__ + FILE *f; + char line[128], *p; + + if (!(f = fopen( "/proc/hardware", "r" ))) { + perror( "/proc/hardware" ); + return; + } + + while( fgets( line, sizeof(line), f ) ) { + if (strncmp( line, "Model:", 6 ) == 0) { + p = line + 6; + p += strspn( p, " \t" ); + if (strncmp( p, "Atari ", 6 ) == 0) + atari_format = 1; + break; } - - if ((test || write_immed) && !rw) { - fprintf(stderr,"-t and -w require -a or -r\n"); - exit(2); - } - if (optind != argc-1) usage(argv[0]); - - printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" ); - fs_open(argv[optind],rw); - read_boot(&fs); - if (verify) printf("Starting check/repair pass.\n"); - while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); - if (test) fix_bad(&fs); - if (salvage_files) reclaim_file(&fs); - else reclaim_free(&fs); - free_clusters = update_free(&fs); - file_unused(); - qfree(&mem_queue); - if (verify) { - printf("Starting verification pass.\n"); - read_fat(&fs); - scan_root(&fs); - reclaim_free(&fs); - qfree(&mem_queue); - } - - if (fs_changed()) { - if (rw) { - if (interactive) - rw = get_key("yn","Perform changes ? (y/n)") == 'y'; - else printf("Performing changes.\n"); - } - else - printf("Leaving file system unchanged.\n"); - } - - printf( "%s: %u files, %lu/%lu clusters\n", argv[optind], - n_files, fs.clusters - free_clusters, fs.clusters ); - - return fs_close(rw) ? 1 : 0; -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ + } + fclose( f ); +#endif +} + + +int main(int argc,char **argv) +{ + DOS_FS fs; + int rw,salvage_files,verify,c; + unsigned long free_clusters; + + rw = salvage_files = verify = 0; + interactive = 1; + check_atari(); + + while ((c = getopt(argc,argv,"Aad:flnrtu:vVwy")) != EOF) + switch (c) { + case 'A': /* toggle Atari format */ + atari_format = !atari_format; + break; + case 'a': + case 'y': + rw = 1; + interactive = 0; + salvage_files = 1; + break; + case 'd': + file_add(optarg,fdt_drop); + break; + case 'f': + salvage_files = 1; + break; + case 'l': + list = 1; + break; + case 'n': + rw = 0; + interactive = 0; + break; + case 'r': + rw = 1; + interactive = 1; + break; + case 't': + test = 1; + break; + case 'u': + file_add(optarg,fdt_undelete); + break; + case 'v': + verbose = 1; + printf("dosfsck " VERSION " (" VERSION_DATE ")\n"); + break; + case 'V': + verify = 1; + break; + case 'w': + write_immed = 1; + break; + default: + usage(argv[0]); + } + + if ((test || write_immed) && !rw) { + fprintf(stderr,"-t and -w require -a or -r\n"); + exit(2); + } + if (optind != argc-1) usage(argv[0]); + + printf( "dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n" ); + fs_open(argv[optind],rw); + read_boot(&fs); + if (verify) printf("Starting check/repair pass.\n"); + while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); + if (test) fix_bad(&fs); + if (salvage_files) reclaim_file(&fs); + else reclaim_free(&fs); + free_clusters = update_free(&fs); + file_unused(); + qfree(&mem_queue); + if (verify) { + printf("Starting verification pass.\n"); + read_fat(&fs); + scan_root(&fs); + reclaim_free(&fs); + qfree(&mem_queue); + } + + if (fs_changed()) { + if (rw) { + if (interactive) + rw = get_key("yn","Perform changes ? (y/n)") == 'y'; + else printf("Performing changes.\n"); + } + else + printf("Leaving file system unchanged.\n"); + } + + printf( "%s: %u files, %lu/%lu clusters\n", argv[optind], + n_files, fs.clusters - free_clusters, fs.clusters ); + + return fs_close(rw) ? 1 : 0; +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/dosfsck.h b/rosapps/sysutils/dosfsck/dosfsck.h index f3ab006ca1b..6fcc5b50dd1 100644 --- a/rosapps/sysutils/dosfsck/dosfsck.h +++ b/rosapps/sysutils/dosfsck/dosfsck.h @@ -1,187 +1,187 @@ -/* dosfsck.h - Common data structures and global variables */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#ifndef _DOSFSCK_H -#define _DOSFSCK_H - -//#include "types.h" - +/* dosfsck.h - Common data structures and global variables */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#ifndef _DOSFSCK_H +#define _DOSFSCK_H + +//#include "types.h" + #ifdef _WIN32 typedef unsigned char __u8; typedef unsigned short __u16; typedef unsigned int __u32; -typedef unsigned __int64 __u64; -typedef unsigned short __le16; +typedef unsigned __int64 __u64; +typedef unsigned short __le16; typedef unsigned int __le32; typedef __int64 loff_t; typedef __int64 ll_t; - -#define CF_LE_W(v) (v) -#define CF_LE_L(v) (v) -#define CT_LE_W(v) (v) -#define CT_LE_L(v) (v) - -#endif - -#define _LINUX_STAT_H /* hack to avoid inclusion of */ -#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ -#define _LINUX_FS_H /* hack to avoid inclusion of */ - -//#include -//# include "types.h" -# include "byteorder.h" - -#include "msdos_fs.h" - -#if 0 -#undef CF_LE_W -#undef CF_LE_L -#undef CT_LE_W -#undef CT_LE_L -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN -#include "byteswap.h" -#if 0 -#define CF_LE_W(v) bswap_16(v) -#define CF_LE_L(v) bswap_32(v) -#define CT_LE_W(v) CF_LE_W(v) -#define CT_LE_L(v) CF_LE_L(v) -#endif -#else -#define CF_LE_W(v) (v) -#define CF_LE_L(v) (v) -#define CT_LE_W(v) (v) -#define CT_LE_L(v) (v) -#endif /* __BIG_ENDIAN */ - -#define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) - + +#define CF_LE_W(v) (v) +#define CF_LE_L(v) (v) +#define CT_LE_W(v) (v) +#define CT_LE_L(v) (v) + +#endif + +#define _LINUX_STAT_H /* hack to avoid inclusion of */ +#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ +#define _LINUX_FS_H /* hack to avoid inclusion of */ + +//#include +//# include "types.h" +# include "byteorder.h" + +#include "msdos_fs.h" + +#if 0 +#undef CF_LE_W +#undef CF_LE_L +#undef CT_LE_W +#undef CT_LE_L +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +#include "byteswap.h" +#if 0 +#define CF_LE_W(v) bswap_16(v) +#define CF_LE_L(v) bswap_32(v) +#define CT_LE_W(v) CF_LE_W(v) +#define CT_LE_L(v) CF_LE_L(v) +#endif +#else +#define CF_LE_W(v) (v) +#define CF_LE_L(v) (v) +#define CT_LE_W(v) (v) +#define CT_LE_L(v) (v) +#endif /* __BIG_ENDIAN */ + +#define VFAT_LN_ATTR (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) + #include -/* ++roman: Use own definition of boot sector structure -- the kernel headers' - * name for it is msdos_boot_sector in 2.0 and fat_boot_sector in 2.1 ... */ -struct boot_sector { - __u8 ignored[3]; /* Boot strap short or near jump */ - __u8 system_id[8]; /* Name - can be used to special case - partition manager volumes */ - __u8 sector_size[2]; /* bytes per logical sector */ - __u8 cluster_size; /* sectors/cluster */ - __u16 reserved; /* reserved sectors */ - __u8 fats; /* number of FATs */ - __u8 dir_entries[2]; /* root directory entries */ - __u8 sectors[2]; /* number of sectors */ - __u8 media; /* media code (unused) */ - __u16 fat_length; /* sectors/FAT */ - __u16 secs_track; /* sectors per track */ - __u16 heads; /* number of heads */ - __u32 hidden; /* hidden sectors (unused) */ - __u32 total_sect; /* number of sectors (if sectors == 0) */ - - /* The following fields are only used by FAT32 */ - __u32 fat32_length; /* sectors/FAT */ - __u16 flags; /* bit 8: fat mirroring, low 4: active fat */ - __u8 version[2]; /* major, minor filesystem version */ - __u32 root_cluster; /* first cluster in root directory */ - __u16 info_sector; /* filesystem info sector */ - __u16 backup_boot; /* backup boot sector */ - __u16 reserved2[6]; /* Unused */ - - /* fill up to 512 bytes */ - __u8 junk[448]; -}; +/* ++roman: Use own definition of boot sector structure -- the kernel headers' + * name for it is msdos_boot_sector in 2.0 and fat_boot_sector in 2.1 ... */ +struct boot_sector { + __u8 ignored[3]; /* Boot strap short or near jump */ + __u8 system_id[8]; /* Name - can be used to special case + partition manager volumes */ + __u8 sector_size[2]; /* bytes per logical sector */ + __u8 cluster_size; /* sectors/cluster */ + __u16 reserved; /* reserved sectors */ + __u8 fats; /* number of FATs */ + __u8 dir_entries[2]; /* root directory entries */ + __u8 sectors[2]; /* number of sectors */ + __u8 media; /* media code (unused) */ + __u16 fat_length; /* sectors/FAT */ + __u16 secs_track; /* sectors per track */ + __u16 heads; /* number of heads */ + __u32 hidden; /* hidden sectors (unused) */ + __u32 total_sect; /* number of sectors (if sectors == 0) */ + + /* The following fields are only used by FAT32 */ + __u32 fat32_length; /* sectors/FAT */ + __u16 flags; /* bit 8: fat mirroring, low 4: active fat */ + __u8 version[2]; /* major, minor filesystem version */ + __u32 root_cluster; /* first cluster in root directory */ + __u16 info_sector; /* filesystem info sector */ + __u16 backup_boot; /* backup boot sector */ + __u16 reserved2[6]; /* Unused */ + + /* fill up to 512 bytes */ + __u8 junk[448]; +}; #include - -struct info_sector { - __u32 magic; /* Magic for info sector ('RRaA') */ - __u8 junk[0x1dc]; - __u32 reserved1; /* Nothing as far as I can tell */ - __u32 signature; /* 0x61417272 ('rrAa') */ - __u32 free_clusters; /* Free cluster count. -1 if unknown */ - __u32 next_cluster; /* Most recently allocated cluster. */ - __u32 reserved2[3]; - __u16 reserved3; - __u16 boot_sign; -}; - -typedef struct { - __u8 name[8],ext[3]; /* name and extension */ - __u8 attr; /* attribute bits */ - __u8 lcase; /* Case for base and extension */ - __u8 ctime_ms; /* Creation time, milliseconds */ - __u16 ctime; /* Creation time */ - __u16 cdate; /* Creation date */ - __u16 adate; /* Last access date */ - __u16 starthi; /* High 16 bits of cluster in FAT32 */ - __u16 time,date,start;/* time, date and first cluster */ - __u32 size; /* file size (in bytes) */ -} DIR_ENT; - -typedef struct _dos_file { - DIR_ENT dir_ent; - char *lfn; - loff_t offset; - struct _dos_file *parent; /* parent directory */ - struct _dos_file *next; /* next entry */ - struct _dos_file *first; /* first entry (directory only) */ -} DOS_FILE; - -typedef struct { - unsigned long value; - unsigned long reserved; - DOS_FILE *owner; - int prev; /* number of previous clusters */ -} FAT_ENTRY; - -typedef struct { - int nfats; - loff_t fat_start; - unsigned int fat_size; /* unit is bytes */ - unsigned int fat_bits; /* size of a FAT entry */ - unsigned int eff_fat_bits; /* # of used bits in a FAT entry */ - unsigned long root_cluster; /* 0 for old-style root dir */ - loff_t root_start; - unsigned int root_entries; - loff_t data_start; - unsigned int cluster_size; - unsigned long clusters; - loff_t fsinfo_start; /* 0 if not present */ - long free_clusters; - loff_t backupboot_start; /* 0 if not present */ - FAT_ENTRY *fat; -} DOS_FS; - -#ifndef offsetof -#define offsetof(t,e) ((int)&(((t *)0)->e)) -#endif - -extern int interactive,list,verbose,test,write_immed; -extern int atari_format; -extern unsigned n_files; -extern void *mem_queue; - -/* value to use as end-of-file marker */ -#define FAT_EOF(fs) ((atari_format ? 0xfff : 0xff8) | FAT_EXTD(fs)) -#define FAT_IS_EOF(fs,v) ((unsigned long)(v) >= (0xff8|FAT_EXTD(fs))) -/* value to mark bad clusters */ -#define FAT_BAD(fs) (0xff7 | FAT_EXTD(fs)) -/* range of values used for bad clusters */ -#define FAT_MIN_BAD(fs) ((atari_format ? 0xff0 : 0xff7) | FAT_EXTD(fs)) -#define FAT_MAX_BAD(fs) ((atari_format ? 0xff7 : 0xff7) | FAT_EXTD(fs)) -#define FAT_IS_BAD(fs,v) ((v) >= FAT_MIN_BAD(fs) && (v) <= FAT_MAX_BAD(fs)) - -/* return -16 as a number with fs->fat_bits bits */ -#define FAT_EXTD(fs) (((1 << fs->eff_fat_bits)-1) & ~0xf) - -#endif - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ + +struct info_sector { + __u32 magic; /* Magic for info sector ('RRaA') */ + __u8 junk[0x1dc]; + __u32 reserved1; /* Nothing as far as I can tell */ + __u32 signature; /* 0x61417272 ('rrAa') */ + __u32 free_clusters; /* Free cluster count. -1 if unknown */ + __u32 next_cluster; /* Most recently allocated cluster. */ + __u32 reserved2[3]; + __u16 reserved3; + __u16 boot_sign; +}; + +typedef struct { + __u8 name[8],ext[3]; /* name and extension */ + __u8 attr; /* attribute bits */ + __u8 lcase; /* Case for base and extension */ + __u8 ctime_ms; /* Creation time, milliseconds */ + __u16 ctime; /* Creation time */ + __u16 cdate; /* Creation date */ + __u16 adate; /* Last access date */ + __u16 starthi; /* High 16 bits of cluster in FAT32 */ + __u16 time,date,start;/* time, date and first cluster */ + __u32 size; /* file size (in bytes) */ +} DIR_ENT; + +typedef struct _dos_file { + DIR_ENT dir_ent; + char *lfn; + loff_t offset; + struct _dos_file *parent; /* parent directory */ + struct _dos_file *next; /* next entry */ + struct _dos_file *first; /* first entry (directory only) */ +} DOS_FILE; + +typedef struct { + unsigned long value; + unsigned long reserved; + DOS_FILE *owner; + int prev; /* number of previous clusters */ +} FAT_ENTRY; + +typedef struct { + int nfats; + loff_t fat_start; + unsigned int fat_size; /* unit is bytes */ + unsigned int fat_bits; /* size of a FAT entry */ + unsigned int eff_fat_bits; /* # of used bits in a FAT entry */ + unsigned long root_cluster; /* 0 for old-style root dir */ + loff_t root_start; + unsigned int root_entries; + loff_t data_start; + unsigned int cluster_size; + unsigned long clusters; + loff_t fsinfo_start; /* 0 if not present */ + long free_clusters; + loff_t backupboot_start; /* 0 if not present */ + FAT_ENTRY *fat; +} DOS_FS; + +#ifndef offsetof +#define offsetof(t,e) ((int)&(((t *)0)->e)) +#endif + +extern int interactive,list,verbose,test,write_immed; +extern int atari_format; +extern unsigned n_files; +extern void *mem_queue; + +/* value to use as end-of-file marker */ +#define FAT_EOF(fs) ((atari_format ? 0xfff : 0xff8) | FAT_EXTD(fs)) +#define FAT_IS_EOF(fs,v) ((unsigned long)(v) >= (0xff8|FAT_EXTD(fs))) +/* value to mark bad clusters */ +#define FAT_BAD(fs) (0xff7 | FAT_EXTD(fs)) +/* range of values used for bad clusters */ +#define FAT_MIN_BAD(fs) ((atari_format ? 0xff0 : 0xff7) | FAT_EXTD(fs)) +#define FAT_MAX_BAD(fs) ((atari_format ? 0xff7 : 0xff7) | FAT_EXTD(fs)) +#define FAT_IS_BAD(fs,v) ((v) >= FAT_MIN_BAD(fs) && (v) <= FAT_MAX_BAD(fs)) + +/* return -16 as a number with fs->fat_bits bits */ +#define FAT_EXTD(fs) (((1 << fs->eff_fat_bits)-1) & ~0xf) + +#endif + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/fat.c b/rosapps/sysutils/dosfsck/fat.c index 921d9f7f012..5f29d5f2a54 100644 --- a/rosapps/sysutils/dosfsck/fat.c +++ b/rosapps/sysutils/dosfsck/fat.c @@ -1,366 +1,366 @@ -/* fat.c - Read/write access to the FAT */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -//#include - -#include "common.h" -#include "dosfsck.h" -#include "io.h" -#include "check.h" -#include "fat.h" +/* fat.c - Read/write access to the FAT */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +//#include + +#include "common.h" +#include "dosfsck.h" +#include "io.h" +#include "check.h" +#include "fat.h" + +#pragma warning(disable: 4018) + +static void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs) +{ + unsigned char *ptr; + + switch(fs->fat_bits) { + case 12: + ptr = &((unsigned char *) fat)[cluster*3/2]; + entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) : + (ptr[0] | ptr[1] << 8)); + break; + case 16: + entry->value = CF_LE_W(((unsigned short *) fat)[cluster]); + break; + case 32: + /* 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. */ + { + unsigned long e = CF_LE_L(((unsigned int *) fat)[cluster]); + entry->value = e & 0xfffffff; + entry->reserved = e >> 28; + } + break; + default: + die("Bad FAT entry size: %d bits.",fs->fat_bits); + } + entry->owner = NULL; +} + + +void read_fat(DOS_FS *fs) +{ + int eff_size; + unsigned long i; + void *first,*second,*use; + int first_ok,second_ok; -#pragma warning(disable: 4018) - -static void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs) -{ - unsigned char *ptr; - - switch(fs->fat_bits) { - case 12: - ptr = &((unsigned char *) fat)[cluster*3/2]; - entry->value = 0xfff & (cluster & 1 ? (ptr[0] >> 4) | (ptr[1] << 4) : - (ptr[0] | ptr[1] << 8)); - break; - case 16: - entry->value = CF_LE_W(((unsigned short *) fat)[cluster]); - break; - case 32: - /* 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. */ - { - unsigned long e = CF_LE_L(((unsigned int *) fat)[cluster]); - entry->value = e & 0xfffffff; - entry->reserved = e >> 28; - } - break; - default: - die("Bad FAT entry size: %d bits.",fs->fat_bits); - } - entry->owner = NULL; -} - - -void read_fat(DOS_FS *fs) -{ - int eff_size; - unsigned long i; - void *first,*second,*use; - int first_ok,second_ok; - eff_size = ((fs->clusters+2)*fs->fat_bits+7)/8; // TMN: Must round up to disk-sector boundary. For now, assume 512-byte disk. if (eff_size % 512) { eff_size += 512 - (eff_size % 512); - } - first = alloc(eff_size); - fs_read(fs->fat_start,eff_size,first); - use = first; - if (fs->nfats > 1) { - second = alloc(eff_size); - fs_read(fs->fat_start+fs->fat_size,eff_size,second); - } - else - second = NULL; - if (second && memcmp(first,second,eff_size) != 0) { - FAT_ENTRY first_media, second_media; - get_fat(&first_media,first,0,fs); - get_fat(&second_media,second,0,fs); - first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); - second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); - if (first_ok && !second_ok) { - printf("FATs differ - using first FAT.\n"); - fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); - } - if (!first_ok && second_ok) { - printf("FATs differ - using second FAT.\n"); - fs_write(fs->fat_start,eff_size,use = second); - } - if (first_ok && second_ok) { - if (interactive) { - printf("FATs differ but appear to be intact. Use which FAT ?\n" - "1) Use first FAT\n2) Use second FAT\n"); - if (get_key("12","?") == '1') - fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); - else fs_write(fs->fat_start,eff_size,use = second); - } - else { - printf("FATs differ but appear to be intact. Using first " - "FAT.\n"); - fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); - } - } - if (!first_ok && !second_ok) { - printf("Both FATs appear to be corrupt. Giving up.\n"); - exit(1); - } - } - fs->fat = qalloc(&mem_queue,sizeof(FAT_ENTRY)*(fs->clusters+2)); - for (i = 2; i < fs->clusters+2; i++) get_fat(&fs->fat[i],use,i,fs); - for (i = 2; i < fs->clusters+2; i++) - if (fs->fat[i].value >= fs->clusters+2 && - (fs->fat[i].value < FAT_MIN_BAD(fs))) { - printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n", - i-2,fs->fat[i].value,fs->clusters+2-1); - set_fat(fs,i,-1); - } - free(first); - if (second) - free(second); -} - - -void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new) -{ - unsigned char data[4]; - int size; - loff_t offs; - - if ((long)new == -1) - new = FAT_EOF(fs); - else if ((long)new == -2) - new = FAT_BAD(fs); - switch( fs->fat_bits ) { - case 12: - offs = fs->fat_start+cluster*3/2; - if (cluster & 1) { - data[0] = ((new & 0xf) << 4) | (fs->fat[cluster-1].value >> 8); - data[1] = new >> 4; - } - else { - data[0] = new & 0xff; - data[1] = (new >> 8) | (cluster == fs->clusters-1 ? 0 : - (0xff & fs->fat[cluster+1].value) << 4); - } - size = 2; - break; - case 16: - offs = fs->fat_start+cluster*2; - *(unsigned short *) data = CT_LE_W(new); - size = 2; - break; - case 32: - offs = fs->fat_start+cluster*4; - /* 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. */ - *(unsigned long *) data = CT_LE_L( (new & 0xfffffff) | - (fs->fat[cluster].reserved << 28) ); - size = 4; - break; - default: - die("Bad FAT entry size: %d bits.",fs->fat_bits); - } - fs->fat[cluster].value = new; - fs_write(offs,size,&data); - fs_write(offs+fs->fat_size,size,&data); -} - - -int bad_cluster(DOS_FS *fs,unsigned long cluster) -{ - return FAT_IS_BAD(fs,fs->fat[cluster].value); -} - - -unsigned long next_cluster(DOS_FS *fs,unsigned long cluster) -{ - unsigned long value; - - value = fs->fat[cluster].value; - if (FAT_IS_BAD(fs,value)) - die("Internal error: next_cluster on bad cluster"); - return FAT_IS_EOF(fs,value) ? -1 : value; -} - - -loff_t cluster_start(DOS_FS *fs,unsigned long cluster) -{ - return fs->data_start+((loff_t)cluster-2)*fs->cluster_size; -} - - -void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner) -{ - if (owner && fs->fat[cluster].owner) - die("Internal error: attempt to change file owner"); - fs->fat[cluster].owner = owner; -} - - -DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster) -{ - return fs->fat[cluster].owner; -} - - -void fix_bad(DOS_FS *fs) -{ - unsigned long i; - - if (verbose) - printf("Checking for bad clusters.\n"); - for (i = 2; i < fs->clusters+2; i++) - if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) - if (!fs_test(cluster_start(fs,i),fs->cluster_size)) { - printf("Cluster %lu is unreadable.\n",i); - set_fat(fs,i,-2); - } -} - - -void reclaim_free(DOS_FS *fs) -{ - int reclaimed; - unsigned long i; - - if (verbose) - printf("Checking for unused clusters.\n"); - reclaimed = 0; - for (i = 2; i < fs->clusters+2; i++) - if (!get_owner(fs,i) && fs->fat[i].value && - !FAT_IS_BAD(fs,fs->fat[i].value)) { - set_fat(fs,i,0); - reclaimed++; - } - if (reclaimed) - printf("Reclaimed %d unused cluster%s (%d bytes).\n",reclaimed, - reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size); -} - - -static void tag_free(DOS_FS *fs,DOS_FILE *ptr) -{ - DOS_FILE *owner; - int prev; - unsigned long i,walk; - - for (i = 2; i < fs->clusters+2; i++) - if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && - !get_owner(fs,i) && !fs->fat[i].prev) { - prev = 0; - for (walk = i; walk > 0 && walk != -1; - walk = next_cluster(fs,walk)) { - if (!(owner = get_owner(fs,walk))) set_owner(fs,walk,ptr); - else if (owner != ptr) - die("Internal error: free chain collides with file"); - else { - set_fat(fs,prev,-1); - break; - } - prev = walk; - } - } -} - - -void reclaim_file(DOS_FS *fs) -{ - DOS_FILE dummy; - int reclaimed,files,changed; - unsigned long i,next,walk; - - if (verbose) - printf("Reclaiming unconnected clusters.\n"); - for (i = 2; i < fs->clusters+2; i++) fs->fat[i].prev = 0; - for (i = 2; i < fs->clusters+2; i++) { - next = fs->fat[i].value; - if (!get_owner(fs,i) && next && next < fs->clusters+2) { - if (get_owner(fs,next) || !fs->fat[next].value || - FAT_IS_BAD(fs,fs->fat[next].value)) set_fat(fs,i,-1); - else fs->fat[next].prev++; - } - } - do { - tag_free(fs,&dummy); - changed = 0; - for (i = 2; i < fs->clusters+2; i++) - if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && - !get_owner(fs, i)) { - if (!fs->fat[fs->fat[i].value].prev--) - die("Internal error: prev going below zero"); - set_fat(fs,i,-1); - changed = 1; - printf("Broke cycle at cluster %lu in free chain.\n",i); - break; - } - } - while (changed); - files = reclaimed = 0; - for (i = 2; i < fs->clusters+2; i++) - if (get_owner(fs,i) == &dummy && !fs->fat[i].prev) { - DIR_ENT de; - loff_t offset; - files++; - offset = alloc_rootdir_entry(fs,&de,"FSCK%04dREC"); - de.start = CT_LE_W(i&0xffff); - if (fs->fat_bits == 32) - de.starthi = CT_LE_W(i>>16); - for (walk = i; walk > 0 && walk != -1; - walk = next_cluster(fs,walk)) { - de.size = CT_LE_L(CF_LE_L(de.size)+fs->cluster_size); - reclaimed++; - } - fs_write(offset,sizeof(DIR_ENT),&de); - } - if (reclaimed) - printf("Reclaimed %d unused cluster%s (%d bytes) in %d chain%s.\n", - reclaimed,reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size,files, - files == 1 ? "" : "s"); -} - - -unsigned long update_free(DOS_FS *fs) -{ - unsigned long i; - unsigned long free = 0; - int do_set = 0; - - for (i = 2; i < fs->clusters+2; i++) - if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) - ++free; - - if (!fs->fsinfo_start) - return free; - - if (verbose) - printf("Checking free cluster summary.\n"); - if (fs->free_clusters >= 0) { - if (free != fs->free_clusters) { - printf( "Free cluster summary wrong (%ld vs. really %ld)\n", - fs->free_clusters,free); - if (interactive) - printf( "1) Correct\n2) Don't correct\n" ); - else printf( " Auto-correcting.\n" ); - if (!interactive || get_key("12","?") == '1') - do_set = 1; - } - } - else { - printf( "Free cluster summary uninitialized (should be %ld)\n", free ); - if (interactive) - printf( "1) Set it\n2) Leave it uninitialized\n" ); - else printf( " Auto-setting.\n" ); - if (!interactive || get_key("12","?") == '1') - do_set = 1; - } - - if (do_set) { - fs->free_clusters = free; - free = CT_LE_L(free); - fs_write(fs->fsinfo_start+offsetof(struct info_sector,free_clusters), - sizeof(free),&free); - } - - return free; -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ + } + first = alloc(eff_size); + fs_read(fs->fat_start,eff_size,first); + use = first; + if (fs->nfats > 1) { + second = alloc(eff_size); + fs_read(fs->fat_start+fs->fat_size,eff_size,second); + } + else + second = NULL; + if (second && memcmp(first,second,eff_size) != 0) { + FAT_ENTRY first_media, second_media; + get_fat(&first_media,first,0,fs); + get_fat(&second_media,second,0,fs); + first_ok = (first_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); + second_ok = (second_media.value & FAT_EXTD(fs)) == FAT_EXTD(fs); + if (first_ok && !second_ok) { + printf("FATs differ - using first FAT.\n"); + fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); + } + if (!first_ok && second_ok) { + printf("FATs differ - using second FAT.\n"); + fs_write(fs->fat_start,eff_size,use = second); + } + if (first_ok && second_ok) { + if (interactive) { + printf("FATs differ but appear to be intact. Use which FAT ?\n" + "1) Use first FAT\n2) Use second FAT\n"); + if (get_key("12","?") == '1') + fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); + else fs_write(fs->fat_start,eff_size,use = second); + } + else { + printf("FATs differ but appear to be intact. Using first " + "FAT.\n"); + fs_write(fs->fat_start+fs->fat_size,eff_size,use = first); + } + } + if (!first_ok && !second_ok) { + printf("Both FATs appear to be corrupt. Giving up.\n"); + exit(1); + } + } + fs->fat = qalloc(&mem_queue,sizeof(FAT_ENTRY)*(fs->clusters+2)); + for (i = 2; i < fs->clusters+2; i++) get_fat(&fs->fat[i],use,i,fs); + for (i = 2; i < fs->clusters+2; i++) + if (fs->fat[i].value >= fs->clusters+2 && + (fs->fat[i].value < FAT_MIN_BAD(fs))) { + printf("Cluster %ld out of range (%ld > %ld). Setting to EOF.\n", + i-2,fs->fat[i].value,fs->clusters+2-1); + set_fat(fs,i,-1); + } + free(first); + if (second) + free(second); +} + + +void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new) +{ + unsigned char data[4]; + int size; + loff_t offs; + + if ((long)new == -1) + new = FAT_EOF(fs); + else if ((long)new == -2) + new = FAT_BAD(fs); + switch( fs->fat_bits ) { + case 12: + offs = fs->fat_start+cluster*3/2; + if (cluster & 1) { + data[0] = ((new & 0xf) << 4) | (fs->fat[cluster-1].value >> 8); + data[1] = new >> 4; + } + else { + data[0] = new & 0xff; + data[1] = (new >> 8) | (cluster == fs->clusters-1 ? 0 : + (0xff & fs->fat[cluster+1].value) << 4); + } + size = 2; + break; + case 16: + offs = fs->fat_start+cluster*2; + *(unsigned short *) data = CT_LE_W(new); + size = 2; + break; + case 32: + offs = fs->fat_start+cluster*4; + /* 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. */ + *(unsigned long *) data = CT_LE_L( (new & 0xfffffff) | + (fs->fat[cluster].reserved << 28) ); + size = 4; + break; + default: + die("Bad FAT entry size: %d bits.",fs->fat_bits); + } + fs->fat[cluster].value = new; + fs_write(offs,size,&data); + fs_write(offs+fs->fat_size,size,&data); +} + + +int bad_cluster(DOS_FS *fs,unsigned long cluster) +{ + return FAT_IS_BAD(fs,fs->fat[cluster].value); +} + + +unsigned long next_cluster(DOS_FS *fs,unsigned long cluster) +{ + unsigned long value; + + value = fs->fat[cluster].value; + if (FAT_IS_BAD(fs,value)) + die("Internal error: next_cluster on bad cluster"); + return FAT_IS_EOF(fs,value) ? -1 : value; +} + + +loff_t cluster_start(DOS_FS *fs,unsigned long cluster) +{ + return fs->data_start+((loff_t)cluster-2)*fs->cluster_size; +} + + +void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner) +{ + if (owner && fs->fat[cluster].owner) + die("Internal error: attempt to change file owner"); + fs->fat[cluster].owner = owner; +} + + +DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster) +{ + return fs->fat[cluster].owner; +} + + +void fix_bad(DOS_FS *fs) +{ + unsigned long i; + + if (verbose) + printf("Checking for bad clusters.\n"); + for (i = 2; i < fs->clusters+2; i++) + if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) + if (!fs_test(cluster_start(fs,i),fs->cluster_size)) { + printf("Cluster %lu is unreadable.\n",i); + set_fat(fs,i,-2); + } +} + + +void reclaim_free(DOS_FS *fs) +{ + int reclaimed; + unsigned long i; + + if (verbose) + printf("Checking for unused clusters.\n"); + reclaimed = 0; + for (i = 2; i < fs->clusters+2; i++) + if (!get_owner(fs,i) && fs->fat[i].value && + !FAT_IS_BAD(fs,fs->fat[i].value)) { + set_fat(fs,i,0); + reclaimed++; + } + if (reclaimed) + printf("Reclaimed %d unused cluster%s (%d bytes).\n",reclaimed, + reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size); +} + + +static void tag_free(DOS_FS *fs,DOS_FILE *ptr) +{ + DOS_FILE *owner; + int prev; + unsigned long i,walk; + + for (i = 2; i < fs->clusters+2; i++) + if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && + !get_owner(fs,i) && !fs->fat[i].prev) { + prev = 0; + for (walk = i; walk > 0 && walk != -1; + walk = next_cluster(fs,walk)) { + if (!(owner = get_owner(fs,walk))) set_owner(fs,walk,ptr); + else if (owner != ptr) + die("Internal error: free chain collides with file"); + else { + set_fat(fs,prev,-1); + break; + } + prev = walk; + } + } +} + + +void reclaim_file(DOS_FS *fs) +{ + DOS_FILE dummy; + int reclaimed,files,changed; + unsigned long i,next,walk; + + if (verbose) + printf("Reclaiming unconnected clusters.\n"); + for (i = 2; i < fs->clusters+2; i++) fs->fat[i].prev = 0; + for (i = 2; i < fs->clusters+2; i++) { + next = fs->fat[i].value; + if (!get_owner(fs,i) && next && next < fs->clusters+2) { + if (get_owner(fs,next) || !fs->fat[next].value || + FAT_IS_BAD(fs,fs->fat[next].value)) set_fat(fs,i,-1); + else fs->fat[next].prev++; + } + } + do { + tag_free(fs,&dummy); + changed = 0; + for (i = 2; i < fs->clusters+2; i++) + if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) && + !get_owner(fs, i)) { + if (!fs->fat[fs->fat[i].value].prev--) + die("Internal error: prev going below zero"); + set_fat(fs,i,-1); + changed = 1; + printf("Broke cycle at cluster %lu in free chain.\n",i); + break; + } + } + while (changed); + files = reclaimed = 0; + for (i = 2; i < fs->clusters+2; i++) + if (get_owner(fs,i) == &dummy && !fs->fat[i].prev) { + DIR_ENT de; + loff_t offset; + files++; + offset = alloc_rootdir_entry(fs,&de,"FSCK%04dREC"); + de.start = CT_LE_W(i&0xffff); + if (fs->fat_bits == 32) + de.starthi = CT_LE_W(i>>16); + for (walk = i; walk > 0 && walk != -1; + walk = next_cluster(fs,walk)) { + de.size = CT_LE_L(CF_LE_L(de.size)+fs->cluster_size); + reclaimed++; + } + fs_write(offset,sizeof(DIR_ENT),&de); + } + if (reclaimed) + printf("Reclaimed %d unused cluster%s (%d bytes) in %d chain%s.\n", + reclaimed,reclaimed == 1 ? "" : "s",reclaimed*fs->cluster_size,files, + files == 1 ? "" : "s"); +} + + +unsigned long update_free(DOS_FS *fs) +{ + unsigned long i; + unsigned long free = 0; + int do_set = 0; + + for (i = 2; i < fs->clusters+2; i++) + if (!get_owner(fs,i) && !FAT_IS_BAD(fs,fs->fat[i].value)) + ++free; + + if (!fs->fsinfo_start) + return free; + + if (verbose) + printf("Checking free cluster summary.\n"); + if (fs->free_clusters >= 0) { + if (free != fs->free_clusters) { + printf( "Free cluster summary wrong (%ld vs. really %ld)\n", + fs->free_clusters,free); + if (interactive) + printf( "1) Correct\n2) Don't correct\n" ); + else printf( " Auto-correcting.\n" ); + if (!interactive || get_key("12","?") == '1') + do_set = 1; + } + } + else { + printf( "Free cluster summary uninitialized (should be %ld)\n", free ); + if (interactive) + printf( "1) Set it\n2) Leave it uninitialized\n" ); + else printf( " Auto-setting.\n" ); + if (!interactive || get_key("12","?") == '1') + do_set = 1; + } + + if (do_set) { + fs->free_clusters = free; + free = CT_LE_L(free); + fs_write(fs->fsinfo_start+offsetof(struct info_sector,free_clusters), + sizeof(free),&free); + } + + return free; +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/fat.h b/rosapps/sysutils/dosfsck/fat.h index 8c2312d9e64..32b23de459b 100644 --- a/rosapps/sysutils/dosfsck/fat.h +++ b/rosapps/sysutils/dosfsck/fat.h @@ -1,64 +1,64 @@ -/* fat.h - Read/write access to the FAT */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _FAT_H -#define _FAT_H - -void read_fat(DOS_FS *fs); - -/* Loads the FAT of the file system described by FS. Initializes the FAT, - replaces broken FATs and rejects invalid cluster entries. */ - -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 - values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or - 0xfff7) */ - -int bad_cluster(DOS_FS *fs,unsigned long cluster); - -/* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero - otherwise. */ - -unsigned long next_cluster(DOS_FS *fs,unsigned long cluster); - -/* 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 - cluster. */ - -loff_t cluster_start(DOS_FS *fs,unsigned long cluster); - -/* Returns the byte offset of CLUSTER, relative to the respective device. */ - -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 - before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is - accepted as the new value. */ - -DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster); - -/* Returns the owner of the repective cluster or NULL if the cluster has no - owner. */ - -void fix_bad(DOS_FS *fs); - -/* Scans the disk for currently unused bad clusters and marks them as bad. */ - -void reclaim_free(DOS_FS *fs); - -/* Marks all allocated, but unused clusters as free. */ - -void reclaim_file(DOS_FS *fs); - -/* 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. - loops, shared clusters, etc.) in the process. */ - -unsigned long update_free(DOS_FS *fs); - -/* Updates free cluster count in FSINFO sector. */ - -#endif +/* fat.h - Read/write access to the FAT */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _FAT_H +#define _FAT_H + +void read_fat(DOS_FS *fs); + +/* Loads the FAT of the file system described by FS. Initializes the FAT, + replaces broken FATs and rejects invalid cluster entries. */ + +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 + values of NEW are -1 (EOF, 0xff8 or 0xfff8) and -2 (bad sector, 0xff7 or + 0xfff7) */ + +int bad_cluster(DOS_FS *fs,unsigned long cluster); + +/* Returns a non-zero integer if the CLUSTERth cluster is marked as bad or zero + otherwise. */ + +unsigned long next_cluster(DOS_FS *fs,unsigned long cluster); + +/* 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 + cluster. */ + +loff_t cluster_start(DOS_FS *fs,unsigned long cluster); + +/* Returns the byte offset of CLUSTER, relative to the respective device. */ + +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 + before, it can be set to NULL or any non-NULL value. Otherwise, only NULL is + accepted as the new value. */ + +DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster); + +/* Returns the owner of the repective cluster or NULL if the cluster has no + owner. */ + +void fix_bad(DOS_FS *fs); + +/* Scans the disk for currently unused bad clusters and marks them as bad. */ + +void reclaim_free(DOS_FS *fs); + +/* Marks all allocated, but unused clusters as free. */ + +void reclaim_file(DOS_FS *fs); + +/* 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. + loops, shared clusters, etc.) in the process. */ + +unsigned long update_free(DOS_FS *fs); + +/* Updates free cluster count in FSINFO sector. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/file.c b/rosapps/sysutils/dosfsck/file.c index 9d6b4ff0c03..ea5079cec45 100644 --- a/rosapps/sysutils/dosfsck/file.c +++ b/rosapps/sysutils/dosfsck/file.c @@ -1,251 +1,251 @@ -/* file.c - Additional file attributes */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#include -#include -#include -#include -//#include - -#define _LINUX_STAT_H /* hack to avoid inclusion of */ -#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ -#define _LINUX_FS_H /* hack to avoid inclusion of */ - -//#include -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -//# define __KERNEL__ -//# include -//# undef __KERNEL__ -//#endif - -#include "dosfsck.h" -#include "msdos_fs.h" - -#include "common.h" -#include "file.h" - - -FDSC *fp_root = NULL; - - -static void put_char(char **p,unsigned char c) -{ - if ((c >= ' ' && c < 0x7f) || c >= 0xa0) *(*p)++ = c; - else { - *(*p)++ = '\\'; - *(*p)++ = '0'+(c >> 6); - *(*p)++ = '0'+((c >> 3) & 7); - *(*p)++ = '0'+(c & 7); - } -} - - -char *file_name(unsigned char *fixed) -{ - static char path[MSDOS_NAME*4+2]; - char *p; - int i,j; - - p = path; - for (i = j = 0; i < 8; i++) - if (fixed[i] != ' ') { - while (j++ < i) *p++ = ' '; - put_char(&p,fixed[i]); - } - if (strncmp(fixed+8," ",3)) { - *p++ = '.'; - for (i = j = 0; i < 3; i++) - if (fixed[i+8] != ' ') { - while (j++ < i) *p++ = ' '; - put_char(&p,fixed[i+8]); - } - } - *p = 0; - return path; -} - - -int file_cvt(unsigned char *name,unsigned char *fixed) -{ - unsigned char c; - int size,ext,cnt; - - size = 8; - ext = 0; - while (*name) { - c = *name; - if (c < ' ' || c > 0x7e || strchr("*?<>|\"/",c)) { - printf("Invalid character in name. Use \\ooo for special " - "characters.\n"); - return 0; - } - if (c == '.') { - if (ext) { - printf("Duplicate dots in name.\n"); - return 0; - } - while (size--) *fixed++ = ' '; - size = 3; - ext = 1; - name++; - continue; - } - if (c == '\\') { - c = 0; - for (cnt = 3; cnt; cnt--) { - if (*name < '0' || *name > '7') { - printf("Invalid octal character.\n"); - return 0; - } - c = c*8+*name++-'0'; - } - if (cnt < 4) { - printf("Expected three octal digits.\n"); - return 0; - } - name += 3; - } - if (islower(c)) c = toupper(c); - if (size) { - *fixed++ = c; - size--; - } - name++; - } - if (*name || size == 8) return 0; - if (!ext) { - while (size--) *fixed++ = ' '; - size = 3; - } - while (size--) *fixed++ = ' '; - return 1; -} - - -void file_add(char *path,FD_TYPE type) -{ - FDSC **current,*walk; - char name[MSDOS_NAME]; - char *here; - - current = &fp_root; - if (*path != '/') die("%s: Absolute path required.",path); - path++; - while (1) { - if ((here = strchr(path,'/'))) *here = 0; - if (!file_cvt(path,name)) exit(2); - for (walk = *current; walk; walk = walk->next) - if (!here && (!strncmp(name,walk->name,MSDOS_NAME) || (type == - fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1)))) - die("Ambiguous name: \"%s\"",path); - else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break; - if (!walk) { - walk = alloc(sizeof(FDSC)); - strncpy(walk->name,name,MSDOS_NAME); - walk->type = here ? fdt_none : type; - walk->first = NULL; - walk->next = *current; - *current = walk; - } - current = &walk->first; - if (!here) break; - *here = '/'; - path = here+1; - } -} - - -FDSC **file_cd(FDSC **curr,char *fixed) -{ - FDSC **walk; - - if (!curr || !*curr) return NULL; - for (walk = curr; *walk; walk = &(*walk)->next) - if (!strncmp((*walk)->name,fixed,MSDOS_NAME) && (*walk)->first) - return &(*walk)->first; - return NULL; -} - - -static FDSC **file_find(FDSC **dir,char *fixed) -{ - if (!dir || !*dir) return NULL; - if (*(unsigned char *) fixed == DELETED_FLAG) { - while (*dir) { - if (!strncmp((*dir)->name+1,fixed+1,MSDOS_NAME-1) && !(*dir)->first) - return dir; - dir = &(*dir)->next; - } - return NULL; - } - while (*dir) { - if (!strncmp((*dir)->name,fixed,MSDOS_NAME) && !(*dir)->first) - return dir; - dir = &(*dir)->next; - } - return NULL; -} - - -FD_TYPE file_type(FDSC **curr,char *fixed) -{ - FDSC **this; - - if ((this = file_find(curr,fixed))) return (*this)->type; - return fdt_none; -} - - -void file_modify(FDSC **curr,char *fixed) -{ - FDSC **this,*next; - - if (!(this = file_find(curr,fixed))) - die("Internal error: file_find failed"); - switch ((*this)->type) { - case fdt_drop: - printf("Dropping %s\n",file_name(fixed)); - *(unsigned char *) fixed = DELETED_FLAG; - break; - case fdt_undelete: - *fixed = *(*this)->name; - printf("Undeleting %s\n",file_name(fixed)); - break; - default: - die("Internal error: file_modify"); - } - next = (*this)->next; - free(*this); - *this = next; -} - - -static void report_unused(FDSC *this) -{ - FDSC *next; - - while (this) { - next = this->next; - if (this->first) report_unused(this->first); - else if (this->type != fdt_none) - printf("Warning: did not %s file %s\n",this->type == fdt_drop ? - "drop" : "undelete",file_name(this->name)); - free(this); - this = next; - } -} - - -void file_unused(void) -{ - report_unused(fp_root); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +/* file.c - Additional file attributes */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#include +#include +#include +#include +//#include + +#define _LINUX_STAT_H /* hack to avoid inclusion of */ +#define _LINUX_STRING_H_ /* hack to avoid inclusion of */ +#define _LINUX_FS_H /* hack to avoid inclusion of */ + +//#include +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +//# define __KERNEL__ +//# include +//# undef __KERNEL__ +//#endif + +#include "dosfsck.h" +#include "msdos_fs.h" + +#include "common.h" +#include "file.h" + + +FDSC *fp_root = NULL; + + +static void put_char(char **p,unsigned char c) +{ + if ((c >= ' ' && c < 0x7f) || c >= 0xa0) *(*p)++ = c; + else { + *(*p)++ = '\\'; + *(*p)++ = '0'+(c >> 6); + *(*p)++ = '0'+((c >> 3) & 7); + *(*p)++ = '0'+(c & 7); + } +} + + +char *file_name(unsigned char *fixed) +{ + static char path[MSDOS_NAME*4+2]; + char *p; + int i,j; + + p = path; + for (i = j = 0; i < 8; i++) + if (fixed[i] != ' ') { + while (j++ < i) *p++ = ' '; + put_char(&p,fixed[i]); + } + if (strncmp(fixed+8," ",3)) { + *p++ = '.'; + for (i = j = 0; i < 3; i++) + if (fixed[i+8] != ' ') { + while (j++ < i) *p++ = ' '; + put_char(&p,fixed[i+8]); + } + } + *p = 0; + return path; +} + + +int file_cvt(unsigned char *name,unsigned char *fixed) +{ + unsigned char c; + int size,ext,cnt; + + size = 8; + ext = 0; + while (*name) { + c = *name; + if (c < ' ' || c > 0x7e || strchr("*?<>|\"/",c)) { + printf("Invalid character in name. Use \\ooo for special " + "characters.\n"); + return 0; + } + if (c == '.') { + if (ext) { + printf("Duplicate dots in name.\n"); + return 0; + } + while (size--) *fixed++ = ' '; + size = 3; + ext = 1; + name++; + continue; + } + if (c == '\\') { + c = 0; + for (cnt = 3; cnt; cnt--) { + if (*name < '0' || *name > '7') { + printf("Invalid octal character.\n"); + return 0; + } + c = c*8+*name++-'0'; + } + if (cnt < 4) { + printf("Expected three octal digits.\n"); + return 0; + } + name += 3; + } + if (islower(c)) c = toupper(c); + if (size) { + *fixed++ = c; + size--; + } + name++; + } + if (*name || size == 8) return 0; + if (!ext) { + while (size--) *fixed++ = ' '; + size = 3; + } + while (size--) *fixed++ = ' '; + return 1; +} + + +void file_add(char *path,FD_TYPE type) +{ + FDSC **current,*walk; + char name[MSDOS_NAME]; + char *here; + + current = &fp_root; + if (*path != '/') die("%s: Absolute path required.",path); + path++; + while (1) { + if ((here = strchr(path,'/'))) *here = 0; + if (!file_cvt(path,name)) exit(2); + for (walk = *current; walk; walk = walk->next) + if (!here && (!strncmp(name,walk->name,MSDOS_NAME) || (type == + fdt_undelete && !strncmp(name+1,walk->name+1,MSDOS_NAME-1)))) + die("Ambiguous name: \"%s\"",path); + else if (here && !strncmp(name,walk->name,MSDOS_NAME)) break; + if (!walk) { + walk = alloc(sizeof(FDSC)); + strncpy(walk->name,name,MSDOS_NAME); + walk->type = here ? fdt_none : type; + walk->first = NULL; + walk->next = *current; + *current = walk; + } + current = &walk->first; + if (!here) break; + *here = '/'; + path = here+1; + } +} + + +FDSC **file_cd(FDSC **curr,char *fixed) +{ + FDSC **walk; + + if (!curr || !*curr) return NULL; + for (walk = curr; *walk; walk = &(*walk)->next) + if (!strncmp((*walk)->name,fixed,MSDOS_NAME) && (*walk)->first) + return &(*walk)->first; + return NULL; +} + + +static FDSC **file_find(FDSC **dir,char *fixed) +{ + if (!dir || !*dir) return NULL; + if (*(unsigned char *) fixed == DELETED_FLAG) { + while (*dir) { + if (!strncmp((*dir)->name+1,fixed+1,MSDOS_NAME-1) && !(*dir)->first) + return dir; + dir = &(*dir)->next; + } + return NULL; + } + while (*dir) { + if (!strncmp((*dir)->name,fixed,MSDOS_NAME) && !(*dir)->first) + return dir; + dir = &(*dir)->next; + } + return NULL; +} + + +FD_TYPE file_type(FDSC **curr,char *fixed) +{ + FDSC **this; + + if ((this = file_find(curr,fixed))) return (*this)->type; + return fdt_none; +} + + +void file_modify(FDSC **curr,char *fixed) +{ + FDSC **this,*next; + + if (!(this = file_find(curr,fixed))) + die("Internal error: file_find failed"); + switch ((*this)->type) { + case fdt_drop: + printf("Dropping %s\n",file_name(fixed)); + *(unsigned char *) fixed = DELETED_FLAG; + break; + case fdt_undelete: + *fixed = *(*this)->name; + printf("Undeleting %s\n",file_name(fixed)); + break; + default: + die("Internal error: file_modify"); + } + next = (*this)->next; + free(*this); + *this = next; +} + + +static void report_unused(FDSC *this) +{ + FDSC *next; + + while (this) { + next = this->next; + if (this->first) report_unused(this->first); + else if (this->type != fdt_none) + printf("Warning: did not %s file %s\n",this->type == fdt_drop ? + "drop" : "undelete",file_name(this->name)); + free(this); + this = next; + } +} + + +void file_unused(void) +{ + report_unused(fp_root); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/file.h b/rosapps/sysutils/dosfsck/file.h index d7f1386801d..f9c3571aaf9 100644 --- a/rosapps/sysutils/dosfsck/file.h +++ b/rosapps/sysutils/dosfsck/file.h @@ -1,55 +1,55 @@ -/* file.h - Additional file attributes */ - -/* Written 1993 by Werner Almesberger */ - - -#ifndef _FILE_H -#define _FILE_H - -typedef enum { fdt_none,fdt_drop,fdt_undelete } FD_TYPE; - -typedef struct _fptr { - char name[MSDOS_NAME]; - FD_TYPE type; - struct _fptr *first; /* first entry */ - struct _fptr *next; /* next file in directory */ -} FDSC; - - -extern FDSC *fp_root; - - -char *file_name(unsigned char *fixed); - -/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file - name. */ - -int file_cvt(unsigned char *name,unsigned char *fixed); - -/* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a - non-zero integer on success, zero on failure. */ - -void file_add(char *path,FD_TYPE type); - -/* Define special attributes for a path. TYPE can be either FDT_DROP or - FDT_UNDELETE. */ - -FDSC **file_cd(FDSC **curr,char *fixed); - -/* Returns a pointer to the directory descriptor of the subdirectory FIXED of - CURR, or NULL if no such subdirectory exists. */ - -FD_TYPE file_type(FDSC **curr,char *fixed); - -/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no - such file exists or if CURR is NULL. */ - -void file_modify(FDSC **curr,char *fixed); - -/* Performs the necessary operation on the entry of CURR that is named FIXED. */ - -void file_unused(void); - -/* Displays warnings for all unused file attributes. */ - -#endif +/* file.h - Additional file attributes */ + +/* Written 1993 by Werner Almesberger */ + + +#ifndef _FILE_H +#define _FILE_H + +typedef enum { fdt_none,fdt_drop,fdt_undelete } FD_TYPE; + +typedef struct _fptr { + char name[MSDOS_NAME]; + FD_TYPE type; + struct _fptr *first; /* first entry */ + struct _fptr *next; /* next file in directory */ +} FDSC; + + +extern FDSC *fp_root; + + +char *file_name(unsigned char *fixed); + +/* Returns a pointer to a pretty-printed representation of a fixed MS-DOS file + name. */ + +int file_cvt(unsigned char *name,unsigned char *fixed); + +/* Converts a pretty-printed file name to the fixed MS-DOS format. Returns a + non-zero integer on success, zero on failure. */ + +void file_add(char *path,FD_TYPE type); + +/* Define special attributes for a path. TYPE can be either FDT_DROP or + FDT_UNDELETE. */ + +FDSC **file_cd(FDSC **curr,char *fixed); + +/* Returns a pointer to the directory descriptor of the subdirectory FIXED of + CURR, or NULL if no such subdirectory exists. */ + +FD_TYPE file_type(FDSC **curr,char *fixed); + +/* Returns the attribute of the file FIXED in directory CURR or FDT_NONE if no + such file exists or if CURR is NULL. */ + +void file_modify(FDSC **curr,char *fixed); + +/* Performs the necessary operation on the entry of CURR that is named FIXED. */ + +void file_unused(void); + +/* Displays warnings for all unused file attributes. */ + +#endif diff --git a/rosapps/sysutils/dosfsck/getopt.c b/rosapps/sysutils/dosfsck/getopt.c index 0783623e9cb..0a37f95d320 100644 --- a/rosapps/sysutils/dosfsck/getopt.c +++ b/rosapps/sysutils/dosfsck/getopt.c @@ -1,63 +1,63 @@ -/* - * $Id$ - * This is an unpublished work copyright (c) 1998 HELIOS Software GmbH - * 30827 Garbsen, Germany - */ - - -#include -#include -#ifdef HAS_UNISTD -# include -#endif - -char *optarg; -int optind = 1; -int opterr = 1; -int optopt; -static int subopt; -static int suboptind = 1; - -int getopt(int argc, char *const argv[], const char * optstring) -{ - char *curopt; - char *p; - int cursubopt; - - if (suboptind == optind-1 && argv[suboptind][subopt] != '\0') { - curopt = (char *)argv[suboptind]; - } else { - curopt = (char *)argv[optind]; - if (curopt == NULL || curopt[0] != '-' || strcmp(curopt, "-") == 0) - return -1; - suboptind = optind; - subopt = 1; - optind++; - if (strcmp(curopt, "--") == 0) - return -1; - } - cursubopt = subopt++; - if ((p = strchr(optstring, curopt[cursubopt])) == NULL) { - optopt = curopt[cursubopt]; - if (opterr) - fprintf(stderr, "%s: illegal option -- %c\n", argv[0], optopt); - return '?'; - } - if (p[1] == ':') { - if (curopt[cursubopt+1] != '\0') { - optarg = curopt+cursubopt+1; - suboptind++; - return p[0]; - } - if (argv[optind] == NULL) { - optopt = p[0]; - if (opterr) - fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], optopt); - if (*optstring == ':') - return ':'; - return '?'; - } - optarg = argv[optind++]; - } - return p[0]; -} +/* + * $Id$ + * This is an unpublished work copyright (c) 1998 HELIOS Software GmbH + * 30827 Garbsen, Germany + */ + + +#include +#include +#ifdef HAS_UNISTD +# include +#endif + +char *optarg; +int optind = 1; +int opterr = 1; +int optopt; +static int subopt; +static int suboptind = 1; + +int getopt(int argc, char *const argv[], const char * optstring) +{ + char *curopt; + char *p; + int cursubopt; + + if (suboptind == optind-1 && argv[suboptind][subopt] != '\0') { + curopt = (char *)argv[suboptind]; + } else { + curopt = (char *)argv[optind]; + if (curopt == NULL || curopt[0] != '-' || strcmp(curopt, "-") == 0) + return -1; + suboptind = optind; + subopt = 1; + optind++; + if (strcmp(curopt, "--") == 0) + return -1; + } + cursubopt = subopt++; + if ((p = strchr(optstring, curopt[cursubopt])) == NULL) { + optopt = curopt[cursubopt]; + if (opterr) + fprintf(stderr, "%s: illegal option -- %c\n", argv[0], optopt); + return '?'; + } + if (p[1] == ':') { + if (curopt[cursubopt+1] != '\0') { + optarg = curopt+cursubopt+1; + suboptind++; + return p[0]; + } + if (argv[optind] == NULL) { + optopt = p[0]; + if (opterr) + fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], optopt); + if (*optstring == ':') + return ':'; + return '?'; + } + optarg = argv[optind++]; + } + return p[0]; +} diff --git a/rosapps/sysutils/dosfsck/io.c b/rosapps/sysutils/dosfsck/io.c index 894a7147aea..e4e231f793c 100644 --- a/rosapps/sysutils/dosfsck/io.c +++ b/rosapps/sysutils/dosfsck/io.c @@ -1,28 +1,28 @@ -/* io.c - Virtual disk input/output */ - -/* Written 1993 by Werner Almesberger */ - -/* - * Thu Feb 26 01:15:36 CET 1998: Martin Schulze - * Fixed nasty bug that caused every file with a name like - * xxxxxxxx.xxx to be treated as bad name that needed to be fixed. - */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - -#include -#include -#include -//#include -#include -//#include -#include +/* io.c - Virtual disk input/output */ + +/* Written 1993 by Werner Almesberger */ + +/* + * Thu Feb 26 01:15:36 CET 1998: Martin Schulze + * Fixed nasty bug that caused every file with a name like + * xxxxxxxx.xxx to be treated as bad name that needed to be fixed. + */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + +#include +#include +#include +//#include +#include +//#include +#include #include -#include -//#include - - +#include +//#include + + #ifdef _WIN32 #define _WIN32_WINNT 0x0400 #include @@ -33,73 +33,73 @@ #define inline #define __attribute__(x) #define BLOCK_SIZE 512 -#endif - - -#include "dosfsck.h" -#include "common.h" -#include "io.h" - - -typedef struct _change { - void *data; - loff_t pos; - int size; - struct _change *next; -} CHANGE; - - -static CHANGE *changes,*last; -static int fd,did_change = 0; - -unsigned device_no; - -static int WIN32open(const char *path, int oflag, ...); -#define open WIN32open +#endif + + +#include "dosfsck.h" +#include "common.h" +#include "io.h" + + +typedef struct _change { + void *data; + loff_t pos; + int size; + struct _change *next; +} CHANGE; + + +static CHANGE *changes,*last; +static int fd,did_change = 0; + +unsigned device_no; + +static int WIN32open(const char *path, int oflag, ...); +#define open WIN32open static int WIN32close(int fd); -#define close WIN32close +#define close WIN32close static int WIN32read(int fd, void *buf, unsigned int len); -#define read WIN32read +#define read WIN32read static int WIN32write(int fd, void *buf, unsigned int len); -#define write WIN32write +#define write WIN32write static loff_t WIN32llseek(int fd, loff_t offset, int whence); #ifdef llseek #undef llseek #endif #define llseek WIN32llseek - -static int is_device = 0; - -void fs_open(char *path,int rw) -{ + +static int is_device = 0; + +void fs_open(char *path,int rw) +{ #ifdef _WIN32 static char dev_buf[] = "\\\\.\\X:"; -#else - struct stat stbuf; -#endif - +#else + struct stat stbuf; +#endif + if (path[1] == ':' && path[2] == '\0') { dev_buf[4] = path[0]; path = dev_buf; // is_device = 1; } - - if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0) - pdie("open %s",path); - changes = last = NULL; - did_change = 0; - -#if 0 - if (fstat(fd,&stbuf) < 0) - pdie("fstat %s",path); - device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0; -#endif -} - - -void fs_read(loff_t pos,int size,void *data) -{ - CHANGE *walk; + + if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0) + pdie("open %s",path); + changes = last = NULL; + did_change = 0; + +#if 0 + if (fstat(fd,&stbuf) < 0) + pdie("fstat %s",path); + device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0; +#endif +} + + +void fs_read(loff_t pos,int size,void *data) +{ + CHANGE *walk; int got; #if 1 // TMN const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: @@ -115,123 +115,123 @@ void fs_read(loff_t pos,int size,void *data) if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %lld",size,pos); #endif assert(got >= size); - got = size; + got = size; assert(seek_delta + size <= readsize); memcpy(data, tmpBuf+seek_delta, size); free(tmpBuf); -#else // TMN: - if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); +#else // TMN: + if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos); -#endif // TMN: - if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos); - for (walk = changes; walk; walk = walk->next) { - if (walk->pos < pos+size && walk->pos+walk->size > pos) { - if (walk->pos < pos) - memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size, - (size_t)(walk->size-pos+walk->pos))); - else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size, - (size_t)(size+pos-walk->pos))); - } - } -} - - -int fs_test(loff_t pos,int size) -{ - void *scratch; - int okay; - -#if 1 // TMN - const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: - const loff_t seekpos_aligned = pos - (pos % 512); // TMN: - const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN: - const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: - scratch = alloc(readsize_aligned); - if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); - okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned; - free(scratch); -#else // TMN: - if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); - scratch = alloc(size); - okay = read(fd,scratch,size) == size; - free(scratch); -#endif // TMN: - return okay; -} - - -void fs_write(loff_t pos,int size,void *data) -{ - CHANGE *new; - int did; - - if (write_immed) { - did_change = 1; - if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); - if ((did = write(fd,data,size)) == size) return; - if (did < 0) pdie("Write %d bytes at %lld",size,pos); - die("Wrote %d bytes instead of %d at %lld",did,size,pos); - } - new = alloc(sizeof(CHANGE)); - new->pos = pos; - memcpy(new->data = alloc(new->size = size),data,size); - new->next = NULL; - if (last) last->next = new; - else changes = new; - last = new; -} - - -static void fs_flush(void) -{ - CHANGE *this; - int size; - - while (changes) { - this = changes; - changes = changes->next; - if (llseek(fd,this->pos,0) != this->pos) - fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n", - (__int64)this->pos,strerror(errno),this->size); - else if ((size = write(fd,this->data,this->size)) < 0) - fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size, - (__int64)this->pos,strerror(errno)); - else if (size != this->size) - fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld." - "\n",size,this->size,(__int64)this->pos); - free(this->data); - free(this); - } -} - - -int fs_close(int write) -{ - CHANGE *next; - int changed; - - changed = !!changes; - if (write) fs_flush(); - else while (changes) { - next = changes->next; - free(changes->data); - free(changes); - changes = next; - } - if (close(fd) < 0) pdie("closing file system"); - return changed || did_change; -} - - -int fs_changed(void) -{ - return !!changes || did_change; -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ - +#endif // TMN: + if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos); + for (walk = changes; walk; walk = walk->next) { + if (walk->pos < pos+size && walk->pos+walk->size > pos) { + if (walk->pos < pos) + memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size, + (size_t)(walk->size-pos+walk->pos))); + else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size, + (size_t)(size+pos-walk->pos))); + } + } +} + + +int fs_test(loff_t pos,int size) +{ + void *scratch; + int okay; + +#if 1 // TMN + const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: + const loff_t seekpos_aligned = pos - (pos % 512); // TMN: + const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN: + const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: + scratch = alloc(readsize_aligned); + if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); + okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned; + free(scratch); +#else // TMN: + if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); + scratch = alloc(size); + okay = read(fd,scratch,size) == size; + free(scratch); +#endif // TMN: + return okay; +} + + +void fs_write(loff_t pos,int size,void *data) +{ + CHANGE *new; + int did; + + if (write_immed) { + did_change = 1; + if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); + if ((did = write(fd,data,size)) == size) return; + if (did < 0) pdie("Write %d bytes at %lld",size,pos); + die("Wrote %d bytes instead of %d at %lld",did,size,pos); + } + new = alloc(sizeof(CHANGE)); + new->pos = pos; + memcpy(new->data = alloc(new->size = size),data,size); + new->next = NULL; + if (last) last->next = new; + else changes = new; + last = new; +} + + +static void fs_flush(void) +{ + CHANGE *this; + int size; + + while (changes) { + this = changes; + changes = changes->next; + if (llseek(fd,this->pos,0) != this->pos) + fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n", + (__int64)this->pos,strerror(errno),this->size); + else if ((size = write(fd,this->data,this->size)) < 0) + fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size, + (__int64)this->pos,strerror(errno)); + else if (size != this->size) + fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld." + "\n",size,this->size,(__int64)this->pos); + free(this->data); + free(this); + } +} + + +int fs_close(int write) +{ + CHANGE *next; + int changed; + + changed = !!changes; + if (write) fs_flush(); + else while (changes) { + next = changes->next; + free(changes->data); + free(changes); + changes = next; + } + if (close(fd) < 0) pdie("closing file system"); + return changed || did_change; +} + + +int fs_changed(void) +{ + return !!changes || did_change; +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ + #define O_SHORT_LIVED _O_SHORT_LIVED //#define O_ACCMODE 3 diff --git a/rosapps/sysutils/dosfsck/io.h b/rosapps/sysutils/dosfsck/io.h index cdf3c586ec8..a9cc75dfc45 100644 --- a/rosapps/sysutils/dosfsck/io.h +++ b/rosapps/sysutils/dosfsck/io.h @@ -1,54 +1,54 @@ -/* io.h - Virtual disk input/output */ - -/* Written 1993 by Werner Almesberger */ - -/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 - * by Roman Hodek */ - - -#ifndef _IO_H -#define _IO_H - -//#include /* for loff_t */ -#include "dosfsck.h" - -/* In earlier versions, an own llseek() was used, but glibc lseek() is - * sufficient (or even better :) for 64 bit offsets in the meantime */ -#define llseek lseek - -void fs_open(char *path,int rw); - -/* Opens the file system PATH. If RW is zero, the file system is opened - read-only, otherwise, it is opened read-write. */ - -void fs_read(loff_t pos,int size,void *data); - -/* Reads SIZE bytes starting at POS into DATA. Performs all applicable - changes. */ - -int fs_test(loff_t pos,int size); - -/* Returns a non-zero integer if SIZE bytes starting at POS can be read without - errors. Otherwise, it returns zero. */ - -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, - starting at POS. If write_immed is zero, the change is added to a list in - memory. */ - -int fs_close(int write); - -/* Closes the file system, performs all pending changes if WRITE is non-zero - and removes the list of changes. Returns a non-zero integer if the file - system has been changed since the last fs_open, zero otherwise. */ - -int fs_changed(void); - -/* Determines whether the file system has changed. See fs_close. */ - -extern unsigned device_no; - -/* Major number of device (0 if file) and size (in 512 byte sectors) */ - -#endif +/* io.h - Virtual disk input/output */ + +/* Written 1993 by Werner Almesberger */ + +/* FAT32, VFAT, Atari format support, and various fixes additions May 1998 + * by Roman Hodek */ + + +#ifndef _IO_H +#define _IO_H + +//#include /* for loff_t */ +#include "dosfsck.h" + +/* In earlier versions, an own llseek() was used, but glibc lseek() is + * sufficient (or even better :) for 64 bit offsets in the meantime */ +#define llseek lseek + +void fs_open(char *path,int rw); + +/* Opens the file system PATH. If RW is zero, the file system is opened + read-only, otherwise, it is opened read-write. */ + +void fs_read(loff_t pos,int size,void *data); + +/* Reads SIZE bytes starting at POS into DATA. Performs all applicable + changes. */ + +int fs_test(loff_t pos,int size); + +/* Returns a non-zero integer if SIZE bytes starting at POS can be read without + errors. Otherwise, it returns zero. */ + +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, + starting at POS. If write_immed is zero, the change is added to a list in + memory. */ + +int fs_close(int write); + +/* Closes the file system, performs all pending changes if WRITE is non-zero + and removes the list of changes. Returns a non-zero integer if the file + system has been changed since the last fs_open, zero otherwise. */ + +int fs_changed(void); + +/* Determines whether the file system has changed. See fs_close. */ + +extern unsigned device_no; + +/* Major number of device (0 if file) and size (in 512 byte sectors) */ + +#endif diff --git a/rosapps/sysutils/dosfsck/lfn.c b/rosapps/sysutils/dosfsck/lfn.c index 0c5c92cd65a..1af73edacdb 100644 --- a/rosapps/sysutils/dosfsck/lfn.c +++ b/rosapps/sysutils/dosfsck/lfn.c @@ -1,480 +1,480 @@ -/* lfn.c - Functions for handling VFAT long filenames */ - -/* Written 1998 by Roman Hodek */ - -#include -#include -#include -#include -#include - -#include "common.h" -#include "io.h" -#include "dosfsck.h" -#include "lfn.h" -#include "file.h" - -typedef struct { - __u8 id; /* sequence number for slot */ - __u8 name0_4[10]; /* first 5 characters in name */ - __u8 attr; /* attribute byte */ - __u8 reserved; /* always 0 */ - __u8 alias_checksum; /* checksum for 8.3 alias */ - __u8 name5_10[12]; /* 6 more characters in name */ - __u16 start; /* starting cluster number, 0 in long slots */ - __u8 name11_12[4]; /* last 2 characters in name */ -} LFN_ENT; - -#define LFN_ID_START 0x40 -#define LFN_ID_SLOTMASK 0x1f - -#define CHARS_PER_LFN 13 - -/* These modul-global vars represent the state of the LFN parser */ -unsigned char *lfn_unicode = NULL; -unsigned char lfn_checksum; -int lfn_slot = -1; -loff_t *lfn_offsets = NULL; -int lfn_parts = 0; - -static unsigned char fat_uni2esc[64] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', - 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', - 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', '+', '-' -}; - -/* This defines which unicode chars are directly convertable to ISO-8859-1 */ -#define UNICODE_CONVERTABLE(cl,ch) (ch == 0 && (cl < 0x80 || cl >= 0xa0)) - -/* for maxlen param */ -#define UNTIL_0 INT_MAX - +/* lfn.c - Functions for handling VFAT long filenames */ + +/* Written 1998 by Roman Hodek */ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "io.h" +#include "dosfsck.h" +#include "lfn.h" +#include "file.h" + +typedef struct { + __u8 id; /* sequence number for slot */ + __u8 name0_4[10]; /* first 5 characters in name */ + __u8 attr; /* attribute byte */ + __u8 reserved; /* always 0 */ + __u8 alias_checksum; /* checksum for 8.3 alias */ + __u8 name5_10[12]; /* 6 more characters in name */ + __u16 start; /* starting cluster number, 0 in long slots */ + __u8 name11_12[4]; /* last 2 characters in name */ +} LFN_ENT; + +#define LFN_ID_START 0x40 +#define LFN_ID_SLOTMASK 0x1f + +#define CHARS_PER_LFN 13 + +/* These modul-global vars represent the state of the LFN parser */ +unsigned char *lfn_unicode = NULL; +unsigned char lfn_checksum; +int lfn_slot = -1; +loff_t *lfn_offsets = NULL; +int lfn_parts = 0; + +static unsigned char fat_uni2esc[64] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', '+', '-' +}; + +/* This defines which unicode chars are directly convertable to ISO-8859-1 */ +#define UNICODE_CONVERTABLE(cl,ch) (ch == 0 && (cl < 0x80 || cl >= 0xa0)) + +/* for maxlen param */ +#define UNTIL_0 INT_MAX + static void copy_lfn_part( char *dst, LFN_ENT *lfn ); static char *cnv_unicode( const unsigned char *uni, int maxlen, int use_q ); /* Convert name part in 'lfn' from unicode to ASCII */ -static __inline char* CNV_THIS_PART(LFN_ENT *lfn) -{ \ - char __part_uni[CHARS_PER_LFN*2]; - copy_lfn_part( __part_uni, lfn ); - cnv_unicode( __part_uni, CHARS_PER_LFN, 0 ); -} - -/* Convert name parts collected so far (from previous slots) from unicode to - * ASCII */ -#define CNV_PARTS_SO_FAR() \ - (cnv_unicode( lfn_unicode+(lfn_slot*CHARS_PER_LFN*2), \ - lfn_parts*CHARS_PER_LFN, 0 )) - -/* 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 - * 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 ) -{ - const unsigned char *up; - unsigned char *out, *cp; - int len, val; - - for( len = 0, up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ){ - if (UNICODE_CONVERTABLE(up[0],up[1])) - ++len; - else - len += 4; - } - 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 ) { - if (UNICODE_CONVERTABLE(up[0],up[1])) - *cp++ = up[0]; - else { - /* here the same escape notation is used as in the Linux kernel */ - *cp++ = ':'; - val = (up[1] << 8) + up[0]; - cp[2] = fat_uni2esc[val & 0x3f]; - val >>= 6; - cp[1] = fat_uni2esc[val & 0x3f]; - val >>= 6; - cp[0] = fat_uni2esc[val & 0x3f]; - cp += 3; - } - } - *cp = 0; - - return( out ); -} - - -static void copy_lfn_part( char *dst, LFN_ENT *lfn ) -{ - memcpy( dst, lfn->name0_4, 10 ); - memcpy( dst+10, lfn->name5_10, 12 ); - memcpy( dst+22, lfn->name11_12, 4 ); -} - - -static void clear_lfn_slots( int start, int end ) -{ - int i; - LFN_ENT empty; - - /* New dir entry is zeroed except first byte, which is set to 0xe5. - * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading - * a directory at the first zero entry... - */ - memset( &empty, 0, sizeof(empty) ); - empty.id = DELETED_FLAG; - - for( i = start; i <= end; ++i ) { - fs_write( lfn_offsets[i], sizeof(LFN_ENT), &empty ); - } -} - -void lfn_reset( void ) -{ - if (lfn_unicode) - free( lfn_unicode ); - lfn_unicode = NULL; - if (lfn_offsets) - free( lfn_offsets ); - lfn_offsets = NULL; - lfn_slot = -1; -} - - -/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part - * of the long name. */ -void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ) -{ - LFN_ENT *lfn = (LFN_ENT *)de; - unsigned offset; - - if (de->attr != VFAT_LN_ATTR) - die("lfn_add_slot called with non-LFN directory entry"); - - if (lfn->id & LFN_ID_START) { - if (lfn_slot != -1) { - int can_clear = 0; - /* There is already a LFN "in progess", so it is an error that a - * new start entry is here. */ - /* Causes: 1) if slot# == expected: start bit set mysteriously, 2) - * old LFN overwritten by new one */ - /* Fixes: 1) delete previous LFN 2) if slot# == expected and - * checksum ok: clear start bit */ - /* XXX: Should delay that until next LFN known (then can better - * display the name) */ - printf( "A new long file name starts within an old one.\n" ); - if ((lfn->id & LFN_ID_SLOTMASK) == lfn_slot && - lfn->alias_checksum == lfn_checksum) { - char *part1 = CNV_THIS_PART(lfn); - char *part2 = CNV_PARTS_SO_FAR(); - printf( " It could be that the LFN start bit is wrong here\n" - " if \"%s\" seems to match \"%s\".\n", part1, part2 ); - free( part1 ); - free( part2 ); - can_clear = 1; - } - if (interactive) { - printf( "1: Delete previous LFN\n2: Leave it as it is.\n" ); - if (can_clear) - printf( "3: Clear start bit and concatenate LFNs\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( can_clear ? "123" : "12", "?" )) { - case '1': - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - break; - case '2': - break; - case '3': - lfn->id &= ~LFN_ID_START; - fs_write( dir_offset+offsetof(LFN_ENT,id), - sizeof(lfn->id), &lfn->id ); - break; - } - } - } - lfn_slot = lfn->id & LFN_ID_SLOTMASK; - lfn_checksum = lfn->alias_checksum; - lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); - lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); - lfn_parts = 0; - } - else if (lfn_slot == -1) { - /* No LFN in progress, but slot found; start bit missing */ - /* Causes: 1) start bit got lost, 2) Previous slot with start bit got - * lost */ - /* Fixes: 1) delete LFN, 2) set start bit */ - char *part = CNV_THIS_PART(lfn); - printf( "Long filename fragment \"%s\" found outside a LFN " - "sequence.\n (Maybe the start bit is missing on the " - "last fragment)\n", part ); - if (interactive) { - printf( "1: Delete fragment\n2: Leave it as it is.\n" - "3: Set start bit\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - if (!lfn_offsets) - lfn_offsets = alloc( sizeof(loff_t) ); - lfn_offsets[0] = dir_offset; - clear_lfn_slots( 0, 0 ); - lfn_reset(); - return; - case '2': - lfn_reset(); - return; - case '3': - lfn->id |= LFN_ID_START; - fs_write( dir_offset+offsetof(LFN_ENT,id), - sizeof(lfn->id), &lfn->id ); - lfn_slot = lfn->id & LFN_ID_SLOTMASK; - lfn_checksum = lfn->alias_checksum; - lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); - lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); - lfn_parts = 0; - break; - } - } - } - else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) { - /* wrong sequence number */ - /* Causes: 1) seq-no destroyed */ - /* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts - * are ok?, maybe only if checksum is ok?) (Attention: space - * for name was allocated before!) */ - int can_fix = 0; - printf( "Unexpected long filename sequence number " - "(%d vs. expected %d).\n", - (lfn->id & LFN_ID_SLOTMASK), lfn_slot ); - if (lfn->alias_checksum == lfn_checksum) { - char *part1 = CNV_THIS_PART(lfn); - char *part2 = CNV_PARTS_SO_FAR(); - printf( " It could be that just the number is wrong\n" - " if \"%s\" seems to match \"%s\".\n", part1, part2 ); - free( part1 ); - free( part2 ); - can_fix = 1; - } - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n" ); - if (can_fix) - printf( "3: Correct sequence number\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( can_fix ? "123" : "12", "?" )) { - case '1': - lfn_offsets[lfn_parts++] = dir_offset; - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return; - case '2': - lfn_reset(); - return; - case '3': - lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot; - fs_write( dir_offset+offsetof(LFN_ENT,id), - sizeof(lfn->id), &lfn->id ); - break; - } - } - } - - if (lfn->alias_checksum != lfn_checksum) { - /* checksum mismatch */ - /* Causes: 1) checksum field here destroyed */ - /* Fixes: 1) delete LFN, 2) fix checksum */ - printf( "Checksum in long filename part wrong " - "(%02x vs. expected %02x).\n", - lfn->alias_checksum, lfn_checksum ); - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is.\n" - "3: Correct checksum\n" ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - lfn_offsets[lfn_parts++] = dir_offset; - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return; - case '2': - break; - case '3': - lfn->alias_checksum = lfn_checksum; - fs_write( dir_offset+offsetof(LFN_ENT,alias_checksum), - sizeof(lfn->alias_checksum), &lfn->alias_checksum ); - break; - } - } - } - - if (lfn_slot != -1) { - lfn_slot--; - offset = lfn_slot * CHARS_PER_LFN*2; - copy_lfn_part( lfn_unicode+offset, lfn ); - if (lfn->id & LFN_ID_START) - lfn_unicode[offset+26] = lfn_unicode[offset+27] = 0; - lfn_offsets[lfn_parts++] = dir_offset; - } - - if (lfn->reserved != 0) { - printf( "Reserved field in VFAT long filename slot is not 0 " - "(but 0x%02x).\n", lfn->reserved ); - if (interactive) - printf( "1: Fix.\n2: Leave it.\n" ); - else printf( "Auto-setting to 0.\n" ); - if (!interactive || get_key("12","?") == '1') { - lfn->reserved = 0; - fs_write( dir_offset+offsetof(LFN_ENT,reserved), - sizeof(lfn->reserved), &lfn->reserved ); - } - } - if (lfn->start != CT_LE_W(0)) { - printf( "Start cluster field in VFAT long filename slot is not 0 " - "(but 0x%04x).\n", lfn->start ); - if (interactive) - printf( "1: Fix.\n2: Leave it.\n" ); - else printf( "Auto-setting to 0.\n" ); - if (!interactive || get_key("12","?") == '1') { - lfn->start = CT_LE_W(0); - fs_write( dir_offset+offsetof(LFN_ENT,start), - sizeof(lfn->start),&lfn->start ); - } - } -} - - -/* This function is always called when de->attr != VFAT_LN_ATTR is found, to - * retrieve the previously constructed LFN. */ -char *lfn_get( DIR_ENT *de ) -{ - char *lfn; - __u8 sum; - int i; - - if (de->attr == VFAT_LN_ATTR) - die("lfn_get called with LFN directory entry"); - -#if 0 - if (de->lcase) - printf( "lcase=%02x\n",de->lcase ); -#endif - - if (lfn_slot == -1) - /* no long name for this file */ - return NULL; - - if (lfn_slot != 0) { - /* The long name isn't finished yet. */ - /* Causes: 1) LFN slot overwritten by non-VFAT aware tool */ - /* Fixes: 1) delete LFN 2) move overwriting entry to somewhere else - * and let user enter missing part of LFN (hard to do :-() - * 3) renumber entries and truncate name */ - char *long_name = CNV_PARTS_SO_FAR(); - char *short_name = file_name(de->name); - printf( "Unfinished long file name \"%s\".\n" - " (Start may have been overwritten by %s)\n", - long_name, short_name ); - free( long_name ); - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is.\n" - "3: Fix numbering (truncates long name and attaches " - "it to short name %s)\n", short_name ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return NULL; - case '2': - lfn_reset(); - return NULL; - case '3': - for( i = 0; i < lfn_parts; ++i ) { - __u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0); - fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id), - sizeof(id), &id ); - } - memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2, - lfn_parts*CHARS_PER_LFN*2 ); - break; - } - } - } - - for (sum = 0, i = 0; i < 11; i++) - sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i]; - if (sum != lfn_checksum) { - /* checksum doesn't match, long name doesn't apply to this alias */ - /* Causes: 1) alias renamed */ - /* Fixes: 1) Fix checksum in LFN entries */ - char *long_name = CNV_PARTS_SO_FAR(); - char *short_name = file_name(de->name); - printf( "Wrong checksum for long file name \"%s\".\n" - " (Short name %s may have changed without updating the long name)\n", - long_name, short_name ); - free( long_name ); - if (interactive) { - printf( "1: Delete LFN\n2: Leave it as it is.\n" - "3: Fix checksum (attaches to short name %s)\n", - short_name ); - } - else printf( " Not auto-correcting this.\n" ); - if (interactive) { - switch( get_key( "123", "?" )) { - case '1': - clear_lfn_slots( 0, lfn_parts-1 ); - lfn_reset(); - return NULL; - case '2': - lfn_reset(); - return NULL; - case '3': - for( i = 0; i < lfn_parts; ++i ) { - fs_write( lfn_offsets[i]+offsetof(LFN_ENT,alias_checksum), - sizeof(sum), &sum ); - } - break; - } - } - } - - lfn = cnv_unicode( lfn_unicode, UNTIL_0, 1 ); - lfn_reset(); - return( lfn ); -} - -void lfn_check_orphaned(void) -{ - char *long_name; - - if (lfn_slot == -1) - return; - - long_name = CNV_PARTS_SO_FAR(); - printf("Orphaned long file name part \"%s\"\n", long_name); - if (interactive) - printf( "1: Delete.\n2: Leave it.\n" ); - else printf( " Auto-deleting.\n" ); - if (!interactive || get_key("12","?") == '1') { - clear_lfn_slots(0, lfn_parts - 1); - } - lfn_reset(); -} - -/* Local Variables: */ -/* tab-width: 8 */ -/* End: */ +static __inline char* CNV_THIS_PART(LFN_ENT *lfn) +{ \ + char __part_uni[CHARS_PER_LFN*2]; + copy_lfn_part( __part_uni, lfn ); + cnv_unicode( __part_uni, CHARS_PER_LFN, 0 ); +} + +/* Convert name parts collected so far (from previous slots) from unicode to + * ASCII */ +#define CNV_PARTS_SO_FAR() \ + (cnv_unicode( lfn_unicode+(lfn_slot*CHARS_PER_LFN*2), \ + lfn_parts*CHARS_PER_LFN, 0 )) + +/* 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 + * 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 ) +{ + const unsigned char *up; + unsigned char *out, *cp; + int len, val; + + for( len = 0, up = uni; (up-uni)/2 < maxlen && (up[0] || up[1]); up += 2 ){ + if (UNICODE_CONVERTABLE(up[0],up[1])) + ++len; + else + len += 4; + } + 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 ) { + if (UNICODE_CONVERTABLE(up[0],up[1])) + *cp++ = up[0]; + else { + /* here the same escape notation is used as in the Linux kernel */ + *cp++ = ':'; + val = (up[1] << 8) + up[0]; + cp[2] = fat_uni2esc[val & 0x3f]; + val >>= 6; + cp[1] = fat_uni2esc[val & 0x3f]; + val >>= 6; + cp[0] = fat_uni2esc[val & 0x3f]; + cp += 3; + } + } + *cp = 0; + + return( out ); +} + + +static void copy_lfn_part( char *dst, LFN_ENT *lfn ) +{ + memcpy( dst, lfn->name0_4, 10 ); + memcpy( dst+10, lfn->name5_10, 12 ); + memcpy( dst+22, lfn->name11_12, 4 ); +} + + +static void clear_lfn_slots( int start, int end ) +{ + int i; + LFN_ENT empty; + + /* New dir entry is zeroed except first byte, which is set to 0xe5. + * This is to avoid that some FAT-reading OSes (not Linux! ;) stop reading + * a directory at the first zero entry... + */ + memset( &empty, 0, sizeof(empty) ); + empty.id = DELETED_FLAG; + + for( i = start; i <= end; ++i ) { + fs_write( lfn_offsets[i], sizeof(LFN_ENT), &empty ); + } +} + +void lfn_reset( void ) +{ + if (lfn_unicode) + free( lfn_unicode ); + lfn_unicode = NULL; + if (lfn_offsets) + free( lfn_offsets ); + lfn_offsets = NULL; + lfn_slot = -1; +} + + +/* This function is only called with de->attr == VFAT_LN_ATTR. It stores part + * of the long name. */ +void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ) +{ + LFN_ENT *lfn = (LFN_ENT *)de; + unsigned offset; + + if (de->attr != VFAT_LN_ATTR) + die("lfn_add_slot called with non-LFN directory entry"); + + if (lfn->id & LFN_ID_START) { + if (lfn_slot != -1) { + int can_clear = 0; + /* There is already a LFN "in progess", so it is an error that a + * new start entry is here. */ + /* Causes: 1) if slot# == expected: start bit set mysteriously, 2) + * old LFN overwritten by new one */ + /* Fixes: 1) delete previous LFN 2) if slot# == expected and + * checksum ok: clear start bit */ + /* XXX: Should delay that until next LFN known (then can better + * display the name) */ + printf( "A new long file name starts within an old one.\n" ); + if ((lfn->id & LFN_ID_SLOTMASK) == lfn_slot && + lfn->alias_checksum == lfn_checksum) { + char *part1 = CNV_THIS_PART(lfn); + char *part2 = CNV_PARTS_SO_FAR(); + printf( " It could be that the LFN start bit is wrong here\n" + " if \"%s\" seems to match \"%s\".\n", part1, part2 ); + free( part1 ); + free( part2 ); + can_clear = 1; + } + if (interactive) { + printf( "1: Delete previous LFN\n2: Leave it as it is.\n" ); + if (can_clear) + printf( "3: Clear start bit and concatenate LFNs\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( can_clear ? "123" : "12", "?" )) { + case '1': + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + break; + case '2': + break; + case '3': + lfn->id &= ~LFN_ID_START; + fs_write( dir_offset+offsetof(LFN_ENT,id), + sizeof(lfn->id), &lfn->id ); + break; + } + } + } + lfn_slot = lfn->id & LFN_ID_SLOTMASK; + lfn_checksum = lfn->alias_checksum; + lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); + lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); + lfn_parts = 0; + } + else if (lfn_slot == -1) { + /* No LFN in progress, but slot found; start bit missing */ + /* Causes: 1) start bit got lost, 2) Previous slot with start bit got + * lost */ + /* Fixes: 1) delete LFN, 2) set start bit */ + char *part = CNV_THIS_PART(lfn); + printf( "Long filename fragment \"%s\" found outside a LFN " + "sequence.\n (Maybe the start bit is missing on the " + "last fragment)\n", part ); + if (interactive) { + printf( "1: Delete fragment\n2: Leave it as it is.\n" + "3: Set start bit\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + if (!lfn_offsets) + lfn_offsets = alloc( sizeof(loff_t) ); + lfn_offsets[0] = dir_offset; + clear_lfn_slots( 0, 0 ); + lfn_reset(); + return; + case '2': + lfn_reset(); + return; + case '3': + lfn->id |= LFN_ID_START; + fs_write( dir_offset+offsetof(LFN_ENT,id), + sizeof(lfn->id), &lfn->id ); + lfn_slot = lfn->id & LFN_ID_SLOTMASK; + lfn_checksum = lfn->alias_checksum; + lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 ); + lfn_offsets = alloc( lfn_slot*sizeof(loff_t) ); + lfn_parts = 0; + break; + } + } + } + else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) { + /* wrong sequence number */ + /* Causes: 1) seq-no destroyed */ + /* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts + * are ok?, maybe only if checksum is ok?) (Attention: space + * for name was allocated before!) */ + int can_fix = 0; + printf( "Unexpected long filename sequence number " + "(%d vs. expected %d).\n", + (lfn->id & LFN_ID_SLOTMASK), lfn_slot ); + if (lfn->alias_checksum == lfn_checksum) { + char *part1 = CNV_THIS_PART(lfn); + char *part2 = CNV_PARTS_SO_FAR(); + printf( " It could be that just the number is wrong\n" + " if \"%s\" seems to match \"%s\".\n", part1, part2 ); + free( part1 ); + free( part2 ); + can_fix = 1; + } + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is (and ignore LFN so far)\n" ); + if (can_fix) + printf( "3: Correct sequence number\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( can_fix ? "123" : "12", "?" )) { + case '1': + lfn_offsets[lfn_parts++] = dir_offset; + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return; + case '2': + lfn_reset(); + return; + case '3': + lfn->id = (lfn->id & ~LFN_ID_SLOTMASK) | lfn_slot; + fs_write( dir_offset+offsetof(LFN_ENT,id), + sizeof(lfn->id), &lfn->id ); + break; + } + } + } + + if (lfn->alias_checksum != lfn_checksum) { + /* checksum mismatch */ + /* Causes: 1) checksum field here destroyed */ + /* Fixes: 1) delete LFN, 2) fix checksum */ + printf( "Checksum in long filename part wrong " + "(%02x vs. expected %02x).\n", + lfn->alias_checksum, lfn_checksum ); + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is.\n" + "3: Correct checksum\n" ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + lfn_offsets[lfn_parts++] = dir_offset; + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return; + case '2': + break; + case '3': + lfn->alias_checksum = lfn_checksum; + fs_write( dir_offset+offsetof(LFN_ENT,alias_checksum), + sizeof(lfn->alias_checksum), &lfn->alias_checksum ); + break; + } + } + } + + if (lfn_slot != -1) { + lfn_slot--; + offset = lfn_slot * CHARS_PER_LFN*2; + copy_lfn_part( lfn_unicode+offset, lfn ); + if (lfn->id & LFN_ID_START) + lfn_unicode[offset+26] = lfn_unicode[offset+27] = 0; + lfn_offsets[lfn_parts++] = dir_offset; + } + + if (lfn->reserved != 0) { + printf( "Reserved field in VFAT long filename slot is not 0 " + "(but 0x%02x).\n", lfn->reserved ); + if (interactive) + printf( "1: Fix.\n2: Leave it.\n" ); + else printf( "Auto-setting to 0.\n" ); + if (!interactive || get_key("12","?") == '1') { + lfn->reserved = 0; + fs_write( dir_offset+offsetof(LFN_ENT,reserved), + sizeof(lfn->reserved), &lfn->reserved ); + } + } + if (lfn->start != CT_LE_W(0)) { + printf( "Start cluster field in VFAT long filename slot is not 0 " + "(but 0x%04x).\n", lfn->start ); + if (interactive) + printf( "1: Fix.\n2: Leave it.\n" ); + else printf( "Auto-setting to 0.\n" ); + if (!interactive || get_key("12","?") == '1') { + lfn->start = CT_LE_W(0); + fs_write( dir_offset+offsetof(LFN_ENT,start), + sizeof(lfn->start),&lfn->start ); + } + } +} + + +/* This function is always called when de->attr != VFAT_LN_ATTR is found, to + * retrieve the previously constructed LFN. */ +char *lfn_get( DIR_ENT *de ) +{ + char *lfn; + __u8 sum; + int i; + + if (de->attr == VFAT_LN_ATTR) + die("lfn_get called with LFN directory entry"); + +#if 0 + if (de->lcase) + printf( "lcase=%02x\n",de->lcase ); +#endif + + if (lfn_slot == -1) + /* no long name for this file */ + return NULL; + + if (lfn_slot != 0) { + /* The long name isn't finished yet. */ + /* Causes: 1) LFN slot overwritten by non-VFAT aware tool */ + /* Fixes: 1) delete LFN 2) move overwriting entry to somewhere else + * and let user enter missing part of LFN (hard to do :-() + * 3) renumber entries and truncate name */ + char *long_name = CNV_PARTS_SO_FAR(); + char *short_name = file_name(de->name); + printf( "Unfinished long file name \"%s\".\n" + " (Start may have been overwritten by %s)\n", + long_name, short_name ); + free( long_name ); + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is.\n" + "3: Fix numbering (truncates long name and attaches " + "it to short name %s)\n", short_name ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return NULL; + case '2': + lfn_reset(); + return NULL; + case '3': + for( i = 0; i < lfn_parts; ++i ) { + __u8 id = (lfn_parts-i) | (i==0 ? LFN_ID_START : 0); + fs_write( lfn_offsets[i]+offsetof(LFN_ENT,id), + sizeof(id), &id ); + } + memmove( lfn_unicode, lfn_unicode+lfn_slot*CHARS_PER_LFN*2, + lfn_parts*CHARS_PER_LFN*2 ); + break; + } + } + } + + for (sum = 0, i = 0; i < 11; i++) + sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i]; + if (sum != lfn_checksum) { + /* checksum doesn't match, long name doesn't apply to this alias */ + /* Causes: 1) alias renamed */ + /* Fixes: 1) Fix checksum in LFN entries */ + char *long_name = CNV_PARTS_SO_FAR(); + char *short_name = file_name(de->name); + printf( "Wrong checksum for long file name \"%s\".\n" + " (Short name %s may have changed without updating the long name)\n", + long_name, short_name ); + free( long_name ); + if (interactive) { + printf( "1: Delete LFN\n2: Leave it as it is.\n" + "3: Fix checksum (attaches to short name %s)\n", + short_name ); + } + else printf( " Not auto-correcting this.\n" ); + if (interactive) { + switch( get_key( "123", "?" )) { + case '1': + clear_lfn_slots( 0, lfn_parts-1 ); + lfn_reset(); + return NULL; + case '2': + lfn_reset(); + return NULL; + case '3': + for( i = 0; i < lfn_parts; ++i ) { + fs_write( lfn_offsets[i]+offsetof(LFN_ENT,alias_checksum), + sizeof(sum), &sum ); + } + break; + } + } + } + + lfn = cnv_unicode( lfn_unicode, UNTIL_0, 1 ); + lfn_reset(); + return( lfn ); +} + +void lfn_check_orphaned(void) +{ + char *long_name; + + if (lfn_slot == -1) + return; + + long_name = CNV_PARTS_SO_FAR(); + printf("Orphaned long file name part \"%s\"\n", long_name); + if (interactive) + printf( "1: Delete.\n2: Leave it.\n" ); + else printf( " Auto-deleting.\n" ); + if (!interactive || get_key("12","?") == '1') { + clear_lfn_slots(0, lfn_parts - 1); + } + lfn_reset(); +} + +/* Local Variables: */ +/* tab-width: 8 */ +/* End: */ diff --git a/rosapps/sysutils/dosfsck/lfn.h b/rosapps/sysutils/dosfsck/lfn.h index 21726ef858b..d062e4a39c8 100644 --- a/rosapps/sysutils/dosfsck/lfn.h +++ b/rosapps/sysutils/dosfsck/lfn.h @@ -1,20 +1,20 @@ -/* lfn.h - Functions for handling VFAT long filenames */ - -/* Written 1998 by Roman Hodek */ - - -#ifndef _LFN_H -#define _LFN_H - -void lfn_reset( void ); -/* Reset the state of the LFN parser. */ - -void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ); -/* Process a dir slot that is a VFAT LFN entry. */ - -char *lfn_get( DIR_ENT *de ); -/* Retrieve the long name for the proper dir entry. */ - -void lfn_check_orphaned(void); - -#endif +/* lfn.h - Functions for handling VFAT long filenames */ + +/* Written 1998 by Roman Hodek */ + + +#ifndef _LFN_H +#define _LFN_H + +void lfn_reset( void ); +/* Reset the state of the LFN parser. */ + +void lfn_add_slot( DIR_ENT *de, loff_t dir_offset ); +/* Process a dir slot that is a VFAT LFN entry. */ + +char *lfn_get( DIR_ENT *de ); +/* Retrieve the long name for the proper dir entry. */ + +void lfn_check_orphaned(void); + +#endif diff --git a/rosapps/sysutils/dosfsck/msdos_fs.h b/rosapps/sysutils/dosfsck/msdos_fs.h index b955808df9a..5647fe833cd 100644 --- a/rosapps/sysutils/dosfsck/msdos_fs.h +++ b/rosapps/sysutils/dosfsck/msdos_fs.h @@ -1,182 +1,182 @@ -#ifndef _LINUX_MSDOS_FS_H -#define _LINUX_MSDOS_FS_H - -/* - * The MS-DOS filesystem constants/structures - */ -#include "byteorder.h" - -#define SECTOR_SIZE 512 /* sector size (bytes) */ -#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ -#define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */ -#define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */ -#define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry)) -#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ -#if 0 -#define CF_LE_W(v) le16_to_cpu(v) -#define CF_LE_L(v) le32_to_cpu(v) -#define CT_LE_W(v) cpu_to_le16(v) -#define CT_LE_L(v) cpu_to_le32(v) -#endif - -#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ - -#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */ -#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */ - -/* directory limit */ -#define FAT_MAX_DIR_ENTRIES (65536) -#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) - -#define ATTR_NONE 0 /* no attribute bits */ -#define ATTR_RO 1 /* read-only */ -#define ATTR_HIDDEN 2 /* hidden */ -#define ATTR_SYS 4 /* system */ -#define ATTR_VOLUME 8 /* volume label */ -#define ATTR_DIR 16 /* directory */ -#define ATTR_ARCH 32 /* archived */ - -/* attribute bits that are copied "as is" */ -#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN) -/* bits that are used by the Windows 95/Windows NT extended FAT */ -#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) - -#define CASE_LOWER_BASE 8 /* base is lower case */ -#define CASE_LOWER_EXT 16 /* extension is lower case */ - -#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ -#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) - -/* valid file mode bits */ -#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO) -/* Convert attribute bits and a mask to the UNIX mode. */ -#define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) - -#define MSDOS_NAME 11 /* maximum name length */ -#define MSDOS_LONGNAME 256 /* maximum name length */ -#define MSDOS_SLOTS 21 /* max # of slots for short and long names */ -#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ -#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */ - -/* media of boot sector */ -#define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0) -#define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \ - MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x)) - -/* start of data cluster's entry (number of reserved clusters) */ -#define FAT_START_ENT 2 - -/* maximum number of clusters */ -#define MAX_FAT12 0xFF4 -#define MAX_FAT16 0xFFF4 -#define MAX_FAT32 0x0FFFFFF6 -#define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \ - MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12) - -/* bad cluster mark */ -#define BAD_FAT12 0xFF7 -#define BAD_FAT16 0xFFF7 -#define BAD_FAT32 0x0FFFFFF7 - -/* standard EOF */ -#define EOF_FAT12 0xFFF -#define EOF_FAT16 0xFFFF -#define EOF_FAT32 0x0FFFFFFF - -#define FAT_ENT_FREE (0) -#define FAT_ENT_BAD (BAD_FAT32) -#define FAT_ENT_EOF (EOF_FAT32) - -#define FAT_FSINFO_SIG1 0x41615252 -#define FAT_FSINFO_SIG2 0x61417272 -#define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ - && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) - -/* - * ioctl commands - */ -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) -/* has used 0x72 ('r') in collision, so skip a few */ -#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) -#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) - -/* - * vfat shortname flags - */ -#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ -#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ -#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ -#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ -#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ - -struct fat_boot_sector { - __u8 ignored[3]; /* Boot strap short or near jump */ - __u8 system_id[8]; /* Name - can be used to special case - partition manager volumes */ - __u8 sector_size[2]; /* bytes per logical sector */ - __u8 sec_per_clus; /* sectors/cluster */ - __le16 reserved; /* reserved sectors */ - __u8 fats; /* number of FATs */ - __u8 dir_entries[2]; /* root directory entries */ - __u8 sectors[2]; /* number of sectors */ - __u8 media; /* media code */ - __le16 fat_length; /* sectors/FAT */ - __le16 secs_track; /* sectors per track */ - __le16 heads; /* number of heads */ - __le32 hidden; /* hidden sectors (unused) */ - __le32 total_sect; /* number of sectors (if sectors == 0) */ - - /* The following fields are only used by FAT32 */ - __le32 fat32_length; /* sectors/FAT */ - __le16 flags; /* bit 8: fat mirroring, low 4: active fat */ - __u8 version[2]; /* major, minor filesystem version */ - __le32 root_cluster; /* first cluster in root directory */ - __le16 info_sector; /* filesystem info sector */ - __le16 backup_boot; /* backup boot sector */ - __le16 reserved2[6]; /* Unused */ -}; - -struct fat_boot_fsinfo { - __le32 signature1; /* 0x41615252L */ - __le32 reserved1[120]; /* Nothing as far as I can tell */ - __le32 signature2; /* 0x61417272L */ - __le32 free_clusters; /* Free cluster count. -1 if unknown */ - __le32 next_cluster; /* Most recently allocated cluster */ - __le32 reserved2[4]; -}; - -struct msdos_dir_entry { - __u8 name[8],ext[3]; /* name and extension */ - __u8 attr; /* attribute bits */ - __u8 lcase; /* Case for base and extension */ - __u8 ctime_cs; /* Creation time, centiseconds (0-199) */ - __le16 ctime; /* Creation time */ - __le16 cdate; /* Creation date */ - __le16 adate; /* Last access date */ - __le16 starthi; /* High 16 bits of cluster in FAT32 */ - __le16 time,date,start;/* time, date and first cluster */ - __le32 size; /* file size (in bytes) */ -}; - -/* Up to 13 characters of the name */ -struct msdos_dir_slot { - __u8 id; /* sequence number for slot */ - __u8 name0_4[10]; /* first 5 characters in name */ - __u8 attr; /* attribute byte */ - __u8 reserved; /* always 0 */ - __u8 alias_checksum; /* checksum for 8.3 alias */ - __u8 name5_10[12]; /* 6 more characters in name */ - __le16 start; /* starting cluster number, 0 in long slots */ - __u8 name11_12[4]; /* last 2 characters in name */ -}; - -struct fat_slot_info { - loff_t i_pos; /* on-disk position of directory entry */ - loff_t slot_off; /* offset for slot or de start */ - int nr_slots; /* number of slots + 1(de) in filename */ - struct msdos_dir_entry *de; - struct buffer_head *bh; -}; - -#endif +#ifndef _LINUX_MSDOS_FS_H +#define _LINUX_MSDOS_FS_H + +/* + * The MS-DOS filesystem constants/structures + */ +#include "byteorder.h" + +#define SECTOR_SIZE 512 /* sector size (bytes) */ +#define SECTOR_BITS 9 /* log2(SECTOR_SIZE) */ +#define MSDOS_DPB (MSDOS_DPS) /* dir entries per block */ +#define MSDOS_DPB_BITS 4 /* log2(MSDOS_DPB) */ +#define MSDOS_DPS (SECTOR_SIZE / sizeof(struct msdos_dir_entry)) +#define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ +#if 0 +#define CF_LE_W(v) le16_to_cpu(v) +#define CF_LE_L(v) le32_to_cpu(v) +#define CT_LE_W(v) cpu_to_le16(v) +#define CT_LE_L(v) cpu_to_le32(v) +#endif + +#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ + +#define MSDOS_ROOT_INO 1 /* == MINIX_ROOT_INO */ +#define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */ + +/* directory limit */ +#define FAT_MAX_DIR_ENTRIES (65536) +#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) + +#define ATTR_NONE 0 /* no attribute bits */ +#define ATTR_RO 1 /* read-only */ +#define ATTR_HIDDEN 2 /* hidden */ +#define ATTR_SYS 4 /* system */ +#define ATTR_VOLUME 8 /* volume label */ +#define ATTR_DIR 16 /* directory */ +#define ATTR_ARCH 32 /* archived */ + +/* attribute bits that are copied "as is" */ +#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN) +/* bits that are used by the Windows 95/Windows NT extended FAT */ +#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) + +#define CASE_LOWER_BASE 8 /* base is lower case */ +#define CASE_LOWER_EXT 16 /* extension is lower case */ + +#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ +#define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) + +/* valid file mode bits */ +#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO) +/* Convert attribute bits and a mask to the UNIX mode. */ +#define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) + +#define MSDOS_NAME 11 /* maximum name length */ +#define MSDOS_LONGNAME 256 /* maximum name length */ +#define MSDOS_SLOTS 21 /* max # of slots for short and long names */ +#define MSDOS_DOT ". " /* ".", padded to MSDOS_NAME chars */ +#define MSDOS_DOTDOT ".. " /* "..", padded to MSDOS_NAME chars */ + +/* media of boot sector */ +#define FAT_VALID_MEDIA(x) ((0xF8 <= (x) && (x) <= 0xFF) || (x) == 0xF0) +#define FAT_FIRST_ENT(s, x) ((MSDOS_SB(s)->fat_bits == 32 ? 0x0FFFFF00 : \ + MSDOS_SB(s)->fat_bits == 16 ? 0xFF00 : 0xF00) | (x)) + +/* start of data cluster's entry (number of reserved clusters) */ +#define FAT_START_ENT 2 + +/* maximum number of clusters */ +#define MAX_FAT12 0xFF4 +#define MAX_FAT16 0xFFF4 +#define MAX_FAT32 0x0FFFFFF6 +#define MAX_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? MAX_FAT32 : \ + MSDOS_SB(s)->fat_bits == 16 ? MAX_FAT16 : MAX_FAT12) + +/* bad cluster mark */ +#define BAD_FAT12 0xFF7 +#define BAD_FAT16 0xFFF7 +#define BAD_FAT32 0x0FFFFFF7 + +/* standard EOF */ +#define EOF_FAT12 0xFFF +#define EOF_FAT16 0xFFFF +#define EOF_FAT32 0x0FFFFFFF + +#define FAT_ENT_FREE (0) +#define FAT_ENT_BAD (BAD_FAT32) +#define FAT_ENT_EOF (EOF_FAT32) + +#define FAT_FSINFO_SIG1 0x41615252 +#define FAT_FSINFO_SIG2 0x61417272 +#define IS_FSINFO(x) (le32_to_cpu((x)->signature1) == FAT_FSINFO_SIG1 \ + && le32_to_cpu((x)->signature2) == FAT_FSINFO_SIG2) + +/* + * ioctl commands + */ +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) +/* has used 0x72 ('r') in collision, so skip a few */ +#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) +#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) + +/* + * vfat shortname flags + */ +#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ +#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ +#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ +#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ +#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ + +struct fat_boot_sector { + __u8 ignored[3]; /* Boot strap short or near jump */ + __u8 system_id[8]; /* Name - can be used to special case + partition manager volumes */ + __u8 sector_size[2]; /* bytes per logical sector */ + __u8 sec_per_clus; /* sectors/cluster */ + __le16 reserved; /* reserved sectors */ + __u8 fats; /* number of FATs */ + __u8 dir_entries[2]; /* root directory entries */ + __u8 sectors[2]; /* number of sectors */ + __u8 media; /* media code */ + __le16 fat_length; /* sectors/FAT */ + __le16 secs_track; /* sectors per track */ + __le16 heads; /* number of heads */ + __le32 hidden; /* hidden sectors (unused) */ + __le32 total_sect; /* number of sectors (if sectors == 0) */ + + /* The following fields are only used by FAT32 */ + __le32 fat32_length; /* sectors/FAT */ + __le16 flags; /* bit 8: fat mirroring, low 4: active fat */ + __u8 version[2]; /* major, minor filesystem version */ + __le32 root_cluster; /* first cluster in root directory */ + __le16 info_sector; /* filesystem info sector */ + __le16 backup_boot; /* backup boot sector */ + __le16 reserved2[6]; /* Unused */ +}; + +struct fat_boot_fsinfo { + __le32 signature1; /* 0x41615252L */ + __le32 reserved1[120]; /* Nothing as far as I can tell */ + __le32 signature2; /* 0x61417272L */ + __le32 free_clusters; /* Free cluster count. -1 if unknown */ + __le32 next_cluster; /* Most recently allocated cluster */ + __le32 reserved2[4]; +}; + +struct msdos_dir_entry { + __u8 name[8],ext[3]; /* name and extension */ + __u8 attr; /* attribute bits */ + __u8 lcase; /* Case for base and extension */ + __u8 ctime_cs; /* Creation time, centiseconds (0-199) */ + __le16 ctime; /* Creation time */ + __le16 cdate; /* Creation date */ + __le16 adate; /* Last access date */ + __le16 starthi; /* High 16 bits of cluster in FAT32 */ + __le16 time,date,start;/* time, date and first cluster */ + __le32 size; /* file size (in bytes) */ +}; + +/* Up to 13 characters of the name */ +struct msdos_dir_slot { + __u8 id; /* sequence number for slot */ + __u8 name0_4[10]; /* first 5 characters in name */ + __u8 attr; /* attribute byte */ + __u8 reserved; /* always 0 */ + __u8 alias_checksum; /* checksum for 8.3 alias */ + __u8 name5_10[12]; /* 6 more characters in name */ + __le16 start; /* starting cluster number, 0 in long slots */ + __u8 name11_12[4]; /* last 2 characters in name */ +}; + +struct fat_slot_info { + loff_t i_pos; /* on-disk position of directory entry */ + loff_t slot_off; /* offset for slot or de start */ + int nr_slots; /* number of slots + 1(de) in filename */ + struct msdos_dir_entry *de; + struct buffer_head *bh; +}; + +#endif diff --git a/rosapps/sysutils/dosfsck/swab.h b/rosapps/sysutils/dosfsck/swab.h index 31bd29157f0..647648c7aa6 100644 --- a/rosapps/sysutils/dosfsck/swab.h +++ b/rosapps/sysutils/dosfsck/swab.h @@ -1,192 +1,192 @@ -#ifndef _LINUX_BYTEORDER_SWAB_H -#define _LINUX_BYTEORDER_SWAB_H - -/* - * linux/byteorder/swab.h - * Byte-swapping, independently from CPU endianness - * swabXX[ps]?(foo) - * - * Francois-Rene Rideau 19971205 - * separated swab functions from cpu_to_XX, - * to clean up support for bizarre-endian architectures. - * - * See asm-i386/byteorder.h and suches for examples of how to provide - * architecture-dependent optimized versions - * - */ - -#include "compiler.h" - -/* casts are necessary for constants, because we never know how for sure - * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. - */ -#define ___swab16(x) \ -({ \ - __u16 __x = (x); \ - ((__u16)( \ - (((__u16)(__x) & (__u16)0x00ffU) << 8) | \ - (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \ -}) - -#define ___swab32(x) \ -({ \ - __u32 __x = (x); \ - ((__u32)( \ - (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ - (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ - (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ - (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ -}) - -#define ___swab64(x) \ -({ \ - __u64 __x = (x); \ - ((__u64)( \ - (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ - (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ - (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ - (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ - (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ - (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ - (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ - (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ -}) - -#define ___constant_swab16(x) \ - ((__u16)( \ - (((__u16)(x) & (__u16)0x00ffU) << 8) | \ - (((__u16)(x) & (__u16)0xff00U) >> 8) )) -#define ___constant_swab32(x) \ - ((__u32)( \ - (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ - (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ - (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ - (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) -#define ___constant_swab64(x) \ - ((__u64)( \ - (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ - (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ - (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ - (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ - (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ - (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ - (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ - (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) - -/* - * provide defaults when no architecture-specific optimization is detected - */ -#ifndef __arch__swab16 -# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); }) -#endif -#ifndef __arch__swab32 -# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); }) -#endif -#ifndef __arch__swab64 -# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); }) -#endif - -#ifndef __arch__swab16p -# define __arch__swab16p(x) __arch__swab16(*(x)) -#endif -#ifndef __arch__swab32p -# define __arch__swab32p(x) __arch__swab32(*(x)) -#endif -#ifndef __arch__swab64p -# define __arch__swab64p(x) __arch__swab64(*(x)) -#endif - -#ifndef __arch__swab16s -# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0) -#endif -#ifndef __arch__swab32s -# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0) -#endif -#ifndef __arch__swab64s -# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0) -#endif - - -/* - * Allow constant folding - */ -#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) -# define __swab16(x) \ -(__builtin_constant_p((__u16)(x)) ? \ - ___swab16((x)) : \ - __fswab16((x))) -# define __swab32(x) \ -(__builtin_constant_p((__u32)(x)) ? \ - ___swab32((x)) : \ - __fswab32((x))) -# define __swab64(x) \ -(__builtin_constant_p((__u64)(x)) ? \ - ___swab64((x)) : \ - __fswab64((x))) -#else -# define __swab16(x) __fswab16(x) -# define __swab32(x) __fswab32(x) -# define __swab64(x) __fswab64(x) -#endif /* OPTIMIZE */ - - -static __inline__ __attribute_const__ __u16 __fswab16(__u16 x) -{ - return __arch__swab16(x); -} -static __inline__ __u16 __swab16p(const __u16 *x) -{ - return __arch__swab16p(x); -} -static __inline__ void __swab16s(__u16 *addr) -{ - __arch__swab16s(addr); -} - -static __inline__ __attribute_const__ __u32 __fswab32(__u32 x) -{ - return __arch__swab32(x); -} -static __inline__ __u32 __swab32p(const __u32 *x) -{ - return __arch__swab32p(x); -} -static __inline__ void __swab32s(__u32 *addr) -{ - __arch__swab32s(addr); -} - -#ifdef __BYTEORDER_HAS_U64__ -static __inline__ __attribute_const__ __u64 __fswab64(__u64 x) -{ -# ifdef __SWAB_64_THRU_32__ - __u32 h = x >> 32; - __u32 l = x & ((1ULL<<32)-1); - return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); -# else - return __arch__swab64(x); -# endif -} -static __inline__ __u64 __swab64p(const __u64 *x) -{ - return __arch__swab64p(x); -} -static __inline__ void __swab64s(__u64 *addr) -{ - __arch__swab64s(addr); -} -#endif /* __BYTEORDER_HAS_U64__ */ - -#if defined(__KERNEL__) -#define swab16 __swab16 -#define swab32 __swab32 -#define swab64 __swab64 -#define swab16p __swab16p -#define swab32p __swab32p -#define swab64p __swab64p -#define swab16s __swab16s -#define swab32s __swab32s -#define swab64s __swab64s -#endif - -#endif /* _LINUX_BYTEORDER_SWAB_H */ +#ifndef _LINUX_BYTEORDER_SWAB_H +#define _LINUX_BYTEORDER_SWAB_H + +/* + * linux/byteorder/swab.h + * Byte-swapping, independently from CPU endianness + * swabXX[ps]?(foo) + * + * Francois-Rene Rideau 19971205 + * separated swab functions from cpu_to_XX, + * to clean up support for bizarre-endian architectures. + * + * See asm-i386/byteorder.h and suches for examples of how to provide + * architecture-dependent optimized versions + * + */ + +#include "compiler.h" + +/* casts are necessary for constants, because we never know how for sure + * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. + */ +#define ___swab16(x) \ +({ \ + __u16 __x = (x); \ + ((__u16)( \ + (((__u16)(__x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \ +}) + +#define ___swab32(x) \ +({ \ + __u32 __x = (x); \ + ((__u32)( \ + (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ +}) + +#define ___swab64(x) \ +({ \ + __u64 __x = (x); \ + ((__u64)( \ + (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ + (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ +}) + +#define ___constant_swab16(x) \ + ((__u16)( \ + (((__u16)(x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(x) & (__u16)0xff00U) >> 8) )) +#define ___constant_swab32(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) +#define ___constant_swab64(x) \ + ((__u64)( \ + (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ + (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) + +/* + * provide defaults when no architecture-specific optimization is detected + */ +#ifndef __arch__swab16 +# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); }) +#endif +#ifndef __arch__swab32 +# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); }) +#endif +#ifndef __arch__swab64 +# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); }) +#endif + +#ifndef __arch__swab16p +# define __arch__swab16p(x) __arch__swab16(*(x)) +#endif +#ifndef __arch__swab32p +# define __arch__swab32p(x) __arch__swab32(*(x)) +#endif +#ifndef __arch__swab64p +# define __arch__swab64p(x) __arch__swab64(*(x)) +#endif + +#ifndef __arch__swab16s +# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0) +#endif +#ifndef __arch__swab32s +# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0) +#endif +#ifndef __arch__swab64s +# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0) +#endif + + +/* + * Allow constant folding + */ +#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) +# define __swab16(x) \ +(__builtin_constant_p((__u16)(x)) ? \ + ___swab16((x)) : \ + __fswab16((x))) +# define __swab32(x) \ +(__builtin_constant_p((__u32)(x)) ? \ + ___swab32((x)) : \ + __fswab32((x))) +# define __swab64(x) \ +(__builtin_constant_p((__u64)(x)) ? \ + ___swab64((x)) : \ + __fswab64((x))) +#else +# define __swab16(x) __fswab16(x) +# define __swab32(x) __fswab32(x) +# define __swab64(x) __fswab64(x) +#endif /* OPTIMIZE */ + + +static __inline__ __attribute_const__ __u16 __fswab16(__u16 x) +{ + return __arch__swab16(x); +} +static __inline__ __u16 __swab16p(const __u16 *x) +{ + return __arch__swab16p(x); +} +static __inline__ void __swab16s(__u16 *addr) +{ + __arch__swab16s(addr); +} + +static __inline__ __attribute_const__ __u32 __fswab32(__u32 x) +{ + return __arch__swab32(x); +} +static __inline__ __u32 __swab32p(const __u32 *x) +{ + return __arch__swab32p(x); +} +static __inline__ void __swab32s(__u32 *addr) +{ + __arch__swab32s(addr); +} + +#ifdef __BYTEORDER_HAS_U64__ +static __inline__ __attribute_const__ __u64 __fswab64(__u64 x) +{ +# ifdef __SWAB_64_THRU_32__ + __u32 h = x >> 32; + __u32 l = x & ((1ULL<<32)-1); + return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); +# else + return __arch__swab64(x); +# endif +} +static __inline__ __u64 __swab64p(const __u64 *x) +{ + return __arch__swab64p(x); +} +static __inline__ void __swab64s(__u64 *addr) +{ + __arch__swab64s(addr); +} +#endif /* __BYTEORDER_HAS_U64__ */ + +#if defined(__KERNEL__) +#define swab16 __swab16 +#define swab32 __swab32 +#define swab64 __swab64 +#define swab16p __swab16p +#define swab32p __swab32p +#define swab64p __swab64p +#define swab16s __swab16s +#define swab32s __swab32s +#define swab64s __swab64s +#endif + +#endif /* _LINUX_BYTEORDER_SWAB_H */ diff --git a/rosapps/sysutils/dosfsck/version.h b/rosapps/sysutils/dosfsck/version.h index 4ef269483fe..e0878fb50bc 100644 --- a/rosapps/sysutils/dosfsck/version.h +++ b/rosapps/sysutils/dosfsck/version.h @@ -1,8 +1,8 @@ -#ifndef _version_h -#define _version_h - -#define VERSION "2.8" -#define VERSION_DATE "28 Feb 2001" - -#endif /* _version_h */ - +#ifndef _version_h +#define _version_h + +#define VERSION "2.8" +#define VERSION_DATE "28 Feb 2001" + +#endif /* _version_h */ + diff --git a/rosapps/sysutils/dosfsck/vfat.h b/rosapps/sysutils/dosfsck/vfat.h index 72953d8216b..6f2e7cea6a4 100755 --- a/rosapps/sysutils/dosfsck/vfat.h +++ b/rosapps/sysutils/dosfsck/vfat.h @@ -1,744 +1,744 @@ -/* $Id: vfat.h 16656 2005-07-20 02:52:52Z ion $ */ - -#include -#include -#include -#include -#include -#include -#include - -#define USE_ROS_CC_AND_FS - -#include -struct _BootSector -{ - unsigned char magic0, res0, magic1; - unsigned char OEMName[8]; - unsigned short BytesPerSector; - unsigned char SectorsPerCluster; - unsigned short ReservedSectors; - unsigned char FATCount; - unsigned short RootEntries, Sectors; - unsigned char Media; - unsigned short FATSectors, SectorsPerTrack, Heads; - unsigned long HiddenSectors, SectorsHuge; - unsigned char Drive, Res1, Sig; - unsigned long VolumeID; - unsigned char VolumeLabel[11], SysType[8]; - unsigned char Res2[448]; - unsigned short Signatur1; -}; - -struct _BootSector32 -{ - unsigned char magic0, res0, magic1; // 0 - unsigned char OEMName[8]; // 3 - unsigned short BytesPerSector; // 11 - unsigned char SectorsPerCluster; // 13 - unsigned short ReservedSectors; // 14 - unsigned char FATCount; // 16 - unsigned short RootEntries, Sectors; // 17 - unsigned char Media; // 21 - unsigned short FATSectors, SectorsPerTrack, Heads; // 22 - unsigned long HiddenSectors, SectorsHuge; // 28 - unsigned long FATSectors32; // 36 - unsigned short ExtFlag; // 40 - unsigned short FSVersion; // 42 - unsigned long RootCluster; // 44 - unsigned short FSInfoSector; // 48 - unsigned short BootBackup; // 50 - unsigned char Res3[12]; // 52 - unsigned char Drive; // 64 - unsigned char Res4; // 65 - unsigned char ExtBootSignature; // 66 - unsigned long VolumeID; // 67 - unsigned char VolumeLabel[11], SysType[8]; // 71 - unsigned char Res2[420]; // 90 - unsigned short Signature1; // 510 -}; - -struct _BootSectorFatX -{ - unsigned char SysType[4]; // 0 - unsigned long VolumeID; // 4 - unsigned long SectorsPerCluster; // 8 - unsigned short FATCount; // 12 - unsigned long Unknown; // 14 - unsigned char Unused[4078]; // 18 -}; - -struct _FsInfoSector -{ - unsigned long ExtBootSignature2; // 0 - unsigned char Res6[480]; // 4 - unsigned long FSINFOSignature; // 484 - unsigned long FreeCluster; // 488 - unsigned long NextCluster; // 492 - unsigned char Res7[12]; // 496 - unsigned long Signatur2; // 508 -}; - -typedef struct _BootSector BootSector; - -struct _FATDirEntry -{ - union - { - struct { unsigned char Filename[8], Ext[3]; }; - unsigned char ShortName[11]; - }; - unsigned char Attrib; - unsigned char lCase; - unsigned char CreationTimeMs; - unsigned short CreationTime,CreationDate,AccessDate; - unsigned short FirstClusterHigh; // higher - unsigned short UpdateTime; //time create/update - unsigned short UpdateDate; //date create/update - unsigned short FirstCluster; - unsigned long FileSize; -}; - -typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY; - -struct _FATXDirEntry -{ - unsigned char FilenameLength; // 0 - unsigned char Attrib; // 1 - unsigned char Filename[42]; // 2 - unsigned long FirstCluster; // 44 - unsigned long FileSize; // 48 - unsigned short UpdateTime; // 52 - unsigned short UpdateDate; // 54 - unsigned short CreationTime; // 56 - unsigned short CreationDate; // 58 - unsigned short AccessTime; // 60 - unsigned short AccessDate; // 62 -}; - -struct _slot -{ - unsigned char id; // sequence number for slot - WCHAR name0_4[5]; // first 5 characters in name - unsigned char attr; // attribute byte - unsigned char reserved; // always 0 - unsigned char alias_checksum; // checksum for 8.3 alias - WCHAR name5_10[6]; // 6 more characters in name - unsigned char start[2]; // starting cluster number - WCHAR name11_12[2]; // last 2 characters in name -}; - -typedef struct _slot slot; - -#include - -#define VFAT_CASE_LOWER_BASE 8 // base is lower case -#define VFAT_CASE_LOWER_EXT 16 // extension is lower case - -#define LONGNAME_MAX_LENGTH 256 // max length for a long filename - -#define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat))) -#define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat))) -#define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat))) - -#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5) -#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0) -#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f) -#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) - -#define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5) -#define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff) -#define FATX_ENTRY_LONG(DirEntry) (FALSE) -#define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) - -#define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY)) -#define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY)) - -typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY; - -union _DIR_ENTRY -{ - FAT_DIR_ENTRY Fat; - FATX_DIR_ENTRY FatX; -}; - -typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY; - -#define BLOCKSIZE 512 - -#define FAT16 (1) -#define FAT12 (2) -#define FAT32 (3) -#define FATX16 (4) -#define FATX32 (5) - -#define VCB_VOLUME_LOCKED 0x0001 -#define VCB_DISMOUNT_PENDING 0x0002 -#define VCB_IS_FATX 0x0004 -#define VCB_IS_DIRTY 0x4000 /* Volume is dirty */ -#define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */ - -typedef struct -{ - ULONG VolumeID; - ULONG FATStart; - ULONG FATCount; - ULONG FATSectors; - ULONG rootDirectorySectors; - ULONG rootStart; - ULONG dataStart; - ULONG RootCluster; - ULONG SectorsPerCluster; - ULONG BytesPerSector; - ULONG BytesPerCluster; - ULONG NumberOfClusters; - ULONG FatType; - ULONG Sectors; - BOOLEAN FixedMedia; -} FATINFO, *PFATINFO; - -struct _VFATFCB; -struct _VFAT_DIRENTRY_CONTEXT; - -typedef struct _HASHENTRY -{ - ULONG Hash; - struct _VFATFCB* self; - struct _HASHENTRY* next; -} -HASHENTRY; - -#define FCB_HASH_TABLE_SIZE 65536 - -typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION; - -typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG); -typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG); -typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG); - -typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN); - -typedef struct DEVICE_EXTENSION -{ - ERESOURCE DirResource; - ERESOURCE FatResource; - - KSPIN_LOCK FcbListLock; - LIST_ENTRY FcbListHead; - ULONG HashTableSize; - struct _HASHENTRY** FcbHashTable; - - PDEVICE_OBJECT StorageDevice; - PFILE_OBJECT FATFileObject; - FATINFO FatInfo; - ULONG LastAvailableCluster; - ULONG AvailableClusters; - BOOLEAN AvailableClustersValid; - ULONG Flags; - struct _VFATFCB * VolumeFcb; - - /* Pointers to functions for manipulating FAT. */ - PGET_NEXT_CLUSTER GetNextCluster; - PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster; - PWRITE_CLUSTER WriteCluster; - ULONG CleanShutBitMask; - - /* Pointers to functions for manipulating directory entries. */ - PGET_NEXT_DIR_ENTRY GetNextDirEntry; - - ULONG BaseDateYear; - - LIST_ENTRY VolumeListEntry; -} DEVICE_EXTENSION, VCB, *PVCB; - -typedef struct -{ - PDRIVER_OBJECT DriverObject; - PDEVICE_OBJECT DeviceObject; - ULONG Flags; - ERESOURCE VolumeListLock; - LIST_ENTRY VolumeListHead; - NPAGED_LOOKASIDE_LIST FcbLookasideList; - NPAGED_LOOKASIDE_LIST CcbLookasideList; - NPAGED_LOOKASIDE_LIST IrpContextLookasideList; - FAST_IO_DISPATCH FastIoDispatch; - CACHE_MANAGER_CALLBACKS CacheMgrCallbacks; -} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA; - -extern PVFAT_GLOBAL_DATA VfatGlobalData; - -#define FCB_CACHE_INITIALIZED 0x0001 -#define FCB_DELETE_PENDING 0x0002 -#define FCB_IS_FAT 0x0004 -#define FCB_IS_PAGE_FILE 0x0008 -#define FCB_IS_VOLUME 0x0010 -#define FCB_IS_DIRTY 0x0020 -#define FCB_IS_FATX_ENTRY 0x0040 - -typedef struct _VFATFCB -{ - /* FCB header required by ROS/NT */ - FSRTL_COMMON_FCB_HEADER RFCB; - SECTION_OBJECT_POINTERS SectionObjectPointers; - ERESOURCE MainResource; - ERESOURCE PagingIoResource; - /* end FCB header required by ROS/NT */ - - /* directory entry for this file or directory */ - DIR_ENTRY entry; - - /* Pointer to attributes in entry */ - PUCHAR Attributes; - - /* long file name, points into PathNameBuffer */ - UNICODE_STRING LongNameU; - - /* short file name */ - UNICODE_STRING ShortNameU; - - /* directory name, points into PathNameBuffer */ - UNICODE_STRING DirNameU; - - /* path + long file name 260 max*/ - UNICODE_STRING PathNameU; - - /* buffer for PathNameU */ - PWCHAR PathNameBuffer; - - /* buffer for ShortNameU */ - WCHAR ShortNameBuffer[13]; - - /* */ - LONG RefCount; - - /* List of FCB's for this volume */ - LIST_ENTRY FcbListEntry; - - /* pointer to the parent fcb */ - struct _VFATFCB* parentFcb; - - /* Flags for the fcb */ - ULONG Flags; - - /* pointer to the file object which has initialized the fcb */ - PFILE_OBJECT FileObject; - - /* Directory index for the short name entry */ - ULONG dirIndex; - - /* Directory index where the long name starts */ - ULONG startIndex; - - /* Share access for the file object */ - SHARE_ACCESS FCBShareAccess; - - /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */ - ULONG OpenHandleCount; - - /* Entry into the hash table for the path + long name */ - HASHENTRY Hash; - - /* Entry into the hash table for the path + short name */ - HASHENTRY ShortHash; - - /* List of byte-range locks for this file */ - FILE_LOCK FileLock; - - /* - * Optimalization: caching of last read/write cluster+offset pair. Can't - * be in VFATCCB because it must be reset everytime the allocated clusters - * change. - */ - FAST_MUTEX LastMutex; - ULONG LastCluster; - ULONG LastOffset; -} VFATFCB, *PVFATFCB; - -typedef struct _VFATCCB -{ - LARGE_INTEGER CurrentByteOffset; - /* for DirectoryControl */ - ULONG Entry; - /* for DirectoryControl */ - UNICODE_STRING SearchPattern; -} VFATCCB, *PVFATCCB; - -#ifndef TAG -#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) -#endif - -#define TAG_CCB TAG('V', 'C', 'C', 'B') -#define TAG_FCB TAG('V', 'F', 'C', 'B') -#define TAG_IRP TAG('V', 'I', 'R', 'P') - -#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry)) - -typedef struct __DOSTIME -{ - USHORT Second:5; - USHORT Minute:6; - USHORT Hour:5; -} -DOSTIME, *PDOSTIME; - -typedef struct __DOSDATE -{ - USHORT Day:5; - USHORT Month:4; - USHORT Year:5; -} -DOSDATE, *PDOSDATE; - -#define IRPCONTEXT_CANWAIT 0x0001 -#define IRPCONTEXT_PENDINGRETURNED 0x0002 - -typedef struct -{ - PIRP Irp; - PDEVICE_OBJECT DeviceObject; - PDEVICE_EXTENSION DeviceExt; - ULONG Flags; - WORK_QUEUE_ITEM WorkQueueItem; - PIO_STACK_LOCATION Stack; - UCHAR MajorFunction; - UCHAR MinorFunction; - PFILE_OBJECT FileObject; - ULONG RefCount; - KEVENT Event; -} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; - -typedef struct _VFAT_DIRENTRY_CONTEXT -{ - ULONG StartIndex; - ULONG DirIndex; - DIR_ENTRY DirEntry; - UNICODE_STRING LongNameU; - UNICODE_STRING ShortNameU; -} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT; - - -/* ------------------------------------------------------ shutdown.c */ - -NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject, - PIRP Irp); - -/* -------------------------------------------------------- volume.c */ - -NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); - -/* ------------------------------------------------------ blockdev.c */ - -NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, - IN PLARGE_INTEGER ReadOffset, - IN ULONG ReadLength, - IN PUCHAR Buffer, - IN BOOLEAN Override); - -NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext, - IN PLARGE_INTEGER ReadOffset, - IN ULONG ReadLength, - IN ULONG BufferOffset, - IN BOOLEAN Wait); - -NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, - IN PLARGE_INTEGER WriteOffset, - IN ULONG WriteLength, - IN ULONG BufferOffset, - IN BOOLEAN Wait); - -NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, - IN ULONG CtlCode, - IN PVOID InputBuffer, - IN ULONG InputBufferSize, - IN OUT PVOID OutputBuffer, - IN OUT PULONG pOutputBufferSize, - IN BOOLEAN Override); - -/* ----------------------------------------------------------- dir.c */ - -NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT); - -BOOLEAN FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, - USHORT DosDate, - USHORT DosTime, - PLARGE_INTEGER SystemTime); - -BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER SystemTime, - USHORT *pDosDate, - USHORT *pDosTime); - -/* -------------------------------------------------------- create.c */ - -NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject, - PVFATFCB* parentFcb); - -NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt, - PVFATFCB Parent, - PUNICODE_STRING FileToFindU, - PVFAT_DIRENTRY_CONTEXT DirContext, - BOOLEAN First); - -VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, - PUNICODE_STRING NameU); - -NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, - PVPB Vpb); - -/* --------------------------------------------------------- close.c */ - -NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, - PFILE_OBJECT FileObject); - -/* ------------------------------------------------------- cleanup.c */ - -NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext); - -/* --------------------------------------------------------- fastio.c */ - -VOID -VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch); - -BOOLEAN NTAPI -VfatAcquireForLazyWrite(IN PVOID Context, - IN BOOLEAN Wait); - -VOID NTAPI -VfatReleaseFromLazyWrite(IN PVOID Context); - -BOOLEAN NTAPI -VfatAcquireForReadAhead(IN PVOID Context, - IN BOOLEAN Wait); - -VOID NTAPI -VfatReleaseFromReadAhead(IN PVOID Context); - -/* --------------------------------------------------------- fsctl.c */ - -NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext); - -/* --------------------------------------------------------- finfo.c */ - -NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS -VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, - PVFATFCB Fcb, - PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER AllocationSize); - -/* --------------------------------------------------------- iface.c */ - -NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath); - -/* --------------------------------------------------------- dirwr.c */ - -NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt, - PUNICODE_STRING PathNameU, - PVFATFCB* Fcb, - PVFATFCB ParentFcb, - ULONG RequestedOptions, - UCHAR ReqAttr); - -NTSTATUS VfatUpdateEntry (PVFATFCB pFcb); - -NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB); - -BOOLEAN -vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, - PVFATFCB pDirFcb, - ULONG nbSlots, - PULONG start); - -/* -------------------------------------------------------- string.c */ - -VOID -vfatSplitPathName(PUNICODE_STRING PathNameU, - PUNICODE_STRING DirNameU, - PUNICODE_STRING FileNameU); - -BOOLEAN vfatIsLongIllegal(WCHAR c); - -BOOLEAN wstrcmpjoki (PWSTR s1, - PWSTR s2); - -/* ----------------------------------------------------------- fat.c */ - -NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, - PULONG Cluster); - -NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue, - PULONG OldValue); - -NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, - PULONG Cluster); - -NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue, - PULONG OldValue); - -NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, - PULONG Cluster); - -NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue, - PULONG OldValue); - -NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, - ULONG FirstCluster, - ULONG FileOffset, - PULONG Cluster, - BOOLEAN Extend); - -ULONGLONG ClusterToSector (PDEVICE_EXTENSION DeviceExt, - ULONG Cluster); - -NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS GetNextClusterExtend (PDEVICE_EXTENSION DeviceExt, - ULONG CurrentCluster, - PULONG NextCluster); - -NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER Clusters); - -NTSTATUS -WriteCluster(PDEVICE_EXTENSION DeviceExt, - ULONG ClusterToWrite, - ULONG NewValue); - -/* ------------------------------------------------------ direntry.c */ - -ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, - PDIR_ENTRY pDirEntry); - -BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb); - -NTSTATUS FATGetNextDirEntry(PVOID * pContext, - PVOID * pPage, - IN PVFATFCB pDirFcb, - IN PVFAT_DIRENTRY_CONTEXT DirContext, - BOOLEAN First); - -NTSTATUS FATXGetNextDirEntry(PVOID * pContext, - PVOID * pPage, - IN PVFATFCB pDirFcb, - IN PVFAT_DIRENTRY_CONTEXT DirContext, - BOOLEAN First); - -/* ----------------------------------------------------------- fcb.c */ - -PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB, - PUNICODE_STRING pFileNameU); - -VOID vfatDestroyFCB (PVFATFCB pFCB); - -VOID vfatDestroyCCB(PVFATCCB pCcb); - -VOID vfatGrabFCB (PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); - -VOID vfatReleaseFCB (PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); - -VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB, - PVFATFCB pFCB); - -PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, - PUNICODE_STRING pFileNameU); - -PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); - -PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); - -BOOLEAN vfatFCBIsDirectory (PVFATFCB FCB); - -BOOLEAN vfatFCBIsRoot(PVFATFCB FCB); - -NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, - PVFATFCB fcb, - PFILE_OBJECT fileObject); - -NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, - PVFATFCB parentFCB, - PUNICODE_STRING FileToFindU, - PVFATFCB * fileFCB); - -NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, - PVFATFCB *pParentFCB, - PVFATFCB *pFCB, - PUNICODE_STRING pFileNameU); - -NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb, - PVFATFCB directoryFCB, - PVFAT_DIRENTRY_CONTEXT DirContext, - PVFATFCB * fileFCB); - -/* ------------------------------------------------------------ rw.c */ - -NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, - ULONG FirstCluster, - PULONG CurrentCluster, - BOOLEAN Extend); - -/* ----------------------------------------------------------- misc.c */ - -NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext); - -PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, - PIRP Irp); - -VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject, - PIRP Irp); - -PVOID VfatGetUserBuffer(IN PIRP); - -NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG, - IN LOCK_OPERATION); - -NTSTATUS -VfatSetExtendedAttributes(PFILE_OBJECT FileObject, - PVOID Ea, - ULONG EaLength); -/* ------------------------------------------------------------- flush.c */ - -NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext); - -NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb); - - -/* EOF */ +/* $Id: vfat.h 16656 2005-07-20 02:52:52Z ion $ */ + +#include +#include +#include +#include +#include +#include +#include + +#define USE_ROS_CC_AND_FS + +#include +struct _BootSector +{ + unsigned char magic0, res0, magic1; + unsigned char OEMName[8]; + unsigned short BytesPerSector; + unsigned char SectorsPerCluster; + unsigned short ReservedSectors; + unsigned char FATCount; + unsigned short RootEntries, Sectors; + unsigned char Media; + unsigned short FATSectors, SectorsPerTrack, Heads; + unsigned long HiddenSectors, SectorsHuge; + unsigned char Drive, Res1, Sig; + unsigned long VolumeID; + unsigned char VolumeLabel[11], SysType[8]; + unsigned char Res2[448]; + unsigned short Signatur1; +}; + +struct _BootSector32 +{ + unsigned char magic0, res0, magic1; // 0 + unsigned char OEMName[8]; // 3 + unsigned short BytesPerSector; // 11 + unsigned char SectorsPerCluster; // 13 + unsigned short ReservedSectors; // 14 + unsigned char FATCount; // 16 + unsigned short RootEntries, Sectors; // 17 + unsigned char Media; // 21 + unsigned short FATSectors, SectorsPerTrack, Heads; // 22 + unsigned long HiddenSectors, SectorsHuge; // 28 + unsigned long FATSectors32; // 36 + unsigned short ExtFlag; // 40 + unsigned short FSVersion; // 42 + unsigned long RootCluster; // 44 + unsigned short FSInfoSector; // 48 + unsigned short BootBackup; // 50 + unsigned char Res3[12]; // 52 + unsigned char Drive; // 64 + unsigned char Res4; // 65 + unsigned char ExtBootSignature; // 66 + unsigned long VolumeID; // 67 + unsigned char VolumeLabel[11], SysType[8]; // 71 + unsigned char Res2[420]; // 90 + unsigned short Signature1; // 510 +}; + +struct _BootSectorFatX +{ + unsigned char SysType[4]; // 0 + unsigned long VolumeID; // 4 + unsigned long SectorsPerCluster; // 8 + unsigned short FATCount; // 12 + unsigned long Unknown; // 14 + unsigned char Unused[4078]; // 18 +}; + +struct _FsInfoSector +{ + unsigned long ExtBootSignature2; // 0 + unsigned char Res6[480]; // 4 + unsigned long FSINFOSignature; // 484 + unsigned long FreeCluster; // 488 + unsigned long NextCluster; // 492 + unsigned char Res7[12]; // 496 + unsigned long Signatur2; // 508 +}; + +typedef struct _BootSector BootSector; + +struct _FATDirEntry +{ + union + { + struct { unsigned char Filename[8], Ext[3]; }; + unsigned char ShortName[11]; + }; + unsigned char Attrib; + unsigned char lCase; + unsigned char CreationTimeMs; + unsigned short CreationTime,CreationDate,AccessDate; + unsigned short FirstClusterHigh; // higher + unsigned short UpdateTime; //time create/update + unsigned short UpdateDate; //date create/update + unsigned short FirstCluster; + unsigned long FileSize; +}; + +typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY; + +struct _FATXDirEntry +{ + unsigned char FilenameLength; // 0 + unsigned char Attrib; // 1 + unsigned char Filename[42]; // 2 + unsigned long FirstCluster; // 44 + unsigned long FileSize; // 48 + unsigned short UpdateTime; // 52 + unsigned short UpdateDate; // 54 + unsigned short CreationTime; // 56 + unsigned short CreationDate; // 58 + unsigned short AccessTime; // 60 + unsigned short AccessDate; // 62 +}; + +struct _slot +{ + unsigned char id; // sequence number for slot + WCHAR name0_4[5]; // first 5 characters in name + unsigned char attr; // attribute byte + unsigned char reserved; // always 0 + unsigned char alias_checksum; // checksum for 8.3 alias + WCHAR name5_10[6]; // 6 more characters in name + unsigned char start[2]; // starting cluster number + WCHAR name11_12[2]; // last 2 characters in name +}; + +typedef struct _slot slot; + +#include + +#define VFAT_CASE_LOWER_BASE 8 // base is lower case +#define VFAT_CASE_LOWER_EXT 16 // extension is lower case + +#define LONGNAME_MAX_LENGTH 256 // max length for a long filename + +#define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat))) +#define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat))) +#define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat))) + +#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5) +#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0) +#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f) +#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) + +#define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5) +#define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff) +#define FATX_ENTRY_LONG(DirEntry) (FALSE) +#define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08) + +#define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY)) +#define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY)) + +typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY; + +union _DIR_ENTRY +{ + FAT_DIR_ENTRY Fat; + FATX_DIR_ENTRY FatX; +}; + +typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY; + +#define BLOCKSIZE 512 + +#define FAT16 (1) +#define FAT12 (2) +#define FAT32 (3) +#define FATX16 (4) +#define FATX32 (5) + +#define VCB_VOLUME_LOCKED 0x0001 +#define VCB_DISMOUNT_PENDING 0x0002 +#define VCB_IS_FATX 0x0004 +#define VCB_IS_DIRTY 0x4000 /* Volume is dirty */ +#define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */ + +typedef struct +{ + ULONG VolumeID; + ULONG FATStart; + ULONG FATCount; + ULONG FATSectors; + ULONG rootDirectorySectors; + ULONG rootStart; + ULONG dataStart; + ULONG RootCluster; + ULONG SectorsPerCluster; + ULONG BytesPerSector; + ULONG BytesPerCluster; + ULONG NumberOfClusters; + ULONG FatType; + ULONG Sectors; + BOOLEAN FixedMedia; +} FATINFO, *PFATINFO; + +struct _VFATFCB; +struct _VFAT_DIRENTRY_CONTEXT; + +typedef struct _HASHENTRY +{ + ULONG Hash; + struct _VFATFCB* self; + struct _HASHENTRY* next; +} +HASHENTRY; + +#define FCB_HASH_TABLE_SIZE 65536 + +typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION; + +typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG); +typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG); +typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG); + +typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN); + +typedef struct DEVICE_EXTENSION +{ + ERESOURCE DirResource; + ERESOURCE FatResource; + + KSPIN_LOCK FcbListLock; + LIST_ENTRY FcbListHead; + ULONG HashTableSize; + struct _HASHENTRY** FcbHashTable; + + PDEVICE_OBJECT StorageDevice; + PFILE_OBJECT FATFileObject; + FATINFO FatInfo; + ULONG LastAvailableCluster; + ULONG AvailableClusters; + BOOLEAN AvailableClustersValid; + ULONG Flags; + struct _VFATFCB * VolumeFcb; + + /* Pointers to functions for manipulating FAT. */ + PGET_NEXT_CLUSTER GetNextCluster; + PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster; + PWRITE_CLUSTER WriteCluster; + ULONG CleanShutBitMask; + + /* Pointers to functions for manipulating directory entries. */ + PGET_NEXT_DIR_ENTRY GetNextDirEntry; + + ULONG BaseDateYear; + + LIST_ENTRY VolumeListEntry; +} DEVICE_EXTENSION, VCB, *PVCB; + +typedef struct +{ + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; + ERESOURCE VolumeListLock; + LIST_ENTRY VolumeListHead; + NPAGED_LOOKASIDE_LIST FcbLookasideList; + NPAGED_LOOKASIDE_LIST CcbLookasideList; + NPAGED_LOOKASIDE_LIST IrpContextLookasideList; + FAST_IO_DISPATCH FastIoDispatch; + CACHE_MANAGER_CALLBACKS CacheMgrCallbacks; +} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA; + +extern PVFAT_GLOBAL_DATA VfatGlobalData; + +#define FCB_CACHE_INITIALIZED 0x0001 +#define FCB_DELETE_PENDING 0x0002 +#define FCB_IS_FAT 0x0004 +#define FCB_IS_PAGE_FILE 0x0008 +#define FCB_IS_VOLUME 0x0010 +#define FCB_IS_DIRTY 0x0020 +#define FCB_IS_FATX_ENTRY 0x0040 + +typedef struct _VFATFCB +{ + /* FCB header required by ROS/NT */ + FSRTL_COMMON_FCB_HEADER RFCB; + SECTION_OBJECT_POINTERS SectionObjectPointers; + ERESOURCE MainResource; + ERESOURCE PagingIoResource; + /* end FCB header required by ROS/NT */ + + /* directory entry for this file or directory */ + DIR_ENTRY entry; + + /* Pointer to attributes in entry */ + PUCHAR Attributes; + + /* long file name, points into PathNameBuffer */ + UNICODE_STRING LongNameU; + + /* short file name */ + UNICODE_STRING ShortNameU; + + /* directory name, points into PathNameBuffer */ + UNICODE_STRING DirNameU; + + /* path + long file name 260 max*/ + UNICODE_STRING PathNameU; + + /* buffer for PathNameU */ + PWCHAR PathNameBuffer; + + /* buffer for ShortNameU */ + WCHAR ShortNameBuffer[13]; + + /* */ + LONG RefCount; + + /* List of FCB's for this volume */ + LIST_ENTRY FcbListEntry; + + /* pointer to the parent fcb */ + struct _VFATFCB* parentFcb; + + /* Flags for the fcb */ + ULONG Flags; + + /* pointer to the file object which has initialized the fcb */ + PFILE_OBJECT FileObject; + + /* Directory index for the short name entry */ + ULONG dirIndex; + + /* Directory index where the long name starts */ + ULONG startIndex; + + /* Share access for the file object */ + SHARE_ACCESS FCBShareAccess; + + /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */ + ULONG OpenHandleCount; + + /* Entry into the hash table for the path + long name */ + HASHENTRY Hash; + + /* Entry into the hash table for the path + short name */ + HASHENTRY ShortHash; + + /* List of byte-range locks for this file */ + FILE_LOCK FileLock; + + /* + * Optimalization: caching of last read/write cluster+offset pair. Can't + * be in VFATCCB because it must be reset everytime the allocated clusters + * change. + */ + FAST_MUTEX LastMutex; + ULONG LastCluster; + ULONG LastOffset; +} VFATFCB, *PVFATFCB; + +typedef struct _VFATCCB +{ + LARGE_INTEGER CurrentByteOffset; + /* for DirectoryControl */ + ULONG Entry; + /* for DirectoryControl */ + UNICODE_STRING SearchPattern; +} VFATCCB, *PVFATCCB; + +#ifndef TAG +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) +#endif + +#define TAG_CCB TAG('V', 'C', 'C', 'B') +#define TAG_FCB TAG('V', 'F', 'C', 'B') +#define TAG_IRP TAG('V', 'I', 'R', 'P') + +#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry)) + +typedef struct __DOSTIME +{ + USHORT Second:5; + USHORT Minute:6; + USHORT Hour:5; +} +DOSTIME, *PDOSTIME; + +typedef struct __DOSDATE +{ + USHORT Day:5; + USHORT Month:4; + USHORT Year:5; +} +DOSDATE, *PDOSDATE; + +#define IRPCONTEXT_CANWAIT 0x0001 +#define IRPCONTEXT_PENDINGRETURNED 0x0002 + +typedef struct +{ + PIRP Irp; + PDEVICE_OBJECT DeviceObject; + PDEVICE_EXTENSION DeviceExt; + ULONG Flags; + WORK_QUEUE_ITEM WorkQueueItem; + PIO_STACK_LOCATION Stack; + UCHAR MajorFunction; + UCHAR MinorFunction; + PFILE_OBJECT FileObject; + ULONG RefCount; + KEVENT Event; +} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; + +typedef struct _VFAT_DIRENTRY_CONTEXT +{ + ULONG StartIndex; + ULONG DirIndex; + DIR_ENTRY DirEntry; + UNICODE_STRING LongNameU; + UNICODE_STRING ShortNameU; +} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT; + + +/* ------------------------------------------------------ shutdown.c */ + +NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* -------------------------------------------------------- volume.c */ + +NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +/* ------------------------------------------------------ blockdev.c */ + +NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, + IN PLARGE_INTEGER ReadOffset, + IN ULONG ReadLength, + IN PUCHAR Buffer, + IN BOOLEAN Override); + +NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext, + IN PLARGE_INTEGER ReadOffset, + IN ULONG ReadLength, + IN ULONG BufferOffset, + IN BOOLEAN Wait); + +NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext, + IN PLARGE_INTEGER WriteOffset, + IN ULONG WriteLength, + IN ULONG BufferOffset, + IN BOOLEAN Wait); + +NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize, + IN BOOLEAN Override); + +/* ----------------------------------------------------------- dir.c */ + +NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT); + +BOOLEAN FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, + USHORT DosDate, + USHORT DosTime, + PLARGE_INTEGER SystemTime); + +BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER SystemTime, + USHORT *pDosDate, + USHORT *pDosTime); + +/* -------------------------------------------------------- create.c */ + +NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVFATFCB* parentFcb); + +NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt, + PVFATFCB Parent, + PUNICODE_STRING FileToFindU, + PVFAT_DIRENTRY_CONTEXT DirContext, + BOOLEAN First); + +VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, + PUNICODE_STRING NameU); + +NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, + PVPB Vpb); + +/* --------------------------------------------------------- close.c */ + +NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject); + +/* ------------------------------------------------------- cleanup.c */ + +NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- fastio.c */ + +VOID +VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch); + +BOOLEAN NTAPI +VfatAcquireForLazyWrite(IN PVOID Context, + IN BOOLEAN Wait); + +VOID NTAPI +VfatReleaseFromLazyWrite(IN PVOID Context); + +BOOLEAN NTAPI +VfatAcquireForReadAhead(IN PVOID Context, + IN BOOLEAN Wait); + +VOID NTAPI +VfatReleaseFromReadAhead(IN PVOID Context); + +/* --------------------------------------------------------- fsctl.c */ + +NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- finfo.c */ + +NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS +VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, + PVFATFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER AllocationSize); + +/* --------------------------------------------------------- iface.c */ + +NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath); + +/* --------------------------------------------------------- dirwr.c */ + +NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt, + PUNICODE_STRING PathNameU, + PVFATFCB* Fcb, + PVFATFCB ParentFcb, + ULONG RequestedOptions, + UCHAR ReqAttr); + +NTSTATUS VfatUpdateEntry (PVFATFCB pFcb); + +NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB); + +BOOLEAN +vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, + PVFATFCB pDirFcb, + ULONG nbSlots, + PULONG start); + +/* -------------------------------------------------------- string.c */ + +VOID +vfatSplitPathName(PUNICODE_STRING PathNameU, + PUNICODE_STRING DirNameU, + PUNICODE_STRING FileNameU); + +BOOLEAN vfatIsLongIllegal(WCHAR c); + +BOOLEAN wstrcmpjoki (PWSTR s1, + PWSTR s2); + +/* ----------------------------------------------------------- fat.c */ + +NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, + PULONG Cluster); + +NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue); + +NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, + PULONG Cluster); + +NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue); + +NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, + PULONG Cluster); + +NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue); + +NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, + ULONG FirstCluster, + ULONG FileOffset, + PULONG Cluster, + BOOLEAN Extend); + +ULONGLONG ClusterToSector (PDEVICE_EXTENSION DeviceExt, + ULONG Cluster); + +NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS GetNextClusterExtend (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster); + +NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER Clusters); + +NTSTATUS +WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue); + +/* ------------------------------------------------------ direntry.c */ + +ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, + PDIR_ENTRY pDirEntry); + +BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb); + +NTSTATUS FATGetNextDirEntry(PVOID * pContext, + PVOID * pPage, + IN PVFATFCB pDirFcb, + IN PVFAT_DIRENTRY_CONTEXT DirContext, + BOOLEAN First); + +NTSTATUS FATXGetNextDirEntry(PVOID * pContext, + PVOID * pPage, + IN PVFATFCB pDirFcb, + IN PVFAT_DIRENTRY_CONTEXT DirContext, + BOOLEAN First); + +/* ----------------------------------------------------------- fcb.c */ + +PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB, + PUNICODE_STRING pFileNameU); + +VOID vfatDestroyFCB (PVFATFCB pFCB); + +VOID vfatDestroyCCB(PVFATCCB pCcb); + +VOID vfatGrabFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatReleaseFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, + PUNICODE_STRING pFileNameU); + +PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); + +PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); + +BOOLEAN vfatFCBIsDirectory (PVFATFCB FCB); + +BOOLEAN vfatFCBIsRoot(PVFATFCB FCB); + +NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, + PVFATFCB fcb, + PFILE_OBJECT fileObject); + +NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, + PVFATFCB parentFCB, + PUNICODE_STRING FileToFindU, + PVFATFCB * fileFCB); + +NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, + PVFATFCB *pParentFCB, + PVFATFCB *pFCB, + PUNICODE_STRING pFileNameU); + +NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb, + PVFATFCB directoryFCB, + PVFAT_DIRENTRY_CONTEXT DirContext, + PVFATFCB * fileFCB); + +/* ------------------------------------------------------------ rw.c */ + +NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG FirstCluster, + PULONG CurrentCluster, + BOOLEAN Extend); + +/* ----------------------------------------------------------- misc.c */ + +NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext); + +PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +PVOID VfatGetUserBuffer(IN PIRP); + +NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG, + IN LOCK_OPERATION); + +NTSTATUS +VfatSetExtendedAttributes(PFILE_OBJECT FileObject, + PVOID Ea, + ULONG EaLength); +/* ------------------------------------------------------------- flush.c */ + +NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb); + + +/* EOF */