137da2899SCharles.Forsyth #include "dat.h"
237da2899SCharles.Forsyth #include "fns.h"
337da2899SCharles.Forsyth #include "error.h"
437da2899SCharles.Forsyth
537da2899SCharles.Forsyth extern ulong kerndate;
637da2899SCharles.Forsyth
737da2899SCharles.Forsyth void
mkqid(Qid * q,vlong path,ulong vers,int type)837da2899SCharles.Forsyth mkqid(Qid *q, vlong path, ulong vers, int type)
937da2899SCharles.Forsyth {
1037da2899SCharles.Forsyth q->type = type;
1137da2899SCharles.Forsyth q->vers = vers;
1237da2899SCharles.Forsyth q->path = path;
1337da2899SCharles.Forsyth }
1437da2899SCharles.Forsyth
1537da2899SCharles.Forsyth int
devno(int c,int user)1637da2899SCharles.Forsyth devno(int c, int user)
1737da2899SCharles.Forsyth {
1837da2899SCharles.Forsyth int i;
1937da2899SCharles.Forsyth
2037da2899SCharles.Forsyth for(i = 0; devtab[i] != nil; i++) {
2137da2899SCharles.Forsyth if(devtab[i]->dc == c)
2237da2899SCharles.Forsyth return i;
2337da2899SCharles.Forsyth }
2437da2899SCharles.Forsyth if(user == 0)
2537da2899SCharles.Forsyth panic("devno %C 0x%ux", c, c);
2637da2899SCharles.Forsyth
2737da2899SCharles.Forsyth return -1;
2837da2899SCharles.Forsyth }
2937da2899SCharles.Forsyth
3037da2899SCharles.Forsyth void
devdir(Chan * c,Qid qid,char * n,long length,char * user,long perm,Dir * db)3137da2899SCharles.Forsyth devdir(Chan *c, Qid qid, char *n, long length, char *user, long perm, Dir *db)
3237da2899SCharles.Forsyth {
3337da2899SCharles.Forsyth db->name = n;
3437da2899SCharles.Forsyth if(c->flag&CMSG)
3537da2899SCharles.Forsyth qid.type |= QTMOUNT;
3637da2899SCharles.Forsyth db->qid = qid;
3737da2899SCharles.Forsyth db->type = devtab[c->type]->dc;
3837da2899SCharles.Forsyth db->dev = c->dev;
3937da2899SCharles.Forsyth db->mode = perm | (qid.type << 24);
4037da2899SCharles.Forsyth db->atime = time(0);
4137da2899SCharles.Forsyth db->mtime = kerndate;
4237da2899SCharles.Forsyth db->length = length;
4337da2899SCharles.Forsyth db->uid = user;
4437da2899SCharles.Forsyth db->gid = eve;
4537da2899SCharles.Forsyth db->muid = user;
4637da2899SCharles.Forsyth }
4737da2899SCharles.Forsyth
4837da2899SCharles.Forsyth /*
4937da2899SCharles.Forsyth * the zeroth element of the table MUST be the directory itself for ..
5037da2899SCharles.Forsyth */
5137da2899SCharles.Forsyth int
devgen(Chan * c,char * name,Dirtab * tab,int ntab,int i,Dir * dp)5237da2899SCharles.Forsyth devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
5337da2899SCharles.Forsyth {
5437da2899SCharles.Forsyth USED(name);
5537da2899SCharles.Forsyth if(tab == 0)
5637da2899SCharles.Forsyth return -1;
5737da2899SCharles.Forsyth if(i != DEVDOTDOT){
5837da2899SCharles.Forsyth /* skip over the first element, that for . itself */
5937da2899SCharles.Forsyth i++;
6037da2899SCharles.Forsyth if(i >= ntab)
6137da2899SCharles.Forsyth return -1;
6237da2899SCharles.Forsyth tab += i;
6337da2899SCharles.Forsyth }
6437da2899SCharles.Forsyth devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
6537da2899SCharles.Forsyth return 1;
6637da2899SCharles.Forsyth }
6737da2899SCharles.Forsyth
6837da2899SCharles.Forsyth void
devinit(void)6937da2899SCharles.Forsyth devinit(void)
7037da2899SCharles.Forsyth {
7137da2899SCharles.Forsyth }
7237da2899SCharles.Forsyth
7337da2899SCharles.Forsyth void
devshutdown(void)7437da2899SCharles.Forsyth devshutdown(void)
7537da2899SCharles.Forsyth {
7637da2899SCharles.Forsyth }
7737da2899SCharles.Forsyth
7837da2899SCharles.Forsyth Chan*
devattach(int tc,char * spec)7937da2899SCharles.Forsyth devattach(int tc, char *spec)
8037da2899SCharles.Forsyth {
8137da2899SCharles.Forsyth Chan *c;
8237da2899SCharles.Forsyth char *buf;
8337da2899SCharles.Forsyth
8437da2899SCharles.Forsyth c = newchan();
8537da2899SCharles.Forsyth mkqid(&c->qid, 0, 0, QTDIR);
8637da2899SCharles.Forsyth c->type = devno(tc, 0);
8737da2899SCharles.Forsyth if(spec == nil)
8837da2899SCharles.Forsyth spec = "";
8937da2899SCharles.Forsyth buf = smalloc(4+strlen(spec)+1);
9037da2899SCharles.Forsyth sprint(buf, "#%C%s", tc, spec);
9137da2899SCharles.Forsyth c->name = newcname(buf);
9237da2899SCharles.Forsyth free(buf);
9337da2899SCharles.Forsyth return c;
9437da2899SCharles.Forsyth }
9537da2899SCharles.Forsyth
9637da2899SCharles.Forsyth Chan*
devclone(Chan * c)9737da2899SCharles.Forsyth devclone(Chan *c)
9837da2899SCharles.Forsyth {
9937da2899SCharles.Forsyth Chan *nc;
10037da2899SCharles.Forsyth
10137da2899SCharles.Forsyth if(c->flag & COPEN)
10237da2899SCharles.Forsyth panic("clone of open file type %C\n", devtab[c->type]->dc);
10337da2899SCharles.Forsyth
10437da2899SCharles.Forsyth nc = newchan();
10537da2899SCharles.Forsyth nc->type = c->type;
10637da2899SCharles.Forsyth nc->dev = c->dev;
10737da2899SCharles.Forsyth nc->mode = c->mode;
10837da2899SCharles.Forsyth nc->qid = c->qid;
10937da2899SCharles.Forsyth nc->offset = c->offset;
11037da2899SCharles.Forsyth nc->umh = nil;
11137da2899SCharles.Forsyth nc->mountid = c->mountid;
11237da2899SCharles.Forsyth nc->aux = c->aux;
11337da2899SCharles.Forsyth nc->mqid = c->mqid;
11437da2899SCharles.Forsyth nc->mcp = c->mcp;
11537da2899SCharles.Forsyth return nc;
11637da2899SCharles.Forsyth }
11737da2899SCharles.Forsyth
11837da2899SCharles.Forsyth Walkqid*
devwalk(Chan * c,Chan * nc,char ** name,int nname,Dirtab * tab,int ntab,Devgen * gen)11937da2899SCharles.Forsyth devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
12037da2899SCharles.Forsyth {
121*45a14cc6SCharles.Forsyth int i, j;
122*45a14cc6SCharles.Forsyth volatile int alloc;
12337da2899SCharles.Forsyth Walkqid *wq;
12437da2899SCharles.Forsyth char *n;
12537da2899SCharles.Forsyth Dir dir;
12637da2899SCharles.Forsyth
12737da2899SCharles.Forsyth if(nname > 0)
12837da2899SCharles.Forsyth isdir(c);
12937da2899SCharles.Forsyth
13037da2899SCharles.Forsyth alloc = 0;
13137da2899SCharles.Forsyth wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
13237da2899SCharles.Forsyth if(waserror()){
13337da2899SCharles.Forsyth if(alloc && wq->clone!=nil)
13437da2899SCharles.Forsyth cclose(wq->clone);
13537da2899SCharles.Forsyth free(wq);
13637da2899SCharles.Forsyth return nil;
13737da2899SCharles.Forsyth }
13837da2899SCharles.Forsyth if(nc == nil){
13937da2899SCharles.Forsyth nc = devclone(c);
14037da2899SCharles.Forsyth nc->type = 0; /* device doesn't know about this channel yet */
14137da2899SCharles.Forsyth alloc = 1;
14237da2899SCharles.Forsyth }
14337da2899SCharles.Forsyth wq->clone = nc;
14437da2899SCharles.Forsyth
14537da2899SCharles.Forsyth for(j=0; j<nname; j++){
14637da2899SCharles.Forsyth if(!(nc->qid.type&QTDIR)){
14737da2899SCharles.Forsyth if(j==0)
14837da2899SCharles.Forsyth error(Enotdir);
14937da2899SCharles.Forsyth goto Done;
15037da2899SCharles.Forsyth }
15137da2899SCharles.Forsyth n = name[j];
15237da2899SCharles.Forsyth if(strcmp(n, ".") == 0){
15337da2899SCharles.Forsyth Accept:
15437da2899SCharles.Forsyth wq->qid[wq->nqid++] = nc->qid;
15537da2899SCharles.Forsyth continue;
15637da2899SCharles.Forsyth }
15737da2899SCharles.Forsyth if(strcmp(n, "..") == 0){
15837da2899SCharles.Forsyth (*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir);
15937da2899SCharles.Forsyth nc->qid = dir.qid;
16037da2899SCharles.Forsyth goto Accept;
16137da2899SCharles.Forsyth }
16237da2899SCharles.Forsyth /*
16337da2899SCharles.Forsyth * Ugly problem: If we're using devgen, make sure we're
16437da2899SCharles.Forsyth * walking the directory itself, represented by the first
16537da2899SCharles.Forsyth * entry in the table, and not trying to step into a sub-
16637da2899SCharles.Forsyth * directory of the table, e.g. /net/net. Devgen itself
16737da2899SCharles.Forsyth * should take care of the problem, but it doesn't have
16837da2899SCharles.Forsyth * the necessary information (that we're doing a walk).
16937da2899SCharles.Forsyth */
17037da2899SCharles.Forsyth if(gen==devgen && nc->qid.path!=tab[0].qid.path)
17137da2899SCharles.Forsyth goto Notfound;
17237da2899SCharles.Forsyth for(i=0;; i++) {
17337da2899SCharles.Forsyth switch((*gen)(nc, n, tab, ntab, i, &dir)){
17437da2899SCharles.Forsyth case -1:
17537da2899SCharles.Forsyth Notfound:
17637da2899SCharles.Forsyth if(j == 0)
17737da2899SCharles.Forsyth error(Enonexist);
17837da2899SCharles.Forsyth kstrcpy(up->env->errstr, Enonexist, ERRMAX);
17937da2899SCharles.Forsyth goto Done;
18037da2899SCharles.Forsyth case 0:
18137da2899SCharles.Forsyth continue;
18237da2899SCharles.Forsyth case 1:
18337da2899SCharles.Forsyth if(strcmp(n, dir.name) == 0){
18437da2899SCharles.Forsyth nc->qid = dir.qid;
18537da2899SCharles.Forsyth goto Accept;
18637da2899SCharles.Forsyth }
18737da2899SCharles.Forsyth continue;
18837da2899SCharles.Forsyth }
18937da2899SCharles.Forsyth }
19037da2899SCharles.Forsyth }
19137da2899SCharles.Forsyth /*
19237da2899SCharles.Forsyth * We processed at least one name, so will return some data.
19337da2899SCharles.Forsyth * If we didn't process all nname entries succesfully, we drop
19437da2899SCharles.Forsyth * the cloned channel and return just the Qids of the walks.
19537da2899SCharles.Forsyth */
19637da2899SCharles.Forsyth Done:
19737da2899SCharles.Forsyth poperror();
19837da2899SCharles.Forsyth if(wq->nqid < nname){
19937da2899SCharles.Forsyth if(alloc)
20037da2899SCharles.Forsyth cclose(wq->clone);
20137da2899SCharles.Forsyth wq->clone = nil;
20237da2899SCharles.Forsyth }else if(wq->clone){
20337da2899SCharles.Forsyth /* attach cloned channel to same device */
20437da2899SCharles.Forsyth wq->clone->type = c->type;
20537da2899SCharles.Forsyth }
20637da2899SCharles.Forsyth return wq;
20737da2899SCharles.Forsyth }
20837da2899SCharles.Forsyth
20937da2899SCharles.Forsyth int
devstat(Chan * c,uchar * db,int n,Dirtab * tab,int ntab,Devgen * gen)21037da2899SCharles.Forsyth devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
21137da2899SCharles.Forsyth {
21237da2899SCharles.Forsyth int i;
21337da2899SCharles.Forsyth Dir dir;
21437da2899SCharles.Forsyth char *p, *elem;
21537da2899SCharles.Forsyth
21637da2899SCharles.Forsyth for(i=0;; i++)
21737da2899SCharles.Forsyth switch((*gen)(c, nil, tab, ntab, i, &dir)){
21837da2899SCharles.Forsyth case -1:
21937da2899SCharles.Forsyth if(c->qid.type & QTDIR){
22037da2899SCharles.Forsyth if(c->name == nil)
22137da2899SCharles.Forsyth elem = "???";
22237da2899SCharles.Forsyth else if(strcmp(c->name->s, "/") == 0)
22337da2899SCharles.Forsyth elem = "/";
22437da2899SCharles.Forsyth else
22537da2899SCharles.Forsyth for(elem=p=c->name->s; *p; p++)
22637da2899SCharles.Forsyth if(*p == '/')
22737da2899SCharles.Forsyth elem = p+1;
22837da2899SCharles.Forsyth devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
22937da2899SCharles.Forsyth n = convD2M(&dir, db, n);
23037da2899SCharles.Forsyth if(n == 0)
23137da2899SCharles.Forsyth error(Ebadarg);
23237da2899SCharles.Forsyth return n;
23337da2899SCharles.Forsyth }
23437da2899SCharles.Forsyth print("%s %s: devstat %C %llux\n",
23537da2899SCharles.Forsyth up->text, up->env->user,
23637da2899SCharles.Forsyth devtab[c->type]->dc, c->qid.path);
23737da2899SCharles.Forsyth
23837da2899SCharles.Forsyth error(Enonexist);
23937da2899SCharles.Forsyth case 0:
24037da2899SCharles.Forsyth break;
24137da2899SCharles.Forsyth case 1:
24237da2899SCharles.Forsyth if(c->qid.path == dir.qid.path) {
24337da2899SCharles.Forsyth if(c->flag&CMSG)
24437da2899SCharles.Forsyth dir.mode |= DMMOUNT;
24537da2899SCharles.Forsyth n = convD2M(&dir, db, n);
24637da2899SCharles.Forsyth if(n == 0)
24737da2899SCharles.Forsyth error(Ebadarg);
24837da2899SCharles.Forsyth return n;
24937da2899SCharles.Forsyth }
25037da2899SCharles.Forsyth break;
25137da2899SCharles.Forsyth }
25237da2899SCharles.Forsyth }
25337da2899SCharles.Forsyth
25437da2899SCharles.Forsyth long
devdirread(Chan * c,char * d,long n,Dirtab * tab,int ntab,Devgen * gen)25537da2899SCharles.Forsyth devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
25637da2899SCharles.Forsyth {
25737da2899SCharles.Forsyth long m, dsz;
25837da2899SCharles.Forsyth struct{
25937da2899SCharles.Forsyth Dir d;
26037da2899SCharles.Forsyth char slop[100]; /* TO DO */
26137da2899SCharles.Forsyth }dir;
26237da2899SCharles.Forsyth
26337da2899SCharles.Forsyth for(m=0; m<n; c->dri++) {
26437da2899SCharles.Forsyth switch((*gen)(c, nil, tab, ntab, c->dri, &dir.d)){
26537da2899SCharles.Forsyth case -1:
26637da2899SCharles.Forsyth return m;
26737da2899SCharles.Forsyth
26837da2899SCharles.Forsyth case 0:
26937da2899SCharles.Forsyth break;
27037da2899SCharles.Forsyth
27137da2899SCharles.Forsyth case 1:
27237da2899SCharles.Forsyth dsz = convD2M(&dir.d, (uchar*)d, n-m);
27337da2899SCharles.Forsyth if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */
27437da2899SCharles.Forsyth if(m == 0)
27537da2899SCharles.Forsyth error(Eshort);
27637da2899SCharles.Forsyth return m;
27737da2899SCharles.Forsyth }
27837da2899SCharles.Forsyth m += dsz;
27937da2899SCharles.Forsyth d += dsz;
28037da2899SCharles.Forsyth break;
28137da2899SCharles.Forsyth }
28237da2899SCharles.Forsyth }
28337da2899SCharles.Forsyth
28437da2899SCharles.Forsyth return m;
28537da2899SCharles.Forsyth }
28637da2899SCharles.Forsyth
28737da2899SCharles.Forsyth /*
28837da2899SCharles.Forsyth * error(Eperm) if open permission not granted for up->env->user.
28937da2899SCharles.Forsyth */
29037da2899SCharles.Forsyth void
devpermcheck(char * fileuid,ulong perm,int omode)29137da2899SCharles.Forsyth devpermcheck(char *fileuid, ulong perm, int omode)
29237da2899SCharles.Forsyth {
29337da2899SCharles.Forsyth ulong t;
29437da2899SCharles.Forsyth static int access[] = { 0400, 0200, 0600, 0100 };
29537da2899SCharles.Forsyth
29637da2899SCharles.Forsyth if(strcmp(up->env->user, fileuid) == 0)
29737da2899SCharles.Forsyth perm <<= 0;
29837da2899SCharles.Forsyth else
29937da2899SCharles.Forsyth if(strcmp(up->env->user, eve) == 0)
30037da2899SCharles.Forsyth perm <<= 3;
30137da2899SCharles.Forsyth else
30237da2899SCharles.Forsyth perm <<= 6;
30337da2899SCharles.Forsyth
30437da2899SCharles.Forsyth t = access[omode&3];
30537da2899SCharles.Forsyth if((t&perm) != t)
30637da2899SCharles.Forsyth error(Eperm);
30737da2899SCharles.Forsyth }
30837da2899SCharles.Forsyth
30937da2899SCharles.Forsyth Chan*
devopen(Chan * c,int omode,Dirtab * tab,int ntab,Devgen * gen)31037da2899SCharles.Forsyth devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
31137da2899SCharles.Forsyth {
31237da2899SCharles.Forsyth int i;
31337da2899SCharles.Forsyth Dir dir;
31437da2899SCharles.Forsyth
31537da2899SCharles.Forsyth for(i=0;; i++) {
31637da2899SCharles.Forsyth switch((*gen)(c, nil, tab, ntab, i, &dir)){
31737da2899SCharles.Forsyth case -1:
31837da2899SCharles.Forsyth goto Return;
31937da2899SCharles.Forsyth case 0:
32037da2899SCharles.Forsyth break;
32137da2899SCharles.Forsyth case 1:
32237da2899SCharles.Forsyth if(c->qid.path == dir.qid.path) {
32337da2899SCharles.Forsyth devpermcheck(dir.uid, dir.mode, omode);
32437da2899SCharles.Forsyth goto Return;
32537da2899SCharles.Forsyth }
32637da2899SCharles.Forsyth break;
32737da2899SCharles.Forsyth }
32837da2899SCharles.Forsyth }
32937da2899SCharles.Forsyth Return:
33037da2899SCharles.Forsyth c->offset = 0;
33137da2899SCharles.Forsyth if((c->qid.type&QTDIR) && omode!=OREAD)
33237da2899SCharles.Forsyth error(Eperm);
33337da2899SCharles.Forsyth c->mode = openmode(omode);
33437da2899SCharles.Forsyth c->flag |= COPEN;
33537da2899SCharles.Forsyth return c;
33637da2899SCharles.Forsyth }
33737da2899SCharles.Forsyth
33837da2899SCharles.Forsyth Block*
devbread(Chan * c,long n,ulong offset)33937da2899SCharles.Forsyth devbread(Chan *c, long n, ulong offset)
34037da2899SCharles.Forsyth {
34137da2899SCharles.Forsyth Block *bp;
34237da2899SCharles.Forsyth
34337da2899SCharles.Forsyth bp = allocb(n);
34437da2899SCharles.Forsyth if(waserror()) {
34537da2899SCharles.Forsyth freeb(bp);
34637da2899SCharles.Forsyth nexterror();
34737da2899SCharles.Forsyth }
34837da2899SCharles.Forsyth bp->wp += devtab[c->type]->read(c, bp->wp, n, offset);
34937da2899SCharles.Forsyth poperror();
35037da2899SCharles.Forsyth return bp;
35137da2899SCharles.Forsyth }
35237da2899SCharles.Forsyth
35337da2899SCharles.Forsyth long
devbwrite(Chan * c,Block * bp,ulong offset)35437da2899SCharles.Forsyth devbwrite(Chan *c, Block *bp, ulong offset)
35537da2899SCharles.Forsyth {
35637da2899SCharles.Forsyth long n;
35737da2899SCharles.Forsyth
35837da2899SCharles.Forsyth if(waserror()) {
35937da2899SCharles.Forsyth freeb(bp);
36037da2899SCharles.Forsyth nexterror();
36137da2899SCharles.Forsyth }
36237da2899SCharles.Forsyth n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset);
36337da2899SCharles.Forsyth poperror();
36437da2899SCharles.Forsyth freeb(bp);
36537da2899SCharles.Forsyth
36637da2899SCharles.Forsyth return n;
36737da2899SCharles.Forsyth }
36837da2899SCharles.Forsyth
36937da2899SCharles.Forsyth void
devcreate(Chan * c,char * name,int mode,ulong perm)37037da2899SCharles.Forsyth devcreate(Chan *c, char *name, int mode, ulong perm)
37137da2899SCharles.Forsyth {
37237da2899SCharles.Forsyth USED(c);
37337da2899SCharles.Forsyth USED(name);
37437da2899SCharles.Forsyth USED(mode);
37537da2899SCharles.Forsyth USED(perm);
37637da2899SCharles.Forsyth error(Eperm);
37737da2899SCharles.Forsyth }
37837da2899SCharles.Forsyth
37937da2899SCharles.Forsyth void
devremove(Chan * c)38037da2899SCharles.Forsyth devremove(Chan *c)
38137da2899SCharles.Forsyth {
38237da2899SCharles.Forsyth USED(c);
38337da2899SCharles.Forsyth error(Eperm);
38437da2899SCharles.Forsyth }
38537da2899SCharles.Forsyth
38637da2899SCharles.Forsyth int
devwstat(Chan * c,uchar * dp,int n)38737da2899SCharles.Forsyth devwstat(Chan *c, uchar *dp, int n)
38837da2899SCharles.Forsyth {
38937da2899SCharles.Forsyth USED(c);
39037da2899SCharles.Forsyth USED(dp);
39137da2899SCharles.Forsyth USED(n);
39237da2899SCharles.Forsyth error(Eperm);
39337da2899SCharles.Forsyth return 0;
39437da2899SCharles.Forsyth }
39537da2899SCharles.Forsyth
39637da2899SCharles.Forsyth int
readstr(ulong off,char * buf,ulong n,char * str)39737da2899SCharles.Forsyth readstr(ulong off, char *buf, ulong n, char *str)
39837da2899SCharles.Forsyth {
39937da2899SCharles.Forsyth int size;
40037da2899SCharles.Forsyth
40137da2899SCharles.Forsyth size = strlen(str);
40237da2899SCharles.Forsyth if(off >= size)
40337da2899SCharles.Forsyth return 0;
40437da2899SCharles.Forsyth if(off+n > size)
40537da2899SCharles.Forsyth n = size-off;
40637da2899SCharles.Forsyth memmove(buf, str+off, n);
40737da2899SCharles.Forsyth return n;
40837da2899SCharles.Forsyth }
40937da2899SCharles.Forsyth
41037da2899SCharles.Forsyth int
readnum(ulong off,char * buf,ulong n,ulong val,int size)41137da2899SCharles.Forsyth readnum(ulong off, char *buf, ulong n, ulong val, int size)
41237da2899SCharles.Forsyth {
41337da2899SCharles.Forsyth char tmp[64];
41437da2899SCharles.Forsyth
41537da2899SCharles.Forsyth if(size > 64) size = 64;
41637da2899SCharles.Forsyth
41737da2899SCharles.Forsyth snprint(tmp, sizeof(tmp), "%*.0lud ", size, val);
41837da2899SCharles.Forsyth if(off >= size)
41937da2899SCharles.Forsyth return 0;
42037da2899SCharles.Forsyth if(off+n > size)
42137da2899SCharles.Forsyth n = size-off;
42237da2899SCharles.Forsyth memmove(buf, tmp+off, n);
42337da2899SCharles.Forsyth return n;
42437da2899SCharles.Forsyth }
42537da2899SCharles.Forsyth
42637da2899SCharles.Forsyth /*
42737da2899SCharles.Forsyth * check that the name in a wstat is plausible
42837da2899SCharles.Forsyth */
42937da2899SCharles.Forsyth void
validwstatname(char * name)43037da2899SCharles.Forsyth validwstatname(char *name)
43137da2899SCharles.Forsyth {
43237da2899SCharles.Forsyth validname(name, 0);
43337da2899SCharles.Forsyth if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
43437da2899SCharles.Forsyth error(Efilename);
43537da2899SCharles.Forsyth }
43637da2899SCharles.Forsyth
43737da2899SCharles.Forsyth Dev*
devbyname(char * name)43837da2899SCharles.Forsyth devbyname(char *name)
43937da2899SCharles.Forsyth {
44037da2899SCharles.Forsyth int i;
44137da2899SCharles.Forsyth
44237da2899SCharles.Forsyth for(i = 0; devtab[i] != nil; i++)
44337da2899SCharles.Forsyth if(strcmp(devtab[i]->name, name) == 0)
44437da2899SCharles.Forsyth return devtab[i];
44537da2899SCharles.Forsyth return nil;
44637da2899SCharles.Forsyth }
447