aboutsummaryrefslogtreecommitdiff
path: root/src/libventi/entry.c
blob: aeb8dada34e85b03f6cb5d76dd8495ddeba82b74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <u.h>
#include <libc.h>
#include <venti.h>
#include "cvt.h"

static int
checksize(int n)
{
	if(n < 256 || n > VtMaxLumpSize) {
		werrstr("bad block size %#ux", n);
		return -1;
	}
	return 0;
}

void
vtentrypack(VtEntry *e, uchar *p, int index)
{
	ulong t32;
	int flags;
	uchar *op;
	int depth;

	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;
	U8PUT(p, flags);
	p++;
	memset(p, 0, 5);
	p += 5;
	U48PUT(p, e->size, t32);
	p += 6;
	memmove(p, e->score, VtScoreSize);
	p += VtScoreSize;

	assert(p-op == VtEntrySize);
}

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);
	e->type = (e->flags&_VtEntryDir) ? VtDirType : VtDataType;
	e->type += (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift;
	e->flags &= ~(_VtEntryDir|_VtEntryDepthMask);
	p++;
	p += 5;
	e->size = U48GET(p);
	p += 6;
	memmove(e->score, p, VtScoreSize);
	p += VtScoreSize;

	assert(p-op == VtEntrySize);
	
	if(!(e->flags & VtEntryActive))
		return 0;

	/* 
	 * Some old vac files use psize==0 and dsize==0 when the
	 * file itself has size 0 or is zeros.  Just to make programs not
	 * have to figure out what block sizes of 0 means, rewrite them.
	 */
	if(e->psize == 0 && e->dsize == 0
	&& memcmp(e->score, vtzeroscore, VtScoreSize) == 0){
		e->psize = 4096;
		e->dsize = 4096;
	}
	if(checksize(e->psize) < 0 || checksize(e->dsize) < 0)
		return -1;

	return 0;
}