Added file searching

This commit is contained in:
Conál Paxton 2026-03-04 17:17:30 -05:00
parent a83b935482
commit 3868eb4ac5
16 changed files with 187 additions and 120 deletions

BIN
bin/os

Binary file not shown.

BIN
image.hdd

Binary file not shown.

BIN
image.hdd Normal file

Binary file not shown.

2
limine

@ -1 +1 @@
Subproject commit e0e61c946933696453f591da525ab1f8a66a553d Subproject commit eecf8d682a749701691e31b89f66f330f525c611

Binary file not shown.

View File

@ -1,19 +1,20 @@
obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \ obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \
src/prompt/file.h src/acpi.h src/common.h src/ahci.h src/alloc.h \ src/prompt/file.h src/prompt/file.h src/acpi.h src/common.h src/ahci.h \
src/apic.h src/fat32.h src/lib/stdio.h src/lib/malloc.h \ src/alloc.h src/apic.h src/fat32.h src/lib/ctype.h src/lib/string.h \
src/lib/../common.h src/lib/../kbd.h src/lib/../print.h src/print.h src/lib/stdio.h src/lib/malloc.h src/lib/../kbd.h src/lib/../print.h
src/../include/limine.h: src/../include/limine.h:
src/prompt/lex.h: src/prompt/lex.h:
src/prompt/file.h: src/prompt/file.h:
src/prompt/file.h:
src/acpi.h: src/acpi.h:
src/common.h: src/common.h:
src/ahci.h: src/ahci.h:
src/alloc.h: src/alloc.h:
src/apic.h: src/apic.h:
src/fat32.h: src/fat32.h:
src/lib/ctype.h:
src/lib/string.h:
src/lib/stdio.h: src/lib/stdio.h:
src/lib/malloc.h: src/lib/malloc.h:
src/lib/../common.h:
src/lib/../kbd.h: src/lib/../kbd.h:
src/lib/../print.h: src/lib/../print.h:
src/print.h:

Binary file not shown.

4
run.sh
View File

@ -1,6 +1,6 @@
qemu-system-x86_64 \ # qemu-system-x86_64 \
/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe \
-drive id=disk0,file=image.hdd,format=raw,if=none \ -drive id=disk0,file=image.hdd,format=raw,if=none \
-device ich9-ahci,id=ahci0 \ -device ich9-ahci,id=ahci0 \
-device ide-hd,drive=disk0,bus=ahci0.0 -device ide-hd,drive=disk0,bus=ahci0.0
#/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe image.hdd

View File

