summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-08-05 15:28:01 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2012-08-05 15:28:56 (GMT)
commit86b4fb0c8f3a50c5aa4e99b78b5d62efa0a8408b (patch)
tree996f5ccff6e6d4e9c70d99744fd21adc13a6adda
parent4e026921322553ffaa6a58f6551c29ea890d5e1d (diff)
downloadabcdisk-86b4fb0c8f3a50c5aa4e99b78b5d62efa0a8408b.zip
abcdisk-86b4fb0c8f3a50c5aa4e99b78b5d62efa0a8408b.tar.gz
abcdisk-86b4fb0c8f3a50c5aa4e99b78b5d62efa0a8408b.tar.bz2
abcdisk-86b4fb0c8f3a50c5aa4e99b78b5d62efa0a8408b.tar.xz
Rewrite for generality - snapshot 1
-rw-r--r--Makefile7
-rw-r--r--abcwrite.c207
-rw-r--r--util.c19
-rw-r--r--util.h9
4 files changed, 181 insertions, 61 deletions
diff --git a/Makefile b/Makefile
index 22625f8..a2ff504 100644
--- a/Makefile
+++ b/Makefile
@@ -11,8 +11,11 @@ endif
all : abcwrite$(X)
-abcwrite$(X): abcwrite.c
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+.c.$(O):
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+abcwrite$(X): abcwrite.$(O) util.$(O)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
clean:
rm -f abcwrite$(X) *.$(O) *~
diff --git a/abcwrite.c b/abcwrite.c
index a052cf5..f74aa90 100644
--- a/abcwrite.c
+++ b/abcwrite.c
@@ -15,9 +15,14 @@
#include <sys/stat.h>
#include <sys/types.h>
-const char *program;
+struct diskfmt {
+ const char *name;
+ unsigned int ntracks; /* Total tracks (max 238) */
+ unsigned int track_shift; /* Size of a track in sectors (max 256) */
+ unsigned int cluster_shift; /* Size of a cluster (typically track/8) */
+};
-unsigned char image[238*256*256];
+static struct disk disk;
struct directory {
unsigned char *bitmap; /* Directory entry "bitmap" area */
@@ -35,15 +40,83 @@ struct directory mfd = {
0
};
-/* This is the next unassigned block number */
-int nextblock = 32;
+struct disk {
+ const struct diskfmt *fmt; /* Format descriptor */
+ unsigned char *image; /* Image of the disk */
+ unsigned char *bitmap; /* Pointer to the bitmap inside the disk */
+ struct directory mfd;
+ int nextblock; /* Next unassigned block number */
+};
/*
* Set a bit in the bitmap
*/
-void mark_used(int sector)
+static void mark_used(struct disk *disk, unsigned int cluster)
+{
+ disk->bitmap[cluster >> 3] |= (1U << (cluster & 7));
+}
+
+static struct disk *allocate_disk(const struct diskfmt *fmt)
+{
+ struct disk *disk = xmalloc(sizeof(struct disk));
+ size_t size = (fmt->track * fmt->ntracks) << 8;
+ int i, starter;
+
+ memset(disk, 0, sizeof *disk);
+
+ disk->fmt = fmt;
+ disk->image = xzalloc(size);
+ disk->bitmap = disk->image + 14*256;
+ disk->mfd.bitmap = disk->image + 14*256;
+ disk->mfd.dirsec = disk->image + 16*256;
+ disk->nextblock = 32;
+
+ /* Post-formatting content? */
+ memset(disk->image, 0xe5, size);
+
+ /* Create empty bitmap */
+ memset(disk->bitmap, 0, fmt->tracks);
+ memset(disk->bitmap+fmt->tracks, 0xff, 0xe9-fmt->tracks);
+ memset(disk->bitmap+0xe9, 0x01, 16); /* MFD bitmap */
+ disk->bitmap[0xff] = 0x00;
+
+ /* Mark the first 32 sectors used */
+ starter = 32 >> fmt->cluster_shift;
+ for (i = 0; i < starter; i++)
+ mark_used(disk, i);
+
+ /* Copy bitmap to backup empty bitmap */
+ memcpy(disk->bitmap + 256, disk->bitmap, 256);
+
+ /* Create MFD directory sectors */
+ for ( i = 16 ; i < 32 ; i++ ) {
+ memset(disk->image+(i << 8), 0x00, 16);
+ memset(disk->image+(i << 8)+16, 0xFF, 240);
+ }
+}
+
+/*
+ * Find a free cluster in the bitmap; return the cluster number
+ */
+static int get_cluster(struct disk *disk)
{
- bitmap[sector >> 8] |= (1 << ((sector >> 5) & 7));
+ int i, j;
+ unsigned char b;
+
+ for (i = 0; i < disk->fmt->tracks; i++) {
+ if ((b = disk->bitmap[i]) != 0xff) {
+ i <<= 3;
+ while (b & 1) {
+ b >>= 1;
+ i++;
+ }
+ mark_used(disk, i);
+ return i;
+ }
+ }
+
+ fprintf(stderr, "%s: output disk full\n", stderr);
+ exit(1);
}
/*
@@ -106,6 +179,7 @@ unsigned char *read_file(const char *filename, int *sizep)
int size = 0;
int binary = 0;
unsigned char *data, *dp;
+ int blocks;
if ( !f )
return NULL;
@@ -113,8 +187,7 @@ unsigned char *read_file(const char *filename, int *sizep)
while ( (n = fread(buffer, 1, sizeof buffer, f)) ) {
if ( !binary )
for ( i = 0 ; i < n ; i++ ) {
- if ( buffer[i] & 0x80 || buffer[i] == 0x00 ||
- buffer[i] == 0x03 ) {
+ if ( (buffer[i] & 0x80) || buffer[i] == 0x00 || buffer[i] == 0x03 ) {
binary = 1;
break;
}
@@ -126,11 +199,14 @@ unsigned char *read_file(const char *filename, int *sizep)
rewind(f);
if ( binary ) {
- data = malloc(size);
+ blocks = (size+252)/253;
+ data = xmalloc(blocks*253);
fread(data,size,1,f);
+ memset(data+size,0,blocks*253-size);
+ size = blocks*253;
} else {
int blocks = (size+251)/252 + 1;
- data = malloc(size = blocks*253);
+ data = xmalloc(blocks*253);
dp = data;
while ( memset(buffer, 0, 253),
@@ -138,7 +214,7 @@ unsigned char *read_file(const char *filename, int *sizep)
for ( i = 0 ; i < n ; i++ ) {
if ( buffer[i] == '\n' )
buffer[i] = '\r';
- }
+ }
buffer[n] = '\x03';
memcpy(dp, buffer, 253);
@@ -149,6 +225,9 @@ unsigned char *read_file(const char *filename, int *sizep)
memset(buffer, 0, 6);
buffer[6] = '\x03';
memcpy(dp, buffer, 253);
+ dp += 253;
+
+ size = dp - data;
}
fclose(f);
@@ -161,25 +240,27 @@ unsigned char *read_file(const char *filename, int *sizep)
/*
* Copy a file
*/
-int copy_file(const char *filename, struct directory *dir)
+int copy_file(const char *filename, struct disk *disk, struct directory *dir)
{
int size;
- int nblocks, nclust;
+ int nblocks, nclust, cluster, secperclust;
char mangled_name[12];
int dirs, dirp; /* Directory (sector,position) */
unsigned char *dirent;
- unsigned char *data;
+ unsigned char *data, *src;
int i;
+ int blockno, cleft, block, bleft;
+ unsigned char *header, *dp;
- data = read_file(filename, &size);
+ data = src = read_file(filename, &size);
nblocks = (size+252)/253 + 1;
- nclust = (nblocks+31)/32;
+ secperclust = 1 << disk->fmt->cluster_shift;
+ nclust = (nblocks+secperclust-1) >> disk->fmt->cluster_shift;
mangle_name(mangled_name, filename);
/* Find and create directory entry */
-
dirp = -1;
for ( dirs = 0 ; dirs < 16 ; dirs++ ) {
if ( dir->bitmap[0xEF+dirs] < 0x10 ) {
@@ -189,6 +270,7 @@ int copy_file(const char *filename, struct directory *dir)
}
if ( dirs == 16 ) {
+ /* Directory full */
free(data);
return -1;
}
@@ -196,61 +278,68 @@ int copy_file(const char *filename, struct directory *dir)
dirent = dir->dirsec + dirs*256 + dirp*16;
memcpy(dirent+4, mangled_name, 11);
- dirent[0] = nextblock >> 8;
- dirent[1] = nextblock & 0xE0;
+
+ /* Allocate first cluster */
+ cluster = get_cluster(disk);
+
+ dirent[0] = cluster >> 3;
+ dirent[1] = cluster << 5;
dirent[2] = nblocks & 0xFF;
dirent[3] = nblocks >> 8;
/* Create "file header" */
- {
- int block = nextblock;
- int cleft = nclust;
- unsigned char *header = image + nextblock*256;
+ dp = header = disk->image + (cluster << (disk->fmt->cluster_shift+8));
+ cleft = secperclust - 1; /* Left in the first cluster */
- memset(header, 0, 256);
+ memset(header, 0, 256);
- *header++ = (dirp << 4) + dirs;
- *header++ = 0;
- *header++ = 0;
- *header++ = 0xFF;
+ *header++ = (dirp << 4) + dirs;
+ *header++ = 0; /* Header = block 0 */
+ *header++ = 0; /* Header = block 0 */
+ *header++ = 0xFF;
+ /* Starting extent has one cluster in it */
+ header[0] = cluster >> 3;
+ header[1] = (cluster << 5) + 0; /* Bits[4:0] = extend size minus one */
- while ( cleft ) {
- int nc = cleft > 32 ? 32 : cleft;
- *header++ = block >> 8;
- *header++ = (block & 0xE0) | (nc-1);
- cleft -= nc;
- block += nc;
- }
+ /* Actually copy the file */
+ blockno = 0;
+ while ( size ) {
+ int nbytes = (size > 253) ? 253 : size;
- *header++ = 0xFF;
- *header++ = 0xFF;
- }
+ blockno++;
- /* Actually copy the file */
- {
- int blockno = 1;
- unsigned char *target = image + (nextblock+1)*256;
- unsigned char *dp = data;
-
- while ( size ) {
- int nbytes = (size > 253) ? 253 : size;
- target[0] = (dirp << 4) + dirs;
- target[1] = blockno & 0xFF;
- target[2] = blockno >> 8;
- memcpy(target+3, dp, nbytes);
- memset(target+3+(253-nbytes), 0, 253-nbytes);
-
- blockno++;
- target += 256;
- size -= nbytes;
- dp += nbytes;
+ if (cleft) {
+ dp += 256; /* Subsequent sector */
+ cleft--;
+ } else {
+ cluster = get_cluster(disk);
+ dp = disk->image + (cluster << (disk->fmt->cluster_shift+8));
+ cleft = secperclust - 1;
+ if (cluster == ((header[0] << 3) + (header[1] >> 5) + 1) &&
+ (header[1] & 31) < 31) {
+ header[1]++;
+ } else {
+ header += 2;
+ header[0] = cluster >> 3;
+ header[1] = (cluster << 5) + 0;
+ }
}
+
+ dp[0] = (dirp << 4) + dirs;
+ dp[1] = blockno & 0xFF;
+ dp[2] = blockno >> 8;
+ memcpy(dp+3, src, 253);
+
+ size -= nbytes;
+ src += 253;
}
- free(data);
+ /* Terminate the header */
+ header += 2;
+ header[0] = 0xFF;
+ header[1] = 0xFF;
- for ( i = 0 ; i < nclust*32 ; i++ )
- mark_used(nextblock++);
+ free(data);
return 0;
}
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..e6dfd4c
--- /dev/null
+++ b/util.c
@@ -0,0 +1,19 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "util.h"
+
+const char *program;
+
+void *xmalloc(size_t len)
+{
+ void *p = malloc(len);
+
+ if (!p) {
+ perror(program);
+ exit(1);
+ }
+
+ return p;
+}
+
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..7eaa0d0
--- /dev/null
+++ b/util.h
@@ -0,0 +1,9 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stdlib.h>
+
+extern const char *program;
+void *xmalloc(size_t);
+
+#endif /* UTIL_H */