static int dirfixed(uchar *p, uchar *e, Dir *d) { int len; len = GBIT16(p)+BIT16SZ; if(p + len > e) return -1; p += BIT16SZ; /* ignore size */ d->type = devno(GBIT16(p), 1); p += BIT16SZ; d->dev = GBIT32(p); p += BIT32SZ; d->qid.type = GBIT8(p); p += BIT8SZ; d->qid.vers = GBIT32(p); p += BIT32SZ; d->qid.path = GBIT64(p); p += BIT64SZ; d->mode = GBIT32(p); p += BIT32SZ; d->atime = GBIT32(p); p += BIT32SZ; d->mtime = GBIT32(p); p += BIT32SZ; d->length = GBIT64(p); return len; }
static u8* gqid(u8 *p, u8 *ep, Qid *q) { if(p+QIDSZ > ep) return nil; q->type = GBIT8(p); p += BIT8SZ; q->vers = GBIT32(p); p += BIT32SZ; q->path = GBIT32(p); p += BIT64SZ; return p; }
unsigned int convM2kstat(uint8_t * buf, unsigned int nbuf, struct kstat *ks) { uint8_t *p, *ebuf; char *sv[4]; int i, ns; uint32_t junk; if (nbuf < STATFIXLEN) return 0; p = buf; ebuf = buf + nbuf; p += BIT16SZ; /* ignore size */ junk /*kd->d_type */ = GBIT16(p); p += BIT16SZ; ks->st_rdev = ks->st_dev = GBIT32(p); p += BIT32SZ; junk /*qid.type */ = GBIT8(p); p += BIT8SZ; junk /*qid.vers */ = GBIT32(p); p += BIT32SZ; ks->st_ino = GBIT64(p); p += BIT64SZ; ks->st_mode = GBIT32(p); if (ks->st_mode & DMDIR) { ks->st_mode &= ~DMDIR; ks->st_mode |= __S_IFDIR; } else if (ks->st_mode & DMSYMLINK) { ks->st_mode &= ~DMSYMLINK; ks->st_mode |= __S_IFLNK; } else { ks->st_mode |= __S_IFREG; } p += BIT32SZ; ks->st_atime.tv_sec = GBIT32(p); p += BIT32SZ; ks->st_mtime.tv_sec = GBIT32(p); p += BIT32SZ; ks->st_size = GBIT64(p); p += BIT64SZ; ks->st_blksize = 512; ks->st_blocks = ROUNDUP(ks->st_size, ks->st_blksize) / ks->st_blksize; ks->st_nlink = 2; // links make no sense any more. ks->st_uid = ks->st_gid = 0; return p - buf; }
uchar* read9ppkt(Ioproc *io, int fd) { uchar buf[4], *pkt; int n, nn; n = ioreadn(io, fd, buf, 4); if(n != 4) return nil; n = GBIT32(buf); if(n > MAXMSGSIZE) return nil; pkt = emalloc(n); PBIT32(pkt, n); nn = ioreadn(io, fd, pkt+4, n-4); if(nn != n-4){ free(pkt); return nil; } /* would do this if we ever got one of these, but we only generate them if(pkt[4] == Ropenfd){ newfd = iorecvfd(io, fd); PBIT32(pkt+n-4, newfd); } */ return pkt; }
int xopenfd(Msg *m) { char errs[ERRMAX]; int n, p[2]; Conn *nc; if(pipe(p) < 0){ rerrstr(errs, sizeof errs); err(m, errs); /* XXX return here? */ } if(verbose) fprint(2, "%T xopen pipe %d %d...", p[0], p[1]); /* now we're committed. */ /* a new connection for this fid */ nc = emalloc(sizeof(Conn)); nc->internal = chancreate(sizeof(void*), 0); /* a ref for us */ nc->fdfid = m->fid; m->fid->ref++; nc->fdfid->openfd++; nc->fdmode = m->tx.mode; nc->fd = p[0]; /* a thread to tend the pipe */ threadcreate(openfdthread, nc, STACK); /* if mode is ORDWR, that openfdthread will write; start a reader */ if((m->tx.mode&3) == ORDWR){ nc = emalloc(sizeof(Conn)); nc->internal = chancreate(sizeof(void*), 0); nc->fdfid = m->fid; m->fid->ref++; nc->fdfid->openfd++; nc->fdmode = OREAD; nc->fd = dup(p[0], -1); threadcreate(openfdthread, nc, STACK); } /* steal fid from other connection */ if(delhash(m->c->fid, m->fid->cfid, m->fid) == 0) fidput(m->fid); /* rewrite as Ropenfd */ m->rx.type = Ropenfd; n = GBIT32(m->rpkt); m->rpkt = erealloc(m->rpkt, n+4); PBIT32(m->rpkt+n, p[1]); n += 4; PBIT32(m->rpkt, n); m->rpkt[4] = Ropenfd; m->rx.unixfd = p[1]; return 0; }
void rewritehdr(Fcall *f, uchar *pkt) { int i, n; n = GBIT32(pkt); PBIT16(pkt+5, f->tag); switch(f->type){ case Tversion: case Rversion: restring(pkt, n, f->version); break; case Tauth: PBIT32(pkt+7, f->afid); restring(pkt, n, f->uname); restring(pkt, n, f->aname); break; case Tflush: PBIT16(pkt+7, f->oldtag); break; case Tattach: restring(pkt, n, f->uname); restring(pkt, n, f->aname); PBIT32(pkt+7, f->fid); PBIT32(pkt+11, f->afid); break; case Twalk: PBIT32(pkt+7, f->fid); PBIT32(pkt+11, f->newfid); for(i=0; i<f->nwname; i++) restring(pkt, n, f->wname[i]); break; case Tcreate: restring(pkt, n, f->name); /* fall through */ case Topen: case Tclunk: case Tremove: case Tstat: case Twstat: case Twrite: PBIT32(pkt+7, f->fid); break; case Tread: PBIT32(pkt+7, f->fid); PBIT64(pkt+11, f->offset); break; case Rerror: restring(pkt, n, f->ename); break; } }
static uint8_t *gqid(uint8_t * p, uint8_t * ep, struct qid *q) { if (p + QIDSZ > ep) return NULL; q->type = GBIT8(p); p += BIT8SZ; q->vers = GBIT32(p); p += BIT32SZ; q->path = GBIT64(p); p += BIT64SZ; return p; }
int mwrite9p(Ioproc *io, int fd, uchar *pkt) { int n, nfd; n = GBIT32(pkt); if(verbose > 2) fprint(2, "%T write %d %d %.*H\n", fd, n, n, pkt); if(verbose > 1) fprint(2, "%T before iowrite\n"); if(iowrite(io, fd, pkt, n) != n){ fprint(2, "%T write error: %r\n"); return -1; } if(verbose > 1) fprint(2, "%T after iowrite\n"); if(pkt[4] == Ropenfd){ nfd = GBIT32(pkt+n-4); if(iosendfd(io, fd, nfd) < 0){ fprint(2, "%T send fd error: %r\n"); return -1; } } return 0; }
static usize dirfixed(uint8_t *p, uint8_t *e, Dir *d) { int len; Dev *dev; len = GBIT16(p)+BIT16SZ; if(p + len > e) return 0; p += BIT16SZ; /* ignore size */ dev = devtabget(GBIT16(p), 1); //XDYNX if(dev != nil){ d->type = dev->dc; //devtabdecr(dev); } else d->type = -1; p += BIT16SZ; d->dev = GBIT32(p); p += BIT32SZ; d->qid.type = GBIT8(p); p += BIT8SZ; d->qid.vers = GBIT32(p); p += BIT32SZ; d->qid.path = GBIT64(p); p += BIT64SZ; d->mode = GBIT32(p); p += BIT32SZ; d->atime = GBIT32(p); p += BIT32SZ; d->mtime = GBIT32(p); p += BIT32SZ; d->length = GBIT64(p); return len; }
void inputthread(void *arg) { uchar *pkt; int n, nn, tag; Msg *m; Ioproc *io; threadsetname("input"); if(verbose) fprint(2, "%T input thread\n"); io = ioproc(); USED(arg); while((pkt = read9ppkt(io, 0)) != nil){ n = GBIT32(pkt); if(n < 7){ fprint(2, "%T short 9P packet from server\n"); free(pkt); continue; } if(verbose > 2) fprint(2, "%T read %.*H\n", n, pkt); tag = GBIT16(pkt+5); if((m = msgget(tag)) == nil){ fprint(2, "%T unexpected 9P response tag %d\n", tag); free(pkt); continue; } if((nn = convM2S(pkt, n, &m->rx)) != n){ fprint(2, "%T bad packet - convM2S %d but %d\n", nn, n); free(pkt); msgput(m); continue; } if(verbose > 1) fprint(2, "%T * -> %F%s\n", &m->rx, m->internal ? " (internal)" : ""); m->rpkt = pkt; m->rx.tag = m->ctag; if(m->internal) sendp(m->c->internal, m); else if(m->c->outq) sendq(m->c->outq, m); else msgput(m); } closeioproc(io); /*fprint(2, "%T input eof\n"); */ threadexitsall(0); }
static int readmsg(Chan *c, void *abuf, int n, int *ninep) { int fd, len; uint8_t *buf; buf = abuf; fd = c->chan; qlock(&c->rlock); if(readn(fd, buf, 3) != 3){ qunlock(&c->rlock); print("readn(3) fails: %r\n"); return -1; } if((50 <= buf[0] && buf[0] <= 87 && (buf[0]&1)==0 && GBIT16(buf+1) == 0xFFFF) || buf[0] == 86 /* Tattach */){ *ninep = 1; /* assume message boundaries */ n = read(fd, buf+3, n-3); if(n < 0){ qunlock(&c->rlock); return -1; } return n+3; } *ninep = 2; if(read(fd, buf+3, 1) != 1){ qunlock(&c->rlock); print("read(1) fails: %r\n"); return -1; } len = GBIT32(buf); if(len > n){ print("msg too large\n"); qunlock(&c->rlock); return -1; } if(readn(fd, buf+4, len-4) != len-4){ print("readn(%d) fails: %r\n", len-4); qunlock(&c->rlock); return -1; } qunlock(&c->rlock); return len; }
void repack(Fcall *f, uchar **ppkt) { uint n, nn; uchar *pkt; pkt = *ppkt; n = GBIT32(pkt); nn = sizeS2M(f); if(nn > n){ free(pkt); pkt = emalloc(nn); *ppkt = pkt; } n = convS2M(f, pkt, nn); if(n <= BIT16SZ) sysfatal("convS2M conversion error"); if(n != nn) sysfatal("convS2M and sizeS2M disagree"); }
Msg* mread9p(Ioproc *io, int fd) { int n, nn; uchar *pkt; Msg *m; if((pkt = read9ppkt(io, fd)) == nil) return nil; m = msgnew(0); m->tpkt = pkt; n = GBIT32(pkt); nn = convM2S(pkt, n, &m->tx); if(nn != n){ fprint(2, "%T read bad packet from %d\n", fd); return nil; } return m; }
static int pcicfgrw(Pcidev *pcidev, int rno, int data, int len, int read) { uchar buf[4]; if(read){ memset(buf, 0, sizeof(buf)); if(pread(pcidev->rawfd, buf, len, rno) != len) return -1; switch(len){ case 1: return GBIT8(buf); case 2: return GBIT16(buf); case 4: return GBIT32(buf); default: abort(); } } else { switch(len){ case 1: PBIT8(buf, data); break; case 2: PBIT16(buf, data); break; case 4: PBIT32(buf, data); break; default: abort(); } if(pwrite(pcidev->rawfd, buf, len, rno) != len) return -1; } return 0; }
/* * no syntactic checks. * three causes for error: * 1. message size field is incorrect * 2. input buffer too short for its own data (counts too long, etc.) * 3. too many names or qids * gqid() and gstring() return nil if they would reach beyond buffer. * main switch statement checks range and also can fall through * to test at end of routine. */ uint convM2S(uchar *ap, uint nap, Fcall *f) { uchar *p, *ep; uint i, size; p = ap; ep = p + nap; if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep) return 0; size = GBIT32(p); p += BIT32SZ; if(size < BIT32SZ+BIT8SZ+BIT16SZ) return 0; f->type = GBIT8(p); p += BIT8SZ; f->tag = GBIT16(p); p += BIT16SZ; switch(f->type) { default: return 0; case Tversion: if(p+BIT32SZ > ep) return 0; f->msize = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->version); break; case Tflush: if(p+BIT16SZ > ep) return 0; f->oldtag = GBIT16(p); p += BIT16SZ; break; case Tauth: if(p+BIT32SZ > ep) return 0; f->afid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->uname); if(p == nil) break; p = gstring(p, ep, &f->aname); if(p == nil) break; break; case Tattach: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; if(p+BIT32SZ > ep) return 0; f->afid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->uname); if(p == nil) break; p = gstring(p, ep, &f->aname); if(p == nil) break; break; case Twalk: if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->newfid = GBIT32(p); p += BIT32SZ; f->nwname = GBIT16(p); p += BIT16SZ; if(f->nwname > MAXWELEM) return 0; for(i=0; i<f->nwname; i++){ p = gstring(p, ep, &f->wname[i]); if(p == nil) break; } break; case Topen: if(p+BIT32SZ+BIT8SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->mode = GBIT8(p); p += BIT8SZ; break; case Tcreate: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->name); if(p == nil) break; if(p+BIT32SZ+BIT8SZ > ep) return 0; f->perm = GBIT32(p); p += BIT32SZ; f->mode = GBIT8(p); p += BIT8SZ; break; case Tread: if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->offset = GBIT64(p); p += BIT64SZ; f->count = GBIT32(p); p += BIT32SZ; break; case Twrite: if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->offset = GBIT64(p); p += BIT64SZ; f->count = GBIT32(p); p += BIT32SZ; if(p+f->count > ep) return 0; f->data = (char*)p; p += f->count; break; case Tclunk: case Tremove: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; break; case Tstat: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; break; case Twstat: if(p+BIT32SZ+BIT16SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->nstat = GBIT16(p); p += BIT16SZ; if(p+f->nstat > ep) return 0; f->stat = p; p += f->nstat; break; /* */ case Rversion: if(p+BIT32SZ > ep) return 0; f->msize = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->version); break; case Rerror: p = gstring(p, ep, &f->ename); break; case Rflush: break; case Rauth: p = gqid(p, ep, &f->aqid); if(p == nil) break; break; case Rattach: p = gqid(p, ep, &f->qid); if(p == nil) break; break; case Rwalk: if(p+BIT16SZ > ep) return 0; f->nwqid = GBIT16(p); p += BIT16SZ; if(f->nwqid > MAXWELEM) return 0; for(i=0; i<f->nwqid; i++){ p = gqid(p, ep, &f->wqid[i]); if(p == nil) break; } break; case Ropen: case Rcreate: p = gqid(p, ep, &f->qid); if(p == nil) break; if(p+BIT32SZ > ep) return 0; f->iounit = GBIT32(p); p += BIT32SZ; break; case Rread: if(p+BIT32SZ > ep) return 0; f->count = GBIT32(p); p += BIT32SZ; if(p+f->count > ep) return 0; f->data = (char*)p; p += f->count; break; case Rwrite: if(p+BIT32SZ > ep) return 0; f->count = GBIT32(p); p += BIT32SZ; break; case Rclunk: case Rremove: break; case Rstat: if(p+BIT16SZ > ep) return 0; f->nstat = GBIT16(p); p += BIT16SZ; if(p+f->nstat > ep) return 0; f->stat = p; p += f->nstat; break; case Rwstat: break; } if(p==nil || p>ep) return 0; if(ap+size == p) return size; return 0; }
uint _convM2D(uint8_t *buf, uint nbuf, Dir *d, char *strs) { uint8_t *p, *ebuf; char *sv[4]; int i, ns, nsv[4]; p = buf; ebuf = buf + nbuf; p += BIT16SZ; /* ignore size */ d->type = GBIT16(p); p += BIT16SZ; d->dev = GBIT32(p); p += BIT32SZ; d->qid.type = GBIT8(p); p += BIT8SZ; d->qid.vers = GBIT32(p); p += BIT32SZ; d->qid.path = GBIT64(p); p += BIT64SZ; d->mode = GBIT32(p); p += BIT32SZ; d->atime = GBIT32(p); p += BIT32SZ; d->mtime = GBIT32(p); p += BIT32SZ; d->length = GBIT64(p); p += BIT64SZ; d->name = nil; d->uid = nil; d->gid = nil; d->muid = nil; for(i = 0; i < 4; i++){ if(p + BIT16SZ > ebuf) return 0; ns = GBIT16(p); p += BIT16SZ; if(p + ns > ebuf) return 0; if(strs){ nsv[i] = ns; sv[i] = strs; memmove(strs, p, ns); strs += ns; *strs++ = '\0'; } p += ns; } if(strs){ d->name = sv[0]; d->uid = sv[1]; d->gid = sv[2]; d->muid = sv[3]; }else{ d->name = nullstring; d->uid = nullstring; d->gid = nullstring; d->muid = nullstring; } return p - buf; }
u16 convM2S(u8 *ap, u16 nap, estyx_fcall_t *f) { u8 *p, *ep; u16 i, size; p = ap; ep = p + nap; if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep) return 0; size = GBIT32(p); p += BIT32SZ; if (size<BIT32SZ+BIT8SZ+BIT16SZ) return 0; f->type = GBIT8(p); p += BIT8SZ; f->tag = GBIT16(p); p += BIT16SZ; switch(f->type) { default: return 0; case Tversion: if(p+BIT32SZ > ep) return 0; f->u.version.msize = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->u.version.version); break; case Tflush: if(p+BIT16SZ > ep) return 0; f->u.oldtag = GBIT16(p); p += BIT16SZ; break; case Tauth: if(p+BIT32SZ > ep) return 0; f->u.attach.afid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->u.attach.uname); if(p == nil) break; p = gstring(p, ep, &f->u.attach.aname); if(p == nil) break; break; case Tattach: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; if(p+BIT32SZ > ep) return 0; f->u.attach.afid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->u.attach.uname); if(p == nil) break; p = gstring(p, ep, &f->u.attach.aname); if(p == nil) break; break; case Twalk: if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->u.twalk.newfid = GBIT32(p); p += BIT32SZ; f->u.twalk.nwname = GBIT16(p); p += BIT16SZ; if(f->u.twalk.nwname > MAXWELEM) return 0; for(i=0; i<f->u.twalk.nwname; i++){ p = gstring(p, ep, &f->u.twalk.wname[i]); if(p == nil) break; } break; case Topen: if(p+BIT32SZ+BIT8SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->u.create.mode = GBIT8(p); p += BIT8SZ; break; case Tcreate: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->u.create.name); if(p == nil) break; if(p+BIT32SZ+BIT8SZ > ep) return 0; f->u.create.perm = GBIT32(p); p += BIT32SZ; f->u.create.mode = GBIT8(p); p += BIT8SZ; break; case Tread: if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->u.rw.offset = GBIT32(p); p += BIT64SZ; f->u.rw.count = GBIT32(p); p += BIT32SZ; break; case Twrite: if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->u.rw.offset = GBIT32(p); p += BIT64SZ; f->u.rw.count = GBIT32(p); p += BIT32SZ; if(p+f->u.rw.count > ep) return 0; f->u.rw.data = p; p += f->u.rw.count; break; case Tclunk: case Tremove: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; break; case Tstat: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; break; case Twstat: if(p+BIT32SZ+BIT16SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->u.stat.nstat = GBIT16(p); p += BIT16SZ; if(p+f->u.stat.nstat > ep) return 0; f->u.stat.stat = p; p += f->u.stat.nstat; break; #if 0 // we never receive R packets so no need for this /* */ case Rversion: if(p+BIT32SZ > ep) return 0; f->u.version.msize = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->u.version.version); break; case Rerror: p = gstring(p, ep, &f->u.ename); break; case Rflush: break; case Rauth: p = gqid(p, ep, &f->u.aqid); if(p == nil) break; break; case Rattach: p = gqid(p, ep, &f->u.open.qid); if(p == nil) break; break; case Rwalk: if(p+BIT16SZ > ep) return 0; f->u.rwalk.nwqid = GBIT16(p); p += BIT16SZ; if(f->u.rwalk.nwqid > MAXWELEM) return 0; for(i=0; i<f->u.rwalk.nwqid; i++){ p = gqid(p, ep, &f->u.rwalk.wqid[i]); if(p == nil) break; } break; case Ropen: case Rcreate: p = gqid(p, ep, &f->u.open.qid); if(p == nil) break; if(p+BIT32SZ > ep) return 0; f->u.open.iounit = GBIT32(p); p += BIT32SZ; break; case Rread: if(p+BIT32SZ > ep) return 0; f->u.rw.count = GBIT32(p); p += BIT32SZ; if(p+f->u.rw.count > ep) return 0; f->u.rw.data = data; p += f->u.rw.count; break; case Rwrite: if(p+BIT32SZ > ep) return 0; f->u.rw.count = GBIT32(p); p += BIT32SZ; break; case Rclunk: case Rremove: break; case Rstat: if(p+BIT16SZ > ep) return 0; f->u.stat.nstat = GBIT16(p); p += BIT16SZ; if(p+f->u.stat.nstat > ep) return 0; f->u.stat.stat = p; p += f->u.stat.nstat; break; case Rwstat: break; #endif } if(p==nil || p>ep) return 0; if(ap+size == p) return size; return 0; }
unsigned int convM2kdirent(uint8_t * buf, unsigned int nbuf, struct kdirent *kd, char *strs) { uint8_t *p, *ebuf; char *sv[4]; int i, ns; uint32_t junk; printd("%s >>>>>>>>>nbuf %d STATFIXLEN %d\n", __func__, nbuf, STATFIXLEN); if (nbuf < STATFIXLEN) return 0; p = buf; ebuf = buf + nbuf; p += BIT16SZ; /* ignore size */ kd->d_type = GBIT16(p); p += BIT16SZ; junk = GBIT32(p); p += BIT32SZ; junk = GBIT8(p); p += BIT8SZ; junk = GBIT32(p); p += BIT32SZ; kd->d_ino = GBIT64(p); p += BIT64SZ; junk /* mode */ = GBIT32(p); p += BIT32SZ; junk /*d->atime */ = GBIT32(p); p += BIT32SZ; junk /*d->mtime */ = GBIT32(p); p += BIT32SZ; junk /*d->length */ = GBIT64(p); p += BIT64SZ; /* for now, uids in akaros are ints. Does not * matter; kdirents are limited in what they tell you. * get the name, ignore the rest. Maybe we can * fix this later. */ for (i = 0; i < 4; i++) { if (p + BIT16SZ > ebuf) return 0; ns = GBIT16(p); p += BIT16SZ; if (p + ns > ebuf) return 0; if (strs) { sv[i] = strs; memmove(strs, p, ns); strs += ns; *strs++ = '\0'; } if (i == 0) { kd->d_reclen = ns; printd("memmove %p %p %d\n", kd->d_name, p, ns); memmove(kd->d_name, p, ns); kd->d_name[ns] = 0; } p += ns; } printd("%s returns %d %s\n", __func__, p - buf, kd->d_name); return p - buf; }