richterm

"terminal emulator" with support for text fonts and images for plan9
git clone git://nsmpr.xyz/richterm.git
Log | Files | Refs | README

fs.c (4746B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <fcall.h>
      4 #include <thread.h>
      5 #include <draw.h>
      6 #include <9p.h>
      7 
      8 #include "array.h"
      9 #include "richterm.h"
     10 
     11 Array *consbuf, *ctlbuf, *menubuf;
     12 Channel *consc, *ctlc;
     13 File *fsroot;
     14 File *cons, *consctl, *ctl, *menu, *new, *text;
     15 Reqqueue *rq;
     16 
     17 void arrayopen(Req *);
     18 void arrayread(Req *);
     19 void arraywrite(Req *);
     20 void consread(Req *);
     21 void conswrite(Req *);
     22 void ctlread(Req *);
     23 void ctlwrite(Req *);
     24 void delayedread(Req *);
     25 void fs_destroyfid(Fid *);
     26 void fs_flush(Req *);
     27 void fs_open(Req *);
     28 void fs_read(Req *);
     29 void fs_write(Req *);
     30 void fs_stat(Req *);
     31 
     32 int
     33 initfs(char *srvname)
     34 {
     35 	static Srv srv = {
     36 		.open  = fs_open,
     37 		.read  = fs_read,
     38 		.write = fs_write,
     39 		.flush = fs_flush,
     40 		.stat  = fs_stat,
     41 		.destroyfid = fs_destroyfid,
     42 	};
     43 	consbuf = nil;
     44 	ctlbuf = nil;
     45 	rq = reqqueuecreate();
     46 	menubuf = arraycreate(sizeof(char), 1024, nil);
     47 	consc = chancreate(sizeof(Array *), 1024);
     48 	ctlc = chancreate(sizeof(Array *), 8);
     49 
     50 	srv.tree = alloctree("richterm", "richterm", DMDIR|0555, nil);
     51 	fsroot = srv.tree->root;
     52 
     53 	cons = createfile(fsroot, "cons", "richterm", DMAPPEND|0666,
     54 		fauxalloc(nil, nil, consread, conswrite, nil, nil));
     55 
     56 	consctl = createfile(fsroot, "consctl", "richterm", DMAPPEND|0666, 
     57 		fauxalloc(nil, nil, nil, nil, nil, nil));
     58 
     59 	ctl = createfile(fsroot, "ctl", "richterm", DMAPPEND|0666,
     60 		fauxalloc(nil, nil, ctlread, ctlwrite, nil, nil));
     61 
     62 	text = createfile(fsroot, "text", "richterm", 0666,
     63 		fauxalloc(richdata, arrayopen, arrayread, arraywrite, nil, nil));
     64 	text->length = richdata->count;
     65 
     66 	menu = createfile(fsroot, "menu", "richterm", 0666,
     67 		fauxalloc(menubuf, nil, arrayread, arraywrite, nil, nil));
     68 
     69 	threadpostmountsrv(&srv, srvname, "/mnt/richterm", MREPL);
     70 	return 0;
     71 }
     72 
     73 Faux *
     74 fauxalloc(
     75   Array *data,
     76   void (*open)(Req *),
     77   void (*read)(Req *),
     78   void (*write)(Req *),
     79   void (*stat)(Req *),
     80   void (*destroyfid)(Fid *))
     81 {
     82 	Faux *aux;
     83 	aux = mallocz(sizeof(Faux), 1);
     84 	*aux = (Faux) {data, open, read, write, stat, destroyfid};
     85 	return aux;
     86 }
     87 
     88 void
     89 fs_destroyfid(Fid *)
     90 {
     91 }
     92 
     93 void
     94 fs_open(Req *r)
     95 {
     96 	Faux *aux = r->fid->file->aux;
     97 	if ((aux != nil) && (aux->open != nil)) aux->open(r);
     98 	else respond(r, nil);
     99 }
    100 
    101 void
    102 fs_read(Req *r)
    103 {
    104 	reqqueuepush(rq, r, delayedread);
    105 }
    106 
    107 void
    108 fs_write(Req *r)
    109 {
    110 	Faux *aux;
    111 	aux = r->fid->file->aux;
    112 	if (aux != nil) {
    113 		if (aux->write != nil) {
    114 			aux->write(r);
    115 			nbsend(redrawc, nil);
    116 		}
    117 		else respond(r, "no write");
    118 	} else respond(r, nil);
    119 }
    120 
    121 void
    122 fs_stat(Req *r)
    123 {
    124 	Faux *aux = r->fid->file->aux;
    125 	if (aux != nil) {
    126 		if (aux->stat != nil) aux->stat(r);
    127 		else if (aux->data != nil) {
    128 			r->fid->file->length = aux->data->count;
    129 			r->d.length = aux->data->count;
    130 			respond(r, nil);
    131 		}
    132 	} else respond(r, nil);
    133 }
    134 
    135 void
    136 fs_flush(Req *r)
    137 {
    138 	respond(r, nil);
    139 }
    140 
    141 void
    142 delayedread(Req *r)
    143 {
    144 	Faux *aux;
    145 	aux = r->fid->file->aux;
    146 	if (aux != nil) {
    147 		if (aux->read != nil) aux->read(r);
    148 		else respond(r, "no read");
    149 	} else respond(r, nil);
    150 }
    151 
    152 void
    153 arrayopen(Req *r)
    154 {
    155 	Array *data = ((Faux *)r->fid->file->aux)->data;
    156 
    157 	if ((r->ifcall.mode & OTRUNC) != 0) {
    158 		qlock(data->l);
    159 		data->count = 0;
    160 		qunlock(data->l);
    161 		r->fid->file->length = 0;
    162 	}
    163 	respond(r, nil);
    164 }
    165 
    166 void
    167 arrayread(Req *r)
    168 {
    169 	Array *data = ((Faux *)r->fid->file->aux)->data;
    170 
    171 	qlock(rich.l);
    172 	qlock(data->l);
    173 	readbuf(r, data->p, data->count);
    174 	qunlock(data->l);
    175 	qunlock(rich.l);
    176 
    177 	respond(r, nil);
    178 }
    179 
    180 void
    181 arraywrite(Req *r)
    182 {
    183 	Array *data = ((Faux *)r->fid->file->aux)->data;
    184 
    185 	long count = r->ifcall.count + r->ifcall.offset;
    186 
    187 
    188 	if (count > data->count) arraygrow(data, count - data->count, nil);
    189 
    190 	else data->count = count;
    191 
    192 	qlock(data->l);
    193 
    194 	memcpy(data->p + r->ifcall.offset, r->ifcall.data, r->ifcall.count);
    195 	qunlock(data->l);
    196 
    197 	r->ofcall.count = r->ifcall.count;
    198 
    199 	r->fid->file->length = data->count;
    200 
    201 	respond(r, nil);
    202 }
    203 
    204 void
    205 consread(Req *r)
    206 {
    207 	if (consbuf == nil) recv(consc, &consbuf);
    208 	r->ifcall.offset = 0;
    209 	readbuf(r, consbuf->p, consbuf->count);
    210 	if (arraydel(consbuf, 0, r->ofcall.count) != 0)
    211 		sysfatal("consread: %r");
    212 	if (consbuf->count == 0) {
    213 		arrayfree(consbuf);
    214 		consbuf = nil;
    215 	}
    216 
    217 	respond(r, nil);
    218 }
    219 
    220 void
    221 conswrite(Req *r)
    222 {
    223 	Array *a;
    224 	a = arraycreate(sizeof(char), r->ifcall.count, nil);
    225 	arraygrow(a, r->ifcall.count, r->ifcall.data);
    226 	nbsend(insertc, &a);
    227 	r->ofcall.count = r->ifcall.count;
    228 	respond(r, nil);
    229 }
    230 
    231 void
    232 ctlread(Req *r)
    233 {
    234 	if (ctlbuf == nil) recv(ctlc, &ctlbuf);
    235 	if (ctlbuf == nil) sysfatal("ctlread: ctlbuf is nil: %r");
    236 	r->ifcall.offset = 0;
    237 	readbuf(r, ctlbuf->p, ctlbuf->count);
    238 	if (arraydel(ctlbuf, 0, r->ofcall.count) != 0)
    239 		sysfatal("ctlread: %r");
    240 	if (ctlbuf->count == 0) {
    241 		arrayfree(ctlbuf);
    242 		ctlbuf = nil;
    243 	}
    244 
    245 	respond(r, nil);
    246 }
    247 
    248 void
    249 ctlwrite(Req *r)
    250 {
    251 	respond(r, nil);
    252 }