Adding support for limited-memory embedded systems.

This patch reorganizes heap memory usage by dosfsck and mkdosfs
to support limited-memory embedded systems - in particular, those
based on Xilinx's Microblaze processor. It also adds a few comments.

Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
This commit is contained in:
Steven J. Magnani 2009-05-18 15:01:49 +02:00 committed by Daniel Baumann
parent 89f0b727b5
commit ff1b24e91d
9 changed files with 304 additions and 67 deletions

View File

@ -57,7 +57,8 @@ static struct {
{ 0xff, "5.25\" 320k floppy 2s/40tr/8sec" },
};
#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__ || defined __bfin__
#if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ \
|| defined __ppc64__ || defined __bfin__ || defined __MICROBLAZE__
/* Unaligned fields must first be copied byte-wise */
#define GET_UNALIGNED_W(f) \
({ \
@ -300,6 +301,14 @@ void read_boot(DOS_FS *fs)
fs_read(0,sizeof(b),&b);
logical_sector_size = GET_UNALIGNED_W(b.sector_size);
if (!logical_sector_size) die("Logical sector size is zero.");
/* This was moved up because it's the first thing that will fail */
/* if the platform needs special handling of unaligned multibyte accesses */
/* but such handling isn't being provided. See GET_UNALIGNED_W() above. */
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);
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)

View File

