diff options
author | Russ Cox <rsc@swtch.com> | 2009-05-25 02:11:27 -0700 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2009-05-25 02:11:27 -0700 |
commit | 75d048884cfcb7cc4404b384da50923e22224365 (patch) | |
tree | b918a6a957b1f322ebb2f84c16092e103f91acda /src/libventi/entry.c | |
parent | 33b446b8bbfea80552d462296d27ad4114fbd3fb (diff) | |
download | plan9port-75d048884cfcb7cc4404b384da50923e22224365.tar.gz plan9port-75d048884cfcb7cc4404b384da50923e22224365.tar.bz2 plan9port-75d048884cfcb7cc4404b384da50923e22224365.zip |
venti: 32-bit extensions to data structures
Diffstat (limited to 'src/libventi/entry.c')
-rw-r--r-- | src/libventi/entry.c | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/src/libventi/entry.c b/src/libventi/entry.c index aeb8dada..6485714a 100644 --- a/src/libventi/entry.c +++ b/src/libventi/entry.c @@ -6,13 +6,37 @@ static int checksize(int n) { - if(n < 256 || n > VtMaxLumpSize) { + if(n < 256) { werrstr("bad block size %#ux", n); return -1; } return 0; } +// _VtEntryBig integer format is floating-point: +// (n>>5) << (n&31). +// Convert this number; must be exact or return -1. +int +vttobig(ulong n) +{ + int shift; + ulong n0; + + n0 = n; + shift = 0; + while(n >= (1<<(16 - 5))) { + if(n & 1) + return -1; + shift++; + n >>= 1; + } + + n = (n<<5) | shift; + if(((n>>5)<<(n&31)) != n0) + sysfatal("vttobig %#lux => %#lux failed", n0, n); + return n; +} + void vtentrypack(VtEntry *e, uchar *p, int index) { @@ -20,21 +44,31 @@ vtentrypack(VtEntry *e, uchar *p, int index) int flags; uchar *op; int depth; + int psize, dsize; p += index * VtEntrySize; op = p; - U32PUT(p, e->gen); - p += 4; - U16PUT(p, e->psize); - p += 2; - U16PUT(p, e->dsize); - p += 2; depth = e->type&VtTypeDepthMask; flags = (e->flags&~(_VtEntryDir|_VtEntryDepthMask)); flags |= depth << _VtEntryDepthShift; if(e->type - depth == VtDirType) flags |= _VtEntryDir; + U32PUT(p, e->gen); + p += 4; + psize = e->psize; + dsize = e->dsize; + if(psize >= (1<<16) || dsize >= (1<<16)) { + flags |= _VtEntryBig; + psize = vttobig(psize); + dsize = vttobig(dsize); + if(psize < 0 || dsize < 0) + sysfatal("invalid entry psize/dsize: %d/%d", e->psize, e->dsize); + } + U16PUT(p, psize); + p += 2; + U16PUT(p, dsize); + p += 2; U8PUT(p, flags); p++; memset(p, 0, 5); @@ -62,10 +96,14 @@ vtentryunpack(VtEntry *e, uchar *p, int index) 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); + } e->type = (e->flags&_VtEntryDir) ? VtDirType : VtDataType; e->type += (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift; - e->flags &= ~(_VtEntryDir|_VtEntryDepthMask); - p++; + e->flags &= ~(_VtEntryDir|_VtEntryDepthMask|_VtEntryBig); p += 5; e->size = U48GET(p); p += 6; |