1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
4 #include "error.h"
5
6 /*
7 * integer conversion routines
8 */
9 #define U8GET(p) ((p)[0])
10 #define U16GET(p) (((p)[0]<<8)|(p)[1])
11 #define U32GET(p) (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])
12 #define U48GET(p) (((uvlong)U16GET(p)<<32)|(uvlong)U32GET((p)+2))
13 #define U64GET(p) (((uvlong)U32GET(p)<<32)|(uvlong)U32GET((p)+4))
14
15 #define U8PUT(p,v) (p)[0]=(v)
16 #define U16PUT(p,v) (p)[0]=(v)>>8;(p)[1]=(v)
17 #define U32PUT(p,v) (p)[0]=(v)>>24;(p)[1]=(v)>>16;(p)[2]=(v)>>8;(p)[3]=(v)
18 #define U48PUT(p,v,t32) t32=(v)>>32;U16PUT(p,t32);t32=(v);U32PUT((p)+2,t32)
19 #define U64PUT(p,v,t32) t32=(v)>>32;U32PUT(p,t32);t32=(v);U32PUT((p)+4,t32)
20
21 void
headerPack(Header * h,uchar * p)22 headerPack(Header *h, uchar *p)
23 {
24 memset(p, 0, HeaderSize);
25 U32PUT(p, HeaderMagic);
26 U16PUT(p+4, HeaderVersion);
27 U16PUT(p+6, h->blockSize);
28 U32PUT(p+8, h->super);
29 U32PUT(p+12, h->label);
30 U32PUT(p+16, h->data);
31 U32PUT(p+20, h->end);
32 }
33
34 int
headerUnpack(Header * h,uchar * p)35 headerUnpack(Header *h, uchar *p)
36 {
37 if(U32GET(p) != HeaderMagic){
38 vtSetError("vac header bad magic");
39 return 0;
40 }
41 h->version = U16GET(p+4);
42 if(h->version != HeaderVersion){
43 vtSetError("vac header bad version");
44 return 0;
45 }
46 h->blockSize = U16GET(p+6);
47 h->super = U32GET(p+8);
48 h->label = U32GET(p+12);
49 h->data = U32GET(p+16);
50 h->end = U32GET(p+20);
51 return 1;
52 }
53
54 void
labelPack(Label * l,uchar * p,int i)55 labelPack(Label *l, uchar *p, int i)
56 {
57 p += i*LabelSize;
58 U8PUT(p, l->state);
59 U8PUT(p+1, l->type);
60 U32PUT(p+2, l->epoch);
61 U32PUT(p+6, l->epochClose);
62 U32PUT(p+10, l->tag);
63 }
64
65 int
labelUnpack(Label * l,uchar * p,int i)66 labelUnpack(Label *l, uchar *p, int i)
67 {
68 p += i*LabelSize;
69 l->state = p[0];
70 l->type = p[1];
71 l->epoch = U32GET(p+2);
72 l->epochClose = U32GET(p+6);
73 l->tag = U32GET(p+10);
74
75 if(l->type > BtMax){
76 Bad:
77 vtSetError(EBadLabel);
78 fprint(2, "%s: labelUnpack: bad label: 0x%.2ux 0x%.2ux 0x%.8ux "
79 "0x%.8ux 0x%.8ux\n", argv0, l->state, l->type, l->epoch,
80 l->epochClose, l->tag);
81 return 0;
82 }
83 if(l->state != BsBad && l->state != BsFree){
84 if(!(l->state&BsAlloc) || l->state & ~BsMask)
85 goto Bad;
86 if(l->state&BsClosed){
87 if(l->epochClose == ~(u32int)0)
88 goto Bad;
89 }else{
90 if(l->epochClose != ~(u32int)0)
91 goto Bad;
92 }
93 }
94 return 1;
95 }
96
97 u32int
globalToLocal(uchar score[VtScoreSize])98 globalToLocal(uchar score[VtScoreSize])
99 {
100 int i;
101
102 for(i=0; i<VtScoreSize-4; i++)
103 if(score[i] != 0)
104 return NilBlock;
105
106 return U32GET(score+VtScoreSize-4);
107 }
108
109 void
localToGlobal(u32int addr,uchar score[VtScoreSize])110 localToGlobal(u32int addr, uchar score[VtScoreSize])
111 {
112 memset(score, 0, VtScoreSize-4);
113 U32PUT(score+VtScoreSize-4, addr);
114 }
115
116 void
entryPack(Entry * e,uchar * p,int index)117 entryPack(Entry *e, uchar *p, int index)
118 {
119 ulong t32;
120 int flags;
121
122 p += index * VtEntrySize;
123
124 U32PUT(p, e->gen);
125 U16PUT(p+4, e->psize);
126 U16PUT(p+6, e->dsize);
127 flags = e->flags | ((e->depth << VtEntryDepthShift) & VtEntryDepthMask);
128 U8PUT(p+8, flags);
129 memset(p+9, 0, 5);
130 U48PUT(p+14, e->size, t32);
131
132 if(flags & VtEntryLocal){
133 if(globalToLocal(e->score) == NilBlock)
134 abort();
135 memset(p+20, 0, 7);
136 U8PUT(p+27, e->archive);
137 U32PUT(p+28, e->snap);
138 U32PUT(p+32, e->tag);
139 memmove(p+36, e->score+16, 4);
140 }else
141 memmove(p+20, e->score, VtScoreSize);
142 }
143
144 int
entryUnpack(Entry * e,uchar * p,int index)145 entryUnpack(Entry *e, uchar *p, int index)
146 {
147 p += index * VtEntrySize;
148
149 e->gen = U32GET(p);
150 e->psize = U16GET(p+4);
151 e->dsize = U16GET(p+6);
152 e->flags = U8GET(p+8);
153 e->depth = (e->flags & VtEntryDepthMask) >> VtEntryDepthShift;
154 e->flags &= ~VtEntryDepthMask;
155 e->size = U48GET(p+14);
156
157 if(e->flags & VtEntryLocal){
158 e->archive = p[27];
159 e->snap = U32GET(p+28);
160 e->tag = U32GET(p+32);
161 memset(e->score, 0, 16);
162 memmove(e->score+16, p+36, 4);
163 }else{
164 e->archive = 0;
165 e->snap = 0;
166 e->tag = 0;
167 memmove(e->score, p+20, VtScoreSize);
168 }
169
170 return 1;
171 }
172
173 int
entryType(Entry * e)174 entryType(Entry *e)
175 {
176 return (((e->flags & VtEntryDir) != 0) << 3) | e->depth;
177 }
178
179
180 void
superPack(Super * s,uchar * p)181 superPack(Super *s, uchar *p)
182 {
183 u32int t32;
184
185 memset(p, 0, SuperSize);
186 U32PUT(p, SuperMagic);
187 assert(s->version == SuperVersion);
188 U16PUT(p+4, s->version);
189 U32PUT(p+6, s->epochLow);
190 U32PUT(p+10, s->epochHigh);
191 U64PUT(p+14, s->qid, t32);
192 U32PUT(p+22, s->active);
193 U32PUT(p+26, s->next);
194 U32PUT(p+30, s->current);
195 memmove(p+34, s->last, VtScoreSize);
196 memmove(p+54, s->name, sizeof(s->name));
197 }
198
199 int
superUnpack(Super * s,uchar * p)200 superUnpack(Super *s, uchar *p)
201 {
202 memset(s, 0, sizeof(*s));
203 if(U32GET(p) != SuperMagic)
204 goto Err;
205 s->version = U16GET(p+4);
206 if(s->version != SuperVersion)
207 goto Err;
208 s->epochLow = U32GET(p+6);
209 s->epochHigh = U32GET(p+10);
210 s->qid = U64GET(p+14);
211 if(s->epochLow == 0 || s->epochLow > s->epochHigh || s->qid == 0)
212 goto Err;
213 s->active = U32GET(p+22);
214 s->next = U32GET(p+26);
215 s->current = U32GET(p+30);
216 memmove(s->last, p+34, VtScoreSize);
217 memmove(s->name, p+54, sizeof(s->name));
218 s->name[sizeof(s->name)-1] = 0;
219 return 1;
220 Err:
221 memset(s, 0, sizeof(*s));
222 vtSetError(EBadSuper);
223 return 0;
224 }
225
226