1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "../port/lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "../port/error.h"
7*74a4d8c2SCharles.Forsyth
8*74a4d8c2SCharles.Forsyth extern ulong kerndate;
9*74a4d8c2SCharles.Forsyth
10*74a4d8c2SCharles.Forsyth void
mkqid(Qid * q,vlong path,ulong vers,int type)11*74a4d8c2SCharles.Forsyth mkqid(Qid *q, vlong path, ulong vers, int type)
12*74a4d8c2SCharles.Forsyth {
13*74a4d8c2SCharles.Forsyth q->type = type;
14*74a4d8c2SCharles.Forsyth q->vers = vers;
15*74a4d8c2SCharles.Forsyth q->path = path;
16*74a4d8c2SCharles.Forsyth }
17*74a4d8c2SCharles.Forsyth
18*74a4d8c2SCharles.Forsyth int
devno(int c,int user)19*74a4d8c2SCharles.Forsyth devno(int c, int user)
20*74a4d8c2SCharles.Forsyth {
21*74a4d8c2SCharles.Forsyth int i;
22*74a4d8c2SCharles.Forsyth
23*74a4d8c2SCharles.Forsyth for(i = 0; devtab[i] != nil; i++) {
24*74a4d8c2SCharles.Forsyth if(devtab[i]->dc == c)
25*74a4d8c2SCharles.Forsyth return i;
26*74a4d8c2SCharles.Forsyth }
27*74a4d8c2SCharles.Forsyth if(user == 0)
28*74a4d8c2SCharles.Forsyth panic("devno %C 0x%ux", c, c);
29*74a4d8c2SCharles.Forsyth
30*74a4d8c2SCharles.Forsyth return -1;
31*74a4d8c2SCharles.Forsyth }
32*74a4d8c2SCharles.Forsyth
33*74a4d8c2SCharles.Forsyth void
devdir(Chan * c,Qid qid,char * n,vlong length,char * user,long perm,Dir * db)34*74a4d8c2SCharles.Forsyth devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
35*74a4d8c2SCharles.Forsyth {
36*74a4d8c2SCharles.Forsyth db->name = n;
37*74a4d8c2SCharles.Forsyth if(c->flag&CMSG)
38*74a4d8c2SCharles.Forsyth qid.type |= QTMOUNT;
39*74a4d8c2SCharles.Forsyth db->qid = qid;
40*74a4d8c2SCharles.Forsyth db->type = devtab[c->type]->dc;
41*74a4d8c2SCharles.Forsyth db->dev = c->dev;
42*74a4d8c2SCharles.Forsyth db->mode = perm;
43*74a4d8c2SCharles.Forsyth db->mode |= qid.type << 24;
44*74a4d8c2SCharles.Forsyth db->atime = seconds();
45*74a4d8c2SCharles.Forsyth db->mtime = kerndate;
46*74a4d8c2SCharles.Forsyth db->length = length;
47*74a4d8c2SCharles.Forsyth db->uid = user;
48*74a4d8c2SCharles.Forsyth db->gid = eve;
49*74a4d8c2SCharles.Forsyth db->muid = user;
50*74a4d8c2SCharles.Forsyth }
51*74a4d8c2SCharles.Forsyth
52*74a4d8c2SCharles.Forsyth /*
53*74a4d8c2SCharles.Forsyth * the zeroth element of the table MUST be the directory itself for ..
54*74a4d8c2SCharles.Forsyth */
55*74a4d8c2SCharles.Forsyth int
devgen(Chan * c,char *,Dirtab * tab,int ntab,int i,Dir * dp)56*74a4d8c2SCharles.Forsyth devgen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp)
57*74a4d8c2SCharles.Forsyth {
58*74a4d8c2SCharles.Forsyth if(tab == 0)
59*74a4d8c2SCharles.Forsyth return -1;
60*74a4d8c2SCharles.Forsyth if(i != DEVDOTDOT){
61*74a4d8c2SCharles.Forsyth /* skip over the first element, that for . itself */
62*74a4d8c2SCharles.Forsyth i++;
63*74a4d8c2SCharles.Forsyth if(i >= ntab)
64*74a4d8c2SCharles.Forsyth return -1;
65*74a4d8c2SCharles.Forsyth tab += i;
66*74a4d8c2SCharles.Forsyth }
67*74a4d8c2SCharles.Forsyth devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
68*74a4d8c2SCharles.Forsyth return 1;
69*74a4d8c2SCharles.Forsyth }
70*74a4d8c2SCharles.Forsyth
71*74a4d8c2SCharles.Forsyth void
devreset(void)72*74a4d8c2SCharles.Forsyth devreset(void)
73*74a4d8c2SCharles.Forsyth {
74*74a4d8c2SCharles.Forsyth }
75*74a4d8c2SCharles.Forsyth
76*74a4d8c2SCharles.Forsyth void
devinit(void)77*74a4d8c2SCharles.Forsyth devinit(void)
78*74a4d8c2SCharles.Forsyth {
79*74a4d8c2SCharles.Forsyth }
80*74a4d8c2SCharles.Forsyth
81*74a4d8c2SCharles.Forsyth void
devshutdown(void)82*74a4d8c2SCharles.Forsyth devshutdown(void)
83*74a4d8c2SCharles.Forsyth {
84*74a4d8c2SCharles.Forsyth }
85*74a4d8c2SCharles.Forsyth
86*74a4d8c2SCharles.Forsyth Chan*
devattach(int tc,char * spec)87*74a4d8c2SCharles.Forsyth devattach(int tc, char *spec)
88*74a4d8c2SCharles.Forsyth {
89*74a4d8c2SCharles.Forsyth Chan *c;
90*74a4d8c2SCharles.Forsyth char *buf;
91*74a4d8c2SCharles.Forsyth
92*74a4d8c2SCharles.Forsyth c = newchan();
93*74a4d8c2SCharles.Forsyth mkqid(&c->qid, 0, 0, QTDIR);
94*74a4d8c2SCharles.Forsyth c->type = devno(tc, 0);
95*74a4d8c2SCharles.Forsyth if(spec == nil)
96*74a4d8c2SCharles.Forsyth spec = "";
97*74a4d8c2SCharles.Forsyth buf = smalloc(4+strlen(spec)+1);
98*74a4d8c2SCharles.Forsyth sprint(buf, "#%C%s", tc, spec);
99*74a4d8c2SCharles.Forsyth c->name = newcname(buf);
100*74a4d8c2SCharles.Forsyth free(buf);
101*74a4d8c2SCharles.Forsyth return c;
102*74a4d8c2SCharles.Forsyth }
103*74a4d8c2SCharles.Forsyth
104*74a4d8c2SCharles.Forsyth
105*74a4d8c2SCharles.Forsyth Chan*
devclone(Chan * c)106*74a4d8c2SCharles.Forsyth devclone(Chan *c)
107*74a4d8c2SCharles.Forsyth {
108*74a4d8c2SCharles.Forsyth Chan *nc;
109*74a4d8c2SCharles.Forsyth
110*74a4d8c2SCharles.Forsyth if(c->flag & COPEN)
111*74a4d8c2SCharles.Forsyth panic("clone of open file type %C\n", devtab[c->type]->dc);
112*74a4d8c2SCharles.Forsyth
113*74a4d8c2SCharles.Forsyth nc = newchan();
114*74a4d8c2SCharles.Forsyth
115*74a4d8c2SCharles.Forsyth nc->type = c->type;
116*74a4d8c2SCharles.Forsyth nc->dev = c->dev;
117*74a4d8c2SCharles.Forsyth nc->mode = c->mode;
118*74a4d8c2SCharles.Forsyth nc->qid = c->qid;
119*74a4d8c2SCharles.Forsyth nc->offset = c->offset;
120*74a4d8c2SCharles.Forsyth nc->umh = nil;
121*74a4d8c2SCharles.Forsyth nc->mountid = c->mountid;
122*74a4d8c2SCharles.Forsyth nc->aux = c->aux;
123*74a4d8c2SCharles.Forsyth nc->mqid = c->mqid;
124*74a4d8c2SCharles.Forsyth nc->mcp = c->mcp;
125*74a4d8c2SCharles.Forsyth return nc;
126*74a4d8c2SCharles.Forsyth }
127*74a4d8c2SCharles.Forsyth
128*74a4d8c2SCharles.Forsyth Walkqid*
devwalk(Chan * c,Chan * nc,char ** name,int nname,Dirtab * tab,int ntab,Devgen * gen)129*74a4d8c2SCharles.Forsyth devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
130*74a4d8c2SCharles.Forsyth {
131*74a4d8c2SCharles.Forsyth int i, j, alloc;
132*74a4d8c2SCharles.Forsyth Walkqid *wq;
133*74a4d8c2SCharles.Forsyth char *n;
134*74a4d8c2SCharles.Forsyth Dir dir;
135*74a4d8c2SCharles.Forsyth
136*74a4d8c2SCharles.Forsyth if(nname > 0)
137*74a4d8c2SCharles.Forsyth isdir(c);
138*74a4d8c2SCharles.Forsyth
139*74a4d8c2SCharles.Forsyth alloc = 0;
140*74a4d8c2SCharles.Forsyth wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
141*74a4d8c2SCharles.Forsyth if(waserror()){
142*74a4d8c2SCharles.Forsyth if(alloc && wq->clone!=nil)
143*74a4d8c2SCharles.Forsyth cclose(wq->clone);
144*74a4d8c2SCharles.Forsyth free(wq);
145*74a4d8c2SCharles.Forsyth return nil;
146*74a4d8c2SCharles.Forsyth }
147*74a4d8c2SCharles.Forsyth if(nc == nil){
148*74a4d8c2SCharles.Forsyth nc = devclone(c);
149*74a4d8c2SCharles.Forsyth nc->type = 0; /* device doesn't know about this channel yet */
150*74a4d8c2SCharles.Forsyth alloc = 1;
151*74a4d8c2SCharles.Forsyth }
152*74a4d8c2SCharles.Forsyth wq->clone = nc;
153*74a4d8c2SCharles.Forsyth
154*74a4d8c2SCharles.Forsyth for(j=0; j<nname; j++){
155*74a4d8c2SCharles.Forsyth if(!(nc->qid.type&QTDIR)){
156*74a4d8c2SCharles.Forsyth if(j==0)
157*74a4d8c2SCharles.Forsyth error(Enotdir);
158*74a4d8c2SCharles.Forsyth goto Done;
159*74a4d8c2SCharles.Forsyth }
160*74a4d8c2SCharles.Forsyth n = name[j];
161*74a4d8c2SCharles.Forsyth if(strcmp(n, ".") == 0){
162*74a4d8c2SCharles.Forsyth Accept:
163*74a4d8c2SCharles.Forsyth wq->qid[wq->nqid++] = nc->qid;
164*74a4d8c2SCharles.Forsyth continue;
165*74a4d8c2SCharles.Forsyth }
166*74a4d8c2SCharles.Forsyth if(strcmp(n, "..") == 0){
167*74a4d8c2SCharles.Forsyth (*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir);
168*74a4d8c2SCharles.Forsyth nc->qid = dir.qid;
169*74a4d8c2SCharles.Forsyth goto Accept;
170*74a4d8c2SCharles.Forsyth }
171*74a4d8c2SCharles.Forsyth /*
172*74a4d8c2SCharles.Forsyth * Ugly problem: If we're using devgen, make sure we're
173*74a4d8c2SCharles.Forsyth * walking the directory itself, represented by the first
174*74a4d8c2SCharles.Forsyth * entry in the table, and not trying to step into a sub-
175*74a4d8c2SCharles.Forsyth * directory of the table, e.g. /net/net. Devgen itself
176*74a4d8c2SCharles.Forsyth * should take care of the problem, but it doesn't have
177*74a4d8c2SCharles.Forsyth * the necessary information (that we're doing a walk).
178*74a4d8c2SCharles.Forsyth */
179*74a4d8c2SCharles.Forsyth if(gen==devgen && nc->qid.path!=tab[0].qid.path)
180*74a4d8c2SCharles.Forsyth goto Notfound;
181*74a4d8c2SCharles.Forsyth for(i=0;; i++) {
182*74a4d8c2SCharles.Forsyth switch((*gen)(nc, n, tab, ntab, i, &dir)){
183*74a4d8c2SCharles.Forsyth case -1:
184*74a4d8c2SCharles.Forsyth Notfound:
185*74a4d8c2SCharles.Forsyth if(j == 0)
186*74a4d8c2SCharles.Forsyth error(Enonexist);
187*74a4d8c2SCharles.Forsyth kstrcpy(up->env->errstr, Enonexist, ERRMAX);
188*74a4d8c2SCharles.Forsyth goto Done;
189*74a4d8c2SCharles.Forsyth case 0:
190*74a4d8c2SCharles.Forsyth continue;
191*74a4d8c2SCharles.Forsyth case 1:
192*74a4d8c2SCharles.Forsyth if(strcmp(n, dir.name) == 0){
193*74a4d8c2SCharles.Forsyth nc->qid = dir.qid;
194*74a4d8c2SCharles.Forsyth goto Accept;
195*74a4d8c2SCharles.Forsyth }
196*74a4d8c2SCharles.Forsyth continue;
197*74a4d8c2SCharles.Forsyth }
198*74a4d8c2SCharles.Forsyth }
199*74a4d8c2SCharles.Forsyth }
200*74a4d8c2SCharles.Forsyth /*
201*74a4d8c2SCharles.Forsyth * We processed at least one name, so will return some data.
202*74a4d8c2SCharles.Forsyth * If we didn't process all nname entries succesfully, we drop
203*74a4d8c2SCharles.Forsyth * the cloned channel and return just the Qids of the walks.
204*74a4d8c2SCharles.Forsyth */
205*74a4d8c2SCharles.Forsyth Done:
206*74a4d8c2SCharles.Forsyth poperror();
207*74a4d8c2SCharles.Forsyth if(wq->nqid < nname){
208*74a4d8c2SCharles.Forsyth if(alloc)
209*74a4d8c2SCharles.Forsyth cclose(wq->clone);
210*74a4d8c2SCharles.Forsyth wq->clone = nil;
211*74a4d8c2SCharles.Forsyth }else if(wq->clone){
212*74a4d8c2SCharles.Forsyth /* attach cloned channel to same device */
213*74a4d8c2SCharles.Forsyth wq->clone->type = c->type;
214*74a4d8c2SCharles.Forsyth }
215*74a4d8c2SCharles.Forsyth return wq;
216*74a4d8c2SCharles.Forsyth }
217*74a4d8c2SCharles.Forsyth
218*74a4d8c2SCharles.Forsyth int
devstat(Chan * c,uchar * db,int n,Dirtab * tab,int ntab,Devgen * gen)219*74a4d8c2SCharles.Forsyth devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
220*74a4d8c2SCharles.Forsyth {
221*74a4d8c2SCharles.Forsyth int i;
222*74a4d8c2SCharles.Forsyth Dir dir;
223*74a4d8c2SCharles.Forsyth char *p, *elem;
224*74a4d8c2SCharles.Forsyth
225*74a4d8c2SCharles.Forsyth for(i=0;; i++)
226*74a4d8c2SCharles.Forsyth switch((*gen)(c, nil, tab, ntab, i, &dir)){
227*74a4d8c2SCharles.Forsyth case -1:
228*74a4d8c2SCharles.Forsyth if(c->qid.type & QTDIR){
229*74a4d8c2SCharles.Forsyth if(c->name == nil)
230*74a4d8c2SCharles.Forsyth elem = "???";
231*74a4d8c2SCharles.Forsyth else if(strcmp(c->name->s, "/") == 0)
232*74a4d8c2SCharles.Forsyth elem = "/";
233*74a4d8c2SCharles.Forsyth else
234*74a4d8c2SCharles.Forsyth for(elem=p=c->name->s; *p; p++)
235*74a4d8c2SCharles.Forsyth if(*p == '/')
236*74a4d8c2SCharles.Forsyth elem = p+1;
237*74a4d8c2SCharles.Forsyth devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
238*74a4d8c2SCharles.Forsyth n = convD2M(&dir, db, n);
239*74a4d8c2SCharles.Forsyth if(n == 0)
240*74a4d8c2SCharles.Forsyth error(Ebadarg);
241*74a4d8c2SCharles.Forsyth return n;
242*74a4d8c2SCharles.Forsyth }
243*74a4d8c2SCharles.Forsyth print("%s %s: devstat %C %llux\n",
244*74a4d8c2SCharles.Forsyth up->text, up->env->user,
245*74a4d8c2SCharles.Forsyth devtab[c->type]->dc, c->qid.path);
246*74a4d8c2SCharles.Forsyth
247*74a4d8c2SCharles.Forsyth error(Enonexist);
248*74a4d8c2SCharles.Forsyth case 0:
249*74a4d8c2SCharles.Forsyth break;
250*74a4d8c2SCharles.Forsyth case 1:
251*74a4d8c2SCharles.Forsyth if(c->qid.path == dir.qid.path) {
252*74a4d8c2SCharles.Forsyth if(c->flag&CMSG)
253*74a4d8c2SCharles.Forsyth dir.mode |= DMMOUNT;
254*74a4d8c2SCharles.Forsyth n = convD2M(&dir, db, n);
255*74a4d8c2SCharles.Forsyth if(n == 0)
256*74a4d8c2SCharles.Forsyth error(Ebadarg);
257*74a4d8c2SCharles.Forsyth return n;
258*74a4d8c2SCharles.Forsyth }
259*74a4d8c2SCharles.Forsyth break;
260*74a4d8c2SCharles.Forsyth }
261*74a4d8c2SCharles.Forsyth }
262*74a4d8c2SCharles.Forsyth
263*74a4d8c2SCharles.Forsyth long
devdirread(Chan * c,char * d,long n,Dirtab * tab,int ntab,Devgen * gen)264*74a4d8c2SCharles.Forsyth devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
265*74a4d8c2SCharles.Forsyth {
266*74a4d8c2SCharles.Forsyth long m, dsz;
267*74a4d8c2SCharles.Forsyth struct{
268*74a4d8c2SCharles.Forsyth Dir;
269*74a4d8c2SCharles.Forsyth char slop[100];
270*74a4d8c2SCharles.Forsyth }dir;
271*74a4d8c2SCharles.Forsyth
272*74a4d8c2SCharles.Forsyth for(m=0; m<n; c->dri++) {
273*74a4d8c2SCharles.Forsyth switch((*gen)(c, nil, tab, ntab, c->dri, &dir)){
274*74a4d8c2SCharles.Forsyth case -1:
275*74a4d8c2SCharles.Forsyth return m;
276*74a4d8c2SCharles.Forsyth
277*74a4d8c2SCharles.Forsyth case 0:
278*74a4d8c2SCharles.Forsyth break;
279*74a4d8c2SCharles.Forsyth
280*74a4d8c2SCharles.Forsyth case 1:
281*74a4d8c2SCharles.Forsyth dsz = convD2M(&dir, (uchar*)d, n-m);
282*74a4d8c2SCharles.Forsyth if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */
283*74a4d8c2SCharles.Forsyth if(m == 0)
284*74a4d8c2SCharles.Forsyth error(Eshort);
285*74a4d8c2SCharles.Forsyth return m;
286*74a4d8c2SCharles.Forsyth }
287*74a4d8c2SCharles.Forsyth m += dsz;
288*74a4d8c2SCharles.Forsyth d += dsz;
289*74a4d8c2SCharles.Forsyth break;
290*74a4d8c2SCharles.Forsyth }
291*74a4d8c2SCharles.Forsyth }
292*74a4d8c2SCharles.Forsyth
293*74a4d8c2SCharles.Forsyth return m;
294*74a4d8c2SCharles.Forsyth }
295*74a4d8c2SCharles.Forsyth
296*74a4d8c2SCharles.Forsyth /*
297*74a4d8c2SCharles.Forsyth * error(Eperm) if open permission not granted for up->env->user.
298*74a4d8c2SCharles.Forsyth */
299*74a4d8c2SCharles.Forsyth void
devpermcheck(char * fileuid,ulong perm,int omode)300*74a4d8c2SCharles.Forsyth devpermcheck(char *fileuid, ulong perm, int omode)
301*74a4d8c2SCharles.Forsyth {
302*74a4d8c2SCharles.Forsyth ulong t;
303*74a4d8c2SCharles.Forsyth static int access[] = { 0400, 0200, 0600, 0100 };
304*74a4d8c2SCharles.Forsyth
305*74a4d8c2SCharles.Forsyth if(strcmp(up->env->user, fileuid) == 0)
306*74a4d8c2SCharles.Forsyth perm <<= 0;
307*74a4d8c2SCharles.Forsyth else
308*74a4d8c2SCharles.Forsyth if(strcmp(up->env->user, eve) == 0)
309*74a4d8c2SCharles.Forsyth perm <<= 3;
310*74a4d8c2SCharles.Forsyth else
311*74a4d8c2SCharles.Forsyth perm <<= 6;
312*74a4d8c2SCharles.Forsyth
313*74a4d8c2SCharles.Forsyth t = access[omode&3];
314*74a4d8c2SCharles.Forsyth if((t&perm) != t)
315*74a4d8c2SCharles.Forsyth error(Eperm);
316*74a4d8c2SCharles.Forsyth }
317*74a4d8c2SCharles.Forsyth
318*74a4d8c2SCharles.Forsyth Chan*
devopen(Chan * c,int omode,Dirtab * tab,int ntab,Devgen * gen)319*74a4d8c2SCharles.Forsyth devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
320*74a4d8c2SCharles.Forsyth {
321*74a4d8c2SCharles.Forsyth int i;
322*74a4d8c2SCharles.Forsyth Dir dir;
323*74a4d8c2SCharles.Forsyth
324*74a4d8c2SCharles.Forsyth for(i=0;; i++) {
325*74a4d8c2SCharles.Forsyth switch((*gen)(c, nil, tab, ntab, i, &dir)){
326*74a4d8c2SCharles.Forsyth case -1:
327*74a4d8c2SCharles.Forsyth goto Return;
328*74a4d8c2SCharles.Forsyth case 0:
329*74a4d8c2SCharles.Forsyth break;
330*74a4d8c2SCharles.Forsyth case 1:
331*74a4d8c2SCharles.Forsyth if(c->qid.path == dir.qid.path) {
332*74a4d8c2SCharles.Forsyth devpermcheck(dir.uid, dir.mode, omode);
333*74a4d8c2SCharles.Forsyth goto Return;
334*74a4d8c2SCharles.Forsyth }
335*74a4d8c2SCharles.Forsyth break;
336*74a4d8c2SCharles.Forsyth }
337*74a4d8c2SCharles.Forsyth }
338*74a4d8c2SCharles.Forsyth Return:
339*74a4d8c2SCharles.Forsyth c->offset = 0;
340*74a4d8c2SCharles.Forsyth if((c->qid.type&QTDIR) && omode!=OREAD)
341*74a4d8c2SCharles.Forsyth error(Eperm);
342*74a4d8c2SCharles.Forsyth c->mode = openmode(omode);
343*74a4d8c2SCharles.Forsyth c->flag |= COPEN;
344*74a4d8c2SCharles.Forsyth return c;
345*74a4d8c2SCharles.Forsyth }
346*74a4d8c2SCharles.Forsyth
347*74a4d8c2SCharles.Forsyth void
devcreate(Chan *,char *,int,ulong)348*74a4d8c2SCharles.Forsyth devcreate(Chan*, char*, int, ulong)
349*74a4d8c2SCharles.Forsyth {
350*74a4d8c2SCharles.Forsyth error(Eperm);
351*74a4d8c2SCharles.Forsyth }
352*74a4d8c2SCharles.Forsyth
353*74a4d8c2SCharles.Forsyth Block*
devbread(Chan * c,long n,ulong offset)354*74a4d8c2SCharles.Forsyth devbread(Chan *c, long n, ulong offset)
355*74a4d8c2SCharles.Forsyth {
356*74a4d8c2SCharles.Forsyth Block *bp;
357*74a4d8c2SCharles.Forsyth
358*74a4d8c2SCharles.Forsyth bp = allocb(n);
359*74a4d8c2SCharles.Forsyth if(bp == 0)
360*74a4d8c2SCharles.Forsyth error(Enomem);
361*74a4d8c2SCharles.Forsyth if(waserror()) {
362*74a4d8c2SCharles.Forsyth freeb(bp);
363*74a4d8c2SCharles.Forsyth nexterror();
364*74a4d8c2SCharles.Forsyth }
365*74a4d8c2SCharles.Forsyth bp->wp += devtab[c->type]->read(c, bp->wp, n, offset);
366*74a4d8c2SCharles.Forsyth poperror();
367*74a4d8c2SCharles.Forsyth return bp;
368*74a4d8c2SCharles.Forsyth }
369*74a4d8c2SCharles.Forsyth
370*74a4d8c2SCharles.Forsyth long
devbwrite(Chan * c,Block * bp,ulong offset)371*74a4d8c2SCharles.Forsyth devbwrite(Chan *c, Block *bp, ulong offset)
372*74a4d8c2SCharles.Forsyth {
373*74a4d8c2SCharles.Forsyth long n;
374*74a4d8c2SCharles.Forsyth
375*74a4d8c2SCharles.Forsyth if(waserror()) {
376*74a4d8c2SCharles.Forsyth freeb(bp);
377*74a4d8c2SCharles.Forsyth nexterror();
378*74a4d8c2SCharles.Forsyth }
379*74a4d8c2SCharles.Forsyth n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset);
380*74a4d8c2SCharles.Forsyth poperror();
381*74a4d8c2SCharles.Forsyth freeb(bp);
382*74a4d8c2SCharles.Forsyth
383*74a4d8c2SCharles.Forsyth return n;
384*74a4d8c2SCharles.Forsyth }
385*74a4d8c2SCharles.Forsyth
386*74a4d8c2SCharles.Forsyth void
devremove(Chan *)387*74a4d8c2SCharles.Forsyth devremove(Chan*)
388*74a4d8c2SCharles.Forsyth {
389*74a4d8c2SCharles.Forsyth error(Eperm);
390*74a4d8c2SCharles.Forsyth }
391*74a4d8c2SCharles.Forsyth
392*74a4d8c2SCharles.Forsyth int
devwstat(Chan *,uchar *,int)393*74a4d8c2SCharles.Forsyth devwstat(Chan*, uchar*, int)
394*74a4d8c2SCharles.Forsyth {
395*74a4d8c2SCharles.Forsyth error(Eperm);
396*74a4d8c2SCharles.Forsyth return 0;
397*74a4d8c2SCharles.Forsyth }
398*74a4d8c2SCharles.Forsyth
399*74a4d8c2SCharles.Forsyth void
devpower(int)400*74a4d8c2SCharles.Forsyth devpower(int)
401*74a4d8c2SCharles.Forsyth {
402*74a4d8c2SCharles.Forsyth error(Eperm);
403*74a4d8c2SCharles.Forsyth }
404*74a4d8c2SCharles.Forsyth
405*74a4d8c2SCharles.Forsyth int
devconfig(int,char *,DevConf *)406*74a4d8c2SCharles.Forsyth devconfig(int, char *, DevConf *)
407*74a4d8c2SCharles.Forsyth {
408*74a4d8c2SCharles.Forsyth error(Eperm);
409*74a4d8c2SCharles.Forsyth return 0;
410*74a4d8c2SCharles.Forsyth }
411*74a4d8c2SCharles.Forsyth
412*74a4d8c2SCharles.Forsyth /*
413*74a4d8c2SCharles.Forsyth * check that the name in a wstat is plausible
414*74a4d8c2SCharles.Forsyth */
415*74a4d8c2SCharles.Forsyth void
validwstatname(char * name)416*74a4d8c2SCharles.Forsyth validwstatname(char *name)
417*74a4d8c2SCharles.Forsyth {
418*74a4d8c2SCharles.Forsyth validname(name, 0);
419*74a4d8c2SCharles.Forsyth if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
420*74a4d8c2SCharles.Forsyth error(Efilename);
421*74a4d8c2SCharles.Forsyth }
422*74a4d8c2SCharles.Forsyth
423*74a4d8c2SCharles.Forsyth Dev*
devbyname(char * name)424*74a4d8c2SCharles.Forsyth devbyname(char *name)
425*74a4d8c2SCharles.Forsyth {
426*74a4d8c2SCharles.Forsyth int i;
427*74a4d8c2SCharles.Forsyth
428*74a4d8c2SCharles.Forsyth for(i = 0; devtab[i] != nil; i++)
429*74a4d8c2SCharles.Forsyth if(strcmp(devtab[i]->name, name) == 0)
430*74a4d8c2SCharles.Forsyth return devtab[i];
431*74a4d8c2SCharles.Forsyth return nil;
432*74a4d8c2SCharles.Forsyth }
433