1*dc5a79c1SDavid du Colombier #include <u.h>
2*dc5a79c1SDavid du Colombier #include <libc.h>
3*dc5a79c1SDavid du Colombier #include <fcall.h>
4*dc5a79c1SDavid du Colombier #include <thread.h>
5*dc5a79c1SDavid du Colombier #include <9p.h>
6*dc5a79c1SDavid du Colombier #include "dat.h"
7*dc5a79c1SDavid du Colombier #include "fns.h"
8*dc5a79c1SDavid du Colombier
9*dc5a79c1SDavid du Colombier #define thdr r->ifcall
10*dc5a79c1SDavid du Colombier #define rhdr r->ofcall
11*dc5a79c1SDavid du Colombier
12*dc5a79c1SDavid du Colombier extern int errno;
13*dc5a79c1SDavid du Colombier
14*dc5a79c1SDavid du Colombier static void
response(Req * r)15*dc5a79c1SDavid du Colombier response(Req *r)
16*dc5a79c1SDavid du Colombier {
17*dc5a79c1SDavid du Colombier char *err;
18*dc5a79c1SDavid du Colombier
19*dc5a79c1SDavid du Colombier if (errno) {
20*dc5a79c1SDavid du Colombier err = xerrstr(errno);
21*dc5a79c1SDavid du Colombier chat("%s\n", err);
22*dc5a79c1SDavid du Colombier respond(r, err);
23*dc5a79c1SDavid du Colombier } else {
24*dc5a79c1SDavid du Colombier chat("OK\n");
25*dc5a79c1SDavid du Colombier respond(r, nil);
26*dc5a79c1SDavid du Colombier }
27*dc5a79c1SDavid du Colombier }
28*dc5a79c1SDavid du Colombier
29*dc5a79c1SDavid du Colombier static void
rattach(Req * r)30*dc5a79c1SDavid du Colombier rattach(Req *r)
31*dc5a79c1SDavid du Colombier {
32*dc5a79c1SDavid du Colombier Xfs *xf;
33*dc5a79c1SDavid du Colombier Xfile *root;
34*dc5a79c1SDavid du Colombier
35*dc5a79c1SDavid du Colombier chat("attach(fid=%d,uname=\"%s\",aname=\"%s\",afid=\"%d\")...",
36*dc5a79c1SDavid du Colombier thdr.fid, thdr.uname, thdr.aname, thdr.afid);
37*dc5a79c1SDavid du Colombier
38*dc5a79c1SDavid du Colombier errno = 0;
39*dc5a79c1SDavid du Colombier root = xfile(r->fid, Clean);
40*dc5a79c1SDavid du Colombier if(!root){
41*dc5a79c1SDavid du Colombier errno = Enomem;
42*dc5a79c1SDavid du Colombier goto error;
43*dc5a79c1SDavid du Colombier }
44*dc5a79c1SDavid du Colombier root->xf = xf = getxfs(thdr.aname);
45*dc5a79c1SDavid du Colombier if(!xf)
46*dc5a79c1SDavid du Colombier goto error;
47*dc5a79c1SDavid du Colombier
48*dc5a79c1SDavid du Colombier /* now attach root inode */
49*dc5a79c1SDavid du Colombier if( get_inode(root, EXT2_ROOT_INODE) < 0 )
50*dc5a79c1SDavid du Colombier goto error;
51*dc5a79c1SDavid du Colombier
52*dc5a79c1SDavid du Colombier r->fid->qid.type = QTDIR;
53*dc5a79c1SDavid du Colombier r->fid->qid.vers = 0;
54*dc5a79c1SDavid du Colombier root->xf->rootqid = r->fid->qid;
55*dc5a79c1SDavid du Colombier root->pinbr = EXT2_ROOT_INODE;
56*dc5a79c1SDavid du Colombier root->root = 1;
57*dc5a79c1SDavid du Colombier rhdr.qid = r->fid->qid;
58*dc5a79c1SDavid du Colombier
59*dc5a79c1SDavid du Colombier error:
60*dc5a79c1SDavid du Colombier response(r);
61*dc5a79c1SDavid du Colombier }
62*dc5a79c1SDavid du Colombier static char *
rclone(Fid * fid,Fid * newfid)63*dc5a79c1SDavid du Colombier rclone(Fid *fid, Fid *newfid)
64*dc5a79c1SDavid du Colombier {
65*dc5a79c1SDavid du Colombier Xfile *of = xfile(fid, Asis);
66*dc5a79c1SDavid du Colombier Xfile *nf = xfile(newfid, Clean);
67*dc5a79c1SDavid du Colombier
68*dc5a79c1SDavid du Colombier chat("clone(fid=%d,newfid=%d)...", fid->fid, newfid->fid);
69*dc5a79c1SDavid du Colombier errno = 0;
70*dc5a79c1SDavid du Colombier if(!of)
71*dc5a79c1SDavid du Colombier errno = Eio;
72*dc5a79c1SDavid du Colombier else if(!nf)
73*dc5a79c1SDavid du Colombier errno = Enomem;
74*dc5a79c1SDavid du Colombier else{
75*dc5a79c1SDavid du Colombier Xfile *next = nf->next;
76*dc5a79c1SDavid du Colombier *nf = *of;
77*dc5a79c1SDavid du Colombier nf->next = next;
78*dc5a79c1SDavid du Colombier nf->fid = newfid->fid;
79*dc5a79c1SDavid du Colombier nf->root = 0;
80*dc5a79c1SDavid du Colombier }
81*dc5a79c1SDavid du Colombier chat("%s\n", errno? xerrstr(errno) : "OK");
82*dc5a79c1SDavid du Colombier return errno ? xerrstr(errno) : 0;
83*dc5a79c1SDavid du Colombier }
84*dc5a79c1SDavid du Colombier static char *
rwalk1(Fid * fid,char * name,Qid * qid)85*dc5a79c1SDavid du Colombier rwalk1(Fid *fid, char *name, Qid *qid)
86*dc5a79c1SDavid du Colombier {
87*dc5a79c1SDavid du Colombier Xfile *f=xfile(fid, Asis);
88*dc5a79c1SDavid du Colombier int nr, sinbr = 0;
89*dc5a79c1SDavid du Colombier
90*dc5a79c1SDavid du Colombier chat("walk1(fid=%d,name=\"%s\")...", fid->fid, name);
91*dc5a79c1SDavid du Colombier errno = 0;
92*dc5a79c1SDavid du Colombier if( !f ){
93*dc5a79c1SDavid du Colombier chat("no xfile...");
94*dc5a79c1SDavid du Colombier goto error;
95*dc5a79c1SDavid du Colombier }
96*dc5a79c1SDavid du Colombier if( !(fid->qid.type & QTDIR) ){
97*dc5a79c1SDavid du Colombier chat("qid.type=0x%x...", fid->qid.type);
98*dc5a79c1SDavid du Colombier goto error;
99*dc5a79c1SDavid du Colombier }
100*dc5a79c1SDavid du Colombier sinbr = f->pinbr;
101*dc5a79c1SDavid du Colombier if( name == 0 || name[0] == 0 || !strcmp(name, ".") ){
102*dc5a79c1SDavid du Colombier *qid = fid->qid;
103*dc5a79c1SDavid du Colombier goto ok;
104*dc5a79c1SDavid du Colombier }else if( !strcmp(name, "..") ){
105*dc5a79c1SDavid du Colombier if( fid->qid.path == f->xf->rootqid.path ){
106*dc5a79c1SDavid du Colombier chat("walkup from root...");
107*dc5a79c1SDavid du Colombier *qid = fid->qid;
108*dc5a79c1SDavid du Colombier goto ok;
109*dc5a79c1SDavid du Colombier }
110*dc5a79c1SDavid du Colombier if( get_inode(f, f->pinbr) < 0 )
111*dc5a79c1SDavid du Colombier goto error;
112*dc5a79c1SDavid du Colombier if( f->pinbr == EXT2_ROOT_INODE ){
113*dc5a79c1SDavid du Colombier *qid = f->xf->rootqid;
114*dc5a79c1SDavid du Colombier f->pinbr = EXT2_ROOT_INODE;
115*dc5a79c1SDavid du Colombier } else {
116*dc5a79c1SDavid du Colombier *qid = (Qid){f->pinbr,0,QTDIR};
117*dc5a79c1SDavid du Colombier f->inbr = f->pinbr;
118*dc5a79c1SDavid du Colombier if( (nr = get_file(f, "..")) < 0 )
119*dc5a79c1SDavid du Colombier goto error;
120*dc5a79c1SDavid du Colombier f->pinbr = nr;
121*dc5a79c1SDavid du Colombier }
122*dc5a79c1SDavid du Colombier }else{
123*dc5a79c1SDavid du Colombier f->pinbr = f->inbr;
124*dc5a79c1SDavid du Colombier if( (nr = get_file(f, name)) < 0 )
125*dc5a79c1SDavid du Colombier goto error;
126*dc5a79c1SDavid du Colombier if( get_inode(f, nr) < 0 )
127*dc5a79c1SDavid du Colombier goto error;
128*dc5a79c1SDavid du Colombier *qid = (Qid){nr,0,0};
129*dc5a79c1SDavid du Colombier if( nr == EXT2_ROOT_INODE )
130*dc5a79c1SDavid du Colombier *qid = f->xf->rootqid;
131*dc5a79c1SDavid du Colombier else if( S_ISDIR(getmode(f)) )
132*dc5a79c1SDavid du Colombier qid->type = QTDIR;
133*dc5a79c1SDavid du Colombier /*strcpy(f->name, thdr.name);*/
134*dc5a79c1SDavid du Colombier }
135*dc5a79c1SDavid du Colombier ok:
136*dc5a79c1SDavid du Colombier chat("OK\n");
137*dc5a79c1SDavid du Colombier return 0;
138*dc5a79c1SDavid du Colombier error:
139*dc5a79c1SDavid du Colombier f->pinbr = sinbr;
140*dc5a79c1SDavid du Colombier chat("%s\n", xerrstr(Enonexist));
141*dc5a79c1SDavid du Colombier return xerrstr(Enonexist);
142*dc5a79c1SDavid du Colombier }
143*dc5a79c1SDavid du Colombier static void
rstat(Req * r)144*dc5a79c1SDavid du Colombier rstat(Req *r)
145*dc5a79c1SDavid du Colombier {
146*dc5a79c1SDavid du Colombier Xfile *f=xfile(r->fid, Asis);
147*dc5a79c1SDavid du Colombier
148*dc5a79c1SDavid du Colombier chat("stat(fid=%d)...", thdr.fid);
149*dc5a79c1SDavid du Colombier errno = 0;
150*dc5a79c1SDavid du Colombier if( !f )
151*dc5a79c1SDavid du Colombier errno = Eio;
152*dc5a79c1SDavid du Colombier else{
153*dc5a79c1SDavid du Colombier dostat(r->fid->qid, f, &r->d);
154*dc5a79c1SDavid du Colombier }
155*dc5a79c1SDavid du Colombier response(r);
156*dc5a79c1SDavid du Colombier }
157*dc5a79c1SDavid du Colombier static void
rwstat(Req * r)158*dc5a79c1SDavid du Colombier rwstat(Req *r)
159*dc5a79c1SDavid du Colombier {
160*dc5a79c1SDavid du Colombier Xfile *f=xfile(r->fid, Asis);
161*dc5a79c1SDavid du Colombier
162*dc5a79c1SDavid du Colombier chat("wstat(fid=%d)...", thdr.fid);
163*dc5a79c1SDavid du Colombier errno = 0;
164*dc5a79c1SDavid du Colombier if( !f )
165*dc5a79c1SDavid du Colombier errno = Eio;
166*dc5a79c1SDavid du Colombier else
167*dc5a79c1SDavid du Colombier dowstat(f, &r->d);
168*dc5a79c1SDavid du Colombier response(r);
169*dc5a79c1SDavid du Colombier }
170*dc5a79c1SDavid du Colombier static void
rread(Req * r)171*dc5a79c1SDavid du Colombier rread(Req *r)
172*dc5a79c1SDavid du Colombier {
173*dc5a79c1SDavid du Colombier Xfile *f;
174*dc5a79c1SDavid du Colombier int nr;
175*dc5a79c1SDavid du Colombier
176*dc5a79c1SDavid du Colombier chat("read(fid=%d,offset=%lld,count=%d)...",
177*dc5a79c1SDavid du Colombier thdr.fid, thdr.offset, thdr.count);
178*dc5a79c1SDavid du Colombier errno = 0;
179*dc5a79c1SDavid du Colombier if ( !(f=xfile(r->fid, Asis)) )
180*dc5a79c1SDavid du Colombier goto error;
181*dc5a79c1SDavid du Colombier if( r->fid->qid.type & QTDIR ){
182*dc5a79c1SDavid du Colombier nr = readdir(f, r->rbuf, thdr.offset, thdr.count);
183*dc5a79c1SDavid du Colombier }else
184*dc5a79c1SDavid du Colombier nr = readfile(f, r->rbuf, thdr.offset, thdr.count);
185*dc5a79c1SDavid du Colombier
186*dc5a79c1SDavid du Colombier if(nr >= 0){
187*dc5a79c1SDavid du Colombier rhdr.count = nr;
188*dc5a79c1SDavid du Colombier chat("rcnt=%d...OK\n", nr);
189*dc5a79c1SDavid du Colombier respond(r, nil);
190*dc5a79c1SDavid du Colombier return;
191*dc5a79c1SDavid du Colombier }
192*dc5a79c1SDavid du Colombier error:
193*dc5a79c1SDavid du Colombier errno = Eio;
194*dc5a79c1SDavid du Colombier response(r);
195*dc5a79c1SDavid du Colombier }
196*dc5a79c1SDavid du Colombier static void
rwrite(Req * r)197*dc5a79c1SDavid du Colombier rwrite(Req *r)
198*dc5a79c1SDavid du Colombier {
199*dc5a79c1SDavid du Colombier Xfile *f; int nr;
200*dc5a79c1SDavid du Colombier
201*dc5a79c1SDavid du Colombier chat("write(fid=%d,offset=%lld,count=%d)...",
202*dc5a79c1SDavid du Colombier thdr.fid, thdr.offset, thdr.count);
203*dc5a79c1SDavid du Colombier
204*dc5a79c1SDavid du Colombier errno = 0;
205*dc5a79c1SDavid du Colombier if (!(f=xfile(r->fid, Asis)) ){
206*dc5a79c1SDavid du Colombier errno = Eio;
207*dc5a79c1SDavid du Colombier goto error;
208*dc5a79c1SDavid du Colombier }
209*dc5a79c1SDavid du Colombier if( !S_ISREG(getmode(f)) ){
210*dc5a79c1SDavid du Colombier errno = Elink;
211*dc5a79c1SDavid du Colombier goto error;
212*dc5a79c1SDavid du Colombier }
213*dc5a79c1SDavid du Colombier nr = writefile(f, thdr.data, thdr.offset, thdr.count);
214*dc5a79c1SDavid du Colombier if(nr >= 0){
215*dc5a79c1SDavid du Colombier rhdr.count = nr;
216*dc5a79c1SDavid du Colombier chat("rcnt=%d...OK\n", nr);
217*dc5a79c1SDavid du Colombier respond(r, nil);
218*dc5a79c1SDavid du Colombier return;
219*dc5a79c1SDavid du Colombier }
220*dc5a79c1SDavid du Colombier errno = Eio;
221*dc5a79c1SDavid du Colombier error:
222*dc5a79c1SDavid du Colombier response(r);
223*dc5a79c1SDavid du Colombier }
224*dc5a79c1SDavid du Colombier static void
destroyfid(Fid * fid)225*dc5a79c1SDavid du Colombier destroyfid(Fid *fid)
226*dc5a79c1SDavid du Colombier {
227*dc5a79c1SDavid du Colombier chat("destroy(fid=%d)\n", fid->fid);
228*dc5a79c1SDavid du Colombier xfile(fid, Clunk);
229*dc5a79c1SDavid du Colombier /*syncbuf(xf);*/
230*dc5a79c1SDavid du Colombier }
231*dc5a79c1SDavid du Colombier static void
ropen(Req * r)232*dc5a79c1SDavid du Colombier ropen(Req *r)
233*dc5a79c1SDavid du Colombier {
234*dc5a79c1SDavid du Colombier Xfile *f;
235*dc5a79c1SDavid du Colombier
236*dc5a79c1SDavid du Colombier chat("open(fid=%d,mode=%d)...", thdr.fid, thdr.mode);
237*dc5a79c1SDavid du Colombier
238*dc5a79c1SDavid du Colombier errno = 0;
239*dc5a79c1SDavid du Colombier f = xfile(r->fid, Asis);
240*dc5a79c1SDavid du Colombier if( !f ){
241*dc5a79c1SDavid du Colombier errno = Eio;
242*dc5a79c1SDavid du Colombier goto error;
243*dc5a79c1SDavid du Colombier }
244*dc5a79c1SDavid du Colombier
245*dc5a79c1SDavid du Colombier if(thdr.mode & OTRUNC){
246*dc5a79c1SDavid du Colombier if( !S_ISREG(getmode(f)) ){
247*dc5a79c1SDavid du Colombier errno = Eperm;
248*dc5a79c1SDavid du Colombier goto error;
249*dc5a79c1SDavid du Colombier }
250*dc5a79c1SDavid du Colombier if(truncfile(f) < 0){
251*dc5a79c1SDavid du Colombier goto error;
252*dc5a79c1SDavid du Colombier }
253*dc5a79c1SDavid du Colombier }
254*dc5a79c1SDavid du Colombier chat("f->qid=0x%8.8lux...", r->fid->qid.path);
255*dc5a79c1SDavid du Colombier rhdr.qid = r->fid->qid;
256*dc5a79c1SDavid du Colombier error:
257*dc5a79c1SDavid du Colombier response(r);
258*dc5a79c1SDavid du Colombier }
259*dc5a79c1SDavid du Colombier static void
rcreate(Req * r)260*dc5a79c1SDavid du Colombier rcreate(Req *r)
261*dc5a79c1SDavid du Colombier {
262*dc5a79c1SDavid du Colombier Xfile *f;
263*dc5a79c1SDavid du Colombier int inr, perm;
264*dc5a79c1SDavid du Colombier
265*dc5a79c1SDavid du Colombier chat("create(fid=%d,name=\"%s\",perm=%uo,mode=%d)...",
266*dc5a79c1SDavid du Colombier thdr.fid, thdr.name, thdr.perm, thdr.mode);
267*dc5a79c1SDavid du Colombier
268*dc5a79c1SDavid du Colombier errno = 0;
269*dc5a79c1SDavid du Colombier if(strcmp(thdr.name, ".") == 0 || strcmp(thdr.name, "..") == 0){
270*dc5a79c1SDavid du Colombier errno = Eperm;
271*dc5a79c1SDavid du Colombier goto error;
272*dc5a79c1SDavid du Colombier }
273*dc5a79c1SDavid du Colombier f = xfile(r->fid, Asis);
274*dc5a79c1SDavid du Colombier if( !f ){
275*dc5a79c1SDavid du Colombier errno = Eio;
276*dc5a79c1SDavid du Colombier goto error;
277*dc5a79c1SDavid du Colombier }
278*dc5a79c1SDavid du Colombier if( strlen(thdr.name) > EXT2_NAME_LEN ){
279*dc5a79c1SDavid du Colombier chat("name too long ...");
280*dc5a79c1SDavid du Colombier errno = Elongname;
281*dc5a79c1SDavid du Colombier goto error;
282*dc5a79c1SDavid du Colombier }
283*dc5a79c1SDavid du Colombier
284*dc5a79c1SDavid du Colombier /* create */
285*dc5a79c1SDavid du Colombier errno = 0;
286*dc5a79c1SDavid du Colombier if( thdr.perm & DMDIR ){
287*dc5a79c1SDavid du Colombier perm = (thdr.perm & ~0777) |
288*dc5a79c1SDavid du Colombier (getmode(f) & thdr.perm & 0777);
289*dc5a79c1SDavid du Colombier perm |= S_IFDIR;
290*dc5a79c1SDavid du Colombier inr = create_dir(f, thdr.name, perm);
291*dc5a79c1SDavid du Colombier }else{
292*dc5a79c1SDavid du Colombier perm = (thdr.perm & (~0777|0111)) |
293*dc5a79c1SDavid du Colombier (getmode(f) & thdr.perm & 0666);
294*dc5a79c1SDavid du Colombier perm |= S_IFREG;
295*dc5a79c1SDavid du Colombier inr = create_file(f, thdr.name, perm);
296*dc5a79c1SDavid du Colombier
297*dc5a79c1SDavid du Colombier }
298*dc5a79c1SDavid du Colombier if( inr < 0 )
299*dc5a79c1SDavid du Colombier goto error;
300*dc5a79c1SDavid du Colombier
301*dc5a79c1SDavid du Colombier /* fill with new inode */
302*dc5a79c1SDavid du Colombier f->pinbr = f->inbr;
303*dc5a79c1SDavid du Colombier if( get_inode(f, inr) < 0 ){
304*dc5a79c1SDavid du Colombier errno = Eio;
305*dc5a79c1SDavid du Colombier goto error;
306*dc5a79c1SDavid du Colombier }
307*dc5a79c1SDavid du Colombier r->fid->qid = (Qid){inr, 0, 0};
308*dc5a79c1SDavid du Colombier if( S_ISDIR(getmode(f)) )
309*dc5a79c1SDavid du Colombier r->fid->qid.type |= QTDIR;
310*dc5a79c1SDavid du Colombier chat("f->qid=0x%8.8lux...", r->fid->qid.path);
311*dc5a79c1SDavid du Colombier rhdr.qid = r->fid->qid;
312*dc5a79c1SDavid du Colombier error:
313*dc5a79c1SDavid du Colombier response(r);
314*dc5a79c1SDavid du Colombier }
315*dc5a79c1SDavid du Colombier static void
rremove(Req * r)316*dc5a79c1SDavid du Colombier rremove(Req *r)
317*dc5a79c1SDavid du Colombier {
318*dc5a79c1SDavid du Colombier Xfile *f=xfile(r->fid, Asis);
319*dc5a79c1SDavid du Colombier
320*dc5a79c1SDavid du Colombier chat("remove(fid=%d) ...", thdr.fid);
321*dc5a79c1SDavid du Colombier
322*dc5a79c1SDavid du Colombier errno = 0;
323*dc5a79c1SDavid du Colombier if(!f){
324*dc5a79c1SDavid du Colombier errno = Eio;
325*dc5a79c1SDavid du Colombier goto error;
326*dc5a79c1SDavid du Colombier }
327*dc5a79c1SDavid du Colombier
328*dc5a79c1SDavid du Colombier /* check permission here !!!!*/
329*dc5a79c1SDavid du Colombier
330*dc5a79c1SDavid du Colombier unlink(f);
331*dc5a79c1SDavid du Colombier
332*dc5a79c1SDavid du Colombier error:
333*dc5a79c1SDavid du Colombier response(r);
334*dc5a79c1SDavid du Colombier }
335*dc5a79c1SDavid du Colombier
336*dc5a79c1SDavid du Colombier Srv ext2srv = {
337*dc5a79c1SDavid du Colombier .destroyfid = destroyfid,
338*dc5a79c1SDavid du Colombier .attach = rattach,
339*dc5a79c1SDavid du Colombier .stat = rstat,
340*dc5a79c1SDavid du Colombier .wstat = rwstat,
341*dc5a79c1SDavid du Colombier .clone = rclone,
342*dc5a79c1SDavid du Colombier .walk1 = rwalk1,
343*dc5a79c1SDavid du Colombier .open = ropen,
344*dc5a79c1SDavid du Colombier .read = rread,
345*dc5a79c1SDavid du Colombier .write = rwrite,
346*dc5a79c1SDavid du Colombier .create = rcreate,
347*dc5a79c1SDavid du Colombier .remove = rremove,
348*dc5a79c1SDavid du Colombier };
349