Use it in shell instead of using popen()pull/85/head
@@ -1 +1,2 @@ | |||
*.o | |||
/kernel/user.h |
@@ -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 | |||
@@ -4,6 +4,7 @@ | |||
#include <termios.h> | |||
#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) { | |||
@@ -1,4 +1,3 @@ | |||
*.o | |||
/memdump | |||
/blkdump | |||
/upload |
@@ -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 | |||
@@ -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); |
@@ -7,139 +7,7 @@ | |||
#include <libgen.h> | |||
#include <sys/stat.h> | |||
#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; i<MAX_FN_LEN; i++) { | |||
if (i < fnlen) { | |||
putchar(fn[i]); | |||
} else { | |||
putchar(0); | |||
} | |||
} | |||
// And the last FN char which is always null | |||
putchar(0); | |||
char buf[MAX_FILE_SIZE] = {0}; | |||
rewind(fp); | |||
fread(buf, fsize, 1, fp); | |||
fclose(fp); | |||
fwrite(buf, (blockcount * BLKSIZE) - HEADERSIZE, 1, stdout); | |||
fflush(stdout); | |||
return 0; | |||
} | |||
int spitdir(char *path, char *prefix, char **patterns) | |||
{ | |||
DIR *dp; | |||
struct dirent *ep; | |||
int prefixlen = strlen(prefix); | |||
dp = opendir(path); | |||
if (dp == NULL) { | |||
fprintf(stderr, "Couldn't open directory.\n"); | |||
return 1; | |||
} | |||
while ((ep = readdir(dp))) { | |||
if ((strcmp(ep->d_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() | |||
{ | |||
@@ -0,0 +1,150 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <unistd.h> | |||
#include <dirent.h> | |||
#include <string.h> | |||
#include <fnmatch.h> | |||
#include <libgen.h> | |||
#include <sys/stat.h> | |||
#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; i<MAX_FN_LEN; i++) { | |||
if (i < fnlen) { | |||
PUTC(fn[i]); | |||
} else { | |||
PUTC(0); | |||
} | |||
} | |||
// And the last FN char which is always null | |||
PUTC(0); | |||
char buf[MAX_FILE_SIZE] = {0}; | |||
rewind(fp); | |||
fread(buf, fsize, 1, fp); | |||
fclose(fp); | |||
fwrite(buf, (blockcount * BLKSIZE) - HEADERSIZE, 1, spitstream); | |||
fflush(spitstream); | |||
return 0; | |||
} | |||
int spitdir(char *path, char *prefix, char **patterns) | |||
{ | |||
DIR *dp; | |||
struct dirent *ep; | |||
int prefixlen = strlen(prefix); | |||
dp = opendir(path); | |||
if (dp == NULL) { | |||
fprintf(stderr, "Couldn't open directory.\n"); | |||
return 1; | |||
} | |||
while ((ep = readdir(dp))) { | |||
if ((strcmp(ep->d_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; | |||
} |