@ -111,8 +111,11 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
if (!prev)
die("Root directory has no cluster allocated!");
for (clu_num = prev+1; clu_num != prev; clu_num++) {
FAT_ENTRY entry;
if (clu_num >= fs->clusters+2) clu_num = 2;
if (!fs->fat[clu_num].value)
get_fat(&entry, fs->fat, clu_num, fs);
if (!entry.value)
break;
}
if (clu_num == prev)
@ -183,15 +186,27 @@ loff_t alloc_rootdir_entry(DOS_FS *fs, DIR_ENT *de, const char *pattern)
}
/**
* Construct a full path (starting with '/') for the specified dentry,
* relative to the partition. All components are "long" names where possible.
*
* @param[in] file Information about dentry (file or directory) of interest
*
* return Pointer to static string containing file's full path
*/
static char *path_name(DOS_FILE *file)
{
static char path[PATH_MAX*2];
if (!file) *path = 0;
if (!file) *path = 0; /* Reached the root directory */
else {
if (strlen(path_name(file->parent)) > PATH_MAX)
die("Path name too long.");
if (strcmp(path,"/") != 0) strcat(path,"/");
/* Append the long name to the path,
* or the short name if there isn't a long one
*/
strcpy(strrchr(path,0),file->lfn?file->lfn:file_name(file->dir_ent.name));
}
return path;
@ -461,9 +476,12 @@ static int check_file(DOS_FS *fs,DOS_FILE *file)
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)) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, curr, fs);
if (!curEntry.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);
path_name(file), curEntry.value ? "bad" : "free",curr);
if (prev) set_fat(fs,prev,-1);
else if (!file->offset)
die( "FAT32 root dir starts with a bad cluster!" );
@ -690,6 +708,15 @@ static int check_dir(DOS_FS *fs,DOS_FILE **root,int dots)
}
/**
* Check a dentry's cluster chain for bad clusters.
* If requested, we verify readability and mark unreadable clusters as bad.
*
* @param[inout] fs Information about the filesystem
* @param[in] file dentry to check
* @param[in] read_test Nonzero == verify that dentry's clusters can
* be read
*/
static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test)
{
DOS_FILE *owner;
@ -699,6 +726,11 @@ static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test)
for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2;
walk = next_clu) {
next_clu = next_cluster(fs,walk);
/* In this stage we are checking only for a loop within our own
* cluster chain.
* Cross-linking of clusters is handled in check_file()
*/
if ((owner = get_owner(fs,walk))) {
if (owner == file) {
printf("%s\n Circular cluster chain. Truncating to %lu "
@ -727,6 +759,7 @@ static void test_file(DOS_FS *fs,DOS_FILE *file,int read_test)
}
set_owner(fs,walk,file);
}
/* Revert ownership (for now) */
for (walk = FSTART(file,fs); walk > 0 && walk < fs->clusters+2;
walk = next_cluster(fs,walk))
if (bad_cluster(fs,walk)) break;
@ -742,11 +775,21 @@ static void undelete(DOS_FS *fs,DOS_FILE *file)
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++) {
walk = FSTART(file,fs);
while (left && (walk >= 2) && (walk < fs->clusters+2)) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, walk, fs);
if (!curEntry.value)
break;
left--;
if (prev) set_fat(fs,prev,walk);
prev = walk;
walk++;
}
if (prev) set_fat(fs,prev,-1);
else MODIFY_START(file,0,fs);
@ -763,6 +806,19 @@ static void new_dir( void )
}
/**
* Create a description for a referenced dentry and insert it in our dentry
* tree. Then, go check the dentry's cluster chain for bad clusters and
* cluster loops.
*
* @param[inout] fs Information about the filesystem
* @param[out] chain
* @param[in] parent Information about parent directory of this file
* NULL == no parent ('file' is root directory)
* @param[in] offset Partition-relative byte offset of directory entry of interest
* 0 == Root directory
* @param cp
*/
static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent,
loff_t offset,FDSC **cp)
{
@ -773,6 +829,7 @@ static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent,
if (offset)
fs_read(offset,sizeof(DIR_ENT),&de);
else {
/* Construct a DIR_ENT for the root directory */
memcpy(de.name," ",MSDOS_NAME);
de.attr = ATTR_DIR;
de.size = de.time = de.date = 0;
@ -805,14 +862,15 @@ static void add_file(DOS_FS *fs,DOS_FILE ***chain,DOS_FILE *parent,
if (list) {
printf("Checking file %s",path_name(new));
if (new->lfn)
printf(" (%s)", file_name(new->dir_ent.name) );
printf(" (%s)", file_name(new->dir_ent.name) ); /* (8.3) */
printf("\n");
}
/* Don't include root directory, '.', or '..' in the total file count */
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);
test_file(fs,new,test); /* Bad cluster check */
}
@ -844,6 +902,16 @@ static int scan_dir(DOS_FS *fs,DOS_FILE *this,FDSC **cp)
}
/**
* Recursively scan subdirectories of the specified parent directory.
*
* @param[inout] fs Information about the filesystem
* @param[in] parent Identifies the directory to scan
* @param[in] cp
*
* @return 0 Success
* @return 1 Error
*/
static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp)
{
DOS_FILE *walk;
@ -857,6 +925,14 @@ static int subdirs(DOS_FS *fs,DOS_FILE *parent,FDSC **cp)
}
/**
* Scan all directory and file information for errors.
*
* @param[inout] fs Information about the filesystem
*
* @return 0 Success
* @return 1 Error
*/
int scan_root(DOS_FS *fs)
{
DOS_FILE **chain;

View File

@ -106,6 +106,7 @@ int main(int argc,char **argv)
unsigned n_files_check=0, n_files_verify=0;
unsigned long free_clusters;
memset(&fs, 0, sizeof(fs));
rw = salvage_files = verify = 0;
interactive = 1;
check_atari();

View File

@ -163,8 +163,6 @@ typedef struct _dos_file {
typedef struct {
unsigned long value;
unsigned long reserved;
DOS_FILE *owner;
int prev; /* number of previous clusters */
} FAT_ENTRY;
typedef struct {
@ -182,7 +180,8 @@ typedef struct {
loff_t fsinfo_start; /* 0 if not present */
long free_clusters;
loff_t backupboot_start; /* 0 if not present */
FAT_ENTRY *fat;
unsigned char *fat;
DOS_FILE **cluster_owner;
char *label;
} DOS_FS;

216
src/fat.c
View File

@ -36,7 +36,15 @@
#include "fat.h"
static void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs)
/**
* Fetch the FAT entry for a specified cluster.
*
* @param[out] entry Cluster to which cluster of interest is linked
* @param[in] fat FAT table for the partition
* @param[in] cluster Cluster of interest
* @param[in] fs Information from the FAT boot sectors (bits per FAT entry)
*/
void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs)
{
unsigned char *ptr;
@ -61,18 +69,33 @@ static void get_fat(FAT_ENTRY *entry,void *fat,unsigned long cluster,DOS_FS *fs)
default:
die("Bad FAT entry size: %d bits.",fs->fat_bits);
}
entry->owner = NULL;
}
/**
* Build a bookkeeping structure from the partition's FAT table.
* If the partition has multiple FATs and they don't agree, try to pick a winner,
* and queue a command to overwrite the loser.
* One error that is fixed here is a cluster that links to something out of range.
*
* @param[inout] fs Information about the filesystem
*/
void read_fat(DOS_FS *fs)
{
int eff_size;
unsigned long i;
void *first,*second = NULL;
int first_ok,second_ok;
unsigned long total_num_clusters;
eff_size = ((fs->clusters+2ULL)*fs->fat_bits+7)/8ULL;
/* Clean up from previous pass */
free(fs->fat);
free(fs->cluster_owner);
fs->fat = NULL;
fs->cluster_owner = NULL;
total_num_clusters = fs->clusters + 2UL;
eff_size = (total_num_clusters*fs->fat_bits+7)/8ULL;
first = alloc(eff_size);
fs_read(fs->fat_start,eff_size,first);
if (fs->nfats > 1) {
@ -119,22 +142,37 @@ void read_fat(DOS_FS *fs)
if (second) {
free(second);
}
fs->fat = qalloc(&mem_queue,sizeof(FAT_ENTRY)*(fs->clusters+2ULL));
for (i = 2; i < fs->clusters+2; i++) get_fat(&fs->fat[i],first,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))) {
fs->fat = (unsigned char*) first;
fs->cluster_owner = alloc(total_num_clusters * sizeof(DOS_FILE *));
memset(fs->cluster_owner, 0, (total_num_clusters * sizeof(DOS_FILE *)));
/* Truncate any cluster chains that link to something out of range */
for (i = 2; i < fs->clusters+2; i++) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs);
if (curEntry.value >= fs->clusters+2 &&
(curEntry.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);
i-2, curEntry.value, fs->clusters+2-1);
set_fat(fs,i,-1);
}
free(first);
}
}
/**
* Update the FAT entry for a specified cluster
* (i.e., change the cluster it links to).
* Queue a command to write out this change.
*
* @param[in,out] fs Information about the filesystem
* @param[in] cluster Cluster to change
* @param[in] new Cluster to link to
*/
void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new)
{
unsigned char data[4];
unsigned char *data = NULL;
int size;
loff_t offs;
@ -144,53 +182,80 @@ void set_fat(DOS_FS *fs,unsigned long cluster,unsigned long new)
new = FAT_BAD(fs);
switch( fs->fat_bits ) {
case 12:
data = fs->fat + cluster*3/2;
offs = fs->fat_start+cluster*3/2;
if (cluster & 1) {
data[0] = ((new & 0xf) << 4) | (fs->fat[cluster-1].value >> 8);
FAT_ENTRY prevEntry;
get_fat(&prevEntry, fs->fat, cluster-1, fs);
data[0] = ((new & 0xf) << 4) | (prevEntry.value >> 8);
data[1] = new >> 4;
}
else {
FAT_ENTRY subseqEntry;
get_fat(&subseqEntry, fs->fat, cluster+1, fs);
data[0] = new & 0xff;
data[1] = (new >> 8) | (cluster == fs->clusters-1 ? 0 :
(0xff & fs->fat[cluster+1].value) << 4);
(0xff & subseqEntry.value) << 4);
}
size = 2;
break;
case 16:
data = fs->fat + cluster*2;
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;
{
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, cluster, fs);
data = fs->fat + cluster*4;
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) |
(curEntry.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,size,data);
if (fs->nfats > 1) {
fs_write(offs+fs->fat_size,size,&data);
fs_write(offs+fs->fat_size,size,data);
}
}
int bad_cluster(DOS_FS *fs,unsigned long cluster)
{
return FAT_IS_BAD(fs,fs->fat[cluster].value);
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, cluster, fs);
return FAT_IS_BAD(fs, curEntry.value);
}
/**
* Get the cluster to which the specified cluster is linked.
* If the linked cluster is marked bad, abort.
*
* @param[in] fs Information about the filesystem
* @param[in] cluster Cluster to follow
*
* @return -1 'cluster' is at the end of the chain
* @return Other values Next cluster in this chain
*/
unsigned long next_cluster(DOS_FS *fs,unsigned long cluster)
{
unsigned long value;
FAT_ENTRY curEntry;
value = fs->fat[cluster].value;
get_fat(&curEntry, fs->fat, cluster, fs);
value = curEntry.value;
if (FAT_IS_BAD(fs,value))
die("Internal error: next_cluster on bad cluster");
return FAT_IS_EOF(fs,value) ? -1 : value;
@ -203,17 +268,32 @@ loff_t cluster_start(DOS_FS *fs,unsigned long cluster)
}
/**
* Update internal bookkeeping to show that the specified cluster belongs
* to the specified dentry.
*
* @param[in,out] fs Information about the filesystem
* @param[in] cluster Cluster being assigned
* @param[in] owner Information on dentry that owns this cluster
* (may be NULL)
*/
void set_owner(DOS_FS *fs,unsigned long cluster,DOS_FILE *owner)
{
if (owner && fs->fat[cluster].owner)
if (fs->cluster_owner == NULL)
die("Internal error: attempt to set owner in non-existent table");
if (owner && fs->cluster_owner[cluster] && (fs->cluster_owner[cluster] != owner))
die("Internal error: attempt to change file owner");
fs->fat[cluster].owner = owner;
fs->cluster_owner[cluster] = owner;
}
DOS_FILE *get_owner(DOS_FS *fs,unsigned long cluster)
{
return fs->fat[cluster].owner;
if (fs->cluster_owner == NULL)
return NULL;
else
return fs->cluster_owner[cluster];
}
@ -223,12 +303,16 @@ void fix_bad(DOS_FS *fs)
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))
for (i = 2; i < fs->clusters+2; i++) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs);
if (!get_owner(fs,i) && !FAT_IS_BAD(fs, curEntry.value))
if (!fs_test(cluster_start(fs,i),fs->cluster_size)) {
printf("Cluster %lu is unreadable.\n",i);
set_fat(fs,i,-2);
}
}
}
@ -240,27 +324,35 @@ void reclaim_free(DOS_FS *fs)
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)) {
for (i = 2; i < fs->clusters+2; i++) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs);
if (!get_owner(fs,i) && curEntry.value &&
!FAT_IS_BAD(fs, curEntry.value)) {
set_fat(fs,i,0);
reclaimed++;
}
}
if (reclaimed)
printf("Reclaimed %d unused cluster%s (%llu bytes).\n",reclaimed,
reclaimed == 1 ? "" : "s",(unsigned long long)reclaimed*fs->cluster_size);
}
static void tag_free(DOS_FS *fs,DOS_FILE *ptr)
static void tag_free(DOS_FS *fs,DOS_FILE *ptr,
const unsigned long *prev_cluster)
{
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) {
for (i = 2; i < fs->clusters+2; i++) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs);
if (curEntry.value && !FAT_IS_BAD(fs, curEntry.value) &&
!get_owner(fs,i) && !prev_cluster[i]) {
prev = 0;
for (walk = i; walk > 0 && walk != -1;
walk = next_cluster(fs,walk)) {
@ -274,6 +366,7 @@ static void tag_free(DOS_FS *fs,DOS_FILE *ptr)
prev = walk;
}
}
}
}
@ -282,36 +375,53 @@ void reclaim_file(DOS_FS *fs)
DOS_FILE dummy;
int reclaimed,files,changed;
unsigned long i,next,walk;
unsigned long *prev_cluster = NULL;
unsigned long total_num_clusters;
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;
total_num_clusters = fs->clusters + 2UL;
prev_cluster = alloc(total_num_clusters * sizeof(unsigned long));
memset(prev_cluster, 0, (total_num_clusters * sizeof(unsigned long)));
for (i = 2; i < total_num_clusters; i++) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs);
next = curEntry.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++;
FAT_ENTRY nextEntry;
get_fat(&nextEntry, fs->fat, next, fs);
if (get_owner(fs,next) || !nextEntry.value ||
FAT_IS_BAD(fs, nextEntry.value)) set_fat(fs,i,-1);
else
prev_cluster[next]++;
}
}
do {
tag_free(fs,&dummy);
tag_free(fs,&dummy, prev_cluster);
changed = 0;
for (i = 2; i < fs->clusters+2; i++)
if (fs->fat[i].value && !FAT_IS_BAD(fs,fs->fat[i].value) &&
for (i = 2; i < total_num_clusters; i++) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs);
if (curEntry.value && !FAT_IS_BAD(fs, curEntry.value) &&
!get_owner(fs, i)) {
if (!fs->fat[fs->fat[i].value].prev--)
if (!prev_cluster[curEntry.value]--)
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) {
for (i = 2; i < total_num_clusters; i++)
if (get_owner(fs,i) == &dummy && !prev_cluster[i]) {
DIR_ENT de;
loff_t offset;
files++;
@ -330,6 +440,8 @@ void reclaim_file(DOS_FS *fs)
printf("Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n",
reclaimed,reclaimed == 1 ? "" : "s",(unsigned long long)reclaimed*fs->cluster_size,files,
files == 1 ? "" : "s");
free(prev_cluster);
}
@ -339,9 +451,13 @@ unsigned long update_free(DOS_FS *fs)
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))
for (i = 2; i < fs->clusters+2; i++) {
FAT_ENTRY curEntry;
get_fat(&curEntry, fs->fat, i, fs);
if (!get_owner(fs,i) && !FAT_IS_BAD(fs, curEntry.value))
++free;
}
if (!fs->fsinfo_start)
return free;

