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}
--
⑨