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