View File

@ -28,6 +28,10 @@ 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 get_fat(FAT_ENTRY *entry, void *fat, unsigned long cluster, DOS_FS *fs);
/* Retrieve the FAT entry (next chained cluster) for CLUSTER. */
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

View File

@ -57,6 +57,14 @@ static void put_char(char **p,unsigned char c)
}
/**
* Construct the "pretty-printed" representation of the name in a short directory entry.
*
* @param[in] fixed Pointer to name[0] of a DIR_ENT
*
* @return Pointer to static string containing pretty "8.3" equivalent of the
* name in the directory entry.
*/
char *file_name(unsigned char *fixed)
{
static char path[MSDOS_NAME*4+2];
@ -204,6 +212,8 @@ static FDSC **file_find(FDSC **dir,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. */
FD_TYPE file_type(FDSC **curr,char *fixed)
{
FDSC **this;

View File

@ -103,6 +103,15 @@ void fs_open(char *path,int rw)
}
/**
* Read data from the partition, accounting for any pending updates that are
* queued for writing.
*
* @param[in] pos Byte offset, relative to the beginning of the partition,
* at which to read
* @param[in] size Number of bytes to read
* @param[out] data Where to put the data read
*/
void fs_read(loff_t pos,int size,void *data)
{
CHANGE *walk;

View File

@ -302,6 +302,7 @@ static struct msdos_boot_sector bs; /* Boot sector data */
static int start_data_sector; /* Sector number for the start of the data area */
static int start_data_block; /* Block number for the start of the data area */
static unsigned char *fat; /* File allocation table */
static unsigned alloced_fat_length; /* # of FAT sectors we can keep in memory */
static unsigned char *info_sector; /* FAT32 info sector */
static struct msdos_dir_entry *root_dir; /* Root directory */
static int size_root_dir; /* Size of the root directory in bytes */
@ -309,7 +310,7 @@ static int sectors_per_cluster = 0; /* Number of sectors per disk cluster */
static int root_dir_entries = 0; /* Number of root directory entries */
static char *blank_sector; /* Blank sector - all zeros */
static int hidden_sectors = 0; /* Number of hidden sectors */
static int malloc_entire_fat = FALSE; /* Whether we should malloc() the entire FAT or not */
/* Function prototype definitions */
@ -1219,10 +1220,15 @@ setup_tables (void)
/* Make the file allocation tables! */
if ((fat = (unsigned char *) malloc (fat_length * sector_size)) == NULL)
if (malloc_entire_fat)
alloced_fat_length = fat_length;
else
alloced_fat_length = 1;
if ((fat = (unsigned char *) malloc (alloced_fat_length * sector_size)) == NULL)
die ("unable to allocate space for FAT image in memory");
memset( fat, 0, fat_length * sector_size );
memset( fat, 0, alloced_fat_length * sector_size );
mark_FAT_cluster (0, 0xffffffff); /* Initial fat entries */
mark_FAT_cluster (1, 0xffffffff);
@ -1352,8 +1358,13 @@ write_tables (void)
}
/* seek to start of FATS and write them all */
seekto( reserved_sectors*sector_size, "first FAT" );
for (x = 1; x <= nr_fats; x++)
writebuf( fat, fat_length * sector_size, "FAT" );
for (x = 1; x <= nr_fats; x++) {
int y;
int blank_fat_length = fat_length - alloced_fat_length;
writebuf( fat, alloced_fat_length * sector_size, "FAT" );
for (y=0; y<blank_fat_length; y++)
writebuf( blank_sector, sector_size, "FAT" );
}
/* Write the root directory directly after the last FAT. This is the root
* dir area on FAT12/16, and the first cluster on FAT32. */
writebuf( (char *) root_dir, size_root_dir, "root directory" );
@ -1456,6 +1467,7 @@ main (int argc, char **argv)
case 'c': /* c : Check FS as we build it */
check = TRUE;
malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
break;
case 'C': /* C : Create a new file */
@ -1505,6 +1517,7 @@ main (int argc, char **argv)
case 'l': /* l : Bad block filename */
listfile = optarg;
malloc_entire_fat = TRUE; /* Need to be able to mark clusters bad */
break;
case 'm': /* m : Set boot message */