xref: /plan9-contrib/acme/bin/source/win/fs.c (revision 9bcb93539438d7e15f51959b802af26285e4993f)
1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <thread.h>
5 #include <9p.h>
6 #include "dat.h"
7 
8 Channel *fschan;
9 Channel *writechan;
10 
11 static File *devcons, *devnew;
12 
13 static void
fsread(Req * r)14 fsread(Req *r)
15 {
16 	Fsevent e;
17 
18 	if(r->fid->file == devnew){
19 		if(r->fid->aux==nil){
20 			respond(r, "phase error");
21 			return;
22 		}
23 		readstr(r, r->fid->aux);
24 		respond(r, nil);
25 		return;
26 	}
27 
28 	assert(r->fid->file == devcons);
29 	e.type = 'r';
30 	e.r = r;
31 	send(fschan, &e);
32 }
33 
34 static void
fsflush(Req * r)35 fsflush(Req *r)
36 {
37 	Fsevent e;
38 
39 	e.type = 'f';
40 	e.r = r;
41 	send(fschan, &e);
42 }
43 
44 static void
fswrite(Req * r)45 fswrite(Req *r)
46 {
47 	static Event *e[4];	/* ours, not the one from event.h */
48 	static int n, partial;
49 	Event *ep;
50 	int i, j, ei, nb, wid, pid;
51 	Rune rune;
52 	char *s;
53 	char tmp[UTFmax], *t;
54 
55 	if(r->fid->file == devnew){
56 		if(r->fid->aux){
57 			respond(r, "already created a window");
58 			return;
59 		}
60 		s = emalloc(r->ifcall.count+1);
61 		memmove(s, r->ifcall.data, r->ifcall.count);
62 		s[r->ifcall.count] = 0;
63 		pid = strtol(s, &t, 0);
64 		if(*t==' ')
65 			t++;
66 		i = newpipewin(pid, t);
67 		free(s);
68 		s = emalloc(32);
69 		sprint(s, "%lud", (ulong)i);
70 		r->fid->aux = s;
71 		r->ofcall.count = r->ifcall.count;
72 		respond(r, nil);
73 		return;
74 	}
75 
76 	assert(r->fid->file == devcons);
77 
78 	if(e[0] == nil){
79 		for(i=0; i<nelem(e); i++){
80 			e[i] = emalloc(sizeof(Event));
81 			e[i]->c1 = 'S';
82 		}
83 	}
84 
85 	ep = e[n];
86 	n = (n+1)%nelem(e);
87 	/*
88 	 * lib9p ensures that r->ifcall.count is <= srv->msize - IOHDRSZ,
89 	 * where srv == &fs.
90 	 */
91 	assert((int)r->ifcall.count >= 0);
92 	nb = r->ifcall.count;
93 	if (partial + nb >= sizeof ep->b)
94 		sysfatal("EVENTSIZE < MAXRPC; increase EVENTSIZE & recompile");
95 	memmove(ep->b+partial, r->ifcall.data, nb);
96 	nb += partial;
97 	ep->b[nb] = '\0';
98 	if(strlen(ep->b) < nb){	/* nulls in data */
99 		t = ep->b;
100 		for(i=j=0; i<nb; i++)
101 			if(ep->b[i] != '\0')
102 				t[j++] = ep->b[i];
103 		nb = j;
104 		t[j] = '\0';
105 	}
106 	ei = nb>EVENTSIZE? EVENTSIZE: nb;
107 	/* process bytes into runes, transferring terminal partial runes into next buffer */
108 	for(i=j=0; i<ei && fullrune(ep->b+i, ei-i); i+=wid,j++)
109 		wid = chartorune(&rune, ep->b+i);
110 	memmove(tmp, ep->b+i, nb-i);
111 //	partial = nb-i;			/* redundant */
112 	ep->nb = i;
113 	ep->nr = j;
114 	ep->b[i] = '\0';
115 	if(i != 0){
116 		sendp(win->cevent, ep);
117 		recvp(writechan);
118 	}
119 	partial = nb-i;
120 	memmove(e[n]->b, tmp, partial);
121 	r->ofcall.count = r->ifcall.count;
122 	respond(r, nil);
123 }
124 
125 void
fsdestroyfid(Fid * fid)126 fsdestroyfid(Fid *fid)
127 {
128 	if(fid->aux)
129 		free(fid->aux);
130 }
131 
132 Srv fs = {
133 .read=	fsread,
134 .write=	fswrite,
135 .flush=	fsflush,
136 .destroyfid=	fsdestroyfid,
137 .leavefdsopen=	1,
138 };
139 
140 void
mountcons(void)141 mountcons(void)
142 {
143 	fschan = chancreate(sizeof(Fsevent), 0);
144 	writechan = chancreate(sizeof(void*), 0);
145 	fs.tree = alloctree("win", "win", DMDIR|0555, nil);
146 	devcons = createfile(fs.tree->root, "cons", "win", 0666, nil);
147 	if(devcons == nil)
148 		sysfatal("creating /dev/cons: %r");
149 	devnew = createfile(fs.tree->root, "wnew", "win", 0666, nil);
150 	if(devnew == nil)
151 		sysfatal("creating /dev/wnew: %r");
152 	threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
153 }
154