shithub: build

Download patch

ref: c34bf6a2892dbb1dde83c59be4e224defb09cdfe
parent: 4ffcbbab95b379e47876a1665e1ac5b15fe03754
author: Jacob Moody <moody@posixcafe.org>
date: Sat Aug 19 21:21:38 EDT 2023

write support

--- a/grpfs.c
+++ b/grpfs.c
@@ -10,7 +10,7 @@
 typedef struct XFile XFile;
 typedef struct Grp Grp;
 
-enum { Qfile, Qtile };
+enum { Qfile, Qtile, Qgrp };
 
 struct XFile {
 	char type;
@@ -30,60 +30,47 @@
 	uint pal[256];
 };
 
-ulong
-get16(uchar *b)
-{
-	ulong x;
+#define GET16(p) ((u16int)(p)[0] | (u16int)(p)[1]<<8)
+#define GET32(p) ((u32int)(p)[0] | (u32int)(p)[1]<<8 | (u32int)(p)[2]<<16 | (u32int)(p)[3]<<24)
+#define PUT16(p, u) ((p)[1] = (u)>>8, (p)[0] = (u))
+#define PUT32(p, u) ((p)[3] = (u)>>24, (p)[2] = (u)>>16, (p)[1] = (u)>>8, (p)[0] = (u))
 
-	x = (b[0]<<0) | (b[1]<<8);
-	return x;
-}
+static Grp ggrp;
+static char kens[] = "KenSilverman";
 
-ulong
-get32(uchar *b)
-{
-	ulong x;
-
-	x = (b[0]<<0) | (b[1]<<8) | (b[2]<<16) | (b[3]<<24);
-	return x;
-}
-
-Grp ggrp;
-
 static void
