summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-08-06 00:31:07 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2012-08-06 00:31:07 (GMT)
commitbf11fa1d0c68e4c19524ca7b5f0ab2f3a3e7a347 (patch)
tree532bb91dd91997272bacbe70fefcea263c5317a6
parent74d81744c4f71fa6b032598df5aaa0dae6cf7d0e (diff)
downloadabcdisk-bf11fa1d0c68e4c19524ca7b5f0ab2f3a3e7a347.zip
abcdisk-bf11fa1d0c68e4c19524ca7b5f0ab2f3a3e7a347.tar.gz
abcdisk-bf11fa1d0c68e4c19524ca7b5f0ab2f3a3e7a347.tar.bz2
abcdisk-bf11fa1d0c68e4c19524ca7b5f0ab2f3a3e7a347.tar.xz
Complete format generalization of abcwrite
-rw-r--r--Makefile4
-rw-r--r--abcwrite.c262
-rw-r--r--formats.c27
-rw-r--r--util.h8
4 files changed, 157 insertions, 144 deletions
diff --git a/Makefile b/Makefile
index 7a252ea..186a274 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
CC = cc
-CFLAGS = -W -Wall -O2 -g
+CFLAGS = -W -Wall -Wno-sign-compare -O2 -g
LDFLAGS =
ifneq (,$(findstring _NT,$(shell uname -s)))
O = obj
@@ -14,7 +14,7 @@ all : abcwrite$(X)
.c.$(O):
$(CC) $(CFLAGS) -c -o $@ $<
-abcwrite$(X): abcwrite.$(O) util.$(O)
+abcwrite$(X): abcwrite.$(O) util.$(O) formats.$(O)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
clean:
diff --git a/abcwrite.c b/abcwrite.c
index 654b8cc..fb08343 100644
--- a/abcwrite.c
+++ b/abcwrite.c
@@ -16,16 +16,10 @@
#include <sys/types.h>
#include "util.h"
-struct diskfmt {
- const char *name;
- 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) */
-};
-
-static struct disk disk;
+struct disk;
struct directory {
+ struct disk *disk; /* This directory belongs to... */
unsigned char *bitmap; /* Directory entry "bitmap" area */
unsigned char *dirsec; /* Actual directory sector */
unsigned int block; /* UFD block pointer (0 for MFD) */
@@ -46,6 +40,11 @@ static void mark_used(struct disk *disk, unsigned int cluster)
disk->bitmap[cluster >> 3] |= (1U << (cluster & 7));
}
+static int is_used(struct disk *disk, unsigned int cluster)
+{
+ return (disk->bitmap[cluster >> 3] >> (cluster & 7)) & 1;
+}
+
static struct disk *allocate_disk(const struct diskfmt *fmt)
{
struct disk *disk = xmalloc(sizeof(struct disk));
@@ -57,6 +56,7 @@ static struct disk *allocate_disk(const struct diskfmt *fmt)
disk->fmt = fmt;
disk->image = xmalloc(size);
disk->bitmap = disk->image + 14*256;
+ disk->mfd.disk = disk;
disk->mfd.bitmap = disk->image + 14*256;
disk->mfd.dirsec = disk->image + 16*256;
disk->mfd.block = 0; /* This is the MFD */
@@ -90,23 +90,38 @@ static struct disk *allocate_disk(const struct diskfmt *fmt)
/*
* Find a free cluster in the bitmap; return the cluster number
*/
-static int get_cluster(struct disk *disk)
+static int get_cluster(struct disk *disk, unsigned int cluster_hint)
{
- int i;
- unsigned char b;
-
- for (i = 0; i < disk->fmt->ntracks; i++) {
- if ((b = disk->bitmap[i]) != 0xff) {
- i <<= 3;
- while (b & 1) {
- b >>= 1;
- i++;
+ int nclust, i, x, nc, best, bnc;
+
+ best = -1;
+ bnc = 0;
+
+ nclust = disk->fmt->ntracks
+ << (disk->fmt->track_shift - disk->fmt->cluster_shift);
+
+ for (i = 0; i < nclust; i++) {
+ if (!is_used(disk, i)) {
+ /* How long is this? */
+ for (x = i, nc = 0; i < nclust && nc < cluster_hint; i++) {
+ if (is_used(disk, i))
+ break;
+ nc++;
+ }
+ if (nc == cluster_hint) {
+ /* Found as big as we wanted */
+ mark_used(disk, x);
+ return x;
+ } else if (nc > bnc) {
+ best = x;
+ bnc = nc;
}
- mark_used(disk, i);
- return i;
}
}
+ if (bnc) /* We found *something* at least... */
+ return best;
+
fprintf(stderr, "%s: output disk full\n", program);
exit(1);
}
@@ -230,25 +245,22 @@ unsigned char *read_file(const char *filename, int *sizep)
}
/*
- * Copy a file
+ * Create a file object and return a pointer to the header block.
*/
-int copy_file(const char *filename, struct disk *disk, struct directory *dir)
+static unsigned char *
+create_file(struct directory *dir, const char *mangled_name,
+ unsigned char *data, int size, int ufd)
{
- int size;
- int nblocks, cluster, secperclust;
- char mangled_name[12];
+ struct disk *disk = dir->disk;
+ int nblocks, cluster, secperclust, clusters;
int dirs, dirp; /* Directory (sector,position) */
unsigned char *dirent;
- unsigned char *data, *src;
int blockno, cleft;
unsigned char *header, *dp;
- data = src = read_file(filename, &size);
-
nblocks = (size+252)/253 + 1;
secperclust = 1 << disk->fmt->cluster_shift;
-
- mangle_name(mangled_name, filename);
+ clusters = (nblocks + secperclust - 1) >> disk->fmt->cluster_shift;
/* Find and create directory entry */
dirp = -1;
@@ -261,8 +273,8 @@ int copy_file(const char *filename, struct disk *disk, struct directory *dir)
if ( dirs == 16 ) {
/* Directory full */
- free(data);
- return -1;
+ fprintf(stderr, "%s: directory full\n", program);
+ return NULL;
}
dirent = dir->dirsec + dirs*256 + dirp*16;
@@ -270,7 +282,9 @@ int copy_file(const char *filename, struct disk *disk, struct directory *dir)
memcpy(dirent+4, mangled_name, 11);
/* Allocate first cluster */
- cluster = get_cluster(disk);
+ cluster = get_cluster(disk, clusters--);
+ if (cluster < 0)
+ return NULL;
dirent[0] = cluster >> 3;
dirent[1] = cluster << 5;
@@ -302,7 +316,9 @@ int copy_file(const char *filename, struct disk *disk, struct directory *dir)
dp += 256; /* Subsequent sector */
cleft--;
} else {
- cluster = get_cluster(disk);
+ cluster = get_cluster(disk, clusters--);
+ if (cluster < 0)
+ return NULL;
dp = disk->image + (cluster << (disk->fmt->cluster_shift+8));
cleft = secperclust - 1;
if (cluster == ((header[0] << 3) + (header[1] >> 5) + 1) &&
@@ -315,13 +331,17 @@ int copy_file(const char *filename, struct disk *disk, struct directory *dir)
}
}
- dp[0] = (dirp << 4) + dirs;
- dp[1] = blockno & 0xFF;
- dp[2] = blockno >> 8;
- memcpy(dp+3, src, 253);
+ if (ufd && blockno > 1) {
+ memset(dp, 0xff, 256);
+ } else {
+ dp[0] = (dirp << 4) + dirs;
+ dp[1] = blockno & 0xFF;
+ dp[2] = blockno >> 8;
+ memcpy(dp+3, data, 253);
+ data += 253;
+ }
size -= nbytes;
- src += 253;
}
/* Terminate the header */
@@ -329,109 +349,68 @@ int copy_file(const char *filename, struct disk *disk, struct directory *dir)
header[0] = 0xFF;
header[1] = 0xFF;
- free(data);
-
return 0;
}
/*
- * Create a UFD
+ * Copy a file
*/
-struct directory *make_ufd(const char *filename, struct directory *dir)
+int copy_file(struct directory *dir, const char *filename)
{
- int nblocks, nclust;
+ int size;
char mangled_name[12];
- int dirs, dirp; /* Directory (sector,position) */
- unsigned char *dirent;
- struct directory *ufd = malloc(sizeof(struct directory));
- int i;
+ unsigned char *data;
+ unsigned char *header;
- nblocks = 18;
- nclust = (nblocks+31)/32;
+ data = read_file(filename, &size);
mangle_name(mangled_name, filename);
- memcpy(mangled_name+8, "Ufd", 4);
- /* Find and create directory entry */
-
- dirp = -1;
- for ( dirs = 0 ; dirs < 16 ; dirs++ ) {
- if ( dir->bitmap[0xEF+dirs] < 0x10 ) {
- dirp = dir->bitmap[0xEF+dirs]++;
- break;
- }
- }
-
- if ( dirs == 16 ) {
- free(ufd);
- return NULL;
- }
-
- dirent = dir->dirsec + dirs*256 + dirp*16;
+ header = create_file(dir, mangled_name, data, size, 0);
+ free(data);
+ return header ? 0 : -1;
+}
- memcpy(dirent+4, mangled_name, 11);
- dirent[0] = nextblock >> 8;
- dirent[1] = nextblock & 0xE0;
- dirent[2] = nblocks & 0xFF;
- dirent[3] = nblocks >> 8;
+/*
+ * Create a UFD
+ */
+struct directory *make_ufd(struct directory *dir, const char *filename)
+{
+ char mangled_name[12];
+ unsigned char bitmap[253];
+ unsigned char *header;
+ struct directory *ufd;
+ int dirs_block = dir->block ? dir->block+2 : 0;
- /* Create "file header" */
- {
- int block = nextblock;
- int cleft = nclust;
- unsigned char *header = image + nextblock*256;
-
- memset(header, 0, 256);
-
- *header++ = (dirp << 4) + dirs;
- *header++ = 0;
- *header++ = 0;
- *header++ = 0xFF;
-
- while ( cleft ) {
- int nc = cleft > 32 ? 32 : cleft;
- *header++ = block >> 8;
- *header++ = (block & 0xE0) | (nc-1);
- cleft -= nc;
- block += nc;
- }
+ ufd = xmalloc(sizeof(struct directory));
+ memset(ufd, 0, sizeof *ufd);
+ ufd->disk = dir->disk;
- *header++ = 0xFF;
- *header++ = 0xFF;
- }
+ mangle_name(mangled_name, filename);
+ memcpy(mangled_name+8, "Ufd", 4);
- /* Create "bitmap" */
- {
- unsigned char *bitmap = image + (nextblock+1)*256;
- int dirs_block = dir->block ? dir->block+2 : 0;
+ memset(bitmap, 0, sizeof bitmap);
+ bitmap[0] = dirs_block & 0xFF;
+ bitmap[1] = dirs_block >> 8;
- memset(bitmap, 0, 256);
- bitmap[0] = (dirp << 4) + dirs;
- bitmap[1] = 1;
- bitmap[2] = 0;
- bitmap[3] = dirs_block & 0xFF;
- bitmap[4] = dirs_block >> 8;
- bitmap[5] = (dirp << 4) + dirs;
+ header = create_file(dir, mangled_name, bitmap, 17*253, 1);
+ if (!header)
+ return NULL;
- ufd->bitmap = bitmap;
+ if ((header[6] & header[7]) != 0xff) {
+ fprintf(stderr, "%s: discontiguous UFD (disk too fragmented)\n", program);
+ return NULL;
}
-
- /* Create "data" */
- ufd->dirsec = image + (nextblock+2)*256;
- memset(ufd->dirsec, 0xFF, 16*256);
-
- /* Pointer to this UFD */
- ufd->block = nextblock;
-
- /* Mark sectors used */
- for ( i = 0 ; i < nclust*32 ; i++ )
- mark_used(nextblock++);
+
+ ufd->bitmap = header + 256;
+ ufd->dirsec = header + 512;
+ ufd->block = (header - dir->disk->image) >> 8;
return ufd;
}
/* Copy files as given by tree on stdin */
-int get_files(const char *dirpath, struct directory *ufd)
+int get_files(struct directory *ufd, const char *dirpath)
{
struct stat st;
DIR *d;
@@ -454,10 +433,10 @@ int get_files(const char *dirpath, struct directory *ufd)
continue;
}
if ( S_ISDIR(st.st_mode) ) {
- subdir = make_ufd(filename, ufd);
- get_files(filename, subdir);
+ subdir = make_ufd(ufd, filename);
+ get_files(subdir, filename);
} else {
- copy_file(filename, ufd);
+ copy_file(ufd, filename);
}
}
closedir(d);
@@ -467,37 +446,36 @@ int get_files(const char *dirpath, struct directory *ufd)
int main(int argc, char *argv[])
{
- int i;
+ struct disk *disk;
+ const struct diskfmt *fmt;
+ const char *fmt_name;
+ char * const *argp;
setlocale(LC_ALL, "");
program = argv[0];
- memset(image, 0xe5, 238*256*256);
-
- /* Create empty bitmap */
- image[0xF00] = 0x80;
- memset(image+0xF01, 0x00, 237);
- image[0xFEE] = 0xFF;
- memset(image+0xFEF, 0x01, 16);
- image[0xFFF] = 0x00;
-
- /* Copy empty bitmap to live bitmap */
- memcpy(image+0xE00, image+0xF00, 256);
+ if (argc > 1 && argv[1][0] == '-') {
+ fmt_name = argv[1]+1;
+ argp = argv + 2;
+ } else {
+ fmt_name = "";
+ argp = argv + 1;
+ }
- /* Create directory sectors */
- for ( i = 16 ; i < 32 ; i++ ) {
- memset(image+(i << 8), 0x00, 16);
- memset(image+(i << 8)+16, 0xFF, 240);
+ fmt = get_format(fmt_name);
+ if (!fmt) {
+ fprintf(stderr, "%s: unknown format: %s\n", program, fmt_name);
+ exit(1);
}
- /* Install files */
- get_files(argv[1], &mfd);
+ disk = allocate_disk(fmt);
- /*** DO STUFF ***/
+ /* Install files */
+ get_files(&disk->mfd, *argp);
/* Finally, write out image */
- fwrite(image, 1, 238*256*256, stdout);
+ fwrite(disk->image, 1, fmt->ntracks << (fmt->track_shift + 8), stdout);
return 0;
}
diff --git a/formats.c b/formats.c
new file mode 100644
index 0000000..6acd5a3
--- /dev/null
+++ b/formats.c
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "util.h"
+
+static const struct diskfmt formats[] =
+ {
+ { "fd2", 40, 3, 0 },
+ { "abc830", 80, 3, 0 },
+ { "abc832", 80, 5, 2 },
+ { "abc834", 80, 5, 2 },
+ { "hd", 238, 8, 5 },
+ { "", 238, 8, 5 },
+ { NULL, 0, 0, 0 }
+ };
+
+const struct diskfmt *get_format(const char *name)
+{
+ const struct diskfmt *fmt;
+
+ for (fmt = formats; fmt->name; fmt++) {
+ if (!strcmp(fmt->name, name))
+ return fmt;
+ }
+
+ return NULL;
+}
diff --git a/util.h b/util.h
index 7eaa0d0..52dcf3e 100644
--- a/util.h
+++ b/util.h
@@ -3,6 +3,14 @@
#include <stdlib.h>
+struct diskfmt {
+ const char *name;
+ 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) */
+};
+
+const struct diskfmt *get_format(const char *);
extern const char *program;
void *xmalloc(size_t);