xref: /plan9/sys/src/cmd/usb/lib/fsdir.c (revision d578950961079cf846383c5f4c4eed3f40282dd5)
1*906943f9SDavid du Colombier #include <u.h>
2*906943f9SDavid du Colombier #include <libc.h>
3*906943f9SDavid du Colombier #include <thread.h>
4*906943f9SDavid du Colombier #include <fcall.h>
5*906943f9SDavid du Colombier #include "usb.h"
6*906943f9SDavid du Colombier #include "usbfs.h"
7*906943f9SDavid du Colombier 
8*906943f9SDavid du Colombier typedef struct Rpc Rpc;
9*906943f9SDavid du Colombier 
10*906943f9SDavid du Colombier enum
11*906943f9SDavid du Colombier {
12*906943f9SDavid du Colombier 	Incr = 3,	/* increments for fs array */
13*906943f9SDavid du Colombier 	Dtop = 0,	/* high 32 bits for / 	*/
14*906943f9SDavid du Colombier 	Qdir = 0,	/* low 32 bits for /devdir */
15*906943f9SDavid du Colombier };
16*906943f9SDavid du Colombier 
17*906943f9SDavid du Colombier QLock fslck;
18*906943f9SDavid du Colombier static Usbfs** fs;
19*906943f9SDavid du Colombier static int nfs;
20*906943f9SDavid du Colombier static int fsused;
21*906943f9SDavid du Colombier static int exitonclose = 1;
22*906943f9SDavid du Colombier 
23*906943f9SDavid du Colombier void
usbfsexits(int y)24*906943f9SDavid du Colombier usbfsexits(int y)
25*906943f9SDavid du Colombier {
26*906943f9SDavid du Colombier 	exitonclose = y;
27*906943f9SDavid du Colombier }
28*906943f9SDavid du Colombier 
29*906943f9SDavid du Colombier static int
qiddev(uvlong path)30*906943f9SDavid du Colombier qiddev(uvlong path)
31*906943f9SDavid du Colombier {
32*906943f9SDavid du Colombier 	return (int)(path>>32) & 0xFF;
33*906943f9SDavid du Colombier }
34*906943f9SDavid du Colombier 
35*906943f9SDavid du Colombier static int
qidfile(uvlong path)36*906943f9SDavid du Colombier qidfile(uvlong path)
37*906943f9SDavid du Colombier {
38*906943f9SDavid du Colombier 	return (int)(path & 0xFFFFFFFFULL);
39*906943f9SDavid du Colombier }
40*906943f9SDavid du Colombier 
41*906943f9SDavid du Colombier static uvlong
mkqid(int qd,int qf)42*906943f9SDavid du Colombier mkqid(int qd, int qf)
43*906943f9SDavid du Colombier {
44*906943f9SDavid du Colombier 	return ((uvlong)qd << 32) | (uvlong)qf;
45*906943f9SDavid du Colombier }
46*906943f9SDavid du Colombier 
47*906943f9SDavid du Colombier void
usbfsdirdump(void)48*906943f9SDavid du Colombier usbfsdirdump(void)
49*906943f9SDavid du Colombier {
50*906943f9SDavid du Colombier 	int i;
51*906943f9SDavid du Colombier 
52*906943f9SDavid du Colombier 	qlock(&fslck);
53*906943f9SDavid du Colombier 	fprint(2, "%s: fs list: (%d used %d total)\n", argv0, fsused, nfs);
54*906943f9SDavid du Colombier 	for(i = 1; i < nfs; i++)
55*906943f9SDavid du Colombier 		if(fs[i] != nil)
56*906943f9SDavid du Colombier 			if(fs[i]->dev != nil)
57*906943f9SDavid du Colombier 				fprint(2, "%s\t%s dev %#p refs %ld\n",
58*906943f9SDavid du Colombier 					argv0, fs[i]->name, fs[i]->dev, fs[i]->dev->ref);
59*906943f9SDavid du Colombier 			else
60*906943f9SDavid du Colombier 				fprint(2, "%s:\t%s\n", argv0, fs[i]->name);
61*906943f9SDavid du Colombier 	qunlock(&fslck);
62*906943f9SDavid du Colombier }
63*906943f9SDavid du Colombier 
64*906943f9SDavid du Colombier void
usbfsadd(Usbfs * dfs)65*906943f9SDavid du Colombier usbfsadd(Usbfs *dfs)
66*906943f9SDavid du Colombier {
67*906943f9SDavid du Colombier 	int i, j;
68*906943f9SDavid du Colombier 
69*906943f9SDavid du Colombier 	dprint(2, "%s: fsadd %s\n", argv0, dfs->name);
70*906943f9SDavid du Colombier 	qlock(&fslck);
71*906943f9SDavid du Colombier 	for(i = 1; i < nfs; i++)
72*906943f9SDavid du Colombier 		if(fs[i] == nil)
73*906943f9SDavid du Colombier 			break;
74*906943f9SDavid du Colombier 	if(i >= nfs){
75*906943f9SDavid du Colombier 		if((nfs%Incr) == 0){
76*906943f9SDavid du Colombier 			fs = realloc(fs, sizeof(Usbfs*) * (nfs+Incr));
77*906943f9SDavid du Colombier 			if(fs == nil)
78*906943f9SDavid du Colombier 				sysfatal("realloc: %r");
79*906943f9SDavid du Colombier 			for(j = nfs; j < nfs+Incr; j++)
80*906943f9SDavid du Colombier 				fs[j] = nil;
81*906943f9SDavid du Colombier 		}
82*906943f9SDavid du Colombier 		if(nfs == 0)	/* do not use entry 0 */
83*906943f9SDavid du Colombier 			nfs++;
84*906943f9SDavid du Colombier 		fs[nfs++] = dfs;
85*906943f9SDavid du Colombier 	}else
86*906943f9SDavid du Colombier 		fs[i] = dfs;
87*906943f9SDavid du Colombier 	dfs->qid = mkqid(i, 0);
88*906943f9SDavid du Colombier 	fsused++;
89*906943f9SDavid du Colombier 	qunlock(&fslck);
90*906943f9SDavid du Colombier }
91*906943f9SDavid du Colombier 
92*906943f9SDavid du Colombier static void
usbfsdelnth(int i)93*906943f9SDavid du Colombier usbfsdelnth(int i)
94*906943f9SDavid du Colombier {
95*906943f9SDavid du Colombier 	if(fs[i] != nil){
96*906943f9SDavid du Colombier 		dprint(2, "%s: fsdel %s", argv0, fs[i]->name);
97*906943f9SDavid du Colombier 		if(fs[i]->dev != nil){
98*906943f9SDavid du Colombier 			dprint(2, " dev %#p ref %ld\n",
99*906943f9SDavid du Colombier 				fs[i]->dev, fs[i]->dev->ref);
100*906943f9SDavid du Colombier 		}else
101*906943f9SDavid du Colombier 			dprint(2, "no dev\n");
102*906943f9SDavid du Colombier 		if(fs[i]->end != nil)
103*906943f9SDavid du Colombier 			fs[i]->end(fs[i]);
104*906943f9SDavid du Colombier 		closedev(fs[i]->dev);
105*906943f9SDavid du Colombier 		fsused--;
106*906943f9SDavid du Colombier 	}
107*906943f9SDavid du Colombier 	fs[i] = nil;
108*906943f9SDavid du Colombier 	if(fsused == 0 && exitonclose != 0){
109*906943f9SDavid du Colombier 		fprint(2, "%s: all file systems gone: exiting\n", argv0);
110*906943f9SDavid du Colombier 		threadexitsall(nil);
111*906943f9SDavid du Colombier 	}
112*906943f9SDavid du Colombier }
113*906943f9SDavid du Colombier 
114*906943f9SDavid du Colombier void
usbfsdel(Usbfs * dfs)115*906943f9SDavid du Colombier usbfsdel(Usbfs *dfs)
116*906943f9SDavid du Colombier {
117*906943f9SDavid du Colombier 	int i;
118*906943f9SDavid du Colombier 
119*906943f9SDavid du Colombier 	qlock(&fslck);
120*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
121*906943f9SDavid du Colombier 		if(dfs == nil || fs[i] == dfs){
122*906943f9SDavid du Colombier 			usbfsdelnth(i);
123*906943f9SDavid du Colombier 			if(dfs != nil)
124*906943f9SDavid du Colombier 				break;
125*906943f9SDavid du Colombier 		}
126*906943f9SDavid du Colombier 	qunlock(&fslck);
127*906943f9SDavid du Colombier }
128*906943f9SDavid du Colombier 
129*906943f9SDavid du Colombier static void
fsend(Usbfs *)130*906943f9SDavid du Colombier fsend(Usbfs*)
131*906943f9SDavid du Colombier {
132*906943f9SDavid du Colombier 	dprint(2, "%s: fsend\n", argv0);
133*906943f9SDavid du Colombier 	usbfsdel(nil);
134*906943f9SDavid du Colombier }
135*906943f9SDavid du Colombier 
136*906943f9SDavid du Colombier void
usbfsgone(char * dir)137*906943f9SDavid du Colombier usbfsgone(char *dir)
138*906943f9SDavid du Colombier {
139*906943f9SDavid du Colombier 	int i;
140*906943f9SDavid du Colombier 
141*906943f9SDavid du Colombier 	qlock(&fslck);
142*906943f9SDavid du Colombier 	/* devices may have more than one fs */
143*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
144*906943f9SDavid du Colombier 		if(fs[i] != nil && fs[i]->dev != nil)
145*906943f9SDavid du Colombier 		if(strcmp(fs[i]->dev->dir, dir) == 0)
146*906943f9SDavid du Colombier 			usbfsdelnth(i);
147*906943f9SDavid du Colombier 	qunlock(&fslck);
148*906943f9SDavid du Colombier }
149*906943f9SDavid du Colombier 
150*906943f9SDavid du Colombier static void
fsclone(Usbfs *,Fid * o,Fid * n)151*906943f9SDavid du Colombier fsclone(Usbfs*, Fid *o, Fid *n)
152*906943f9SDavid du Colombier {
153*906943f9SDavid du Colombier 	int qd;
154*906943f9SDavid du Colombier 	Dev *dev;
155*906943f9SDavid du Colombier 	void (*xfsclone)(Usbfs *fs, Fid *of, Fid *nf);
156*906943f9SDavid du Colombier 
157*906943f9SDavid du Colombier 	xfsclone = nil;
158*906943f9SDavid du Colombier 	dev = nil;
159*906943f9SDavid du Colombier 	qd = qiddev(o->qid.path);
160*906943f9SDavid du Colombier 	qlock(&fslck);
161*906943f9SDavid du Colombier 	if(qd != Dtop && fs[qd] != nil && fs[qd]->clone != nil){
162*906943f9SDavid du Colombier 		dev = fs[qd]->dev;
163*906943f9SDavid du Colombier 		if(dev != nil)
164*906943f9SDavid du Colombier 			incref(dev);
165*906943f9SDavid du Colombier 		xfsclone = fs[qd]->clone;
166*906943f9SDavid du Colombier 	}
167*906943f9SDavid du Colombier 	qunlock(&fslck);
168*906943f9SDavid du Colombier 	if(xfsclone != nil){
169*906943f9SDavid du Colombier 		xfsclone(fs[qd], o, n);
170*906943f9SDavid du Colombier 	}
171*906943f9SDavid du Colombier 	if(dev != nil)
172*906943f9SDavid du Colombier 		closedev(dev);
173*906943f9SDavid du Colombier }
174*906943f9SDavid du Colombier 
175*906943f9SDavid du Colombier static int
fswalk(Usbfs *,Fid * fid,char * name)176*906943f9SDavid du Colombier fswalk(Usbfs*, Fid *fid, char *name)
177*906943f9SDavid du Colombier {
178*906943f9SDavid du Colombier 	Qid q;
179*906943f9SDavid du Colombier 	int qd, qf;
180*906943f9SDavid du Colombier 	int i;
181*906943f9SDavid du Colombier 	int rc;
182*906943f9SDavid du Colombier 	Dev *dev;
183*906943f9SDavid du Colombier 	Dir d;
184*906943f9SDavid du Colombier 	int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
185*906943f9SDavid du Colombier 
186*906943f9SDavid du Colombier 	q = fid->qid;
187*906943f9SDavid du Colombier 	qd = qiddev(q.path);
188*906943f9SDavid du Colombier 	qf = qidfile(q.path);
189*906943f9SDavid du Colombier 
190*906943f9SDavid du Colombier 	q.type = QTDIR;
191*906943f9SDavid du Colombier 	q.vers = 0;
192*906943f9SDavid du Colombier 	if(strcmp(name, "..") == 0)
193*906943f9SDavid du Colombier 		if(qd == Dtop || qf == Qdir){
194*906943f9SDavid du Colombier 			q.path = mkqid(Dtop, Qdir);
195*906943f9SDavid du Colombier 			fid->qid = q;
196*906943f9SDavid du Colombier 			return 0;
197*906943f9SDavid du Colombier 		}
198*906943f9SDavid du Colombier 	if(qd != 0){
199*906943f9SDavid du Colombier 		qlock(&fslck);
200*906943f9SDavid du Colombier 		if(fs[qd] == nil){
201*906943f9SDavid du Colombier 			qunlock(&fslck);
202*906943f9SDavid du Colombier 			werrstr(Eio);
203*906943f9SDavid du Colombier 			return -1;
204*906943f9SDavid du Colombier 		}
205*906943f9SDavid du Colombier 		dev = fs[qd]->dev;
206*906943f9SDavid du Colombier 		if(dev != nil)
207*906943f9SDavid du Colombier 			incref(dev);
208*906943f9SDavid du Colombier 		xfswalk = fs[qd]->walk;
209*906943f9SDavid du Colombier 		qunlock(&fslck);
210*906943f9SDavid du Colombier 		rc = xfswalk(fs[qd], fid, name);
211*906943f9SDavid du Colombier 		if(dev != nil)
212*906943f9SDavid du Colombier 			closedev(dev);
213*906943f9SDavid du Colombier 		return rc;
214*906943f9SDavid du Colombier 	}
215*906943f9SDavid du Colombier 	qlock(&fslck);
216*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
217*906943f9SDavid du Colombier 		if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
218*906943f9SDavid du Colombier 			q.path = mkqid(i, Qdir);
219*906943f9SDavid du Colombier 			fs[i]->stat(fs[i], q, &d); /* may be a file */
220*906943f9SDavid du Colombier 			fid->qid = d.qid;
221*906943f9SDavid du Colombier 			qunlock(&fslck);
222*906943f9SDavid du Colombier 			return 0;
223*906943f9SDavid du Colombier 		}
224*906943f9SDavid du Colombier 	qunlock(&fslck);
225*906943f9SDavid du Colombier 	werrstr(Enotfound);
226*906943f9SDavid du Colombier 	return -1;
227*906943f9SDavid du Colombier }
228*906943f9SDavid du Colombier 
229*906943f9SDavid du Colombier static int
fsopen(Usbfs *,Fid * fid,int mode)230*906943f9SDavid du Colombier fsopen(Usbfs*, Fid *fid, int mode)
231*906943f9SDavid du Colombier {
232*906943f9SDavid du Colombier 	int qd;
233*906943f9SDavid du Colombier 	int rc;
234*906943f9SDavid du Colombier 	Dev *dev;
235*906943f9SDavid du Colombier 	int (*xfsopen)(Usbfs *fs, Fid *f, int mode);
236*906943f9SDavid du Colombier 
237*906943f9SDavid du Colombier 	qd = qiddev(fid->qid.path);
238*906943f9SDavid du Colombier 	if(qd == Dtop)
239*906943f9SDavid du Colombier 		return 0;
240*906943f9SDavid du Colombier 	qlock(&fslck);
241*906943f9SDavid du Colombier 	if(fs[qd] == nil){
242*906943f9SDavid du Colombier 		qunlock(&fslck);
243*906943f9SDavid du Colombier 		werrstr(Eio);
244*906943f9SDavid du Colombier 		return -1;
245*906943f9SDavid du Colombier 	}
246*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
247*906943f9SDavid du Colombier 	if(dev != nil)
248*906943f9SDavid du Colombier 		incref(dev);
249*906943f9SDavid du Colombier 	xfsopen = fs[qd]->open;
250*906943f9SDavid du Colombier 	qunlock(&fslck);
251*906943f9SDavid du Colombier 	if(xfsopen != nil)
252*906943f9SDavid du Colombier 		rc = xfsopen(fs[qd], fid, mode);
253*906943f9SDavid du Colombier 	else
254*906943f9SDavid du Colombier 		rc = 0;
255*906943f9SDavid du Colombier 	if(dev != nil)
256*906943f9SDavid du Colombier 		closedev(dev);
257*906943f9SDavid du Colombier 	return rc;
258*906943f9SDavid du Colombier }
259*906943f9SDavid du Colombier 
260*906943f9SDavid du Colombier static int
dirgen(Usbfs *,Qid,int n,Dir * d,void *)261*906943f9SDavid du Colombier dirgen(Usbfs*, Qid, int n, Dir *d, void *)
262*906943f9SDavid du Colombier {
263*906943f9SDavid du Colombier 	int i;
264*906943f9SDavid du Colombier 	Dev *dev;
265*906943f9SDavid du Colombier 	char *nm;
266*906943f9SDavid du Colombier 
267*906943f9SDavid du Colombier 	qlock(&fslck);
268*906943f9SDavid du Colombier 	for(i = 0; i < nfs; i++)
269*906943f9SDavid du Colombier 		if(fs[i] != nil && n-- == 0){
270*906943f9SDavid du Colombier 			d->qid.type = QTDIR;
271*906943f9SDavid du Colombier 			d->qid.path = mkqid(i, Qdir);
272*906943f9SDavid du Colombier 			d->qid.vers = 0;
273*906943f9SDavid du Colombier 			dev = fs[i]->dev;
274*906943f9SDavid du Colombier 			if(dev != nil)
275*906943f9SDavid du Colombier 				incref(dev);
276*906943f9SDavid du Colombier 			nm = d->name;
277*906943f9SDavid du Colombier 			fs[i]->stat(fs[i], d->qid, d);
278*906943f9SDavid du Colombier 			d->name = nm;
279*906943f9SDavid du Colombier 			strncpy(d->name, fs[i]->name, Namesz);
280*906943f9SDavid du Colombier 			if(dev != nil)
281*906943f9SDavid du Colombier 				closedev(dev);
282*906943f9SDavid du Colombier 			qunlock(&fslck);
283*906943f9SDavid du Colombier 			return 0;
284*906943f9SDavid du Colombier 		}
285*906943f9SDavid du Colombier 	qunlock(&fslck);
286*906943f9SDavid du Colombier 	return -1;
287*906943f9SDavid du Colombier }
288*906943f9SDavid du Colombier 
289*906943f9SDavid du Colombier static long
fsread(Usbfs *,Fid * fid,void * data,long cnt,vlong off)290*906943f9SDavid du Colombier fsread(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
291*906943f9SDavid du Colombier {
292*906943f9SDavid du Colombier 	int qd;
293*906943f9SDavid du Colombier 	int rc;
294*906943f9SDavid du Colombier 	Dev *dev;
295*906943f9SDavid du Colombier 	Qid q;
296*906943f9SDavid du Colombier 	long (*xfsread)(Usbfs *fs, Fid *f, void *data, long count, vlong );
297*906943f9SDavid du Colombier 
298*906943f9SDavid du Colombier 	q = fid->qid;
299*906943f9SDavid du Colombier 	qd = qiddev(q.path);
300*906943f9SDavid du Colombier 	if(qd == Dtop)
301*906943f9SDavid du Colombier 		return usbdirread(nil, q, data, cnt, off, dirgen, nil);
302*906943f9SDavid du Colombier 	qlock(&fslck);
303*906943f9SDavid du Colombier 	if(fs[qd] == nil){
304*906943f9SDavid du Colombier 		qunlock(&fslck);
305*906943f9SDavid du Colombier 		werrstr(Eio);
306*906943f9SDavid du Colombier 		return -1;
307*906943f9SDavid du Colombier 	}
308*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
309*906943f9SDavid du Colombier 	if(dev != nil)
310*906943f9SDavid du Colombier 		incref(dev);
311*906943f9SDavid du Colombier 	xfsread = fs[qd]->read;
312*906943f9SDavid du Colombier 	qunlock(&fslck);
313*906943f9SDavid du Colombier 	rc = xfsread(fs[qd], fid, data, cnt, off);
314*906943f9SDavid du Colombier 	if(dev != nil)
315*906943f9SDavid du Colombier 		closedev(dev);
316*906943f9SDavid du Colombier 	return rc;
317*906943f9SDavid du Colombier }
318*906943f9SDavid du Colombier 
319*906943f9SDavid du Colombier static long
fswrite(Usbfs *,Fid * fid,void * data,long cnt,vlong off)320*906943f9SDavid du Colombier fswrite(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
321*906943f9SDavid du Colombier {
322*906943f9SDavid du Colombier 	int qd;
323*906943f9SDavid du Colombier 	int rc;
324*906943f9SDavid du Colombier 	Dev *dev;
325*906943f9SDavid du Colombier 	long (*xfswrite)(Usbfs *fs, Fid *f, void *data, long count, vlong );
326*906943f9SDavid du Colombier 
327*906943f9SDavid du Colombier 	qd = qiddev(fid->qid.path);
328*906943f9SDavid du Colombier 	if(qd == Dtop)
329*906943f9SDavid du Colombier 		sysfatal("fswrite: not for usbd /");
330*906943f9SDavid du Colombier 	qlock(&fslck);
331*906943f9SDavid du Colombier 	if(fs[qd] == nil){
332*906943f9SDavid du Colombier 		qunlock(&fslck);
333*906943f9SDavid du Colombier 		werrstr(Eio);
334*906943f9SDavid du Colombier 		return -1;
335*906943f9SDavid du Colombier 	}
336*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
337*906943f9SDavid du Colombier 	if(dev != nil)
338*906943f9SDavid du Colombier 		incref(dev);
339*906943f9SDavid du Colombier 	xfswrite = fs[qd]->write;
340*906943f9SDavid du Colombier 	qunlock(&fslck);
341*906943f9SDavid du Colombier 	rc = xfswrite(fs[qd], fid, data, cnt, off);
342*906943f9SDavid du Colombier 	if(dev != nil)
343*906943f9SDavid du Colombier 		closedev(dev);
344*906943f9SDavid du Colombier 	return rc;
345*906943f9SDavid du Colombier }
346*906943f9SDavid du Colombier 
347*906943f9SDavid du Colombier 
348*906943f9SDavid du Colombier static void
fsclunk(Usbfs *,Fid * fid)349*906943f9SDavid du Colombier fsclunk(Usbfs*, Fid* fid)
350*906943f9SDavid du Colombier {
351*906943f9SDavid du Colombier 	int qd;
352*906943f9SDavid du Colombier 	Dev *dev;
353*906943f9SDavid du Colombier 	void (*xfsclunk)(Usbfs *fs, Fid *f);
354*906943f9SDavid du Colombier 
355*906943f9SDavid du Colombier 	dev = nil;
356*906943f9SDavid du Colombier 	qd = qiddev(fid->qid.path);
357*906943f9SDavid du Colombier 	qlock(&fslck);
358*906943f9SDavid du Colombier 	if(qd != Dtop && fs[qd] != nil){
359*906943f9SDavid du Colombier 		dev=fs[qd]->dev;
360*906943f9SDavid du Colombier 		if(dev != nil)
361*906943f9SDavid du Colombier 			incref(dev);
362*906943f9SDavid du Colombier 		xfsclunk = fs[qd]->clunk;
363*906943f9SDavid du Colombier 	}else
364*906943f9SDavid du Colombier 		xfsclunk = nil;
365*906943f9SDavid du Colombier 	qunlock(&fslck);
366*906943f9SDavid du Colombier 	if(xfsclunk != nil){
367*906943f9SDavid du Colombier 		xfsclunk(fs[qd], fid);
368*906943f9SDavid du Colombier 	}
369*906943f9SDavid du Colombier 	if(dev != nil)
370*906943f9SDavid du Colombier 		closedev(dev);
371*906943f9SDavid du Colombier }
372*906943f9SDavid du Colombier 
373*906943f9SDavid du Colombier static int
fsstat(Usbfs *,Qid qid,Dir * d)374*906943f9SDavid du Colombier fsstat(Usbfs*, Qid qid, Dir *d)
375*906943f9SDavid du Colombier {
376*906943f9SDavid du Colombier 	int qd;
377*906943f9SDavid du Colombier 	int rc;
378*906943f9SDavid du Colombier 	Dev *dev;
379*906943f9SDavid du Colombier 	int (*xfsstat)(Usbfs *fs, Qid q, Dir *d);
380*906943f9SDavid du Colombier 
381*906943f9SDavid du Colombier 	qd = qiddev(qid.path);
382*906943f9SDavid du Colombier 	if(qd == Dtop){
383*906943f9SDavid du Colombier 		d->qid = qid;
384*906943f9SDavid du Colombier 		d->name = "usb";
385*906943f9SDavid du Colombier 		d->length = 0;
386*906943f9SDavid du Colombier 		d->mode = 0555|DMDIR;
387*906943f9SDavid du Colombier 		return 0;
388*906943f9SDavid du Colombier 	}
389*906943f9SDavid du Colombier 	qlock(&fslck);
390*906943f9SDavid du Colombier 	if(fs[qd] == nil){
391*906943f9SDavid du Colombier 		qunlock(&fslck);
392*906943f9SDavid du Colombier 		werrstr(Eio);
393*906943f9SDavid du Colombier 		return -1;
394*906943f9SDavid du Colombier 	}
395*906943f9SDavid du Colombier 	xfsstat = fs[qd]->stat;
396*906943f9SDavid du Colombier 	dev = fs[qd]->dev;
397*906943f9SDavid du Colombier 	if(dev != nil)
398*906943f9SDavid du Colombier 		incref(dev);
399*906943f9SDavid du Colombier 	qunlock(&fslck);
400*906943f9SDavid du Colombier 	rc = xfsstat(fs[qd], qid, d);
401*906943f9SDavid du Colombier 	if(dev != nil)
402*906943f9SDavid du Colombier 		closedev(dev);
403*906943f9SDavid du Colombier 	return rc;
404*906943f9SDavid du Colombier }
405*906943f9SDavid du Colombier 
406*906943f9SDavid du Colombier Usbfs usbdirfs =
407*906943f9SDavid du Colombier {
408*906943f9SDavid du Colombier 	.walk = fswalk,
409*906943f9SDavid du Colombier 	.clone = fsclone,
410*906943f9SDavid du Colombier 	.clunk = fsclunk,
411*906943f9SDavid du Colombier 	.open = fsopen,
412*906943f9SDavid du Colombier 	.read = fsread,
413*906943f9SDavid du Colombier 	.write = fswrite,
414*906943f9SDavid du Colombier 	.stat = fsstat,
415*906943f9SDavid du Colombier 	.end = fsend,
416*906943f9SDavid du Colombier };
417*906943f9SDavid du Colombier 
418