summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-04-24 00:04:29 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-04-24 00:04:29 +0000
commit401c6d8d9b8a410754a7ff7e18b317c6609e4111 (patch)
treed8b9b946df16162b884d86ee04d6b3025c9b035a
parent0dbf44e2661500eafae199c58405cdd13c41e0dd (diff)
downloadmkfatfs-401c6d8d9b8a410754a7ff7e18b317c6609e4111.tar.gz
mkfatfs-401c6d8d9b8a410754a7ff7e18b317c6609e4111.tar.xz
mkfatfs-401c6d8d9b8a410754a7ff7e18b317c6609e4111.zip
Make the math actually work. Generate a FAT image that at least
has the right things in the right places.
-rw-r--r--fatdata.h1
-rw-r--r--genfat.c53
-rw-r--r--main.c11
-rw-r--r--main.h8
-rw-r--r--writechain.c10
-rw-r--r--writedir.c34
-rw-r--r--writefile.c32
-rw-r--r--writefs.c27
-rw-r--r--xmalloc.c9
-rw-r--r--xmalloc.h1
-rw-r--r--xstdio.c8
-rw-r--r--xstdio.h2
12 files changed, 103 insertions, 93 deletions
diff --git a/fatdata.h b/fatdata.h
index b6bf511..9048c66 100644
--- a/fatdata.h
+++ b/fatdata.h
@@ -32,6 +32,7 @@ struct fatfsparm {
int nfats; /* Number of FATs */
int diskuse; /* FAT+data sectors */
int fattype; /* 12, 16 or 32 */
+ void *resv; /* Reserved sectors data (boot sector etc) */
void *fat; /* FAT map */
};
diff --git a/genfat.c b/genfat.c
index 5607d10..b2277d1 100644
--- a/genfat.c
+++ b/genfat.c
@@ -38,26 +38,15 @@ setfat12ent(unsigned char *fat, unsigned int entry, unsigned int val)
}
}
-static void *
-genfat12(struct direntry *chain, int clusters, int secshift)
+static void
+genfat12(struct direntry *chain, struct fatfsparm *parm)
{
+ unsigned int fat_size;
unsigned char *fat;
- unsigned int fat_size, rest;
- unsigned int secsize = 1U << secshift;
int i, n;
- if ( clusters & 1 )
- clusters++; /* Avoid odd-sized FATs */
-
- fat_size = clusters + (clusters >> 1);
- rest = fat_size & (secsize - 1);
- if ( rest ) {
- /* Round up to the nearest sector */
- fat_size = fat_size - rest + secsize;
- }
-
- fat = xmalloc(fat_size);
- memset(fat, 0, fat_size);
+ fat_size = parm->fatsects << parm->sectorshift;
+ parm->fat = fat = xzalloc(fat_size);
/* FIX: set FAT entries 0 and 1 */
@@ -72,8 +61,6 @@ genfat12(struct direntry *chain, int clusters, int secshift)
chain = chain->nextbyclust;
}
-
- return fat;
}
static inline void
@@ -82,23 +69,15 @@ setfat16ent(le16_t *fat, unsigned int entry, unsigned int val)
write16(&fat[entry], val);
}
-static void *
-genfat16(struct direntry *chain, int clusters, int secshift)
+static void
+genfat16(struct direntry *chain, struct fatfsparm *parm)
{
+ unsigned int fat_size;
le16_t *fat;
- unsigned int fat_size, rest;
- unsigned int secsize = 1U << secshift;
int i, n;
- fat_size = clusters << 1;
- rest = fat_size & (secsize - 1);
- if ( rest ) {
- /* Round up to the nearest sector */
- fat_size = fat_size - rest + secsize;
- }
-
- fat = xmalloc(fat_size);
- memset(fat, 0, fat_size);
+ fat_size = parm->fatsects << parm->sectorshift;
+ parm->fat = fat = xzalloc(fat_size);
/* FIX: set FAT entries 0 and 1 */
@@ -113,21 +92,21 @@ genfat16(struct direntry *chain, int clusters, int secshift)
chain = chain->nextbyclust;
}
-
- return fat;
}
-void *
+void
genfat(struct direntry *allocchain, struct fatfsparm *parm)
{
switch ( parm->fattype ) {
case 12:
- return genfat12(allocchain, parm->clusters, parm->sectorshift);
+ genfat12(allocchain, parm);
+ break;
case 16:
- return genfat16(allocchain, parm->clusters, parm->sectorshift);
+ genfat16(allocchain, parm);
+ break;
default:
assert(0); /* Unknown FAT type */
- return NULL;
+ break;
}
}
diff --git a/main.c b/main.c
index 77db2b5..767c5fb 100644
--- a/main.c
+++ b/main.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "dirtree.h"
+#include "xmalloc.h"
#include "main.h"
const char *program;
@@ -31,21 +32,25 @@ int main(int argc, char *argv[])
int cluster = 2; /* 2 is the first cluster */
int rootdirsize;
struct fatfsparm fsparm;
- void *fat;
program = argv[0];
memset(&fsparm, 0, sizeof fsparm);
- fsparm.sectors = 200000;
+ fsparm.resvsects = 1; /* Should be 10 for FAT32 */
+ fsparm.sectors = 80000;
fsparm.rootdirsects = 224/(512/32);
fsparm.sectorshift = 9;
fsparm.nfats = 2;
getclustsize(&fsparm, 9);
+ fsparm.resv = xzalloc(fsparm.resvsects << fsparm.sectorshift);
+
tree = make_dir_tree(argv[1], &rootdirsize, NULL);
alloc_space(tree, &cluster, fsparm.clustshift, &allocchain);
- fat = genfat(allocchain, &fsparm);
+ genfat(allocchain, &fsparm);
+
+ writefs(stdout, tree, allocchain, &fsparm);
return 0;
}
diff --git a/main.h b/main.h
index 2710f45..ee8db4e 100644
--- a/main.h
+++ b/main.h
@@ -27,7 +27,7 @@ extern const char *program; /* Program name (for errors) */
void
alloc_space(struct direntry *, int *, int, struct direntry **);
-void *
+void
genfat(struct direntry *allocchain, struct fatfsparm *fsparm);
void
@@ -35,12 +35,16 @@ getclustsize(struct fatfsparm *parm,
unsigned int minclustshift);
void
-writerootdir(FILE *, struct direntry *, int);
+writerootdir(FILE *, struct direntry *, struct fatfsparm *);
void
writesubdir(FILE *, struct direntry *, int);
void
writefile(FILE *, struct direntry *, int);
void
+writefs(FILE *f, struct direntry *rootp, struct direntry *allocchain,
+ struct fatfsparm *parm);
+
+void
writeallocchain(FILE *f, struct direntry *dirp,
int *firstcluster, int clustshift);
diff --git a/writechain.c b/writechain.c
index 9591600..5df9eaa 100644
--- a/writechain.c
+++ b/writechain.c
@@ -31,9 +31,19 @@ void
writeallocchain(FILE *f, struct direntry *dirp,
int *firstcluster, int clustshift)
{
+ static unsigned long basis = ~0;
+
/* Write out directories and files in on-disk order */
while ( dirp ) {
+ fprintf(stderr, "Writing %s at cluster %u, offset = %lx\n",
+ dirp->path, dirp->cluster, ftell(f));
assert(*firstcluster == dirp->cluster);
+ if ( dirp->cluster == 2 ) {
+ basis = ftell(f);
+ } else {
+ assert(((dirp->cluster - 2) << clustshift) == ftell(f) - basis);
+ }
+
if ( dirp->attribute & 0x10 ) {
/* Directory */
writesubdir(f, dirp, clustshift);
diff --git a/writedir.c b/writedir.c
index 50265b7..333c033 100644
--- a/writedir.c
+++ b/writedir.c
@@ -29,8 +29,9 @@ writesubdir(FILE *f, struct direntry *dirp, int clustshift)
{
struct direntry *p;
struct fat_dirent dent;
- unsigned int size;
+ unsigned int size, slop;
unsigned int clustsize = 1U << clustshift;
+ unsigned int dirsize = 0;
/* Write . */
memset(&dent, 0, 32);
@@ -39,7 +40,8 @@ writesubdir(FILE *f, struct direntry *dirp, int clustshift)
write16(&dent.firstclust, dirp->cluster);
size = (dirp->dirsize + 2) << 5;
write32(&dent.size, size);
- xfwrite(&dent, 32, 1, f);
+ xfwrite(&dent, 32, f);
+ dirsize += 32;
/* Write .. */
memset(&dent, 0, 32);
@@ -51,10 +53,11 @@ writesubdir(FILE *f, struct direntry *dirp, int clustshift)
size = (dirp->parent->dirsize + 2) << 5;
write32(&dent.size, size);
}
- xfwrite(&dent, 32, 1, f);
+ xfwrite(&dent, 32, f);
+ dirsize += 32;
for ( p = dirp->dir ; p ; p = p->next ) {
- memset(&dent, 0, 32);
+ memset(&dent, 0, 32);
memcpy(&dent.name, p->mangled_name, 11);
write16(&dent.firstclust, p->cluster);
if ( S_ISDIR(p->st.st_mode) ) {
@@ -64,37 +67,40 @@ writesubdir(FILE *f, struct direntry *dirp, int clustshift)
}
write32(&dent.size, size);
write8(&dent.attribute, p->attribute);
- xfwrite(&dent, 32, 1, f);
+ xfwrite(&dent, 32, f);
+ dirsize += 32;
}
/* Pad out the last cluster */
- size = (dirp->dirsize + 2) << 5;
- size &= (clustsize - 1);
- if ( size ) {
- xfwritezero(clustsize-size, f);
- }
+ slop = (dirsize & (clustsize-1));
+ if ( slop )
+ xfwritezero(clustsize-slop, f);
}
/* Write out the root directory to disk */
void
-writerootdir(FILE *f, struct direntry *dirp, int rootdirents)
+writerootdir(FILE *f, struct direntry *dirp, struct fatfsparm *parm)
{
struct direntry *p;
struct fat_dirent dent;
unsigned int size;
+ int rootdirents = parm->rootdirsects << (parm->sectorshift - 5);
+
+ fprintf(stderr, "Writing root directory (%u), offset = %lx\n",
+ parm->rootdirsects, ftell(f));
/* No . or .. in the root directory. Disk label or ldlinux.sys
should be added to the directory tree explicitly. */
- for ( p = dirp->dir ; p ; p = p->next ) {
+ for ( p = dirp ; p ; p = p->next ) {
if ( rootdirents <= 0 ) {
fprintf(stderr, "%s: Fatal error: root directory overflow\n",
program);
exit(EX_DATAERR);
}
- memset(&dent, 0, 32);
+ memset(&dent, 0, sizeof dent);
memcpy(&dent.name, p->mangled_name, 11);
write16(&dent.firstclust, p->cluster);
if ( S_ISDIR(p->st.st_mode) ) {
@@ -104,7 +110,7 @@ writerootdir(FILE *f, struct direntry *dirp, int rootdirents)
}
write32(&dent.size, size);
write8(&dent.attribute, p->attribute);
- xfwrite(&dent, 32, 1, f);
+ xfwrite(&dent, 32, f);
rootdirents--;
}
diff --git a/writefile.c b/writefile.c
index efd5736..a861e16 100644
--- a/writefile.c
+++ b/writefile.c
@@ -21,6 +21,7 @@
#include "xstdio.h"
#include "dirtree.h"
#include "main.h"
+#include "minmax.h"
#define BUFFER_SIZE 65536
@@ -43,13 +44,8 @@ writefile(FILE *f, struct direntry *dirp, int clustshift)
while ( bytestowrite &&
(bytesread = fread(buffer, 1, BUFFER_SIZE, src)) > 0 ) {
- if ( bytesread > bytestowrite )
- writebytes = bytestowrite;
- else
- writebytes = bytesread;
-
- xfwrite(buffer, 1, writebytes, f);
-
+ writebytes = min2(bytestowrite, bytesread);
+ xfwrite(buffer, writebytes, f);
bytestowrite -= writebytes;
}
@@ -60,28 +56,14 @@ writefile(FILE *f, struct direntry *dirp, int clustshift)
fclose(src);
} else {
- /* File data in core */
+ /* Synthesized file; contents in memory */
- if ( dirp->st.st_size > bytestowrite )
- writebytes = bytestowrite;
- else
- writebytes = dirp->st.st_size;
-
- xfwrite(dirp->data, 1, writebytes, f);
+ writebytes = min2(dirp->st.st_size, bytestowrite);
+ xfwrite(dirp->data, writebytes, f);
bytestowrite -= writebytes;
}
/* Fill the remaining cluster (hopefully only one) with zero */
- memset(buffer, 0, BUFFER_SIZE);
- while ( bytestowrite ) {
- if ( BUFFER_SIZE > bytestowrite )
- writebytes = bytestowrite;
- else
- writebytes = BUFFER_SIZE;
-
- xfwrite(buffer, 1, writebytes, f);
-
- bytestowrite -= writebytes;
- }
+ xfwritezero(bytestowrite, f);
}
diff --git a/writefs.c b/writefs.c
index 00e5319..bf58803 100644
--- a/writefs.c
+++ b/writefs.c
@@ -24,24 +24,37 @@
#include "main.h"
void
-writedirtree(FILE *f, struct direntry *rootp, struct direntry *allocchain,
- struct fatfsparm *parm)
+writefs(FILE *f, struct direntry *rootp, struct direntry *allocchain,
+ struct fatfsparm *parm)
{
int cluster = 2; /* 2 is the first cluster */
+ int i;
/* Write superblock */
+ fprintf(stderr, "Writing reserved (%u), offset = %lx\n",
+ parm->resvsects, ftell(f));
+ xfwrite(parm->resv, parm->resvsects << parm->sectorshift, f);
/* Write FATs */
+ for ( i = 0 ; i < parm->nfats ; i++ ) {
+ fprintf(stderr, "Writing FAT %d (%u), offset = %lx\n",
+ i, parm->fatsects, ftell(f));
+ xfwrite(parm->fat, parm->fatsects << parm->sectorshift, f);
+ }
/* Write root directory */
- writerootdir(f, rootp, rootdirents);
+ writerootdir(f, rootp, parm);
/* Write allocation chain */
- writeallocchain(f, allocchain, &cluster, clustshift);
+ writeallocchain(f, allocchain, &cluster, parm->clustshift);
/* Pad image to proper size */
- xfwritezero(f, ((parm->clusters-cluster-2) << parm->clustshift) +
- (parm->slopsectors << parm->sectorshift));
+ fprintf(stderr, "Writing final pad at cluster %u\n", cluster);
+ fprintf(stderr, "offset = %lx, free clusters = %u, slop = %u\n",
+ ftell(f),
+ (parm->clusters-(cluster-2)) << (parm->clustshift - parm->sectorshift),
+ parm->slopsectors);
+ xfwritezero(((parm->clusters-(cluster-2)) << parm->clustshift) +
+ (parm->slopsectors << parm->sectorshift), f);
}
-
diff --git a/xmalloc.c b/xmalloc.c
index 46ff2dc..04cb23c 100644
--- a/xmalloc.c
+++ b/xmalloc.c
@@ -33,6 +33,15 @@ xmalloc(size_t size)
return p;
}
+void *
+xzalloc(size_t size)
+{
+ void *p = xmalloc(size);
+ memset(p, 0, size);
+
+ return p;
+}
+
char *
xstrdup(const char *str)
{
diff --git a/xmalloc.h b/xmalloc.h
index 770af18..aa064d9 100644
--- a/xmalloc.h
+++ b/xmalloc.h
@@ -22,6 +22,7 @@
#include <stdlib.h> /* size_t */
void *xmalloc(size_t);
+void *xzalloc(size_t);
char *xstrdup(const char *);
#endif
diff --git a/xstdio.c b/xstdio.c
index 50b468f..c07c4e6 100644
--- a/xstdio.c
+++ b/xstdio.c
@@ -27,14 +27,14 @@ static const char lotsofzero[LOTSOFZERO];
extern const char *program;
size_t
-xfwrite(const void *p, size_t size, size_t nmemb, FILE *stream)
+xfwrite(const void *p, size_t size, FILE *stream)
{
- if ( fwrite(p, size, nmemb, stream) != nmemb ) {
+ if ( fwrite(p, 1, size, stream) != size ) {
perror(program);
exit(EX_IOERR);
}
- return nmemb;
+ return size;
}
size_t
@@ -42,7 +42,7 @@ xfwritezero(size_t size, FILE *stream)
{
size_t left = size;
while ( left ) {
- left -= xfwrite(lotsofzero, 1, min2(left,LOTSOFZERO), stream);
+ left -= xfwrite(lotsofzero, min2(left,LOTSOFZERO), stream);
}
return size;
}
diff --git a/xstdio.h b/xstdio.h
index 82debf3..c9e2adf 100644
--- a/xstdio.h
+++ b/xstdio.h
@@ -23,7 +23,7 @@
#include <stdio.h>
size_t
-xfwrite(const void *, size_t, size_t, FILE *);
+xfwrite(const void *, size_t, FILE *);
size_t
xfwritezero(size_t, FILE *);