1 /*
2 * hfsutils - tools for reading and writing Macintosh HFS volumes
3 * Copyright (C) 1996, 1997 Robert Leslie
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 # include <string.h>
21 # include <errno.h>
22 # include <stdlib.h>
23
24 # include "internal.h"
25 # include "data.h"
26 # include "record.h"
27
28 /*
29 * NAME: record->packcatkey()
30 * DESCRIPTION: pack a catalog record key
31 */
r_packcatkey(CatKeyRec * key,unsigned char * pkey,int * len)32 void r_packcatkey(CatKeyRec *key, unsigned char *pkey, int *len)
33 {
34 unsigned char *start = pkey;
35
36 d_storeb(&pkey, key->ckrKeyLen);
37 d_storeb(&pkey, key->ckrResrv1);
38 d_storel(&pkey, key->ckrParID);
39 d_stores(&pkey, key->ckrCName, sizeof(key->ckrCName));
40
41 if (len)
42 *len = HFS_RECKEYSKIP(start);
43 }
44
45 /*
46 * NAME: record->unpackcatkey()
47 * DESCRIPTION: unpack a catalog record key
48 */
r_unpackcatkey(unsigned char * pkey,CatKeyRec * key)49 void r_unpackcatkey(unsigned char *pkey, CatKeyRec *key)
50 {
51 d_fetchb(&pkey, (char *) &key->ckrKeyLen);
52 d_fetchb(&pkey, (char *) &key->ckrResrv1);
53 d_fetchl(&pkey, (long *) &key->ckrParID);
54 d_fetchs(&pkey, key->ckrCName, sizeof(key->ckrCName));
55 }
56
57 /*
58 * NAME: record->packextkey()
59 * DESCRIPTION: pack an extents record key
60 */
r_packextkey(ExtKeyRec * key,unsigned char * pkey,int * len)61 void r_packextkey(ExtKeyRec *key, unsigned char *pkey, int *len)
62 {
63 unsigned char *start = pkey;
64
65 d_storeb(&pkey, key->xkrKeyLen);
66 d_storeb(&pkey, key->xkrFkType);
67 d_storel(&pkey, key->xkrFNum);
68 d_storew(&pkey, key->xkrFABN);
69
70 if (len)
71 *len = HFS_RECKEYSKIP(start);
72 }
73
74 /*
75 * NAME: record->unpackextkey()
76 * DESCRIPTION: unpack an extents record key
77 */
r_unpackextkey(unsigned char * pkey,ExtKeyRec * key)78 void r_unpackextkey(unsigned char *pkey, ExtKeyRec *key)
79 {
80 d_fetchb(&pkey, (char *) &key->xkrKeyLen);
81 d_fetchb(&pkey, (char *) &key->xkrFkType);
82 d_fetchl(&pkey, (long *) &key->xkrFNum);
83 d_fetchw(&pkey, (short *) &key->xkrFABN);
84 }
85
86 /*
87 * NAME: record->comparecatkeys()
88 * DESCRIPTION: compare two (packed) catalog record keys
89 */
r_comparecatkeys(unsigned char * pkey1,unsigned char * pkey2)90 int r_comparecatkeys(unsigned char *pkey1, unsigned char *pkey2)
91 {
92 CatKeyRec key1;
93 CatKeyRec key2;
94 int diff;
95
96 r_unpackcatkey(pkey1, &key1);
97 r_unpackcatkey(pkey2, &key2);
98
99 diff = key1.ckrParID - key2.ckrParID;
100 if (diff)
101 return diff;
102
103 return d_relstring(key1.ckrCName, key2.ckrCName);
104 }
105
106 /*
107 * NAME: record->compareextkeys()
108 * DESCRIPTION: compare two (packed) extents record keys
109 */
r_compareextkeys(unsigned char * pkey1,unsigned char * pkey2)110 int r_compareextkeys(unsigned char *pkey1, unsigned char *pkey2)
111 {
112 ExtKeyRec key1;
113 ExtKeyRec key2;
114 int diff;
115
116 r_unpackextkey(pkey1, &key1);
117 r_unpackextkey(pkey2, &key2);
118
119 diff = key1.xkrFNum - key2.xkrFNum;
120 if (diff)
121 return diff;
122
123 diff = (unsigned char) key1.xkrFkType -
124 (unsigned char) key2.xkrFkType;
125 if (diff)
126 return diff;
127
128 return key1.xkrFABN - key2.xkrFABN;
129 }
130
131 /*
132 * NAME: record->packcatdata()
133 * DESCRIPTION: pack catalog record data
134 */
r_packcatdata(CatDataRec * data,unsigned char * pdata,int * len)135 void r_packcatdata(CatDataRec *data, unsigned char *pdata, int *len)
136 {
137 unsigned char *start = pdata;
138 int i;
139
140 d_storeb(&pdata, data->cdrType);
141 d_storeb(&pdata, data->cdrResrv2);
142
143 switch (data->cdrType)
144 {
145 case cdrDirRec:
146 d_storew(&pdata, data->u.dir.dirFlags);
147 d_storew(&pdata, data->u.dir.dirVal);
148 d_storel(&pdata, data->u.dir.dirDirID);
149 d_storel(&pdata, data->u.dir.dirCrDat);
150 d_storel(&pdata, data->u.dir.dirMdDat);
151 d_storel(&pdata, data->u.dir.dirBkDat);
152
153 d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.top);
154 d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.left);
155 d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.bottom);
156 d_storew(&pdata, data->u.dir.dirUsrInfo.frRect.right);
157 d_storew(&pdata, data->u.dir.dirUsrInfo.frFlags);
158 d_storew(&pdata, data->u.dir.dirUsrInfo.frLocation.v);
159 d_storew(&pdata, data->u.dir.dirUsrInfo.frLocation.h);
160 d_storew(&pdata, data->u.dir.dirUsrInfo.frView);
161
162 d_storew(&pdata, data->u.dir.dirFndrInfo.frScroll.v);
163 d_storew(&pdata, data->u.dir.dirFndrInfo.frScroll.h);
164 d_storel(&pdata, data->u.dir.dirFndrInfo.frOpenChain);
165 d_storew(&pdata, data->u.dir.dirFndrInfo.frUnused);
166 d_storew(&pdata, data->u.dir.dirFndrInfo.frComment);
167 d_storel(&pdata, data->u.dir.dirFndrInfo.frPutAway);
168
169 for (i = 0; i < 4; ++i)
170 d_storel(&pdata, data->u.dir.dirResrv[i]);
171
172 break;
173
174 case cdrFilRec:
175 d_storeb(&pdata, data->u.fil.filFlags);
176 d_storeb(&pdata, data->u.fil.filTyp);
177
178 d_storel(&pdata, data->u.fil.filUsrWds.fdType);
179 d_storel(&pdata, data->u.fil.filUsrWds.fdCreator);
180 d_storew(&pdata, data->u.fil.filUsrWds.fdFlags);
181 d_storew(&pdata, data->u.fil.filUsrWds.fdLocation.v);
182 d_storew(&pdata, data->u.fil.filUsrWds.fdLocation.h);
183 d_storew(&pdata, data->u.fil.filUsrWds.fdFldr);
184
185 d_storel(&pdata, data->u.fil.filFlNum);
186
187 d_storew(&pdata, data->u.fil.filStBlk);
188 d_storel(&pdata, data->u.fil.filLgLen);
189 d_storel(&pdata, data->u.fil.filPyLen);
190
191 d_storew(&pdata, data->u.fil.filRStBlk);
192 d_storel(&pdata, data->u.fil.filRLgLen);
193 d_storel(&pdata, data->u.fil.filRPyLen);
194
195 d_storel(&pdata, data->u.fil.filCrDat);
196 d_storel(&pdata, data->u.fil.filMdDat);
197 d_storel(&pdata, data->u.fil.filBkDat);
198
199 d_storew(&pdata, data->u.fil.filFndrInfo.fdIconID);
200 for (i = 0; i < 4; ++i)
201 d_storew(&pdata, data->u.fil.filFndrInfo.fdUnused[i]);
202 d_storew(&pdata, data->u.fil.filFndrInfo.fdComment);
203 d_storel(&pdata, data->u.fil.filFndrInfo.fdPutAway);
204
205 d_storew(&pdata, data->u.fil.filClpSize);
206
207 for (i = 0; i < 3; ++i)
208 {
209 d_storew(&pdata, data->u.fil.filExtRec[i].xdrStABN);
210 d_storew(&pdata, data->u.fil.filExtRec[i].xdrNumABlks);
211 }
212
213 for (i = 0; i < 3; ++i)
214 {
215 d_storew(&pdata, data->u.fil.filRExtRec[i].xdrStABN);
216 d_storew(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks);
217 }
218
219 d_storel(&pdata, data->u.fil.filResrv);
220 break;
221
222 case cdrThdRec:
223 for (i = 0; i < 2; ++i)
224 d_storel(&pdata, data->u.dthd.thdResrv[i]);
225
226 d_storel(&pdata, data->u.dthd.thdParID);
227 d_stores(&pdata, data->u.dthd.thdCName, sizeof(data->u.dthd.thdCName));
228 break;
229
230 case cdrFThdRec:
231 for (i = 0; i < 2; ++i)
232 d_storel(&pdata, data->u.fthd.fthdResrv[i]);
233
234 d_storel(&pdata, data->u.fthd.fthdParID);
235 d_stores(&pdata, data->u.fthd.fthdCName, sizeof(data->u.fthd.fthdCName));
236 break;
237
238 default:
239 abort();
240 }
241
242 if (len)
243 *len += pdata - start;
244 }
245
246 /*
247 * NAME: record->unpackcatdata()
248 * DESCRIPTION: unpack catalog record data
249 */
r_unpackcatdata(unsigned char * pdata,CatDataRec * data)250 void r_unpackcatdata(unsigned char *pdata, CatDataRec *data)
251 {
252 int i;
253
254 d_fetchb(&pdata, (char *) &data->cdrType);
255 d_fetchb(&pdata, (char *) &data->cdrResrv2);
256
257 switch (data->cdrType)
258 {
259 case cdrDirRec:
260 d_fetchw(&pdata, &data->u.dir.dirFlags);
261 d_fetchw(&pdata, (short *) &data->u.dir.dirVal);
262 d_fetchl(&pdata, (long *) &data->u.dir.dirDirID);
263 d_fetchl(&pdata, &data->u.dir.dirCrDat);
264 d_fetchl(&pdata, &data->u.dir.dirMdDat);
265 d_fetchl(&pdata, &data->u.dir.dirBkDat);
266
267 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.top);
268 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.left);
269 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.bottom);
270 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frRect.right);
271 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frFlags);
272 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frLocation.v);
273 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frLocation.h);
274 d_fetchw(&pdata, &data->u.dir.dirUsrInfo.frView);
275
276 d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frScroll.v);
277 d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frScroll.h);
278 d_fetchl(&pdata, &data->u.dir.dirFndrInfo.frOpenChain);
279 d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frUnused);
280 d_fetchw(&pdata, &data->u.dir.dirFndrInfo.frComment);
281 d_fetchl(&pdata, &data->u.dir.dirFndrInfo.frPutAway);
282
283 for (i = 0; i < 4; ++i)
284 d_fetchl(&pdata, &data->u.dir.dirResrv[i]);
285
286 break;
287
288 case cdrFilRec:
289 d_fetchb(&pdata, (char *) &data->u.fil.filFlags);
290 d_fetchb(&pdata, (char *) &data->u.fil.filTyp);
291
292 d_fetchl(&pdata, &data->u.fil.filUsrWds.fdType);
293 d_fetchl(&pdata, &data->u.fil.filUsrWds.fdCreator);
294 d_fetchw(&pdata, &data->u.fil.filUsrWds.fdFlags);
295 d_fetchw(&pdata, &data->u.fil.filUsrWds.fdLocation.v);
296 d_fetchw(&pdata, &data->u.fil.filUsrWds.fdLocation.h);
297 d_fetchw(&pdata, &data->u.fil.filUsrWds.fdFldr);
298
299 d_fetchl(&pdata, (long *) &data->u.fil.filFlNum);
300
301 d_fetchw(&pdata, (short *) &data->u.fil.filStBlk);
302 d_fetchl(&pdata, (long *) &data->u.fil.filLgLen);
303 d_fetchl(&pdata, (long *) &data->u.fil.filPyLen);
304
305 d_fetchw(&pdata, (short *) &data->u.fil.filRStBlk);
306 d_fetchl(&pdata, (long *) &data->u.fil.filRLgLen);
307 d_fetchl(&pdata, (long *) &data->u.fil.filRPyLen);
308
309 d_fetchl(&pdata, &data->u.fil.filCrDat);
310 d_fetchl(&pdata, &data->u.fil.filMdDat);
311 d_fetchl(&pdata, &data->u.fil.filBkDat);
312
313 d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdIconID);
314 for (i = 0; i < 4; ++i)
315 d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdUnused[i]);
316 d_fetchw(&pdata, &data->u.fil.filFndrInfo.fdComment);
317 d_fetchl(&pdata, &data->u.fil.filFndrInfo.fdPutAway);
318
319 d_fetchw(&pdata, (short *) &data->u.fil.filClpSize);
320
321 for (i = 0; i < 3; ++i)
322 {
323 d_fetchw(&pdata, (short *) &data->u.fil.filExtRec[i].xdrStABN);
324 d_fetchw(&pdata, (short *) &data->u.fil.filExtRec[i].xdrNumABlks);
325 }
326
327 for (i = 0; i < 3; ++i)
328 {
329 d_fetchw(&pdata, (short *) &data->u.fil.filRExtRec[i].xdrStABN);
330 d_fetchw(&pdata, (short *) &data->u.fil.filRExtRec[i].xdrNumABlks);
331 }
332
333 d_fetchl(&pdata, &data->u.fil.filResrv);
334 break;
335
336 case cdrThdRec:
337 for (i = 0; i < 2; ++i)
338 d_fetchl(&pdata, &data->u.dthd.thdResrv[i]);
339
340 d_fetchl(&pdata, (long *) &data->u.dthd.thdParID);
341 d_fetchs(&pdata, data->u.dthd.thdCName, sizeof(data->u.dthd.thdCName));
342 break;
343
344 case cdrFThdRec:
345 for (i = 0; i < 2; ++i)
346 d_fetchl(&pdata, &data->u.fthd.fthdResrv[i]);
347
348 d_fetchl(&pdata, (long *) &data->u.fthd.fthdParID);
349 d_fetchs(&pdata, data->u.fthd.fthdCName, sizeof(data->u.fthd.fthdCName));
350 break;
351
352 default:
353 abort();
354 }
355 }
356
357 /*
358 * NAME: record->packextdata()
359 * DESCRIPTION: pack extent record data
360 */
r_packextdata(ExtDataRec * data,unsigned char * pdata,int * len)361 void r_packextdata(ExtDataRec *data, unsigned char *pdata, int *len)
362 {
363 unsigned char *start = pdata;
364 int i;
365
366 for (i = 0; i < 3; ++i)
367 {
368 d_storew(&pdata, (*data)[i].xdrStABN);
369 d_storew(&pdata, (*data)[i].xdrNumABlks);
370 }
371
372 if (len)
373 *len += pdata - start;
374 }
375
376 /*
377 * NAME: record->unpackextdata()
378 * DESCRIPTION: unpack extent record data
379 */
r_unpackextdata(unsigned char * pdata,ExtDataRec * data)380 void r_unpackextdata(unsigned char *pdata, ExtDataRec *data)
381 {
382 int i;
383
384 for (i = 0; i < 3; ++i)
385 {
386 d_fetchw(&pdata, (short *) &(*data)[i].xdrStABN);
387 d_fetchw(&pdata, (short *) &(*data)[i].xdrNumABlks);
388 }
389 }
390
391 /*
392 * NAME: record->makecatkey()
393 * DESCRIPTION: construct a catalog record key
394 */
r_makecatkey(CatKeyRec * key,long parid,char * name)395 void r_makecatkey(CatKeyRec *key, long parid, char *name)
396 {
397 int len;
398
399 len = strlen(name) + 1;
400
401 key->ckrKeyLen = 0x05 + len + (len & 1);
402 key->ckrResrv1 = 0;
403 key->ckrParID = parid;
404
405 strcpy(key->ckrCName, name);
406 }
407
408 /*
409 * NAME: record->makeextkey()
410 * DESCRIPTION: construct an extents record key
411 */
r_makeextkey(ExtKeyRec * key,int fork,long fnum,unsigned int fabn)412 void r_makeextkey(ExtKeyRec *key, int fork, long fnum, unsigned int fabn)
413 {
414 key->xkrKeyLen = 0x07;
415 key->xkrFkType = fork;
416 key->xkrFNum = fnum;
417 key->xkrFABN = fabn;
418 }
419
420 /*
421 * NAME: record->unpackdirent()
422 * DESCRIPTION: unpack catalog information into hfsdirent structure
423 */
r_unpackdirent(long parid,char * name,CatDataRec * data,hfsdirent * ent)424 void r_unpackdirent(long parid, char *name, CatDataRec *data, hfsdirent *ent)
425 {
426 strcpy(ent->name, name);
427 ent->parid = parid;
428
429 switch (data->cdrType)
430 {
431 case cdrDirRec:
432 ent->flags = HFS_ISDIR;
433 ent->cnid = data->u.dir.dirDirID;
434 ent->crdate = d_toutime(data->u.dir.dirCrDat);
435 ent->mddate = d_toutime(data->u.dir.dirMdDat);
436 ent->dsize = data->u.dir.dirVal;
437 ent->rsize = 0;
438
439 ent->type[0] = ent->creator[0] = 0;
440
441 ent->fdflags = data->u.dir.dirUsrInfo.frFlags;
442 break;
443
444 case cdrFilRec:
445 ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0;
446 ent->cnid = data->u.fil.filFlNum;
447 ent->crdate = d_toutime(data->u.fil.filCrDat);
448 ent->mddate = d_toutime(data->u.fil.filMdDat);
449 ent->dsize = data->u.fil.filLgLen;
450 ent->rsize = data->u.fil.filRLgLen;
451
452 d_putl((unsigned char *) ent->type, data->u.fil.filUsrWds.fdType);
453 d_putl((unsigned char *) ent->creator, data->u.fil.filUsrWds.fdCreator);
454
455 ent->type[4] = ent->creator[4] = 0;
456
457 ent->fdflags = data->u.fil.filUsrWds.fdFlags;
458 break;
459 }
460 }
461
462 /*
463 * NAME: record->packdirent()
464 * DESCRIPTION: make changes to a catalog record
465 */
r_packdirent(CatDataRec * data,hfsdirent * ent)466 void r_packdirent(CatDataRec *data, hfsdirent *ent)
467 {
468 switch (data->cdrType)
469 {
470 case cdrDirRec:
471 data->u.dir.dirCrDat = d_tomtime(ent->crdate);
472 data->u.dir.dirMdDat = d_tomtime(ent->mddate);
473
474 data->u.dir.dirUsrInfo.frFlags = ent->fdflags;
475 break;
476
477 case cdrFilRec:
478 if (ent->flags & HFS_ISLOCKED)
479 data->u.fil.filFlags |= (1 << 0);
480 else
481 data->u.fil.filFlags &= ~(1 << 0);
482
483 data->u.fil.filCrDat = d_tomtime(ent->crdate);
484 data->u.fil.filMdDat = d_tomtime(ent->mddate);
485
486 data->u.fil.filUsrWds.fdType = d_getl((unsigned char *) ent->type);
487 data->u.fil.filUsrWds.fdCreator = d_getl((unsigned char *) ent->creator);
488
489 data->u.fil.filUsrWds.fdFlags = ent->fdflags;
490 break;
491 }
492 }
493