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