int entryUnpack(Entry *e, uchar *p, int index) { p += index * VtEntrySize; e->gen = U32GET(p); e->psize = U16GET(p+4); e->dsize = U16GET(p+6); e->flags = U8GET(p+8); e->depth = (e->flags & VtEntryDepthMask) >> VtEntryDepthShift; e->flags &= ~VtEntryDepthMask; e->size = U48GET(p+14); if(e->flags & VtEntryLocal){ e->archive = p[27]; e->snap = U32GET(p+28); e->tag = U32GET(p+32); memset(e->score, 0, 16); memmove(e->score+16, p+36, 4); }else{ e->archive = 0; e->snap = 0; e->tag = 0; memmove(e->score, p+20, VtScoreSize); } return 1; }
int labelUnpack(Label *l, uchar *p, int i) { p += i*LabelSize; l->state = p[0]; l->type = p[1]; l->epoch = U32GET(p+2); l->epochClose = U32GET(p+6); l->tag = U32GET(p+10); if(l->type > BtMax){ Bad: vtSetError(EBadLabel); fprint(2, "%s: labelUnpack: bad label: 0x%.2ux 0x%.2ux 0x%.8ux " "0x%.8ux 0x%.8ux\n", argv0, l->state, l->type, l->epoch, l->epochClose, l->tag); return 0; } if(l->state != BsBad && l->state != BsFree){ if(!(l->state&BsAlloc) || l->state & ~BsMask) goto Bad; if(l->state&BsClosed){ if(l->epochClose == ~(u32int)0) goto Bad; }else{ if(l->epochClose != ~(u32int)0) goto Bad; } } return 1; }
int mbUnpack(MetaBlock *mb, uchar *p, int n) { u32int magic; int i; int eo, en, omin; uchar *q; mb->maxsize = n; mb->buf = p; if(n == 0){ memset(mb, 0, sizeof(MetaBlock)); return 1; } magic = U32GET(p); if(magic != MetaMagic && magic != MetaMagic-1) goto Err; mb->size = U16GET(p+4); mb->free = U16GET(p+6); mb->maxindex = U16GET(p+8); mb->nindex = U16GET(p+10); mb->botch = magic != MetaMagic; if(mb->size > n) goto Err; omin = MetaHeaderSize + mb->maxindex*MetaIndexSize; if(n < omin) goto Err; p += MetaHeaderSize; /* check the index table - ensures that meUnpack and meCmp never fail */ for(i=0; i<mb->nindex; i++){ eo = U16GET(p); en = U16GET(p+2); if(eo < omin || eo+en > mb->size || en < 8) goto Err; q = mb->buf + eo; if(U32GET(q) != DirMagic) goto Err; p += 4; } return 1; Err: vtSetError(EBadMeta); return 0; }
/* * read in the chained buffers for bucket b, * and return it's total number of IEntries */ static uint32_t readiebuck(IEBucks *ib, int b) { uint32_t head, m, n; head = ib->bucks[b].head; n = 0; m = ib->bucks[b].used; if(m == 0) m = ib->usable; if(0) if(ib->bucks[b].total) fprint(2, "\tbucket %d: %lld entries\n", b, ib->bucks[b].total/IEntrySize); while(head != TWID32){ if(readpart(ib->part, (uint64_t)head * ib->size, &ib->buf[n], m+U32Size) < 0){ seterr(EOk, "can't read index sort bucket: %r"); return TWID32; } n += m; head = U32GET(&ib->buf[n]); m = ib->usable; } if(n != ib->bucks[b].total) fprint(2, "\tbucket %d: expected %d entries, got %d\n", b, (int)ib->bucks[b].total/IEntrySize, n/IEntrySize); return n / IEntrySize; }
int headerUnpack(Header *h, uchar *p) { if(U32GET(p) != HeaderMagic){ vtSetError("vac header bad magic"); return 0; } h->version = U16GET(p+4); if(h->version != HeaderVersion){ vtSetError("vac header bad version"); return 0; } h->blockSize = U16GET(p+6); h->super = U32GET(p+8); h->label = U32GET(p+12); h->data = U32GET(p+16); h->end = U32GET(p+20); return 1; }
u32int globalToLocal(uchar score[VtScoreSize]) { int i; for(i=0; i<VtScoreSize-4; i++) if(score[i] != 0) return NilBlock; return U32GET(score+VtScoreSize-4); }
uint32_t globalToLocal(uint8_t score[VtScoreSize]) { int i; for(i=0; i<VtScoreSize-4; i++) if(score[i] != 0) return NilBlock; //return (int64_t)NilBlock; return U32GET(score+VtScoreSize-4); }
int superUnpack(Super *s, uchar *p) { memset(s, 0, sizeof(*s)); if(U32GET(p) != SuperMagic) goto Err; s->version = U16GET(p+4); if(s->version != SuperVersion) goto Err; s->epochLow = U32GET(p+6); s->epochHigh = U32GET(p+10); s->qid = U64GET(p+14); if(s->epochLow == 0 || s->epochLow > s->epochHigh || s->qid == 0) goto Err; s->active = U32GET(p+22); s->next = U32GET(p+26); s->current = U32GET(p+30); memmove(s->last, p+34, VtScoreSize); memmove(s->name, p+54, sizeof(s->name)); s->name[sizeof(s->name)-1] = 0; return 1; Err: memset(s, 0, sizeof(*s)); vtSetError(EBadSuper); return 0; }
int vtentryunpack(VtEntry *e, uchar *p, int index) { uchar *op; p += index * VtEntrySize; op = p; e->gen = U32GET(p); p += 4; e->psize = U16GET(p); p += 2; e->dsize = U16GET(p); p += 2; e->flags = U8GET(p); p++; if(e->flags & _VtEntryBig) { e->psize = (e->psize>>5)<<(e->psize & 31); e->dsize = (e->dsize>>5)<<(e->dsize & 31); }
int deUnpack(DirEntry *dir, MetaEntry *me) { int t, nn, n, version; uchar *p; p = me->p; n = me->size; memset(dir, 0, sizeof(DirEntry)); if(0)print("deUnpack\n"); /* magic */ if(n < 4 || U32GET(p) != DirMagic) goto Err; p += 4; n -= 4; if(0)print("deUnpack: got magic\n"); /* version */ if(n < 2) goto Err; version = U16GET(p); if(version < 7 || version > 9) goto Err; p += 2; n -= 2; if(0)print("deUnpack: got version\n"); /* elem */ if(!stringUnpack(&dir->elem, &p, &n)) goto Err; if(0)print("deUnpack: got elem\n"); /* entry */ if(n < 4) goto Err; dir->entry = U32GET(p); p += 4; n -= 4; if(0)print("deUnpack: got entry\n"); if(version < 9){ dir->gen = 0; dir->mentry = dir->entry+1; dir->mgen = 0; }else{ if(n < 3*4) goto Err; dir->gen = U32GET(p); dir->mentry = U32GET(p+4); dir->mgen = U32GET(p+8); p += 3*4; n -= 3*4; } if(0)print("deUnpack: got gen etc\n"); /* size is gotten from VtEntry */ dir->size = 0; /* qid */ if(n < 8) goto Err; dir->qid = U64GET(p); p += 8; n -= 8; if(0)print("deUnpack: got qid\n"); /* skip replacement */ if(version == 7){ if(n < VtScoreSize) goto Err; p += VtScoreSize; n -= VtScoreSize; } /* uid */ if(!stringUnpack(&dir->uid, &p, &n)) goto Err; /* gid */ if(!stringUnpack(&dir->gid, &p, &n)) goto Err; /* mid */ if(!stringUnpack(&dir->mid, &p, &n)) goto Err; if(0)print("deUnpack: got ids\n"); if(n < 5*4) goto Err; dir->mtime = U32GET(p); dir->mcount = U32GET(p+4); dir->ctime = U32GET(p+8); dir->atime = U32GET(p+12); dir->mode = U32GET(p+16); p += 5*4; n -= 5*4; if(0)print("deUnpack: got times\n"); /* optional meta data */ while(n > 0){ if(n < 3) goto Err; t = p[0]; nn = U16GET(p+1); p += 3; n -= 3; if(n < nn) goto Err; switch(t){ case DePlan9: /* not valid in version >= 9 */ if(version >= 9) break; if(dir->plan9 || nn != 12) goto Err; dir->plan9 = 1; dir->p9path = U64GET(p); dir->p9version = U32GET(p+8); if(dir->mcount == 0) dir->mcount = dir->p9version; break; case DeGen: /* not valid in version >= 9 */ if(version >= 9) break; break; case DeQidSpace: if(dir->qidSpace || nn != 16) goto Err; dir->qidSpace = 1; dir->qidOffset = U64GET(p); dir->qidMax = U64GET(p+8); break; } p += nn; n -= nn; } if(0)print("deUnpack: got options\n"); if(p != me->p + me->size) goto Err; if(0)print("deUnpack: correct size\n"); return 1; Err: if(0)print("deUnpack: XXXXXXXXXXXX EBadMeta\n"); vtSetError(EBadMeta); deCleanup(dir); return 0; }
/* * BUG: currently this expects to be called from replies only. * e.g., the type is adjusted to account for this. */ int convP2C(uint8 *ap, Pcall *c) { uint8 *p = ap; uint size; uint32 chk, chk1; c->type = 0xff + *p++; if(*p++ != 0) return 0; c->tag = *p++; size = c->size = *p++; if(pumpchk(p-4, 4, &chk) == 0){ /* TODO: soft error/warning when we don't have it. */ if(chk != U32GETLE(p)){ werrstr("header checksum mismatch: got %8ux, expected %8ux", chk, U32GETLE(p)); return -1; } } p += 4; if(size > 0){ chk = crc32(p, size); chk1 = U32GET(p+size); if(chk != chk1){ werrstr("payload checksum mismatch: got %8ux, expected %8ux", chk1, chk); return -1; } } c->err = Eok; switch(c->type){ default: break; case Rkeepalive: c->backoffms = U16GETLE(p); break; case Rbolus: { Mbolus *b = &c->bolus; p += 2; b->insulin = U16GETLE(p); p += 2; b->minutes = U16GETLE(p)*6; break; } case Rdeliverystatus: { p += 1; switch(*p){ case 0x01: c->deliverystatus = DeliveryBusy; break; case 0x02: c->deliverystatus = DeliveryDone; break; default: c->deliverystatus = DeliveryUnknown; break; } } /* TODO: check against sizes */ case Rstatus: { Mstatus *s = &c->status; /* 4 bytes unknown */ s->year = 2007 + (p[4]&0xf); s->month = 1 + (p[4]>>4); s->day = p[5]; s->hour = p[6]; s->minute = p[7]; /* 5 bytes unknown */ s->basal = (p[13]<<8) | p[12]; s->insulin = p[14]; /* 3 bytes unknown */ if(!(p[17]&0x1)) s->temp = 0; else if(p[18] > 128) s->temp = (int8)-(256-p[18]); else s->temp = p[18]; /* 2 bytes unknown */ s->temptotal = p[22]*60 + p[23]; s->temptime = s->temptotal-(p[20]*60 + p[21]); break; } case Rstatus1: { Mstatus1 *s = &c->status1; s->prognum = p[1]; s->insulin = p[6]; s->daily = 10*((p[3]<<8) | p[2]); s->hourly = (p[5]<<8) | p[4]; /* p[7] unknown. */ memcpy(s->progname, p+8, 10); s->progname[10] = 0; break; } case Rstatus2: { Mstatus2 *s = &c->status2; // Last bolus s->year = 2007 + (p[6]&0xf); s->month = 1 + (p[6]>>4); s->day = p[7]; s->hour = p[8]; s->minute = p[9]; s->bolus = (p[5]<<8) | p[4]; s->iob = 10* ((p[17]<<8) | p[16]); break; } case Rstatus3: { Mstatus3 *s = &c->status3; s->bolus = U32GETLE(p+4); s->basal = U32GETLE(p+8); panic("bug"); s->temp = p[2] & 0x1; s->suspend = p[2] & 0x2; } case Rstatus4: { Mstatus4 *s = &c->status4; s->active = p[1] == 0x01; /* tbd. */ s->year = 2007+(p[2]&0xf); s->month = 1+(p[2]>>4); s->starthour = p[4]; s->startminute = p[5]; s->endhour = p[6]; s->endminute = p[7]; s->delivered = U16GETLE(p+8); s->total = U16GETLE(p+10); } } /* Fill status bits where we (think) we have them. */ switch(c->type){ case Rbolus: case R2c: case Rdeliverystatus: case Rstatus: if(p[0] & BIT(4)) c->flag |= Fwarn; } /* TODO: check against size */ return 0; }
static int diskarenaclump(HConnect *c, Arena *arena, vlong off, char *scorestr) { uchar *blk, *blk2; Clump cl; char err[ERRMAX]; uchar xscore[VtScoreSize], score[VtScoreSize]; Unwhack uw; int n; if(scorestr){ if(vtparsescore(scorestr, nil, score) < 0){ hprint(&c->hout, "bad score %s: %r\n", scorestr); return -1; } if(off < 0){ off = findintoc(c, arena, score); if(off < 0){ hprint(&c->hout, "score %V not found in arena %s\n", score, arena->name); return -1; } hprint(&c->hout, "score %V at %#llx\n", score, off); } }else memset(score, 0, sizeof score); if(off < 0){ hprint(&c->hout, "bad offset %#llx\n", off); return -1; } off += arena->base; blk = vtmalloc(ClumpSize + VtMaxLumpSize); if(readpart(arena->part, off, blk, ClumpSize + VtMaxLumpSize) != ClumpSize + VtMaxLumpSize){ hprint(&c->hout, "reading at %#llx: %r\n", off); vtfree(blk); return -1; } if(unpackclump(&cl, blk, arena->clumpmagic) < 0){ hprint(&c->hout, "unpackclump: %r\n<br>"); rerrstr(err, sizeof err); if(strstr(err, "magic")){ hprint(&c->hout, "trying again with magic=%#ux<br>\n", U32GET(blk)); if(unpackclump(&cl, blk, U32GET(blk)) < 0){ hprint(&c->hout, "unpackclump: %r\n<br>\n"); goto error; } }else goto error; } hprint(&c->hout, "<pre>type=%d size=%d uncsize=%d score=%V\n", cl.info.type, cl.info.size, cl.info.uncsize, cl.info.score); hprint(&c->hout, "encoding=%d creator=%d time=%d %s</pre>\n", cl.encoding, cl.creator, cl.time, fmttime(err, cl.time)); if(cl.info.type == VtCorruptType) hprint(&c->hout, "clump is marked corrupt<br>\n"); if(cl.info.size >= VtMaxLumpSize){ hprint(&c->hout, "clump too big\n"); goto error; } switch(cl.encoding){ case ClumpECompress: blk2 = vtmalloc(VtMaxLumpSize); unwhackinit(&uw); n = unwhack(&uw, blk2, cl.info.uncsize, blk+ClumpSize, cl.info.size); if(n < 0){ hprint(&c->hout, "decompression failed\n"); vtfree(blk2); goto error; } if(n != cl.info.uncsize){ hprint(&c->hout, "got wrong amount: %d wanted %d\n", n, cl.info.uncsize); // hhex(blk2, n); vtfree(blk2); goto error; } scoremem(xscore, blk2, cl.info.uncsize); vtfree(blk2); break; case ClumpENone: scoremem(xscore, blk+ClumpSize, cl.info.size); break; } hprint(&c->hout, "score=%V<br>\n", xscore); if(scorestr && scorecmp(score, xscore) != 0) hprint(&c->hout, "score does NOT match expected %V\n", score); vtfree(blk); return 0; error: // hhex(blk, ClumpSize + VtMaxLumpSize); vtfree(blk); return -1; }