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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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