From 4cde58fd83ef4a7b5bb7c1e9413b4d90943b6c13 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Tue, 31 Dec 2019 13:57:52 -0500 Subject: [PATCH] cfspack: make into a library Use it in shell instead of using popen() --- .gitignore | 1 + emul/Makefile | 7 +- emul/shell/shell.c | 33 ++++----- tools/.gitignore | 1 - tools/cfspack/Makefile | 6 +- tools/cfspack/cfs.h | 10 +++ tools/cfspack/cfspack.c | 134 +---------------------------------- tools/cfspack/libcfs.c | 150 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 187 insertions(+), 155 deletions(-) create mode 100644 tools/cfspack/cfs.h create mode 100644 tools/cfspack/libcfs.c diff --git a/.gitignore b/.gitignore index 1a241e4..eefeb2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +*.o /kernel/user.h diff --git a/emul/Makefile b/emul/Makefile index 102f543..14e8938 100644 --- a/emul/Makefile +++ b/emul/Makefile @@ -1,4 +1,4 @@ -CFSPACK = ../tools/cfspack/cfspack +CFSPACK_OBJ = ../tools/cfspack/libcfs.o TARGETS = shell/shell zasm/zasm runbin/runbin KERNEL = ../kernel APPS = ../apps @@ -9,6 +9,7 @@ SHELLAPPS = zasm ed SHELLTGTS = ${SHELLAPPS:%=cfsin/%} CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h OBJS = emul.o libz80/libz80.o +SHELLOBJS = $(OBJS) $(CFSPACK_OBJ) .PHONY: all all: $(TARGETS) $(AVRABIN) $(CFSIN_CONTENTS) @@ -20,8 +21,8 @@ shell/shell.bin: shell/glue.asm $(ZASMBIN) shell/shell-bin.h: shell/shell.bin ./bin2c.sh KERNEL < shell/shell.bin | tee $@ > /dev/null -shell/shell: shell/shell.c $(OBJS) shell/shell-bin.h - $(CC) shell/shell.c $(OBJS) -o $@ +shell/shell: shell/shell.c $(SHELLOBJS) shell/shell-bin.h + $(CC) shell/shell.c $(SHELLOBJS) -o $@ zasm/kernel-bin.h: zasm/kernel.bin ./bin2c.sh KERNEL < zasm/kernel.bin | tee $@ > /dev/null diff --git a/emul/shell/shell.c b/emul/shell/shell.c index d24e565..7c8206c 100644 --- a/emul/shell/shell.c +++ b/emul/shell/shell.c @@ -4,6 +4,7 @@ #include #include "../emul.h" #include "shell-bin.h" +#include "../../tools/cfspack/cfs.h" /* Collapse OS shell with filesystem * @@ -138,6 +139,17 @@ int main(int argc, char *argv[]) fprintf(stderr, "Can't open %s\n", optarg); return 1; } + fprintf(stderr, "Initializing filesystem from %s\n", optarg); + int i = 0; + int c; + while ((c = fgetc(fp)) != EOF && i < MAX_FSDEV_SIZE) { + fsdev[i++] = c & 0xff; + } + if (i == MAX_FSDEV_SIZE) { + fprintf(stderr, "Filesytem image too large.\n"); + return 1; + } + pclose(fp); break; default: fprintf(stderr, "Usage: shell [-f fsdev]\n"); @@ -146,25 +158,14 @@ int main(int argc, char *argv[]) } // Setup fs blockdev if (fp == NULL) { - fp = popen("../cfspack/cfspack cfsin", "r"); - if (fp == NULL) { + fprintf(stderr, "Initializing filesystem from cfsin\n"); + fp = fmemopen(fsdev, MAX_FSDEV_SIZE, "w"); + set_spit_stream(fp); + if (spitdir("cfsin", "", NULL) != 0) { fprintf(stderr, "Can't initialize filesystem. Leaving blank.\n"); } + fclose(fp); } - if (fp != NULL) { - fprintf(stderr, "Initializing filesystem\n"); - int i = 0; - int c; - while ((c = fgetc(fp)) != EOF && i < MAX_FSDEV_SIZE) { - fsdev[i++] = c & 0xff; - } - if (i == MAX_FSDEV_SIZE) { - fprintf(stderr, "Filesytem image too large.\n"); - return 1; - } - pclose(fp); - } - bool tty = isatty(fileno(stdin)); struct termios termInfo; if (tty) { diff --git a/tools/.gitignore b/tools/.gitignore index 41f9626..2535376 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,4 +1,3 @@ -*.o /memdump /blkdump /upload diff --git a/tools/cfspack/Makefile b/tools/cfspack/Makefile index 7c70151..106b2bd 100644 --- a/tools/cfspack/Makefile +++ b/tools/cfspack/Makefile @@ -1,10 +1,12 @@ TARGETS = cfspack cfsunpack +CFSPACK_OBJS = cfspack.o libcfs.o + .PHONY: all all: $(TARGETS) -cfspack: cfspack.c - $(CC) $(CFLAGS) -o $@ cfspack.c +cfspack: $(CFSPACK_OBJS) + $(CC) $(LDFLAGS) -o $@ $(CFSPACK_OBJS) cfsunpack: cfsunpack.c $(CC) $(CFLAGS) -o $@ cfsunpack.c diff --git a/tools/cfspack/cfs.h b/tools/cfspack/cfs.h new file mode 100644 index 0000000..08bb156 --- /dev/null +++ b/tools/cfspack/cfs.h @@ -0,0 +1,10 @@ +#define BLKSIZE 0x100 +#define HEADERSIZE 0x20 +#define MAX_FN_LEN 25 // 26 - null char +#define MAX_FILE_SIZE (BLKSIZE * 0x100) - HEADERSIZE + +void set_spit_stream(FILE *stream); +int is_regular_file(char *path); +void spitempty(); +int spitblock(char *fullpath, char *fn); +int spitdir(char *path, char *prefix, char **patterns); diff --git a/tools/cfspack/cfspack.c b/tools/cfspack/cfspack.c index fcf193a..2846627 100644 --- a/tools/cfspack/cfspack.c +++ b/tools/cfspack/cfspack.c @@ -7,139 +7,7 @@ #include #include -#define BLKSIZE 0x100 -#define HEADERSIZE 0x20 -#define MAX_FN_LEN 25 // 26 - null char -#define MAX_FILE_SIZE (BLKSIZE * 0x100) - HEADERSIZE - -int is_regular_file(char *path) -{ - struct stat path_stat; - stat(path, &path_stat); - return S_ISREG(path_stat.st_mode); -} - -void spitempty() -{ - putchar('C'); - putchar('F'); - putchar('S'); - for (int i=0; i<0x20-3; i++) { - putchar(0); - } -} - -int spitblock(char *fullpath, char *fn) -{ - FILE *fp = fopen(fullpath, "r"); - fseek(fp, 0, SEEK_END); - long fsize = ftell(fp); - if (fsize > MAX_FILE_SIZE) { - fclose(fp); - fprintf(stderr, "File too big: %s %ld\n", fullpath, fsize); - return 1; - } - /* Compute block count. - * We always have at least one, which contains 0x100 bytes - 0x20, which is - * metadata. The rest of the blocks have a steady 0x100. - */ - unsigned char blockcount = 1; - int fsize2 = fsize - (BLKSIZE - HEADERSIZE); - if (fsize2 > 0) { - blockcount += (fsize2 / BLKSIZE); - } - if (blockcount * BLKSIZE < fsize + HEADERSIZE) { - blockcount++; - } - putchar('C'); - putchar('F'); - putchar('S'); - putchar(blockcount); - // file size is little endian - putchar(fsize & 0xff); - putchar((fsize >> 8) & 0xff); - int fnlen = strlen(fn); - for (int i=0; id_name, ".") == 0) || strcmp(ep->d_name, "..") == 0) { - continue; - } - if (ep->d_type != DT_DIR && ep->d_type != DT_REG) { - fprintf(stderr, "Only regular file or directories are supported\n"); - return 1; - } - int slen = strlen(ep->d_name); - if (prefixlen + slen> MAX_FN_LEN) { - fprintf(stderr, "Filename too long: %s/%s\n", prefix, ep->d_name); - return 1; - } - char fullpath[0x1000]; - strcpy(fullpath, path); - strcat(fullpath, "/"); - strcat(fullpath, ep->d_name); - char newprefix[MAX_FN_LEN]; - strcpy(newprefix, prefix); - if (prefixlen > 0) { - strcat(newprefix, "/"); - } - strcat(newprefix, ep->d_name); - if (ep->d_type == DT_DIR) { - int r = spitdir(fullpath, newprefix, patterns); - if (r != 0) { - return r; - } - } else { - char **p = patterns; - // if we have no pattern, we match all - int matches = (*p) == NULL ? 1 : 0; - while (*p) { - if (fnmatch(*p, ep->d_name, 0) == 0) { - matches = 1; - break; - } - p++; - } - if (!matches) { - continue; - } - - int r = spitblock(fullpath, newprefix); - if (r != 0) { - return r; - } - } - } - closedir(dp); - return 0; -} +#include "cfs.h" void usage() { diff --git a/tools/cfspack/libcfs.c b/tools/cfspack/libcfs.c new file mode 100644 index 0000000..746619c --- /dev/null +++ b/tools/cfspack/libcfs.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cfs.h" + +#define PUTC(c) putc(c, spitstream) + +static FILE *spitstream = stdout; + +void set_spit_stream(FILE *stream) +{ + spitstream = stream; +} + +int is_regular_file(char *path) +{ + struct stat path_stat; + stat(path, &path_stat); + return S_ISREG(path_stat.st_mode); +} + +void spitempty() +{ + PUTC('C'); + PUTC('F'); + PUTC('S'); + for (int i=0; i<0x20-3; i++) { + PUTC(0); + } +} + +int spitblock(char *fullpath, char *fn) +{ + FILE *fp = fopen(fullpath, "r"); + fseek(fp, 0, SEEK_END); + long fsize = ftell(fp); + if (fsize > MAX_FILE_SIZE) { + fclose(fp); + fprintf(stderr, "File too big: %s %ld\n", fullpath, fsize); + return 1; + } + /* Compute block count. + * We always have at least one, which contains 0x100 bytes - 0x20, which is + * metadata. The rest of the blocks have a steady 0x100. + */ + unsigned char blockcount = 1; + int fsize2 = fsize - (BLKSIZE - HEADERSIZE); + if (fsize2 > 0) { + blockcount += (fsize2 / BLKSIZE); + } + if (blockcount * BLKSIZE < fsize + HEADERSIZE) { + blockcount++; + } + PUTC('C'); + PUTC('F'); + PUTC('S'); + PUTC(blockcount); + // file size is little endian + PUTC(fsize & 0xff); + PUTC((fsize >> 8) & 0xff); + int fnlen = strlen(fn); + for (int i=0; id_name, ".") == 0) || strcmp(ep->d_name, "..") == 0) { + continue; + } + if (ep->d_type != DT_DIR && ep->d_type != DT_REG) { + fprintf(stderr, "Only regular file or directories are supported\n"); + return 1; + } + int slen = strlen(ep->d_name); + if (prefixlen + slen> MAX_FN_LEN) { + fprintf(stderr, "Filename too long: %s/%s\n", prefix, ep->d_name); + return 1; + } + char fullpath[0x1000]; + strcpy(fullpath, path); + strcat(fullpath, "/"); + strcat(fullpath, ep->d_name); + char newprefix[MAX_FN_LEN]; + strcpy(newprefix, prefix); + if (prefixlen > 0) { + strcat(newprefix, "/"); + } + strcat(newprefix, ep->d_name); + if (ep->d_type == DT_DIR) { + int r = spitdir(fullpath, newprefix, patterns); + if (r != 0) { + return r; + } + } else { + char **p = patterns; + // if we have no pattern, we match all + if (p && *p) { + int matches = 0; + while (*p) { + if (fnmatch(*p, ep->d_name, 0) == 0) { + matches = 1; + break; + } + p++; + } + if (!matches) { + continue; + } + } + + int r = spitblock(fullpath, newprefix); + if (r != 0) { + return r; + } + } + } + closedir(dp); + return 0; +}