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; }
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; }
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; }
static uchar* gqid(uchar *p, uchar *ep, Qid *q) { if(p+QIDSZ > ep) return nil; q->type = GBIT8(p); p += BIT8SZ; q->vers = GBIT32(p); p += BIT32SZ; q->path = GBIT64(p); p += BIT64SZ; return p; }
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; }
/* * 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; }
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; }
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; }