2 * libhfs - library for reading and writing Macintosh HFS volumes
3 * Copyright (C) 1996-1998 Robert Leslie
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.
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.
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., 51 Franklin Street - Fifth Floor, Boston,
20 * $Id: record.c,v 1.9 1998/11/02 22:09:07 rob Exp $
29 * NAME: record->packcatkey()
30 * DESCRIPTION: pack a catalog record key
32 void r_packcatkey(const CatKeyRec *key, byte *pkey, unsigned int *len)
34 const byte *start = pkey;
36 d_storesb(&pkey, key->ckrKeyLen);
37 d_storesb(&pkey, key->ckrResrv1);
38 d_storeul(&pkey, key->ckrParID);
40 d_storestr(&pkey, key->ckrCName, sizeof(key->ckrCName));
43 *len = HFS_RECKEYSKIP(start);
47 * NAME: record->unpackcatkey()
48 * DESCRIPTION: unpack a catalog record key
50 void r_unpackcatkey(const byte *pkey, CatKeyRec *key)
52 d_fetchsb(&pkey, &key->ckrKeyLen);
53 d_fetchsb(&pkey, &key->ckrResrv1);
54 d_fetchul(&pkey, &key->ckrParID);
56 d_fetchstr(&pkey, key->ckrCName, sizeof(key->ckrCName));
60 * NAME: record->packextkey()
61 * DESCRIPTION: pack an extents record key
63 void r_packextkey(const ExtKeyRec *key, byte *pkey, unsigned int *len)
65 const byte *start = pkey;
67 d_storesb(&pkey, key->xkrKeyLen);
68 d_storesb(&pkey, key->xkrFkType);
69 d_storeul(&pkey, key->xkrFNum);
70 d_storeuw(&pkey, key->xkrFABN);
73 *len = HFS_RECKEYSKIP(start);
77 * NAME: record->unpackextkey()
78 * DESCRIPTION: unpack an extents record key
80 void r_unpackextkey(const byte *pkey, ExtKeyRec *key)
82 d_fetchsb(&pkey, &key->xkrKeyLen);
83 d_fetchsb(&pkey, &key->xkrFkType);
84 d_fetchul(&pkey, &key->xkrFNum);
85 d_fetchuw(&pkey, &key->xkrFABN);
89 * NAME: record->comparecatkeys()
90 * DESCRIPTION: compare two (packed) catalog record keys
92 int r_comparecatkeys(const CatKeyRec *key1, const CatKeyRec *key2)
96 diff = key1->ckrParID - key2->ckrParID;
100 return d_relstring(key1->ckrCName, key2->ckrCName);
104 * NAME: record->compareextkeys()
105 * DESCRIPTION: compare two (packed) extents record keys
107 int r_compareextkeys(const ExtKeyRec *key1, const ExtKeyRec *key2)
111 diff = key1->xkrFNum - key2->xkrFNum;
115 diff = (unsigned char) key1->xkrFkType -
116 (unsigned char) key2->xkrFkType;
120 return key1->xkrFABN - key2->xkrFABN;
124 * NAME: record->packcatdata()
125 * DESCRIPTION: pack catalog record data
127 void r_packcatdata(const CatDataRec *data, byte *pdata, unsigned int *len)
129 const byte *start = pdata;
132 d_storesb(&pdata, data->cdrType);
133 d_storesb(&pdata, data->cdrResrv2);
135 switch (data->cdrType)
138 d_storesw(&pdata, data->u.dir.dirFlags);
139 d_storeuw(&pdata, data->u.dir.dirVal);
140 d_storeul(&pdata, data->u.dir.dirDirID);
141 d_storesl(&pdata, data->u.dir.dirCrDat);
142 d_storesl(&pdata, data->u.dir.dirMdDat);
143 d_storesl(&pdata, data->u.dir.dirBkDat);
145 d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.top);
146 d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.left);
147 d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.bottom);
148 d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.right);
149 d_storesw(&pdata, data->u.dir.dirUsrInfo.frFlags);
150 d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.v);
151 d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.h);
152 d_storesw(&pdata, data->u.dir.dirUsrInfo.frView);
154 d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.v);
155 d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.h);
156 d_storesl(&pdata, data->u.dir.dirFndrInfo.frOpenChain);
157 d_storesw(&pdata, data->u.dir.dirFndrInfo.frUnused);
158 d_storesw(&pdata, data->u.dir.dirFndrInfo.frComment);
159 d_storesl(&pdata, data->u.dir.dirFndrInfo.frPutAway);
161 for (i = 0; i < 4; ++i)
162 d_storesl(&pdata, data->u.dir.dirResrv[i]);
167 d_storesb(&pdata, data->u.fil.filFlags);
168 d_storesb(&pdata, data->u.fil.filTyp);
170 d_storesl(&pdata, data->u.fil.filUsrWds.fdType);
171 d_storesl(&pdata, data->u.fil.filUsrWds.fdCreator);
172 d_storesw(&pdata, data->u.fil.filUsrWds.fdFlags);
173 d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.v);
174 d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.h);
175 d_storesw(&pdata, data->u.fil.filUsrWds.fdFldr);
177 d_storeul(&pdata, data->u.fil.filFlNum);
179 d_storeuw(&pdata, data->u.fil.filStBlk);
180 d_storeul(&pdata, data->u.fil.filLgLen);
181 d_storeul(&pdata, data->u.fil.filPyLen);
183 d_storeuw(&pdata, data->u.fil.filRStBlk);
184 d_storeul(&pdata, data->u.fil.filRLgLen);
185 d_storeul(&pdata, data->u.fil.filRPyLen);
187 d_storesl(&pdata, data->u.fil.filCrDat);
188 d_storesl(&pdata, data->u.fil.filMdDat);
189 d_storesl(&pdata, data->u.fil.filBkDat);
191 d_storesw(&pdata, data->u.fil.filFndrInfo.fdIconID);
192 for (i = 0; i < 4; ++i)
193 d_storesw(&pdata, data->u.fil.filFndrInfo.fdUnused[i]);
194 d_storesw(&pdata, data->u.fil.filFndrInfo.fdComment);
195 d_storesl(&pdata, data->u.fil.filFndrInfo.fdPutAway);
197 d_storeuw(&pdata, data->u.fil.filClpSize);
199 for (i = 0; i < 3; ++i)
201 d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrStABN);
202 d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrNumABlks);
205 for (i = 0; i < 3; ++i)
207 d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrStABN);
208 d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks);
211 d_storesl(&pdata, data->u.fil.filResrv);
216 for (i = 0; i < 2; ++i)
217 d_storesl(&pdata, data->u.dthd.thdResrv[i]);
219 d_storeul(&pdata, data->u.dthd.thdParID);
221 d_storestr(&pdata, data->u.dthd.thdCName,
222 sizeof(data->u.dthd.thdCName));
227 for (i = 0; i < 2; ++i)
228 d_storesl(&pdata, data->u.fthd.fthdResrv[i]);
230 d_storeul(&pdata, data->u.fthd.fthdParID);
232 d_storestr(&pdata, data->u.fthd.fthdCName,
233 sizeof(data->u.fthd.fthdCName));
242 *len += pdata - start;
246 * NAME: record->unpackcatdata()
247 * DESCRIPTION: unpack catalog record data
249 void r_unpackcatdata(const byte *pdata, CatDataRec *data)
253 d_fetchsb(&pdata, &data->cdrType);
254 d_fetchsb(&pdata, &data->cdrResrv2);
256 switch (data->cdrType)
259 d_fetchsw(&pdata, &data->u.dir.dirFlags);
260 d_fetchuw(&pdata, &data->u.dir.dirVal);
261 d_fetchul(&pdata, &data->u.dir.dirDirID);
262 d_fetchsl(&pdata, &data->u.dir.dirCrDat);
263 d_fetchsl(&pdata, &data->u.dir.dirMdDat);
264 d_fetchsl(&pdata, &data->u.dir.dirBkDat);
266 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.top);
267 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.left);
268 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.bottom);
269 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.right);
270 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frFlags);
271 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.v);
272 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.h);
273 d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frView);
275 d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.v);
276 d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.h);
277 d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frOpenChain);
278 d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frUnused);
279 d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frComment);
280 d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frPutAway);
282 for (i = 0; i < 4; ++i)
283 d_fetchsl(&pdata, &data->u.dir.dirResrv[i]);
288 d_fetchsb(&pdata, &data->u.fil.filFlags);
289 d_fetchsb(&pdata, &data->u.fil.filTyp);
291 d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdType);
292 d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdCreator);
293 d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFlags);
294 d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.v);
295 d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.h);
296 d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFldr);
298 d_fetchul(&pdata, &data->u.fil.filFlNum);
300 d_fetchuw(&pdata, &data->u.fil.filStBlk);
301 d_fetchul(&pdata, &data->u.fil.filLgLen);
302 d_fetchul(&pdata, &data->u.fil.filPyLen);
304 d_fetchuw(&pdata, &data->u.fil.filRStBlk);
305 d_fetchul(&pdata, &data->u.fil.filRLgLen);
306 d_fetchul(&pdata, &data->u.fil.filRPyLen);
308 d_fetchsl(&pdata, &data->u.fil.filCrDat);
309 d_fetchsl(&pdata, &data->u.fil.filMdDat);
310 d_fetchsl(&pdata, &data->u.fil.filBkDat);
312 d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdIconID);
313 for (i = 0; i < 4; ++i)
314 d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdUnused[i]);
315 d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdComment);
316 d_fetchsl(&pdata, &data->u.fil.filFndrInfo.fdPutAway);
318 d_fetchuw(&pdata, &data->u.fil.filClpSize);
320 for (i = 0; i < 3; ++i)
322 d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrStABN);
323 d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrNumABlks);
326 for (i = 0; i < 3; ++i)
328 d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrStABN);
329 d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrNumABlks);
332 d_fetchsl(&pdata, &data->u.fil.filResrv);
337 for (i = 0; i < 2; ++i)
338 d_fetchsl(&pdata, &data->u.dthd.thdResrv[i]);
340 d_fetchul(&pdata, &data->u.dthd.thdParID);
342 d_fetchstr(&pdata, data->u.dthd.thdCName,
343 sizeof(data->u.dthd.thdCName));
348 for (i = 0; i < 2; ++i)
349 d_fetchsl(&pdata, &data->u.fthd.fthdResrv[i]);
351 d_fetchul(&pdata, &data->u.fthd.fthdParID);
353 d_fetchstr(&pdata, data->u.fthd.fthdCName,
354 sizeof(data->u.fthd.fthdCName));
364 * NAME: record->packextdata()
365 * DESCRIPTION: pack extent record data
367 void r_packextdata(const ExtDataRec *data, byte *pdata, unsigned int *len)
369 const byte *start = pdata;
372 for (i = 0; i < 3; ++i)
374 d_storeuw(&pdata, (*data)[i].xdrStABN);
375 d_storeuw(&pdata, (*data)[i].xdrNumABlks);
379 *len += pdata - start;
383 * NAME: record->unpackextdata()
384 * DESCRIPTION: unpack extent record data
386 void r_unpackextdata(const byte *pdata, ExtDataRec *data)
390 for (i = 0; i < 3; ++i)
392 d_fetchuw(&pdata, &(*data)[i].xdrStABN);
393 d_fetchuw(&pdata, &(*data)[i].xdrNumABlks);
398 * NAME: record->makecatkey()
399 * DESCRIPTION: construct a catalog record key
401 void r_makecatkey(CatKeyRec *key, unsigned long parid, const char *name)
405 len = strlen(name) + 1;
407 key->ckrKeyLen = 0x05 + len + (len & 1);
409 key->ckrParID = parid;
411 strcpy(key->ckrCName, name);
415 * NAME: record->makeextkey()
416 * DESCRIPTION: construct an extents record key
418 void r_makeextkey(ExtKeyRec *key,
419 int fork, unsigned long fnum, unsigned int fabn)
421 key->xkrKeyLen = 0x07;
422 key->xkrFkType = fork;
428 * NAME: record->packcatrec()
429 * DESCRIPTION: create a packed catalog record
431 void r_packcatrec(const CatKeyRec *key, const CatDataRec *data,
432 byte *precord, unsigned int *len)
434 r_packcatkey(key, precord, len);
435 r_packcatdata(data, HFS_RECDATA(precord), len);
439 * NAME: record->packextrec()
440 * DESCRIPTION: create a packed extents record
442 void r_packextrec(const ExtKeyRec *key, const ExtDataRec *data,
443 byte *precord, unsigned int *len)
445 r_packextkey(key, precord, len);
446 r_packextdata(data, HFS_RECDATA(precord), len);
450 * NAME: record->packdirent()
451 * DESCRIPTION: make changes to a catalog record
453 void r_packdirent(CatDataRec *data, const hfsdirent *ent)
455 switch (data->cdrType)
458 data->u.dir.dirCrDat = d_mtime(ent->crdate);
459 data->u.dir.dirMdDat = d_mtime(ent->mddate);
460 data->u.dir.dirBkDat = d_mtime(ent->bkdate);
462 data->u.dir.dirUsrInfo.frFlags = ent->fdflags;
463 data->u.dir.dirUsrInfo.frLocation.v = ent->fdlocation.v;
464 data->u.dir.dirUsrInfo.frLocation.h = ent->fdlocation.h;
466 data->u.dir.dirUsrInfo.frRect.top = ent->u.dir.rect.top;
467 data->u.dir.dirUsrInfo.frRect.left = ent->u.dir.rect.left;
468 data->u.dir.dirUsrInfo.frRect.bottom = ent->u.dir.rect.bottom;
469 data->u.dir.dirUsrInfo.frRect.right = ent->u.dir.rect.right;
474 if (ent->flags & HFS_ISLOCKED)
475 data->u.fil.filFlags |= (1 << 0);
477 data->u.fil.filFlags &= ~(1 << 0);
479 data->u.fil.filCrDat = d_mtime(ent->crdate);
480 data->u.fil.filMdDat = d_mtime(ent->mddate);
481 data->u.fil.filBkDat = d_mtime(ent->bkdate);
483 data->u.fil.filUsrWds.fdFlags = ent->fdflags;
484 data->u.fil.filUsrWds.fdLocation.v = ent->fdlocation.v;
485 data->u.fil.filUsrWds.fdLocation.h = ent->fdlocation.h;
487 data->u.fil.filUsrWds.fdType =
488 d_getsl((const unsigned char *) ent->u.file.type);
489 data->u.fil.filUsrWds.fdCreator =
490 d_getsl((const unsigned char *) ent->u.file.creator);
497 * NAME: record->unpackdirent()
498 * DESCRIPTION: unpack catalog information into hfsdirent structure
500 void r_unpackdirent(unsigned long parid, const char *name,
501 const CatDataRec *data, hfsdirent *ent)
503 strcpy(ent->name, name);
506 switch (data->cdrType)
509 ent->flags = HFS_ISDIR;
510 ent->cnid = data->u.dir.dirDirID;
512 ent->crdate = d_ltime(data->u.dir.dirCrDat);
513 ent->mddate = d_ltime(data->u.dir.dirMdDat);
514 ent->bkdate = d_ltime(data->u.dir.dirBkDat);
516 ent->fdflags = data->u.dir.dirUsrInfo.frFlags;
517 ent->fdlocation.v = data->u.dir.dirUsrInfo.frLocation.v;
518 ent->fdlocation.h = data->u.dir.dirUsrInfo.frLocation.h;
520 ent->u.dir.valence = data->u.dir.dirVal;
522 ent->u.dir.rect.top = data->u.dir.dirUsrInfo.frRect.top;
523 ent->u.dir.rect.left = data->u.dir.dirUsrInfo.frRect.left;
524 ent->u.dir.rect.bottom = data->u.dir.dirUsrInfo.frRect.bottom;
525 ent->u.dir.rect.right = data->u.dir.dirUsrInfo.frRect.right;
530 ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0;
531 ent->cnid = data->u.fil.filFlNum;
533 ent->crdate = d_ltime(data->u.fil.filCrDat);
534 ent->mddate = d_ltime(data->u.fil.filMdDat);
535 ent->bkdate = d_ltime(data->u.fil.filBkDat);
537 ent->fdflags = data->u.fil.filUsrWds.fdFlags;
538 ent->fdlocation.v = data->u.fil.filUsrWds.fdLocation.v;
539 ent->fdlocation.h = data->u.fil.filUsrWds.fdLocation.h;
541 ent->u.file.dsize = data->u.fil.filLgLen;
542 ent->u.file.rsize = data->u.fil.filRLgLen;
544 d_putsl((unsigned char *) ent->u.file.type,
545 data->u.fil.filUsrWds.fdType);
546 d_putsl((unsigned char *) ent->u.file.creator,
547 data->u.fil.filUsrWds.fdCreator);
549 ent->u.file.type[4] = ent->u.file.creator[4] = 0;