plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

entry.c (2550B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <venti.h>
      4 #include "cvt.h"
      5 
      6 static int
      7 checksize(int n)
      8 {
      9 	if(n < 256) {
     10 		werrstr("bad block size %#ux", n);
     11 		return -1;
     12 	}
     13 	return 0;
     14 }
     15 
     16 // _VtEntryBig integer format is floating-point:
     17 // (n>>5) << (n&31).
     18 // Convert this number; must be exact or return -1.
     19 int
     20 vttobig(ulong n)
     21 {
     22 	int shift;
     23 	ulong n0;
     24 
     25 	n0 = n;
     26 	shift = 0;
     27 	while(n >= (1<<(16 - 5))) {
     28 		if(n & 1)
     29 			return -1;
     30 		shift++;
     31 		n >>= 1;
     32 	}
     33 
     34 	n = (n<<5) | shift;
     35 	if(((n>>5)<<(n&31)) != n0)
     36 		sysfatal("vttobig %#lux => %#lux failed", n0, n);
     37 	return n;
     38 }
     39 
     40 void
     41 vtentrypack(VtEntry *e, uchar *p, int index)
     42 {
     43 	ulong t32;
     44 	int flags;
     45 	uchar *op;
     46 	int depth;
     47 	int psize, dsize;
     48 
     49 	p += index * VtEntrySize;
     50 	op = p;
     51 
     52 	depth = e->type&VtTypeDepthMask;
     53 	flags = (e->flags&~(_VtEntryDir|_VtEntryDepthMask));
     54 	flags |= depth << _VtEntryDepthShift;
     55 	if(e->type - depth == VtDirType)
     56 		flags |= _VtEntryDir;
     57 	U32PUT(p, e->gen);
     58 	p += 4;
     59 	psize = e->psize;
     60 	dsize = e->dsize;
     61 	if(psize >= (1<<16) || dsize >= (1<<16)) {
     62 		flags |= _VtEntryBig;
     63 		psize = vttobig(psize);
     64 		dsize = vttobig(dsize);
     65 		if(psize < 0 || dsize < 0)
     66 			sysfatal("invalid entry psize/dsize: %ld/%ld", e->psize, e->dsize);
     67 	}
     68 	U16PUT(p, psize);
     69 	p += 2;
     70 	U16PUT(p, dsize);
     71 	p += 2;
     72 	U8PUT(p, flags);
     73 	p++;
     74 	memset(p, 0, 5);
     75 	p += 5;
     76 	U48PUT(p, e->size, t32);
     77 	p += 6;
     78 	memmove(p, e->score, VtScoreSize);
     79 	p += VtScoreSize;
     80 
     81 	assert(p-op == VtEntrySize);
     82 }
     83 
     84 int
     85 vtentryunpack(VtEntry *e, uchar *p, int index)
     86 {
     87 	uchar *op;
     88 
     89 	p += index * VtEntrySize;
     90 	op = p;
     91 
     92 	e->gen = U32GET(p);
     93 	p += 4;
     94 	e->psize = U16GET(p);
     95 	p += 2;
     96 	e->dsize = U16GET(p);
     97 	p += 2;
     98 	e->flags = U8GET(p);
     99 	p++;
    100 	if(e->flags & _VtEntryBig) {
    101 		e->psize = (e->psize>>5)<<(e->psize & 31);
    102 		e->dsize = (e->dsize>>5)<<(e->dsize & 31);
    103 	}
    104 	e->type = (e->flags&_VtEntryDir) ? VtDirType : VtDataType;
    105 	e->type += (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift;
    106 	e->flags &= ~(_VtEntryDir|_VtEntryDepthMask|_VtEntryBig);
    107 	p += 5;
    108 	e->size = U48GET(p);
    109 	p += 6;
    110 	memmove(e->score, p, VtScoreSize);
    111 	p += VtScoreSize;
    112 
    113 	assert(p-op == VtEntrySize);
    114 
    115 	if(!(e->flags & VtEntryActive))
    116 		return 0;
    117 
    118 	/*
    119 	 * Some old vac files use psize==0 and dsize==0 when the
    120 	 * file itself has size 0 or is zeros.  Just to make programs not
    121 	 * have to figure out what block sizes of 0 means, rewrite them.
    122 	 */
    123 	if(e->psize == 0 && e->dsize == 0
    124 	&& memcmp(e->score, vtzeroscore, VtScoreSize) == 0){
    125 		e->psize = 4096;
    126 		e->dsize = 4096;
    127 	}
    128 	if(checksize(e->psize) < 0 || checksize(e->dsize) < 0)
    129 		return -1;
    130 
    131 	return 0;
    132 }