foxdos/tool/mfstool.c

267 lines
6.6 KiB
C
Raw Normal View History

2023-10-27 21:54:33 -07:00
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <fs.h> // structs for mothfs
#include <mfs_hdr.h> // bootcode
#define setbit(x, y) x[y >> 3] |= 1 << (y & 7)
typedef struct {
char* name;
int (*fn)(int, char**);
} multicall;
int pstrlen(char* d, char* typ) {
int i = 0;
while((d[i] ^ '/') && d[i] != 0) i++; // slash or null terminated
*typ = d[i] ? 1 : 0;
return i;
}
char** psplit(char* path, int* i) {
int l, a = 8;
char** rpth = malloc(sizeof(char*)*a);
*i = 0;
char x = 1, dir = 0;
if(*path == '/') {
rpth[(*i)++] = memcpy(malloc(2), "/", 2);
path++;
}
if(path[strlen(path) - 1] == '/') dir = 1;
2023-10-29 02:05:53 -07:00
while(x) {
2023-10-27 21:54:33 -07:00
while(*path == '/') path++;
2023-10-29 02:05:53 -07:00
if(!*path) break;
2023-10-27 21:54:33 -07:00
l = pstrlen(path, &x);
2023-10-29 02:05:53 -07:00
if(*path == '.' && l < 3) {
// nop - will not handle case l == 0 or l == 1
if(l == 2) {
if(path[1] == '.') {
2023-11-01 00:37:13 -07:00
printf("handling .. at i == %i\n", *i);
2023-10-29 02:05:53 -07:00
if(*i != !!strcmp(rpth[0], "/")) {
printf("..: free rpth[%i]\n", *i);
free(memcpy(rpth[--(*i)], "\0", 1)); // will not overwrite first element if it is "/" or index oob
} else if(strcmp(rpth[0], "/")) {
int acc = 0;
for(int z = 0; z < *i; z++) {
acc += !!strcmp(rpth[z], "..");
printf("check rpth[%i]:\t%s\n", z, rpth[z]);
}
printf("acc = %i\n", acc);
2023-11-01 00:37:13 -07:00
if(!acc) {
printf("INSERT ..\n");
goto addent;
}
2023-10-29 02:05:53 -07:00
}
} else goto addent;
}
} else { // insert string
addent: rpth[*i] = memcpy(malloc(l + 1), path, l);
2023-10-29 00:03:39 -07:00
rpth[(*i)++][l] = 0;
}
2023-10-29 02:05:53 -07:00
path += l + x; // prevent buffer overrun
2023-10-27 21:54:33 -07:00
if(*i >= a) rpth = realloc(rpth, sizeof(char*)*(a += 4));
}
2023-10-29 02:05:53 -07:00
printf("end psplit\n\n");
2023-10-27 21:54:33 -07:00
if(dir) {
if(*i + 1 >= a) rpth = realloc(rpth, sizeof(char*)*(a += 4));
rpth[(*i)++] = memcpy(malloc(2), "/", 2);
}
2023-10-29 02:05:53 -07:00
// TODO free a-*i elements from end to avoid leak
2023-10-27 21:54:33 -07:00
return rpth;
}
int xstrlen(char* s) {
int i = strlen(s) - 1;
for(;s[i] != '.' && i; i--);
return i;
}
// s: passed path
// d: path in fs to check against
// TODO does this even work
int nmatch(char* s, char* d) {
int x = xstrlen(s);
for(int i = 0; i < (x > 8 ? 8 : x); i++) {
if(
(s[i] & ((s[i] >= 'a' && s[i] <= 'z') ? 0xDF: 0xFF)) != d[i]
) return 0;
}
s = s + x + 1;
x = strlen(s);
for(int i = 0; i < (x > 3 ? 3 : x); i++) {
if(
(s[i] & ((s[i] >= 'a' && s[i] <= 'z') ? 0xDF: 0xFF)) != d[i]
) return 0;
}
2023-11-01 00:37:13 -07:00
return 1;
2023-10-27 21:54:33 -07:00
}
// returns sector of file or directory
uint32_t mfs_traverse(int fd, uint32_t from, char* name) {
uint64_t r = 0; // sector to return?
mothfs_file d, next;
int sz;
char** rpth = psplit(name, &sz);
2023-10-29 00:03:39 -07:00
uint32_t* ns = malloc(512);
2023-10-27 21:54:33 -07:00
int i = 0;
if(!strcmp(*rpth, "/")) {
lseek(fd, 0, SEEK_SET);
read(fd, &d, 512);
2023-10-29 00:03:39 -07:00
mothfs_header* e = (mothfs_header*)&d; // reuse buffer
2023-10-27 21:54:33 -07:00
from = e->reserved + e->abm + 1;
i++;
}
for(; i < sz; i++) { // TODO . and ..
lseek(fd, ((uint64_t)from) << 9, SEEK_SET);
read(fd, &d, 512);
2023-11-01 00:37:13 -07:00
uint32_t* sp = d.data + 121;
2023-10-27 21:54:33 -07:00
switch(d.type) {
case 0: // file
2023-10-29 00:03:39 -07:00
r = strcmp(rpth[sz - 1], "/") ? from : 0; // fail if last element of path is a /
if(sz - !strcmp(rpth[sz - 1], "/") - 1 != i) r = 0; // TODO does this work. fail if the current element is not the last one, excluding a possible "/"
2023-10-27 21:54:33 -07:00
goto ret;
break;
2023-10-29 00:03:39 -07:00
case 1: // directory
2023-10-27 21:54:33 -07:00
for(int c = 0; c < 121; c++) {
if(!d.data[c]) {
r = 0;
goto ret;
}
lseek(fd, ((uint64_t)d.data[c]) << 9, SEEK_SET);
read(fd, &next, 512);
2023-11-01 00:37:13 -07:00
if(nmatch((char*)next.name, rpth[i])) {
2023-10-27 21:54:33 -07:00
// TODO set r if last element
2023-10-29 00:03:39 -07:00
if(i == sz - 1 - !strcmp(rpth[sz - 1], "/")) {
r = d.data[c];
goto ret;
}
from = d.data[c];
2023-10-27 21:54:33 -07:00
break;
}
2023-10-29 00:03:39 -07:00
} // else check linked sector:
2023-10-27 21:54:33 -07:00
cls: lseek(fd, ((uint64_t)(*sp)) << 9, SEEK_SET);
read(fd, ns, 512);
for(int c = 0; c < 127; c++) {
if(!ns[c]) {
r = 0;
goto ret;
}
lseek(fd, ((uint64_t)d.data[c]) << 9, SEEK_SET);
read(fd, &next, 512);
2023-11-01 00:37:13 -07:00
if(nmatch((char*)next.name, rpth[i])) {
2023-10-27 21:54:33 -07:00
// TODO set r if last element
2023-10-29 00:03:39 -07:00
if(i == sz - 1 - !strcmp(rpth[sz - 1], "/")) {
r = d.data[c];
goto ret;
}
from = d.data[c];
2023-10-27 21:54:33 -07:00
break;
}
2023-10-29 00:03:39 -07:00
} // else go to next linked sector:
2023-10-27 21:54:33 -07:00
sp = ns + 127;
goto cls;
break;
}
}
ret: for(; i < sz; i++) free(rpth[i]);
free(rpth);
2023-10-29 00:03:39 -07:00
free(ns);
2023-10-27 21:54:33 -07:00
return r;
}
#define LFIL argv[1]
#define SIZE argv[2]
#define SKIP argv[3]
int mfs_new(int argc, char** argv) {
if(argc < 4) return !!printf("need arguments: [file] [size] [sector offset]\n");
int fd;
if((fd = open(LFIL, O_RDWR|O_CREAT, 0644)) < 0) return !!printf("could not open %s\n", LFIL);
uint64_t sz = atol(SIZE);
sz = (sz + ((sz & 0x1FF) ? 512 : 0)) >> 9; // round up to number of sectors
uint64_t skip = atol(SKIP);
ftruncate(fd, sz << 9);
mothfs_header* header = (mothfs_header*)mfs_hdr;
header->size = sz;
header->offset = skip;
header->reserved = 127;
// currently uses 1/8 of the partition but that isnt too bad for now
header->abm = (sz + ((sz & 7) ? 8 : 0)) >> 3;
write(fd, header, 512); // write bootloader
// start writing initial abm
lseek(fd, 512*(header->reserved + 1), SEEK_SET);
// volume name
memcpy(header->volname, "mothfs\0????????", 15); // this will look really funny if parsed wrong
// reserve the boot sector, bootcode area, and abm
uint8_t* rsv = malloc(header->abm << 9);
memset(rsv, 0, header->abm << 9);
for(unsigned long i = 0; i < 1 + header->reserved + header->abm; i++) setbit(rsv, i);
write(fd, rsv, header->abm << 9);
free(rsv);
mothfs_file root;
memset(&root, 0, sizeof(mothfs_file));
root.type = MFS_DIR;
root.ext = 0;
*root.data = 0; // no files yet - that is the user's job
// set root to itself
root.dir = ((uint64_t)lseek(fd, 0, SEEK_CUR)) >> 9;
write(fd, &root, 512);
2023-11-01 00:37:13 -07:00
return 0;
2023-10-27 21:54:33 -07:00
}
int mfs_insert(int argc, char** argv) {
if(argc < 3) return !!printf("need arguments: [mothfs file] [file to insert]\n");
2023-11-01 00:37:13 -07:00
return 1;
2023-10-27 21:54:33 -07:00
}
2023-10-29 02:05:53 -07:00
#define NUM_MULTICALL 2
2023-10-27 21:54:33 -07:00
multicall mc[NUM_MULTICALL] = {
{"new", mfs_new},
2023-10-29 02:05:53 -07:00
{"insert", mfs_insert},
2023-10-27 21:54:33 -07:00
};
int main(int argc, char** argv) {
int y;
2023-10-29 02:05:53 -07:00
//char** x = psplit("/pl/../././../p2/p3/..//", &y);
//char** x = psplit("/p2/", &y);
2023-11-01 00:37:13 -07:00
//char** x = psplit("../../p2/", &y);
2023-10-29 02:05:53 -07:00
char** x = psplit("pl/../../././../p2/p3/..//", &y);
2023-10-27 21:54:33 -07:00
printf("%i\n", y);
2023-10-29 02:05:53 -07:00
for(int i = 0; i < y; i++) printf("%i:\t%s\n", i, x[i]);
2023-10-27 21:54:33 -07:00
if(argc < 2) err: {
printf("valid functions:");
for(int i = 0; i < NUM_MULTICALL; i++) printf(" %s%c", mc[i].name, ((NUM_MULTICALL - i) ^ 1) ? ',' : '\n');
return 1;
}
for(int i = 0; i < NUM_MULTICALL; i++) if(!strcmp(argv[1], mc[i].name)) return mc[i].fn(argc - 1, argv + 1);
goto err;
}