-fsreadtile(Req *r)
+fsreadtile(Req *r, XFile *f)
 {
-	XFile *f;
 	static uchar buf[64*1024];
 	uint *dot;
 	int i;
 
 	f = r->fid->file->aux;
-	if(f->buf == nil){
-		f->buf = mallocz((11 * 5) + 5 + (f->x * f->y * 4), 1);
-		sprint((char*)f->buf, "%11s %11d %11d %11d %11d", "a8r8g8b8", 0, 0, f->x, f->y);
-		dot = (uint*)(f->buf + (11 * 5) + 5);
-		pread(ggrp.fd, buf, f->x * f->y, f->off);
-		for(i = 0; i < f->x * f->y; i++)
-			dot[i] = ggrp.pal[buf[i]];
-		f->size = (11 * 5) + 5 + (f->x * f->y * 4);
+	if(f->buf != nil){
+	Service:
+		readbuf(r, f->buf, f->size);
+		respond(r, nil);
+		return;
 	}
-	readbuf(r, f->buf, f->size);
-	respond(r, nil);
+
+	f->buf = mallocz((11 * 5) + 5 + (f->x * f->y * 4), 1);
+	sprint((char*)f->buf, "%11s %11d %11d %11d %11d", "a8r8g8b8", 0, 0, f->x, f->y);
+	dot = (uint*)(f->buf + (11 * 5) + 5);
+	pread(ggrp.fd, buf, f->x * f->y, f->off);
+	for(i = 0; i < f->x * f->y; i++)
+		dot[i] = ggrp.pal[buf[i]];
+	f->size = (11 * 5) + 5 + (f->x * f->y * 4);
+	goto Service;
 }
 
 static void
-fsread(Req *r)
+fsreadfile(Req *r, XFile *f)
 {
-	XFile *f;
-
-	f = r->fid->file->aux;
-
-	if(f->type == Qtile){
-		fsreadtile(r);
+	if(f->buf){
+		readbuf(r, f->buf, f->size);
+		respond(r, nil);
 		return;
 	}
-
 	r->ofcall.count = r->ifcall.count;
 	if(r->ifcall.offset >= f->size){
 		r->ofcall.count = 0;
@@ -96,8 +83,128 @@
 	respond(r, nil);
 }
 
+static void
+fsreadgrp(Req *r, XFile*)
+{
+	int i, j;
+	XFile *f;
+	vlong off;
+	u32int count;
+	uchar buf[8192];
+	uchar *p;
+
+	off = r->ifcall.offset;
+	count = r->ifcall.count;
+	if(off < 12 + 4){
+		memcpy(buf, kens, 12);
+		PUT32(buf+12, ggrp.nf);
+		readbuf(r, buf, 16);
+		respond(r, nil);
+		return;
+	}
+	off -= 12 + 4;
+	if(off < 16 * ggrp.nf){
+		assert(sizeof buf > 16*ggrp.nf);
+		p = buf;
+		for(i = 0; i < ggrp.nf; i++){
+			memcpy(p, ggrp.f[i].name, 12);
+			for(j = 0; j < 12; j++)
+				*p++ = toupper(*p);
+			PUT32(p, ggrp.f[i].size);
+			p+=4;
+		}
+		r->ifcall.offset = off;
+		readbuf(r, buf, 16*ggrp.nf);
+		respond(r, nil);
+		return;
+	}
+	off -= 16*ggrp.nf;
+	for(i = 0; i < ggrp.nf; i++){
+		f = ggrp.f+i;
+		if(off >= f->size){
+			off -= f->size;
+			continue;
+		}
+		if(count+off >= f->size)
+			count = f->size-off;
+		if(f->buf != nil){
+			r->ifcall.offset = off;
+			r->ifcall.count = count;
+			readbuf(r, f->buf, f->size);
+		} else
+			r->ofcall.count = pread(ggrp.fd, r->ofcall.data, count, off+f->off);
+		respond(r, nil);
+		return;
+	}
+	r->ofcall.count = 0;
+	respond(r, nil);
+}
+
+void (*readftab[])(Req*,XFile*) = {
+	[Qfile] fsreadfile,
+	[Qtile] fsreadtile,
+	[Qgrp]  fsreadgrp,
+};
+
+static void
+fsread(Req *r)
+{
+	XFile *f;
+
+	f = r->fid->file->aux;
+	if(f->type >= nelem(readftab))
+		sysfatal("invalid type %d", f->type);
+	readftab[f->type](r, f);
+}
+
+static void
+fswritefile(Req *r, XFile *f)
+{
+	vlong i, n;
+
+	if(f->buf == nil){
+		f->buf = malloc(f->size);
+		for(n = 0; n != f->size;){
+			i = pread(ggrp.fd, f->buf + n, f->size - n, f->off + n);
+			if(i < 0){
+				responderror(r);
+				return;
+			}
+			n += i;
+		}
+	}
+	if(r->ifcall.count + r->ifcall.offset > f->size){
+		f->size = r->ifcall.count + r->ifcall.offset;
+		f->buf = realloc(f->buf, f->size);
+	}
+	memmove(f->buf + r->ifcall.offset, r->ifcall.data, r->ifcall.count);
+	r->ofcall.count = r->ifcall.count;
+	respond(r, nil);
+}
+
+void (*writeftab[])(Req*,XFile*) = {
+	[Qfile] fswritefile,
+	[Qtile] nil,
+	[Qgrp]  nil,
+};
+
+static void
+fswrite(Req *r)
+{
+	XFile *f;
+
+	f = r->fid->file->aux;
+	if(f->type >= nelem(writeftab))
+		sysfatal("invalid type %d", f->type);
+	if(writeftab[f->type] == nil)
+		respond(r, "not supported");
+	else
+		writeftab[f->type](r, f);
+}
+
 Srv fs = {
 	.read=fsread,
+	.write=fswrite,
 };
 
 void
@@ -112,15 +219,15 @@
 	Bseek(b, off, 0);
 	n = Bread(b, buf, 16);
 	off += n;
-	nt = get32(buf+12) - get32(buf+8) + 1;
+	nt = GET32(buf+12) - GET32(buf+8) + 1;
 
 	for(i = 0; i < nt; i++){
 		Bread(b, buf, 2);
-		tilesx[i] = get16(buf);
+		tilesx[i] = GET16(buf);
 	}
 	for(i = 0; i < nt; i++){
 		Bread(b, buf, 2);
-		tilesy[i] = get16(buf);
+		tilesy[i] = GET16(buf);
 	}
 	off += (nt * 2) + (nt * 2) + (nt * 4);
 
@@ -152,7 +259,6 @@
 void
 parsegrp(int fd)
 {
-	char *kens = "KenSilverman";
 	uchar buf[64];
 	uchar *p;
 	int i, n;
@@ -173,9 +279,12 @@
 
 	user = getenv("user");
 	fs.tree = alloctree(user, "sys", 0644, nil);
+	f = mallocz(sizeof *f, 1);
+	f->type = Qgrp;
+	createfile(fs.tree->root, "GRP", user, 0444, f);
 	off += n;
 	ggrp.fd = fd;
-	ggrp.nf = get32((uchar*)buf);
+	ggrp.nf = GET32((uchar*)buf);
 	ggrp.f = f = mallocz(sizeof(XFile) * ggrp.nf, 1);
 	for(i = 0; i < ggrp.nf; i++,f++){
 		n = Bread(b, buf, 12);
@@ -186,7 +295,7 @@
 		off += n;
 		n = Bread(b, buf, 4);
 		off += n;
-		f->size = get32((uchar*)buf);
+		f->size = GET32((uchar*)buf);
 	}
 
 	ggrp.nt = 0;