1 #include <u.h>
2 #include <libc.h>
3 #include <oventi.h>
4
5 /*
6 * integer conversion routines
7 */
8 #define U8GET(p) ((p)[0])
9 #define U16GET(p) (((p)[0]<<8)|(p)[1])
10 #define U32GET(p) ((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
11 #define U48GET(p) (((vlong)U16GET(p)<<32)|(vlong)U32GET((p)+2))
12 #define U64GET(p) (((vlong)U32GET(p)<<32)|(vlong)U32GET((p)+4))
13
14 #define U8PUT(p,v) (p)[0]=(v)
15 #define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v)
16 #define U32PUT(p,v) (p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
17 #define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
18 #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
19
20 static int
checkSize(int n)21 checkSize(int n)
22 {
23 if(n < 256 || n > VtMaxLumpSize) {
24 vtSetError("bad block size");
25 return 0;
26 }
27 return 1;
28 }
29
30
31 void
vtRootPack(VtRoot * r,uchar * p)32 vtRootPack(VtRoot *r, uchar *p)
33 {
34 uchar *op = p;
35
36 U16PUT(p, r->version);
37 p += 2;
38 memmove(p, r->name, sizeof(r->name));
39 p += sizeof(r->name);
40 memmove(p, r->type, sizeof(r->type));
41 p += sizeof(r->type);
42 memmove(p, r->score, VtScoreSize);
43 p += VtScoreSize;
44 U16PUT(p, r->blockSize);
45 p += 2;
46 memmove(p, r->prev, VtScoreSize);
47 p += VtScoreSize;
48
49 assert(p-op == VtRootSize);
50 }
51
52 int
vtRootUnpack(VtRoot * r,uchar * p)53 vtRootUnpack(VtRoot *r, uchar *p)
54 {
55 uchar *op = p;
56
57 memset(r, 0, sizeof(*r));
58
59 r->version = U16GET(p);
60 if(r->version != VtRootVersion) {
61 vtSetError("unknown root version");
62 return 0;
63 }
64 p += 2;
65 memmove(r->name, p, sizeof(r->name));
66 r->name[sizeof(r->name)-1] = 0;
67 p += sizeof(r->name);
68 memmove(r->type, p, sizeof(r->type));
69 r->type[sizeof(r->type)-1] = 0;
70 p += sizeof(r->type);
71 memmove(r->score, p, VtScoreSize);
72 p += VtScoreSize;
73 r->blockSize = U16GET(p);
74 if(!checkSize(r->blockSize))
75 return 0;
76 p += 2;
77 memmove(r->prev, p, VtScoreSize);
78 p += VtScoreSize;
79
80 assert(p-op == VtRootSize);
81 return 1;
82 }
83
84 void
vtEntryPack(VtEntry * e,uchar * p,int index)85 vtEntryPack(VtEntry *e, uchar *p, int index)
86 {
87 ulong t32;
88 int flags;
89 uchar *op;
90
91 p += index * VtEntrySize;
92 op = p;
93
94 U32PUT(p, e->gen);
95 p += 4;
96 U16PUT(p, e->psize);
97 p += 2;
98 U16PUT(p, e->dsize);
99 p += 2;
100 flags = e->flags | ((e->depth << VtEntryDepthShift) & VtEntryDepthMask);
101 U8PUT(p, flags);
102 p++;
103 memset(p, 0, 5);
104 p += 5;
105 U48PUT(p, e->size, t32);
106 p += 6;
107 memmove(p, e->score, VtScoreSize);
108 p += VtScoreSize;
109
110 assert(p-op == VtEntrySize);
111 }
112
113 int
vtEntryUnpack(VtEntry * e,uchar * p,int index)114 vtEntryUnpack(VtEntry *e, uchar *p, int index)
115 {
116 uchar *op;
117
118 p += index * VtEntrySize;
119 op = p;
120
121 e->gen = U32GET(p);
122 p += 4;
123 e->psize = U16GET(p);
124 p += 2;
125 e->dsize = U16GET(p);
126 p += 2;
127 e->flags = U8GET(p);
128 e->depth = (e->flags & VtEntryDepthMask) >> VtEntryDepthShift;
129 e->flags &= ~VtEntryDepthMask;
130 p++;
131 p += 5;
132 e->size = U48GET(p);
133 p += 6;
134 memmove(e->score, p, VtScoreSize);
135 p += VtScoreSize;
136
137 assert(p-op == VtEntrySize);
138
139 if(!(e->flags & VtEntryActive))
140 return 1;
141
142 if(!checkSize(e->psize) || !checkSize(e->dsize))
143 return 0;
144
145 return 1;
146 }
147
148