]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ext2srv/ext2fs.c
mothra: fix alt display resizing, filter control characters in panel entries, use...
[plan9front.git] / sys / src / cmd / ext2srv / ext2fs.c
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
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
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 *
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 *
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
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
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
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
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
225 destroyfid(Fid *fid)
226 {
227         chat("destroy(fid=%d)\n", fid->fid);
228         xfile(fid, Clunk);
229         /*syncbuf(xf);*/
230 }
231 static void
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
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
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 };