shithub: fsgen

Download patch

ref: 74dc57b5fcfa1c98de646674040741f543d358ec
parent: 3c203e383e93d0ae44263e9f824d66f8e1f7878d
author: sirjofri <sirjofri@sirjofri.de>
date: Tue Dec 16 16:34:38 EST 2025

first directory listings work

--- a/code.c
+++ b/code.c
@@ -85,11 +85,28 @@
 printls(VFile *file)
 {
 	char buf[64];
-	pathtostring(buf, sizeof(buf), file->path);
-	print("static void\nfsls_%s(...)\n", buf);
+	genfuncname(file, buf, sizeof(buf), "ls");
+	print("static int\n%s(int index, Dir *dir", buf);
+	printvars(file, ", char *");
+	print(")\n");
 }
 
 void
+printlsend(VFile *file)
+{
+	char buf[32];
+	genfuncname(file, buf, sizeof(buf), "ls");
+	print("}\n\n");
+	print("static int\nCall_%s(int i, Dir *d, void *aux)\n{\n", buf);
+	print("	FileAux *a = aux;\n");
+	print("	USED(a);\n");
+	print("	return %s(i, d", buf);
+	printvars(file, ", a->");
+	print(");\n");
+	print("}\n\n");
+}
+
+void
 printpre()
 {
 	print("%s",
@@ -289,6 +306,10 @@
 		if (f->hasstat) {
 			genfuncname(f, buf, sizeof(buf), "stat");
 			print("		.stat = Call_%s,\n", buf);
+		}
+		if (f->hasls) {
+			genfuncname(f, buf, sizeof(buf), "ls");
+			print("		.ls = Call_%s,\n", buf);
 		}
 		print("	},\n");
 		rprintfilenames(v->children);
--- a/dat.h
+++ b/dat.h
@@ -4,6 +4,7 @@
 struct VFile {
 	char *path;
 	int isdir;
+	int hasls;
 	int hasread;
 	int haswrite;
 	int hasstat;
--- a/fns.h
+++ b/fns.h
@@ -9,6 +9,8 @@
 
 void printgenfunc(VFile*, char*);
 void printgenfuncend(VFile*, char*);
+void printls(VFile*);
+void printlsend(VFile*);
 void printfs(void);
 void printpre(void);
 
--- a/fshandler.inc
+++ b/fshandler.inc
@@ -1,19 +1,89 @@
 #line 0 "fshandler.inc"
+
+typedef struct DirreadArgs DirreadArgs;
+struct DirreadArgs {
+	int *hierarchy;
+	int (*func)(int,Dir*,void*);
+	int num;
+	void *aux;
+};
+
+static int
+default_dirread(int i, Dir *d, void *aux)
+{
+	int q;
+	int ret;
+	DirreadArgs *args = aux;
+	int *fh = args->hierarchy;
+	Filedata *fd;
+	
+	if (!fh)
+		return -1;
+	
+//	fprint(2, "gen: %d %d %p\n", i, args->num, args->func);
+	
+	/* for some very strange reason, after setting args->num, the values are still the same for the next round. I have no idea why this could happen, and it also shouldn't hurt, it's just not clean. */
+	if (args->func) {
+		if (args->num < 0) {
+			ret = args->func(i, d, args->aux);
+			if (ret == 0)
+				return ret;
+			/* set numbers and skip future loops */
+			args->num = i;
+		}
+	} else {
+		args->num = 0;
+	}
+//	fprint(2, "pfu: %d %d %p\n", i, args->num, args->func);
+	
+	i -= args->num;
+Next:
+	q = fh[i];
+	if (!q)
+		return -1;
+	
+	fd = &filedata[q];
+	if (fd->dir.name[0] == '{') {
+		/* if this is a variable, skip */
+		i++;
+		args->num++;
+		goto Next;
+	}
+	
+	d->name = estrdup9p(fd->dir.name);
+	d->uid = estrdup9p("none");
+	d->gid = estrdup9p("none");
+	d->muid = estrdup9p("none");
+	return 0;
+}
+
 static void
 fsread(Req *r)
 {
 	int q;
 	Filedata *fd;
+	DirreadArgs args;
 	
 	q = breakqid(r->fid->qid.path);
 	
 	fd = &filedata[q];
-	if (!fd->read) {
+	if (fd->read) {
+		fd->read(r);
+		/* if read is implemented, it should respond */
+		return;
+	}
+	
+	if (fd->dir.mode&DMDIR) {
+		args.hierarchy = filehierarchy[q];
+		args.func = fd->ls;
+		args.num = -1;
+		args.aux = r->fid->aux;
+		
+		dirread9p(r, default_dirread, &args);
 		respond(r, nil);
 		return;
 	}
-	fd->read(r);
-	/* if read is implemented, it should respond */
+	respond(r, "read error");
 }
 
 static void
--- a/main.c
+++ b/main.c
@@ -102,11 +102,11 @@
 				break;
 			}
 			if (strcmp("ls{", s) == 0) {
-				if (currentfile->isdir) {
+				if (currentfile->hasls) {
 					werrstr("%s already has a ls function", currentfile->path);
 					goto Err;
 				}
-				currentfile->isdir++;
+				currentfile->hasls++;
 				state = COPY;
 				break;
 			}
@@ -171,7 +171,7 @@
 				break;
 			}
 			if (strcmp("ls}", s) == 0) {
-				printgenfuncend(currentfile, "ls");
+				printlsend(currentfile);
 				state = HASFILE;
 				break;
 			}
@@ -211,7 +211,7 @@
 				break;
 			}
 			if (strcmp("ls{", s) == 0) {
-				printgenfunc(currentfile, "ls");
+				printls(currentfile);
 				print("#line %d \"%s\"\n", line, file);
 				print("{\n");
 				state = COPY;
--- a/preamble.inc
+++ b/preamble.inc
@@ -13,6 +13,7 @@
 	void (*read)(Req*);
 	void (*write)(Req*);
 	void (*stat)(Req*);
+	int (*ls)(int,Dir*,void*);
 	
 	Dir dir;
 };
--- a/test/test.fs
+++ b/test/test.fs
@@ -33,5 +33,32 @@
 	respond(r, nil);
 r}
 w{
-	respond(r, "write");
+	respond(r, "write prohibited");
 w}
+
+# implement a directory listing
+/test
+ls{
+	// fprint(2, "test_ls: %d\n", index);
+	
+	switch (index) {
+	case 0:
+		dir->name = estrdup9p("File0");
+		break;
+	case 1:
+		dir->name = estrdup9p("File1");
+		break;
+	case 2:
+		dir->name = estrdup9p("File2");
+		break;
+	case 3:
+		dir->name = estrdup9p("File3");
+		break;
+	default:
+		return -1;
+	}
+	dir->uid = estrdup9p("none");
+	dir->gid = estrdup9p("none");
+	dir->muid = estrdup9p("none");
+	return 0;
+ls}
--