Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / hfs / record.c
1 /*
2  * libhfs - library for reading and writing Macintosh HFS volumes
3  * Copyright (C) 1996-1998 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., 51 Franklin Street - Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  * $Id: record.c,v 1.9 1998/11/02 22:09:07 rob Exp $
21  */
22
23 #include "config.h"
24 #include "libhfs.h"
25 #include "record.h"
26 #include "data.h"
27
28 /*
29  * NAME:        record->packcatkey()
30  * DESCRIPTION: pack a catalog record key
31  */
32 void r_packcatkey(const CatKeyRec *key, byte *pkey, unsigned int *len)
33 {
34   const byte *start = pkey;
35
36   d_storesb(&pkey, key->ckrKeyLen);
37   d_storesb(&pkey, key->ckrResrv1);
38   d_storeul(&pkey, key->ckrParID);
39
40   d_storestr(&pkey, key->ckrCName, sizeof(key->ckrCName));
41
42   if (len)
43     *len = HFS_RECKEYSKIP(start);
44 }
45
46 /*
47  * NAME:        record->unpackcatkey()
48  * DESCRIPTION: unpack a catalog record key
49  */
50 void r_unpackcatkey(const byte *pkey, CatKeyRec *key)
51 {
52   d_fetchsb(&pkey, &key->ckrKeyLen);
53   d_fetchsb(&pkey, &key->ckrResrv1);
54   d_fetchul(&pkey, &key->ckrParID);
55
56   d_fetchstr(&pkey, key->ckrCName, sizeof(key->ckrCName));
57 }
58
59 /*
60  * NAME:        record->packextkey()
61  * DESCRIPTION: pack an extents record key
62  */
63 void r_packextkey(const ExtKeyRec *key, byte *pkey, unsigned int *len)
64 {
65   const byte *start = pkey;
66
67   d_storesb(&pkey, key->xkrKeyLen);
68   d_storesb(&pkey, key->xkrFkType);
69   d_storeul(&pkey, key->xkrFNum);
70   d_storeuw(&pkey, key->xkrFABN);
71
72   if (len)
73     *len = HFS_RECKEYSKIP(start);
74 }
75
76 /*
77  * NAME:        record->unpackextkey()
78  * DESCRIPTION: unpack an extents record key
79  */
80 void r_unpackextkey(const byte *pkey, ExtKeyRec *key)
81 {
82   d_fetchsb(&pkey, &key->xkrKeyLen);
83   d_fetchsb(&pkey, &key->xkrFkType);
84   d_fetchul(&pkey, &key->xkrFNum);
85   d_fetchuw(&pkey, &key->xkrFABN);
86 }
87
88 /*
89  * NAME:        record->comparecatkeys()
90  * DESCRIPTION: compare two (packed) catalog record keys
91  */
92 int r_comparecatkeys(const CatKeyRec *key1, const CatKeyRec *key2)
93 {
94   int diff;
95
96   diff = key1->ckrParID - key2->ckrParID;
97   if (diff)
98     return diff;
99
100   return d_relstring(key1->ckrCName, key2->ckrCName);
101 }
102
103 /*
104  * NAME:        record->compareextkeys()
105  * DESCRIPTION: compare two (packed) extents record keys
106  */
107 int r_compareextkeys(const ExtKeyRec *key1, const ExtKeyRec *key2)
108 {
109   int diff;
110
111   diff = key1->xkrFNum - key2->xkrFNum;
112   if (diff)
113     return diff;
114
115   diff = (unsigned char) key1->xkrFkType -
116          (unsigned char) key2->xkrFkType;
117   if (diff)
118     return diff;
119
120   return key1->xkrFABN - key2->xkrFABN;
121 }
122
123 /*
124  * NAME:        record->packcatdata()
125  * DESCRIPTION: pack catalog record data
126  */
127 void r_packcatdata(const CatDataRec *data, byte *pdata, unsigned int *len)
128 {
129   const byte *start = pdata;
130   int i;
131
132   d_storesb(&pdata, data->cdrType);
133   d_storesb(&pdata, data->cdrResrv2);
134
135   switch (data->cdrType)
136     {
137     case cdrDirRec:
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);
144
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);
153
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);
160
161       for (i = 0; i < 4; ++i)
162         d_storesl(&pdata, data->u.dir.dirResrv[i]);
163
164       break;
165
166     case cdrFilRec:
167       d_storesb(&pdata, data->u.fil.filFlags);
168       d_storesb(&pdata, data->u.fil.filTyp);
169
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);
176
177       d_storeul(&pdata, data->u.fil.filFlNum);
178
179       d_storeuw(&pdata, data->u.fil.filStBlk);
180       d_storeul(&pdata, data->u.fil.filLgLen);
181       d_storeul(&pdata, data->u.fil.filPyLen);
182
183       d_storeuw(&pdata, data->u.fil.filRStBlk);
184       d_storeul(&pdata, data->u.fil.filRLgLen);
185       d_storeul(&pdata, data->u.fil.filRPyLen);
186
187       d_storesl(&pdata, data->u.fil.filCrDat);
188       d_storesl(&pdata, data->u.fil.filMdDat);
189       d_storesl(&pdata, data->u.fil.filBkDat);
190
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);
196
197       d_storeuw(&pdata, data->u.fil.filClpSize);
198
199       for (i = 0; i < 3; ++i)
200         {
201           d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrStABN);
202           d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrNumABlks);
203         }
204
205       for (i = 0; i < 3; ++i)
206         {
207           d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrStABN);
208           d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks);
209         }
210
211       d_storesl(&pdata, data->u.fil.filResrv);
212
213       break;
214
215     case cdrThdRec:
216       for (i = 0; i < 2; ++i)
217         d_storesl(&pdata, data->u.dthd.thdResrv[i]);
218
219       d_storeul(&pdata, data->u.dthd.thdParID);
220
221       d_storestr(&pdata, data->u.dthd.thdCName,
222                  sizeof(data->u.dthd.thdCName));
223
224       break;
225
226     case cdrFThdRec:
227       for (i = 0; i < 2; ++i)
228         d_storesl(&pdata, data->u.fthd.fthdResrv[i]);
229
230       d_storeul(&pdata, data->u.fthd.fthdParID);
231
232       d_storestr(&pdata, data->u.fthd.fthdCName,
233                  sizeof(data->u.fthd.fthdCName));
234
235       break;
236
237     default:
238       ASSERT(0);
239     }
240
241   if (len)
242     *len += pdata - start;
243 }
244
245 /*
246  * NAME:        record->unpackcatdata()
247  * DESCRIPTION: unpack catalog record data
248  */
249 void r_unpackcatdata(const byte *pdata, CatDataRec *data)
250 {
251   int i;
252
253   d_fetchsb(&pdata, &data->cdrType);
254   d_fetchsb(&pdata, &data->cdrResrv2);
255
256   switch (data->cdrType)
257     {
258     case cdrDirRec:
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);
265
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);
274
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);
281
282       for (i = 0; i < 4; ++i)
283         d_fetchsl(&pdata, &data->u.dir.dirResrv[i]);
284
285       break;
286
287     case cdrFilRec:
288       d_fetchsb(&pdata, &data->u.fil.filFlags);
289       d_fetchsb(&pdata, &data->u.fil.filTyp);
290
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);
297
298       d_fetchul(&pdata, &data->u.fil.filFlNum);
299
300       d_fetchuw(&pdata, &data->u.fil.filStBlk);
301       d_fetchul(&pdata, &data->u.fil.filLgLen);
302       d_fetchul(&pdata, &data->u.fil.filPyLen);
303
304       d_fetchuw(&pdata, &data->u.fil.filRStBlk);
305       d_fetchul(&pdata, &data->u.fil.filRLgLen);
306       d_fetchul(&pdata, &data->u.fil.filRPyLen);
307
308       d_fetchsl(&pdata, &data->u.fil.filCrDat);
309       d_fetchsl(&pdata, &data->u.fil.filMdDat);
310       d_fetchsl(&pdata, &data->u.fil.filBkDat);
311
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);
317
318       d_fetchuw(&pdata, &data->u.fil.filClpSize);
319
320       for (i = 0; i < 3; ++i)
321         {
322           d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrStABN);
323           d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrNumABlks);
324         }
325
326       for (i = 0; i < 3; ++i)
327         {
328           d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrStABN);
329           d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrNumABlks);
330         }
331
332       d_fetchsl(&pdata, &data->u.fil.filResrv);
333
334       break;
335
336     case cdrThdRec:
337       for (i = 0; i < 2; ++i)
338         d_fetchsl(&pdata, &data->u.dthd.thdResrv[i]);
339
340       d_fetchul(&pdata, &data->u.dthd.thdParID);
341
342       d_fetchstr(&pdata, data->u.dthd.thdCName,
343                  sizeof(data->u.dthd.thdCName));
344
345       break;
346
347     case cdrFThdRec:
348       for (i = 0; i < 2; ++i)
349         d_fetchsl(&pdata, &data->u.fthd.fthdResrv[i]);
350
351       d_fetchul(&pdata, &data->u.fthd.fthdParID);
352
353       d_fetchstr(&pdata, data->u.fthd.fthdCName,
354                  sizeof(data->u.fthd.fthdCName));
355
356       break;
357
358     default:
359       ASSERT(0);
360     }
361 }
362
363 /*
364  * NAME:        record->packextdata()
365  * DESCRIPTION: pack extent record data
366  */
367 void r_packextdata(const ExtDataRec *data, byte *pdata, unsigned int *len)
368 {
369   const byte *start = pdata;
370   int i;
371
372   for (i = 0; i < 3; ++i)
373     {
374       d_storeuw(&pdata, (*data)[i].xdrStABN);
375       d_storeuw(&pdata, (*data)[i].xdrNumABlks);
376     }
377
378   if (len)
379     *len += pdata - start;
380 }
381
382 /*
383  * NAME:        record->unpackextdata()
384  * DESCRIPTION: unpack extent record data
385  */
386 void r_unpackextdata(const byte *pdata, ExtDataRec *data)
387 {
388   int i;
389
390   for (i = 0; i < 3; ++i)
391     {
392       d_fetchuw(&pdata, &(*data)[i].xdrStABN);
393       d_fetchuw(&pdata, &(*data)[i].xdrNumABlks);
394     }
395 }
396
397 /*
398  * NAME:        record->makecatkey()
399  * DESCRIPTION: construct a catalog record key
400  */
401 void r_makecatkey(CatKeyRec *key, unsigned long parid, const char *name)
402 {
403   int len;
404
405   len = strlen(name) + 1;
406
407   key->ckrKeyLen = 0x05 + len + (len & 1);
408   key->ckrResrv1 = 0;
409   key->ckrParID  = parid;
410
411   strcpy(key->ckrCName, name);
412 }
413
414 /*
415  * NAME:        record->makeextkey()
416  * DESCRIPTION: construct an extents record key
417  */
418 void r_makeextkey(ExtKeyRec *key,
419                   int fork, unsigned long fnum, unsigned int fabn)
420 {
421   key->xkrKeyLen = 0x07;
422   key->xkrFkType = fork;
423   key->xkrFNum   = fnum;
424   key->xkrFABN   = fabn;
425 }
426
427 /*
428  * NAME:        record->packcatrec()
429  * DESCRIPTION: create a packed catalog record
430  */
431 void r_packcatrec(const CatKeyRec *key, const CatDataRec *data,
432                   byte *precord, unsigned int *len)
433 {
434   r_packcatkey(key, precord, len);
435   r_packcatdata(data, HFS_RECDATA(precord), len);
436 }
437
438 /*
439  * NAME:        record->packextrec()
440  * DESCRIPTION: create a packed extents record
441  */
442 void r_packextrec(const ExtKeyRec *key, const ExtDataRec *data,
443                   byte *precord, unsigned int *len)
444 {
445   r_packextkey(key, precord, len);
446   r_packextdata(data, HFS_RECDATA(precord), len);
447 }
448
449 /*
450  * NAME:        record->packdirent()
451  * DESCRIPTION: make changes to a catalog record
452  */
453 void r_packdirent(CatDataRec *data, const hfsdirent *ent)
454 {
455   switch (data->cdrType)
456     {
457     case cdrDirRec:
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);
461
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;
465
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;
470
471       break;
472
473     case cdrFilRec:
474       if (ent->flags & HFS_ISLOCKED)
475         data->u.fil.filFlags |=  (1 << 0);
476       else
477         data->u.fil.filFlags &= ~(1 << 0);
478
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);
482
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;
486
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);
491
492       break;
493     }
494 }
495
496 /*
497  * NAME:        record->unpackdirent()
498  * DESCRIPTION: unpack catalog information into hfsdirent structure
499  */
500 void r_unpackdirent(unsigned long parid, const char *name,
501                     const CatDataRec *data, hfsdirent *ent)
502 {
503   strcpy(ent->name, name);
504   ent->parid = parid;
505
506   switch (data->cdrType)
507     {
508     case cdrDirRec:
509       ent->flags = HFS_ISDIR;
510       ent->cnid  = data->u.dir.dirDirID;
511
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);
515
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;
519
520       ent->u.dir.valence = data->u.dir.dirVal;
521
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;
526
527       break;
528
529     case cdrFilRec:
530       ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0;
531       ent->cnid  = data->u.fil.filFlNum;
532
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);
536
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;
540
541       ent->u.file.dsize = data->u.fil.filLgLen;
542       ent->u.file.rsize = data->u.fil.filRLgLen;
543
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);
548
549       ent->u.file.type[4] = ent->u.file.creator[4] = 0;
550
551       break;
552     }
553 }