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 vtrootunpack(VtRoot *r, uint8_t *p) { uint8_t *op = p; uint vers; memset(r, 0, sizeof(*r)); vers = U16GET(p); if(vers != VtRootVersion) { werrstr("unknown root version"); return -1; } p += 2; memmove(r->name, p, sizeof(r->name)); r->name[sizeof(r->name)-1] = 0; p += sizeof(r->name); memmove(r->type, p, sizeof(r->type)); r->type[sizeof(r->type)-1] = 0; p += sizeof(r->type); memmove(r->score, p, VtScoreSize); p += VtScoreSize; r->blocksize = U16GET(p); if(checksize(r->blocksize) < 0) return -1; p += 2; memmove(r->prev, p, VtScoreSize); p += VtScoreSize; assert(p-op == VtRootSize); return 0; }
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; }
/* * This is the old and broken meCmp. * This cmp routine reverse the sense of the comparison * when one string is a prefix of the other. * In other words, it put "ab" after "abc" rather * than before. This behaviour is ok; binary search * and sort still work. However, it is goes against * the usual convention. */ static int meCmpOld(MetaEntry *me, char *s) { int n; uchar *p; p = me->p; /* skip magic & version */ p += 6; n = U16GET(p); p += 2; if(n > me->size - 8) n = me->size - 8; while(n > 0){ if(*s == 0) return -1; if(*p < (uchar)*s) return -1; if(*p > (uchar)*s) return 1; p++; s++; n--; } return *s != 0; }
static MetaChunk * metaChunks(MetaBlock *mb) { MetaChunk *mc; int oo, o, n, i; uchar *p; mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk)); p = mb->buf + MetaHeaderSize; for(i = 0; i<mb->nindex; i++){ mc[i].offset = U16GET(p); mc[i].size = U16GET(p+2); mc[i].index = i; p += MetaIndexSize; } qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp); /* check block looks ok */ oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; o = oo; n = 0; for(i=0; i<mb->nindex; i++){ o = mc[i].offset; n = mc[i].size; if(o < oo) goto Err; oo += n; } if(o+n > mb->size) goto Err; if(mb->size - oo != mb->free) goto Err; return mc; Err: fprint(2, "metaChunks failed!\n"); oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; for(i=0; i<mb->nindex; i++){ fprint(2, "\t%d: %d %d\n", i, mc[i].offset, mc[i].offset + mc[i].size); oo += mc[i].size; } fprint(2, "\tused=%d size=%d free=%d free2=%d\n", oo, mb->size, mb->free, mb->size - oo); vtSetError(EBadMeta); vtMemFree(mc); return nil; }
void meUnpack(MetaEntry *me, MetaBlock *mb, int i) { uchar *p; int eo, en; assert(i >= 0 && i < mb->nindex); p = mb->buf + MetaHeaderSize + i*MetaIndexSize; eo = U16GET(p); en = U16GET(p+2); me->p = mb->buf + eo; me->size = en; /* checked by mbUnpack */ assert(me->size >= 8); }
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; }
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 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; }
static int stringUnpack(char **s, uchar **p, int *n) { int nn; if(*n < 2) return 0; nn = U16GET(*p); *p += 2; *n -= 2; if(nn > *n) return 0; *s = vtMemAlloc(nn+1); memmove(*s, *p, nn); (*s)[nn] = 0; *p += nn; *n -= nn; return 1; }
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; }