xref: /plan9/sys/src/cmd/ext2srv/ext2fs.c (revision dc5a79c1208f0704eeb474acc990728f8b4854f5)
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