@ -3,6 +3,8 @@
#include "ahci.h" #include "ahci.h"
#include "alloc.h" #include "alloc.h"
#include "common.h" #include "common.h"
#include "lib/ctype.h"
#include "lib/string.h"
#include "lib/stdio.h" #include "lib/stdio.h"
// FAT32 BPB (BIOS Parameter Block) sits at the start of sector 0 // FAT32 BPB (BIOS Parameter Block) sits at the start of sector 0
@ -141,3 +143,110 @@ enum fat32_attr {
static u32 fat32_dirent_cluster(fat32_dirent_t* dirent) { static u32 fat32_dirent_cluster(fat32_dirent_t* dirent) {
return ((u32)dirent->cluster_high << 16) | dirent->cluster_low; return ((u32)dirent->cluster_high << 16) | dirent->cluster_low;
} }
static void fat32_to_name83(const char* name, u8* out) {
memset(out, ' ', 11);
const char* dot = NULL;
for (const char* p = name; *p; p++) {
if (*p == '.') dot = p;
}
// copy base name (up to 8 chars)
int base_len = dot ? (int)(dot - name) : (int)strlen(name);
if (base_len > 8) base_len = 8;
for (int i = 0; i < base_len; i++)
out[i] = (u8) toupper((unsigned char)name[i]);
// copy extension (up to 3 chars)
if (dot && dot[1]) {
const char* ext = dot + 1;
int ext_len = (int)strlen(ext);
if (ext_len > 3) ext_len = 3;
for (int i = 0; i < ext_len; i++)
out[8 + i] = (u8) toupper((unsigned char)ext[i]);
}
}
static fat32_dirent_t* fat32_find(int port, fat32_vol_t* vol, u32 dir_cluster, const u8* name83) {
u32 cluster_size = vol->sectors_per_cluster * TODO_MAKE_ME_DYNAMIC_BLOCK_SIZE;
u8* buff = (u8*) alloc(cluster_size);
u32 cluster = dir_cluster;
while (!fat32_is_eof(cluster)) {
if (fat32_read_cluster(port, vol, cluster, buff) < 0) {
printf("fat32_find: read failed at cluster=%u\n", cluster);
break;
}
u32 entries_per_cluster = cluster_size / sizeof(fat32_dirent_t);
fat32_dirent_t* dir = (fat32_dirent_t*) buff;
for (u32 i = 0; i < entries_per_cluster; i++) {
fat32_dirent_t* e = &dir[i];
if (e->name[0] == 0x00) goto not_found;
if (e->name[0] == 0xE5) continue;
if ((e->attr & ATTR_LFN) == ATTR_LFN) continue;
if (e->attr & ATTR_VOL_ID) continue;
if (memcmp(e->name, name83, 8) == 0 && memcmp(e->ext, name83 + 8, 3) == 0) {
fat32_dirent_t* result = (fat32_dirent_t*) alloc(sizeof(fat32_dirent_t));
*result = *e;
return result;
}
}
cluster = fat32_next(port, vol, cluster);
}
not_found:
return NULL;
}
// fat32_find_path: resolve a full path like "/dir/subdir/file.txt"
// leading slash is optional, "" or "/" both refer to root
static fat32_dirent_t* fat32_find_path(int port, fat32_vol_t* vol, const char* path) {
u32 cluster = vol->root_cluster;
// skip leading slash
if (*path == '/') path++;
// root itself
if (*path == '\0') return NULL;
char part[12];
while (*path) {
// extract next path component
int len = 0;
while (path[len] && path[len] != '/') len++;
if (len > 11) return NULL; // can't possibly be valid 8.3
printn(path, len);
memcpy(part, path, len);
part[len] = '\0';
path += len;
if (*path == '/') path++;
put('\n');
// convert component to 8.3
u8 name83[11];
fat32_dirent_t* e = fat32_find(port, vol, cluster, name83);
if (!e) return NULL;
// if there's more path to walk, this must be a directory
if (*path != '\0') {
if (!(e->attr & ATTR_DIR)) return NULL;
cluster = fat32_dirent_cluster(e);
// free(e); // if you're tracking allocs
continue;
}
// last component — return it whether file or dir
return e;
}
return NULL;
}

35
src/lib/ctype.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
static bool isdigit(int ch) {
return (ch <= '9' && ch >= '0');
}
static bool isalpha(int ch) {
return (ch <= 'z' && ch >= 'a')
|| (ch <= 'Z' && ch >= 'A');
}
static bool isalnum(int ch) {
return isdigit(ch) || isalpha(ch);
}
static int toupper(int ch) {
if(ch >= 'a' && ch <= 'z')
ch += 'A'-'a';
return ch;
}
static int tolower(int ch) {
if(ch >= 'A' && ch <= 'Z')
ch += 'a'-'A';
return ch;
}
static bool isxdigit(int ch) {
return isdigit(ch) || (isalpha(ch) && tolower(ch) <= 'f');
}
// cribbed from musl
static bool isspace(int ch) {
return ch == ' ' || (unsigned)ch-'\t' < 5;
}

View File

@ -143,49 +143,46 @@ static inline char *_fmt_uint(char *end, u64 val, int base, bool upper) {
static inline int vprintf(const char *fmt, va_list ap) { static inline int vprintf(const char *fmt, va_list ap) {
int written = 0; int written = 0;
#define _EMIT(c) do { put(c); written++; } while(0) #define _EMIT(c) do { put(c); written++; } while(0)
#define _EMITS(s) do { const char *_p=(s); while(*_p){_EMIT(*_p);_p++;} } while(0) #define _EMITS(s) do { const char *_p=(s); while(*_p){_EMIT(*_p);_p++;} } while(0)
while (*fmt) { while (*fmt) {
if (*fmt != '%') { _EMIT(*fmt++); continue; } if (*fmt != '%') { _EMIT(*fmt++); continue; }
fmt++; /* skip '%' */ fmt++; /* skip '%' */
/* flags */ /* flags */
bool left_align = false; bool left_align = false;
bool zero_pad = false; bool zero_pad = false;
if (*fmt == '-') { left_align = true; fmt++; } if (*fmt == '-') { left_align = true; fmt++; }
if (*fmt == '0') { zero_pad = true; fmt++; } if (*fmt == '0') { zero_pad = true; fmt++; }
/* width */ /* width */
int width = 0; int width = 0;
while (*fmt >= '0' && *fmt <= '9') width = width*10 + (*fmt++ - '0'); while (*fmt >= '0' && *fmt <= '9') width = width*10 + (*fmt++ - '0');
/* precision: %.N */
int precision = -1; /* -1 = no precision specified */
if (*fmt == '.') {
fmt++;
precision = 0;
while (*fmt >= '0' && *fmt <= '9') precision = precision*10 + (*fmt++ - '0');
}
/* length modifier */ /* length modifier */
int lng = 0; /* 0=int, 1=long, 2=long long */ int lng = 0; /* 0=int, 1=long, 2=long long */
if (*fmt == 'l') { lng=1; fmt++; } if (*fmt == 'l') { lng=1; fmt++; }
if (*fmt == 'l') { lng=2; fmt++; } if (*fmt == 'l') { lng=2; fmt++; }
char tmp[66]; char tmp[66];
char *s = NULL; char *s = NULL;
char cbuf[2] = {0,0}; char cbuf[2] = {0,0};
bool neg = false; bool neg = false;
switch (*fmt++) { switch (*fmt++) {
case '%': case '%':
_EMIT('%'); _EMIT('%');
continue; continue;
case 'c': case 'c':
cbuf[0] = (char)va_arg(ap, int); cbuf[0] = (char)va_arg(ap, int);
s = cbuf; s = cbuf;
break; break;
case 's': case 's':
s = va_arg(ap, char *); s = va_arg(ap, char *);
if (!s) s = "(null)"; if (!s) s = "(null)";
break; break;
case 'd': case 'i': { case 'd': case 'i': {
i64 v = (lng==2) ? va_arg(ap,long long) : i64 v = (lng==2) ? va_arg(ap,long long) :
(lng==1) ? va_arg(ap,long) : (lng==1) ? va_arg(ap,long) :
@ -194,7 +191,6 @@ static inline int vprintf(const char *fmt, va_list ap) {
s = _fmt_uint(tmp+65, (u64)v, 10, false); s = _fmt_uint(tmp+65, (u64)v, 10, false);
break; break;
} }
case 'u': { case 'u': {
u64 v = (lng==2) ? va_arg(ap,unsigned long long) : u64 v = (lng==2) ? va_arg(ap,unsigned long long) :
(lng==1) ? va_arg(ap,unsigned long) : (lng==1) ? va_arg(ap,unsigned long) :
@ -202,7 +198,6 @@ static inline int vprintf(const char *fmt, va_list ap) {
s = _fmt_uint(tmp+65, v, 10, false); s = _fmt_uint(tmp+65, v, 10, false);
break; break;
} }
case 'o': { case 'o': {
u64 v = (lng==2) ? va_arg(ap,unsigned long long) : u64 v = (lng==2) ? va_arg(ap,unsigned long long) :
(lng==1) ? va_arg(ap,unsigned long) : (lng==1) ? va_arg(ap,unsigned long) :
@ -210,7 +205,6 @@ static inline int vprintf(const char *fmt, va_list ap) {
s = _fmt_uint(tmp+65, v, 8, false); s = _fmt_uint(tmp+65, v, 8, false);
break; break;
} }
case 'x': { case 'x': {
u64 v = (lng==2) ? va_arg(ap,unsigned long long) : u64 v = (lng==2) ? va_arg(ap,unsigned long long) :
(lng==1) ? va_arg(ap,unsigned long) : (lng==1) ? va_arg(ap,unsigned long) :
@ -218,7 +212,6 @@ static inline int vprintf(const char *fmt, va_list ap) {
s = _fmt_uint(tmp+65, v, 16, false); s = _fmt_uint(tmp+65, v, 16, false);
break; break;
} }
case 'X': { case 'X': {
u64 v = (lng==2) ? va_arg(ap,unsigned long long) : u64 v = (lng==2) ? va_arg(ap,unsigned long long) :
(lng==1) ? va_arg(ap,unsigned long) : (lng==1) ? va_arg(ap,unsigned long) :
@ -226,7 +219,6 @@ static inline int vprintf(const char *fmt, va_list ap) {
s = _fmt_uint(tmp+65, v, 16, true); s = _fmt_uint(tmp+65, v, 16, true);
break; break;
} }
case 'p': { case 'p': {
u64 v = (u64)(uintptr_t)va_arg(ap, void *); u64 v = (u64)(uintptr_t)va_arg(ap, void *);
print("0x"); print("0x");
@ -234,30 +226,33 @@ static inline int vprintf(const char *fmt, va_list ap) {
s = _fmt_uint(tmp+65, v, 16, false); s = _fmt_uint(tmp+65, v, 16, false);
break; break;
} }
default: default:
_EMIT('?'); _EMIT('?');
continue; continue;
} }
/* apply precision to string length (%.8s style) */
/* padding / output */
int slen = 0; int slen = 0;
if (precision >= 0) {
/* count up to precision chars, stop at null */
const char *p = s;
while (slen < precision && *p) { slen++; p++; }
} else {
for (const char *p = s; *p; p++) slen++; for (const char *p = s; *p; p++) slen++;
}
if (neg) slen++; /* for '-' */ if (neg) slen++; /* for '-' */
int pad = width - slen; int pad = width - slen;
if (!left_align && pad > 0) { if (!left_align && pad > 0) {
char pc = zero_pad ? '0' : ' '; char pc = zero_pad ? '0' : ' ';
if (neg && zero_pad) { _EMIT('-'); neg=false; written++; } if (neg && zero_pad) { _EMIT('-'); neg=false; written++; }
while (pad-- > 0) { _EMIT(pc); written++; } while (pad-- > 0) { _EMIT(pc); written++; }
} }
if (neg) { _EMIT('-'); written++; } if (neg) { _EMIT('-'); written++; }
while (*s) { _EMIT(*s++); written++; } /* emit exactly slen chars (respects precision cutoff) */
int emit = neg ? slen - 1 : slen;
for (int i = 0; i < emit && *s; i++) { _EMIT(*s++); written++; }
if (left_align && pad > 0) if (left_align && pad > 0)
while (pad-- > 0) { _EMIT(' '); written++; } while (pad-- > 0) { _EMIT(' '); written++; }
} }
#undef _EMIT #undef _EMIT
#undef _EMITS #undef _EMITS
return written; return written;

8
src/lib/string.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
static size_t strlen(const char* str) {
size_t len = 0;
while(*(str++))
len++;
return len;
}

View File

@ -329,44 +329,11 @@ void kmain() {
ls(port, 0, &vol, vol.root_cluster); ls(port, 0, &vol, vol.root_cluster);
//dealloc((void*) bpb, 1<<12); print("Attempting to find FORTU.NE\n");
fat32_dirent_t* fortune = fat32_find_path(port, &vol, "fort/fortu.ne");
// #define LINES 40
// size_t max_len = MAX_LINE_LEN;
// char* lines[LINES];
// size_t n_lines = 0; printf("Fortune size: %d\n", fortune->file_size);
// for(n_lines = 0; n_lines < LINES; n_lines++) {
// char* line = getline_alloc(max_len);
// if(!line)
// break;
// if(line[0] == 'F' && line[1] == 'I' && line[2] == '\n')
// break;
// lines[n_lines] = line;
// }
// const char* name = "stdin";
// struct file input = {
// .row = 0,
// .col = 0,
// .rows = n_lines,
// .lines = (char**)lines,
// .name = name,
// .tokens = NULL,
// .tail = &input.tokens,
// };
// int res = lex(&input);
// print("Number of Errors: ");
// print8(res);
// printf("\n# of Tokens: %d\n", input.tokens->len);
// struct token* token = input.tokens;
// for(;token; token = token->next) {
// print_tok(token);
// }
hang(); hang();
} }

View File

@ -23,7 +23,7 @@ size_t register_iden(const char* data, size_t len, uint64_t hash) {
for(i = 0; i < identbl_len; i++) { for(i = 0; i < identbl_len; i++) {
if(hash == identbl[i].hash && if(hash == identbl[i].hash &&
identbl[i].len == len && identbl[i].len == len &&
strneq(data, identbl[i].data, len)) { strneq(data, (const char*)identbl[i].data, len)) {
return i; return i;
} }
} }

View File

@ -3,19 +3,14 @@
#include "iden.h" #include "iden.h"
#include "lex.h" #include "lex.h"
#include "../lib/stdio.h" #include "../lib/stdio.h"
#include "../lib/ctype.h"
#include "../lib/string.h"
static int lex_error(struct file* state, const char* err) { static int lex_error(struct file* state, const char* err) {
printf("%s:%d:%d: %s\n", state->name, state->row+1, state->col+1, err); printf("%s:%d:%d: %s\n", state->name, state->row+1, state->col+1, err);
return 1; return 1;
} }
static size_t strlen(const char* str) {
size_t len = 0;
while(*(str++))
len++;
return len;
}
static bool strneq(const char* l, const char* r, size_t n) { static bool strneq(const char* l, const char* r, size_t n) {
for(size_t i = 0; i < n; i++) { for(size_t i = 0; i < n; i++) {
if(r[i] != l[i]) if(r[i] != l[i])
@ -71,41 +66,6 @@ static struct token* tok(enum tokentype type, struct file* state, int col, void*
} }
static bool isdigit(int ch) {
return (ch <= '9' && ch >= '0');
}
static bool isalpha(int ch) {
return (ch <= 'z' && ch >= 'a')
|| (ch <= 'Z' && ch >= 'A');
}
static bool isalnum(int ch) {
return isdigit(ch) || isalpha(ch);
}
static int toupper(int ch) {
if(ch >= 'a' && ch <= 'z')
ch += 'A'-'a';
return ch;
}
static int tolower(int ch) {
if(ch >= 'A' && ch <= 'Z')
ch += 'a'-'A';
return ch;
}
static bool isxdigit(int ch) {
return isdigit(ch) || (isalpha(ch) && tolower(ch) <= 'f');
}
// cribbed from musl
static bool isspace(int ch) {
return ch == ' ' || (unsigned)ch-'\t' < 5;
}
static int parse_num(struct file* state, int save, int sign) { static int parse_num(struct file* state, int save, int sign) {
int64_t num = 0; int64_t num = 0;
int ch = state->lines[state->row][state->col]; int ch = state->lines[state->row][state->col];

View File

@ -1,5 +1,6 @@
#include "iden.h" #include "iden.h"
#include "lex.h" #include "lex.h"
#include "../lib/stdio.h"
#include "../print.h" #include "../print.h"
#include "../common.h" #include "../common.h"
@ -48,16 +49,7 @@ void print_tok(struct token* tok) {
case TOK_IDEN: { case TOK_IDEN: {
color = 0x137FFF; color = 0x137FFF;
struct iden* id = &identbl[tok->iden]; struct iden* id = &identbl[tok->iden];
print("iden: { .hash = 0x"); printf("iden: { .hash = 0x%x, .data = \"%s\"\" (%d)\n", id->hash, *id->data, (int)id->len);
print32(id->hash);
print(", .data = \"");
print(id->data);
print("\" (");
/* print pointer value as hex */
print("ptr"); /* pointer printing omitted; add if needed */
print("), .len = ");
print32((int)id->len);
print(" }:\n");
break; break;
} }
case TOK_OP: { case TOK_OP: {