10 mkqid(Qid *q, vlong path, ulong vers, int type)
18 devno(int c, int user)
22 for(i = 0; devtab[i] != nil; i++){
23 if(devtab[i]->dc == c)
27 panic("devno %C 0x%ux", c, c);
33 devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
37 db->type = devtab[c->type]->dc;
39 db->mode = (qid.type << 24) | perm;
40 db->atime = seconds();
49 * the zeroth element of the table MUST be the directory itself for ..
52 devgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
57 i++; /* skip first element for . itself */
62 devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
77 devattach(int tc, char *spec)
83 mkqid(&c->qid, 0, 0, QTDIR);
84 c->type = devno(tc, 0);
87 buf = smalloc(4+strlen(spec)+1);
88 sprint(buf, "#%C%s", tc, spec);
89 c->name = newcname(buf);
101 panic("clone of open file type %C\n", devtab[c->type]->dc);
109 nc->offset = c->offset;
115 devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
125 wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
127 if(alloc && wq->clone!=nil)
134 nc->type = 0; /* device doesn't know about this channel yet */
139 for(j=0; j<nname; j++){
142 if(strcmp(n, ".") == 0){
144 wq->qid[wq->nqid++] = nc->qid;
147 if(strcmp(n, "..") == 0){
148 (*gen)(nc, tab, ntab, DEVDOTDOT, &dir);
153 switch((*gen)(nc, tab, ntab, i, &dir)){
157 strncpy(up->error, Enonexist, ERRMAX);
162 if(strcmp(n, dir.name) == 0){
171 * We processed at least one name, so will return some data.
172 * If we didn't process all nname entries succesfully, we drop
173 * the cloned channel and return just the Qids of the walks.
177 if(wq->nqid < nname){
182 /* attach cloned channel to same device */
183 wq->clone->type = c->type;
189 devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
196 switch((*gen)(c, tab, ntab, i, &dir)){
198 if(c->qid.type & QTDIR){
201 else if(strcmp(c->name->s, "/") == 0)
204 for(elem=p=c->name->s; *p; p++)
207 devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
208 return convD2M(&dir, db, n);
215 if(c->qid.path == dir.qid.path){
216 return convD2M(&dir, db, n);
223 devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
233 switch((*gen)(c, tab, ntab, k, &dir)){
238 c->offset++; /* BUG??? (was DIRLEN: skip entry) */
242 dsz = convD2M(&dir, (uchar*)d, n-m);
243 if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */
258 * error(Eperm) if open permission not granted for up->user.
261 devpermcheck(char *fileuid, ulong perm, int omode)
264 static int access[] = { 0400, 0200, 0600, 0100 };
266 if(strcmp(up->user, fileuid) == 0)
269 if(strcmp(up->user, eve) == 0)
280 devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
286 switch((*gen)(c, tab, ntab, i, &dir)){
292 if(c->qid.path == dir.qid.path){
293 devpermcheck(dir.uid, dir.mode, omode);
301 if((c->qid.type&QTDIR) && omode!=OREAD)
303 c->mode = openmode(omode);
309 devcreate(Chan*, char*, int, ulong)
315 devbread(Chan *, long, ulong)
317 panic("no block read");
322 devbwrite(Chan *, Block *, ulong)
324 panic("no block write");
335 devwstat(Chan*, uchar*, int)