mirror of
https://github.com/hsoft/collapseos.git
synced 2024-12-25 04:58:05 +11:00
cfspack: make into a library
Use it in shell instead of using popen()
This commit is contained in:
parent
72357fec86
commit
4cde58fd83
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
tools/.gitignore
vendored
1
tools/.gitignore
vendored
@ -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
|
||||
|
10
tools/cfspack/cfs.h
Normal file
10
tools/cfspack/cfs.h
Normal file
@ -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()
|
||||
{
|
||||
|
150
tools/cfspack/libcfs.c
Normal file
150
tools/cfspack/libcfs.c
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user