static void rstat(Req *r, char *error) { int n; uchar *statbuf; uchar tmp[BIT16SZ]; if(error) return; if(convD2M(&r->d, tmp, BIT16SZ) != BIT16SZ){ r->error = "convD2M(_,_,BIT16SZ) did not return BIT16SZ"; return; } n = GBIT16(tmp)+BIT16SZ; statbuf = emalloc9p(n); if(statbuf == nil){ r->error = "out of memory"; return; } r->ofcall.nstat = convD2M(&r->d, statbuf, n); r->ofcall.stat = statbuf; /* freed in closereq */ if(r->ofcall.nstat <= BIT16SZ){ r->error = "convD2M fails"; free(statbuf); return; } }
int devstat(struct chan *c, uint8_t * db, int n, struct dirtab *tab, int ntab, Devgen * gen) { int i; struct dir dir; char *p, *elem; dir.qid.path = 0; for (i = 0;; i++) switch ((*gen) (c, NULL, tab, ntab, i, &dir)) { case -1: if (c->qid.type & QTDIR) { printd("DEVSTAT got a dir: %llu\n", c->qid.path); if (c->name == NULL) elem = "???"; else if (strcmp(c->name->s, "/") == 0) elem = "/"; else for (elem = p = c->name->s; *p; p++) if (*p == '/') elem = p + 1; devdir(c, c->qid, elem, 0, eve, DMDIR | 0555, &dir); n = convD2M(&dir, db, n); if (n == 0) error(Ebadarg); return n; } printd("DEVSTAT fails:%c %llu\n", devtab[c->type].dc, c->qid.path); set_errno(ENOENT); error(Enonexist); case 0: printd("DEVSTAT got 0\n"); break; case 1: printd("DEVSTAT gen returns path %p name %s, want path %p\n", dir.qid.path, dir.name, c->qid.path); if (c->qid.path == dir.qid.path) { if (c->flag & CMSG) dir.mode |= DMMOUNT; n = convD2M(&dir, db, n); if (n == 0) error(Ebadarg); return n; } break; } }
__private_extern__ int wstat_9p(mount_9p *nmp, fid_9p fid, dir_9p *dp) { Fcall tx, rx; void *p; uint32_t n; int e, dotu; TRACE(); dotu = ISSET(nmp->flags, F_DOTU); n = sizeD2M(dp, dotu); p = malloc_9p(n); if (p == NULL) return ENOMEM; if(convD2M(dp, p, n, dotu) != n){ free_9p(p); return EINVAL; } tx.type = Twstat; tx.fid = fid; tx.stat = p; tx.nstat = n; e = rpc_9p(nmp, &tx, &rx, NULL); free_9p(p); return e; }
/* * Read a directory of IP addresses or account names */ int hread(Fid *fidp, int cnt) { uchar *q, *eq, *oq; int i, n, path; Address *p; Node *np; if(debugfd >= 0) fprint(debugfd, "hread %d\n", cnt); np = fidp->node; oq = q = rbuf+IOHDRSZ; eq = q+cnt; if(fidp->dirindex >= np->count) return 0; path = np->baseqid; for(i = fidp->dirindex; q < eq && i < np->count; i++){ p = &np->addrs[i]; dummy.d.name = p->name; dummy.d.qid.path = path++; if((n=convD2M(&dummy.d, q, eq-q)) <= BIT16SZ) break; q += n; } fidp->dirindex = i; return q - oq; }
void dirread9p(Req *r, Dirgen *gen, void *aux) { int start; uchar *p, *ep; uint rv; Dir d; if(r->ifcall.offset == 0) start = 0; else start = r->fid->dirindex; p = (uchar*)r->ofcall.data; ep = p+r->ifcall.count; while(p < ep){ memset(&d, 0, sizeof d); if((*gen)(start, &d, aux) < 0) break; rv = convD2M(&d, p, ep-p); free(d.name); free(d.muid); free(d.uid); free(d.gid); if(rv <= BIT16SZ) break; p += rv; start++; } r->fid->dirindex = start; r->ofcall.count = p - (uchar*)r->ofcall.data; }
long devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen) { long m, dsz; struct{ Dir d; char slop[100]; }dir; for(m=0; m<n; c->dri++) { switch((*gen)(c, nil, tab, ntab, c->dri, &dir.d)){ case -1: return m; case 0: break; case 1: dsz = convD2M(&dir.d, (uchar*)d, n-m); if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */ if(m == 0) error(Eshort); return m; } m += dsz; d += dsz; break; } } return m; }
/* * Read a directory */ int dread(Fid *fidp, int cnt) { uchar *q, *eq, *oq; int n, skip; Node *np; if(debugfd >= 0) fprint(debugfd, "dread %d\n", cnt); np = fidp->node; oq = q = rbuf+IOHDRSZ; eq = q+cnt; if(fidp->dirindex >= np->count) return 0; skip = fidp->dirindex; for(np = np->children; skip > 0 && np; np = np->sibs) skip--; if(np == 0) return 0; for(; q < eq && np; np = np->sibs){ if(debugfd >= 0) printnode(np); if((n=convD2M(&np->d, q, eq-q)) <= BIT16SZ) break; q += n; fidp->dirindex++; } return q - oq; }
int32_t devdirread(Chan *c, char *d, int32_t n, Dirtab *tab, int ntab, Devgen *gen) { if (0) print_func_entry(); int32_t m, dsz; Dir dir; for(m=0; m<n; c->dri++) { switch((*gen)(c, nil, tab, ntab, c->dri, &dir)){ case -1: if (0) print_func_exit(); return m; case 0: break; case 1: dsz = convD2M(&dir, (uint8_t*)d, n-m); if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */ if(m == 0) error(Eshort); if (0) print_func_exit(); return m; } m += dsz; d += dsz; break; } } if (0) print_func_exit(); return m; }
static int cmd9pTwstat(Fcall* f, int, char **argv) { Dir d; static uchar buf[DIRMAX]; memset(&d, 0, sizeof d); nulldir(&d); d.name = argv[1]; d.uid = argv[2]; d.gid = argv[3]; d.mode = cmd9pStrtoul(argv[4]); d.mtime = cmd9pStrtoul(argv[5]); d.length = cmd9pStrtoull(argv[6]); f->fid = strtol(argv[0], 0, 0); f->stat = buf; f->nstat = convD2M(&d, buf, sizeof buf); if(f->nstat < BIT16SZ){ vtSetError("Twstat: convD2M failed (internal error)"); return 0; } return 1; }
void fsstat(Fs *fs, Request *r, Fid *f) { char err[ERRMAX]; Dir d; Symbol *dp; int n; uchar statbuf[Nstat]; if(f->qid.type & QTDIR) n = stat(f->path, statbuf, sizeof statbuf); else { dp = f->dp; d.name = dp->sym; d.uid = "none"; d.gid = "none"; d.muid = "none"; d.qid.type = QTFILE; d.qid.path = (uvlong)dp; d.qid.vers = 0; d.length = f->df->file[dp->fno].tarlen; d.mode = 0444; d.mtime = time(nil); d.atime = time(nil); n = convD2M(&d, statbuf, sizeof statbuf); } if(n <= BIT16SZ){ errstr(err, sizeof err); fsreply(fs, r, err); } else { r->f.stat = statbuf; r->f.nstat = n; fsreply(fs, r, nil); } }
static void rread(Fcall* f) { ulong n, rn, nn, delta; Dir d; Fid* fp; if (!isfdir(f, &fp)) return; if (f->count == 0) goto done; cleannames(); for (n = nn = 0; n < f->count; n += rn){ rn = convM2D((uchar*)f->data + n, f->count - n, &d, statbuf); if (rn <= BIT16SZ) break; d.name = importname(d.name); //dprint("⇒ %D\n", &d); nn += convD2M(&d, (uchar*)dirbuf + nn, sizeof(dirbuf) - nn); } delta = nn - n; setaux(fp, getaux(fp) + delta); f->count = nn; f->data = dirbuf; done: closefid(fp); }
static int fsstat(Chan *c, uchar *buf, int n) { Dir d; char *path; UnixFd *ufd; ufd = c->aux; if(Trace) print("fsstat %s\n", ufd->path->s); if(n < BIT16SZ) error(Eshortstat); path = fspath(c, nil); if(fsdirstat(path, c->dev, &d) < 0){ free(path); oserror(); } if(strcmp(ufd->path->s, "/") == 0) d.name = "/"; n = convD2M(&d, buf, n); free(path); return n; }
static int pipestat(Chan *c, uchar *db, int n) { Pipe *p; Dir dir; p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdir: devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir); break; case Qdata0: devdir(c, c->qid, "data", qlen(p->q[0]), eve, p->perm, &dir); break; case Qdata1: devdir(c, c->qid, "data1", qlen(p->q[1]), eve, p->perm, &dir); break; default: panic("pipestat"); } n = convD2M(&dir, db, n); if(n < BIT16SZ) error(Eshortstat); return n; }
static int pipestat(struct chan *c, uint8_t * db, int n) { Pipe *p; struct dir dir; struct dirtab *tab; int perm; p = c->aux; tab = p->pipedir; switch (NETTYPE(c->qid.path)) { case Qdir: devdir(c, c->qid, ".", 0, eve, DMDIR | 0555, &dir); break; case Qdata0: perm = tab[1].perm; perm |= qreadable(p->q[0]) ? DMREADABLE : 0; perm |= qwritable(p->q[0]) ? DMWRITABLE : 0; devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, perm, &dir); break; case Qdata1: perm = tab[2].perm; perm |= qreadable(p->q[1]) ? DMREADABLE : 0; perm |= qwritable(p->q[1]) ? DMWRITABLE : 0; devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, perm, &dir); break; default: panic("pipestat"); } n = convD2M(&dir, db, n); if (n < BIT16SZ) error(ENODATA, ERROR_FIXME); return n; }
int32_t devstat(Chan *c, uint8_t *db, int32_t n, Dirtab *tab, int ntab, Devgen *gen) { if (0) print_func_entry(); int i; Dir dir; char *p, *elem; for(i=0;; i++){ switch((*gen)(c, nil, tab, ntab, i, &dir)){ case -1: if(c->qid.type & QTDIR){ if(c->path == nil) elem = "???"; else if(strcmp(c->path->s, "/") == 0) elem = "/"; else for(elem=p=c->path->s; *p; p++) if(*p == '/') elem = p+1; devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir); n = convD2M(&dir, db, n); if(n == 0) error(Ebadarg); if (0) print_func_exit(); return n; } error(Enonexist); case 0: break; case 1: if(c->qid.path == dir.qid.path) { if(c->flag&CMSG) dir.mode |= DMMOUNT; n = convD2M(&dir, db, n); if(n == 0) error(Ebadarg); if (0) print_func_exit(); return n; } break; } } if (0) print_func_exit(); }
int devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen) { int i; Dir dir; char *p, *elem; for(i=0;; i++) switch((*gen)(c, nil, tab, ntab, i, &dir)){ case -1: if(c->qid.type & QTDIR){ if(c->name == nil) elem = "???"; else if(strcmp(c->name->s, "/") == 0) elem = "/"; else for(elem=p=c->name->s; *p; p++) if(*p == '/') elem = p+1; devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir); n = convD2M(&dir, db, n); if(n == 0) error(Ebadarg); return n; } print("devstat %C %llux\n", devtab[c->type]->dc, c->qid.path); error(Enonexist); case 0: break; case 1: if(c->qid.path == dir.qid.path) { if(c->flag&CMSG) dir.mode |= DMMOUNT; n = convD2M(&dir, db, n); if(n == 0) error(Ebadarg); return n; } break; } error(Egreg); /* not reached? */ return -1; }
int preaddir(Fid *f, uchar *data, int n, vlong offset) { int r = 0, m; Dir *d; DEBUG(DFD, "\tpreaddir n=%d wo=%lld fo=%lld\n", n, offset, f->offset); if(offset == 0 && f->offset != 0){ if(seek(f->fid, 0, 0) != 0) return -1; f->offset = f->cdir = f->ndir = 0; free(f->dir); f->dir = nil; }else if(offset != f->offset){ werrstr("can't seek dir %lld to %lld", f->offset, offset); return -1; } while(n > 0){ if(f->dir == nil){ f->ndir = dirread(f->fid, &f->dir); if(f->ndir < 0) return f->ndir; if(f->ndir == 0) return r; } d = &f->dir[f->cdir++]; if(exclude){ char *p = makepath(f->f, d->name); if(excludefile(p)){ free(p); goto skipentry; } free(p); } m = convD2M(d, data, n); DEBUG(DFD, "\t\tconvD2M %d\n", m); if(m <= BIT16SZ){ DEBUG(DFD, "\t\t\tneeded %d\n", GBIT16(data)); /* not enough room for full entry; leave for next time */ f->cdir--; return r; }else{ data += m; n -= m; r += m; f->offset += m; } skipentry: if(f->cdir >= f->ndir){ f->cdir = f->ndir = 0; free(f->dir); f->dir = nil; } } return r; }
static long fsdirread(Chan *c, uchar *va, long count, vlong offset) { char *path; int n, total; struct dirent *de; UnixFd *ufd; Dir d; ufd = c->aux; qlock(&ufd->dirlock); if(waserror()){ qunlock(&ufd->dirlock); nexterror(); } if(ufd->diroffset != offset){ if(offset != 0) error(Ebadarg); ufd->diroffset = 0; ufd->nextde = nil; rewinddir(ufd->dir); } total = 0; while(total+BIT16SZ < count) { if(ufd->nextde){ de = ufd->nextde; ufd->nextde = nil; } else if((de = readdir(ufd->dir)) == nil) break; if(isdots(de->d_name)) continue; path = fspath(c, de->d_name); if(fsdirstat(path, c->dev, &d) < 0){ free(path); continue; } n = convD2M(&d, (uchar*)va+total, count-total); free(path); if(n == BIT16SZ){ ufd->nextde = de; break; } total += n; } ufd->diroffset += total; qunlock(&ufd->dirlock); poperror(); return total; }
static void rstat(Fcall* f) { Dir d; cleannames(); convM2D(f->stat, f->nstat, &d, statbuf); d.name = importname(d.name); f->nstat = convD2M(&d, (uchar*)dirbuf, sizeof(dirbuf)); f->stat = (uchar*)dirbuf; if (statcheck(f->stat, f->nstat) < 0) dprint("stat fails\n"); }
static void twstat(Fcall* f) { Dir d; cleannames(); if (convM2D(f->stat, f->nstat, &d, statbuf) <= BIT16SZ) return; d.name = exportname(d.name); f->nstat = convD2M(&d, (uchar*)dirbuf, sizeof(dirbuf)); f->stat = (uchar*)dirbuf; if (statcheck(f->stat, f->nstat) < 0) dprint("stat fails\n"); }
void rread(Job *job, Mfile *mf) { int i, n; long clock; ulong cnt; vlong off; char *err; uchar buf[Maxfdata]; Dir dir; n = 0; err = nil; off = job->request.offset; cnt = job->request.count; *buf = '\0'; job->reply.data = (char*)buf; if(mf->qid.type & QTDIR){ clock = time(nil); if(off == 0){ memset(&dir, 0, sizeof dir); dir.name = "dns"; dir.qid.type = QTFILE; dir.qid.vers = vers; dir.qid.path = Qdns; dir.mode = 0666; dir.length = 0; dir.uid = dir.gid = dir.muid = mf->user; dir.atime = dir.mtime = clock; /* wrong */ n = convD2M(&dir, buf, sizeof buf); } } else if (off < 0) err = "negative read offset"; else { /* first offset will always be zero */ for(i = 1; i <= mf->nrr; i++) if(mf->rr[i] > off) break; if(i <= mf->nrr) { if(off + cnt > mf->rr[i]) n = mf->rr[i] - off; else n = cnt; assert(n >= 0); job->reply.data = mf->reply + off; } } job->reply.count = n; sendmsg(job, err); }
int dirwstat(char *name, Dir *d) { uchar *buf; int r; r = sizeD2M(d); buf = malloc(r); if(buf == nil) return -1; convD2M(d, buf, r); r = wstat(name, buf, r); free(buf); return r; }
int32_t readdirfile(Readdir *r, uint8_t *buf, int32_t n) { int32_t x, m; Filelist *fl; for(fl=r->fl, m=0; fl && m+2<=n; fl=fl->link, m+=x){ if(fl->f == nil) x = 0; else if((x=convD2M(&fl->f->Dir, buf+m, n-m)) <= BIT16SZ) break; } r->fl = fl; return m; }
void rstat(void) { Xfile *f; Dir dir; chat("stat(fid=%d)...", req->fid); f=xfile(req->fid, Asis); setnames(&dir, fdata); (*f->xf->s->stat)(f, &dir); if(chatty) showdir(2, &dir); rep->nstat = convD2M(&dir, statbuf, sizeof statbuf); rep->stat = statbuf; }
int dirfwstat(int fd, Dir *d) { uint8_t *buf; int r; r = sizeD2M(d); buf = malloc(r); if(buf == nil) return -1; convD2M(d, buf, r); r = fwstat(fd, buf, r); free(buf); return r; }
static int fsstat(Chan *c, uchar *buf, int n) { Dir d; Ufsinfo *uif; if(n < BIT16SZ) error(Eshortstat); uif = c->aux; d.name = lastelem(c); wfdtodir(uif->path, &d, nil); d.type = 'U'; d.dev = c->dev; return convD2M(&d, buf, n); }
static void rstat(Fcall *f) { Fid *fidp; fidp = newfid(f->fid); if (fidp->node->d.type == Dummynode) dummy.d.name = fidp->name; f->stat = (uchar*)rbuf+4+1+2+2; /* knows about stat(5) */ f->nstat = convD2M(&fidp->node->d, f->stat, MAXRPC); if(f->nstat <= BIT16SZ) reply(f, "ratfs: convD2M"); else reply(f, 0); return; }
int ramstat(Ram *r, uchar *buf, int nbuf) { Dir dir; dir.name = r->name; dir.qid = r->qid; dir.mode = r->perm; dir.length = r->ndata; dir.uid = r->user; dir.gid = r->group; dir.muid = r->user; dir.atime = r->atime; dir.mtime = r->mtime; return convD2M(&dir, buf, nbuf); }
void rread(Job *job, Mfile *mf) { int i, n, cnt; long off; Dir dir; uchar buf[Maxfdata]; char *err; long clock; n = 0; err = 0; off = job->request.offset; cnt = job->request.count; if(mf->qid.type & QTDIR){ clock = time(0); if(off == 0){ dir.name = "dns"; dir.qid.type = QTFILE; dir.qid.vers = vers; dir.qid.path = Qdns; dir.mode = 0666; dir.length = 0; dir.uid = mf->user; dir.gid = mf->user; dir.muid = mf->user; dir.atime = clock; /* wrong */ dir.mtime = clock; /* wrong */ n = convD2M(&dir, buf, sizeof buf); } job->reply.data = (char*)buf; } else { for(i = 1; i <= mf->nrr; i++) if(mf->rr[i] > off) break; if(i > mf->nrr) goto send; if(off + cnt > mf->rr[i]) n = mf->rr[i] - off; else n = cnt; job->reply.data = mf->reply + off; } send: job->reply.count = n; sendmsg(job, err); }
int dostat(int id, Dirtab *dir, uint8_t *buf, int nbuf, uint clock) { Dir d; d.qid.path = QID(id, dir->qid); d.qid.vers = 0; d.qid.type = dir->type; d.mode = dir->perm; d.length = 0; /* would be nice to do better */ d.name = dir->name; d.uid = user; d.gid = user; d.muid = user; d.atime = clock; d.mtime = clock; return convD2M(&d, buf, nbuf); }