1 /*- 2 * Copyright (c) 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley 6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7 * Support code is derived from software contributed to Berkeley 8 * by Atsushi Murai (amurai@spec.co.jp). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/bio.h> 43 #include <sys/buf.h> 44 #include <sys/vnode.h> 45 #include <sys/mount.h> 46 #include <sys/kernel.h> 47 #include <sys/vimage.h> 48 49 #include <fs/cd9660/iso.h> 50 #include <fs/cd9660/cd9660_node.h> 51 #include <fs/cd9660/cd9660_rrip.h> 52 #include <fs/cd9660/iso_rrip.h> 53 54 typedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 55 56 typedef struct { 57 char type[2]; 58 rrt_func_t *func; 59 void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 60 int result; 61 } RRIP_TABLE; 62 63 static int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 64 static int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 65 static int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 66 static void cd9660_rrip_defattr(struct iso_directory_record *isodir, 67 ISO_RRIP_ANALYZE *ana); 68 static void cd9660_rrip_defname(struct iso_directory_record *isodir, 69 ISO_RRIP_ANALYZE *ana); 70 static void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 71 ISO_RRIP_ANALYZE *ana); 72 static int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 73 static int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 74 static int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 75 static int cd9660_rrip_loop(struct iso_directory_record *isodir, 76 ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table); 77 static int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 78 static int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 79 static int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 80 static int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 81 static int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 82 83 /* 84 * POSIX file attribute 85 */ 86 static int 87 cd9660_rrip_attr(p,ana) 88 ISO_RRIP_ATTR *p; 89 ISO_RRIP_ANALYZE *ana; 90 { 91 ana->inop->inode.iso_mode = isonum_733(p->mode); 92 ana->inop->inode.iso_uid = isonum_733(p->uid); 93 ana->inop->inode.iso_gid = isonum_733(p->gid); 94 ana->inop->inode.iso_links = isonum_733(p->links); 95 ana->fields &= ~ISO_SUSP_ATTR; 96 return ISO_SUSP_ATTR; 97 } 98 99 static void 100 cd9660_rrip_defattr(isodir,ana) 101 struct iso_directory_record *isodir; 102 ISO_RRIP_ANALYZE *ana; 103 { 104 /* But this is a required field! */ 105 printf("RRIP without PX field?\n"); 106 cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 107 } 108 109 /* 110 * Symbolic Links 111 */ 112 static int 113 cd9660_rrip_slink(p,ana) 114 ISO_RRIP_SLINK *p; 115 ISO_RRIP_ANALYZE *ana; 116 { 117 ISO_RRIP_SLINK_COMPONENT *pcomp; 118 ISO_RRIP_SLINK_COMPONENT *pcompe; 119 int len, wlen, cont; 120 char *outbuf, *inbuf; 121 122 pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 123 pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 124 len = *ana->outlen; 125 outbuf = ana->outbuf; 126 cont = ana->cont; 127 128 /* 129 * Gathering a Symbolic name from each component with path 130 */ 131 for (; 132 pcomp < pcompe; 133 pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 134 + isonum_711(pcomp->clen))) { 135 136 if (!cont) { 137 if (len < ana->maxlen) { 138 len++; 139 *outbuf++ = '/'; 140 } 141 } 142 cont = 0; 143 144 inbuf = ".."; 145 wlen = 0; 146 147 switch (*pcomp->cflag) { 148 149 case ISO_SUSP_CFLAG_CURRENT: 150 /* Inserting Current */ 151 wlen = 1; 152 break; 153 154 case ISO_SUSP_CFLAG_PARENT: 155 /* Inserting Parent */ 156 wlen = 2; 157 break; 158 159 case ISO_SUSP_CFLAG_ROOT: 160 /* Inserting slash for ROOT */ 161 /* Double slash, nothing really to do here. */ 162 break; 163 164 case ISO_SUSP_CFLAG_VOLROOT: 165 /* Inserting a mount point i.e. "/cdrom" */ 166 /* same as above */ 167 outbuf -= len; 168 len = 0; 169 inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 170 wlen = strlen(inbuf); 171 break; 172 173 case ISO_SUSP_CFLAG_HOST: 174 /* XXXRW: locking. */ 175 /* Inserting hostname i.e. "kurt.tools.de" */ 176 inbuf = V_hostname; 177 wlen = strlen(V_hostname); 178 break; 179 180 case ISO_SUSP_CFLAG_CONTINUE: 181 cont = 1; 182 /* FALLTHROUGH */ 183 case 0: 184 /* Inserting component */ 185 wlen = isonum_711(pcomp->clen); 186 inbuf = pcomp->name; 187 break; 188 default: 189 printf("RRIP with incorrect flags?"); 190 wlen = ana->maxlen + 1; 191 break; 192 } 193 194 if (len + wlen > ana->maxlen) { 195 /* indicate error to caller */ 196 ana->cont = 1; 197 ana->fields = 0; 198 ana->outbuf -= *ana->outlen; 199 *ana->outlen = 0; 200 return 0; 201 } 202 203 bcopy(inbuf,outbuf,wlen); 204 outbuf += wlen; 205 len += wlen; 206 207 } 208 ana->outbuf = outbuf; 209 *ana->outlen = len; 210 ana->cont = cont; 211 212 if (!isonum_711(p->flags)) { 213 ana->fields &= ~ISO_SUSP_SLINK; 214 return ISO_SUSP_SLINK; 215 } 216 return 0; 217 } 218 219 /* 220 * Alternate name 221 */ 222 static int 223 cd9660_rrip_altname(p,ana) 224 ISO_RRIP_ALTNAME *p; 225 ISO_RRIP_ANALYZE *ana; 226 { 227 char *inbuf; 228 int wlen; 229 int cont; 230 231 inbuf = ".."; 232 wlen = 0; 233 cont = 0; 234 235 switch (*p->flags) { 236 case ISO_SUSP_CFLAG_CURRENT: 237 /* Inserting Current */ 238 wlen = 1; 239 break; 240 241 case ISO_SUSP_CFLAG_PARENT: 242 /* Inserting Parent */ 243 wlen = 2; 244 break; 245 246 case ISO_SUSP_CFLAG_HOST: 247 /* XXXRW: locking. */ 248 /* Inserting hostname i.e. "kurt.tools.de" */ 249 inbuf = V_hostname; 250 wlen = strlen(V_hostname); 251 break; 252 253 case ISO_SUSP_CFLAG_CONTINUE: 254 cont = 1; 255 /* FALLTHROUGH */ 256 case 0: 257 /* Inserting component */ 258 wlen = isonum_711(p->h.length) - 5; 259 inbuf = (char *)p + 5; 260 break; 261 262 default: 263 printf("RRIP with incorrect NM flags?\n"); 264 wlen = ana->maxlen + 1; 265 break; 266 } 267 268 if ((*ana->outlen += wlen) > ana->maxlen) { 269 /* treat as no name field */ 270 ana->fields &= ~ISO_SUSP_ALTNAME; 271 ana->outbuf -= *ana->outlen - wlen; 272 *ana->outlen = 0; 273 return 0; 274 } 275 276 bcopy(inbuf,ana->outbuf,wlen); 277 ana->outbuf += wlen; 278 279 if (!cont) { 280 ana->fields &= ~ISO_SUSP_ALTNAME; 281 return ISO_SUSP_ALTNAME; 282 } 283 return 0; 284 } 285 286 static void 287 cd9660_rrip_defname(isodir,ana) 288 struct iso_directory_record *isodir; 289 ISO_RRIP_ANALYZE *ana; 290 { 291 isofntrans(isodir->name,isonum_711(isodir->name_len), 292 ana->outbuf,ana->outlen, 293 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level, 294 ana->imp->im_flags, ana->imp->im_d2l); 295 switch (*ana->outbuf) { 296 default: 297 break; 298 case 1: 299 *ana->outlen = 2; 300 /* FALLTHROUGH */ 301 case 0: 302 /* outlen is 1 already */ 303 strcpy(ana->outbuf,".."); 304 break; 305 } 306 } 307 308 /* 309 * Parent or Child Link 310 */ 311 static int 312 cd9660_rrip_pclink(p,ana) 313 ISO_RRIP_CLINK *p; 314 ISO_RRIP_ANALYZE *ana; 315 { 316 *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 317 ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 318 return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 319 } 320 321 /* 322 * Relocated directory 323 */ 324 static int 325 cd9660_rrip_reldir(p,ana) 326 ISO_RRIP_RELDIR *p; 327 ISO_RRIP_ANALYZE *ana; 328 { 329 /* special hack to make caller aware of RE field */ 330 *ana->outlen = 0; 331 ana->fields = 0; 332 return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 333 } 334 335 static int 336 cd9660_rrip_tstamp(p,ana) 337 ISO_RRIP_TSTAMP *p; 338 ISO_RRIP_ANALYZE *ana; 339 { 340 u_char *ptime; 341 342 ptime = p->time; 343 344 /* Check a format of time stamp (7bytes/17bytes) */ 345 if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 346 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 347 ptime += 7; 348 349 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 350 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 351 ISO_FTYPE_RRIP); 352 ptime += 7; 353 } else 354 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 355 356 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 357 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 358 ISO_FTYPE_RRIP); 359 ptime += 7; 360 } else 361 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 362 363 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 364 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 365 ISO_FTYPE_RRIP); 366 else 367 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 368 369 } else { 370 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 371 ptime += 17; 372 373 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 374 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 375 ptime += 17; 376 } else 377 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 378 379 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 380 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 381 ptime += 17; 382 } else 383 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 384 385 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 386 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 387 else 388 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 389 390 } 391 ana->fields &= ~ISO_SUSP_TSTAMP; 392 return ISO_SUSP_TSTAMP; 393 } 394 395 static void 396 cd9660_rrip_deftstamp(isodir,ana) 397 struct iso_directory_record *isodir; 398 ISO_RRIP_ANALYZE *ana; 399 { 400 cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 401 } 402 403 /* 404 * POSIX device modes 405 */ 406 static int 407 cd9660_rrip_device(p,ana) 408 ISO_RRIP_DEVICE *p; 409 ISO_RRIP_ANALYZE *ana; 410 { 411 u_int high, low; 412 413 high = isonum_733(p->dev_t_high); 414 low = isonum_733(p->dev_t_low); 415 416 if (high == 0) 417 ana->inop->inode.iso_rdev = makedev(umajor(low), uminor(low)); 418 else 419 ana->inop->inode.iso_rdev = makedev(high, uminor(low)); 420 ana->fields &= ~ISO_SUSP_DEVICE; 421 return ISO_SUSP_DEVICE; 422 } 423 424 /* 425 * Flag indicating 426 */ 427 static int 428 cd9660_rrip_idflag(p,ana) 429 ISO_RRIP_IDFLAG *p; 430 ISO_RRIP_ANALYZE *ana; 431 { 432 ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 433 /* special handling of RE field */ 434 if (ana->fields&ISO_SUSP_RELDIR) 435 return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 436 437 return ISO_SUSP_IDFLAG; 438 } 439 440 /* 441 * Continuation pointer 442 */ 443 static int 444 cd9660_rrip_cont(p,ana) 445 ISO_RRIP_CONT *p; 446 ISO_RRIP_ANALYZE *ana; 447 { 448 ana->iso_ce_blk = isonum_733(p->location); 449 ana->iso_ce_off = isonum_733(p->offset); 450 ana->iso_ce_len = isonum_733(p->length); 451 return ISO_SUSP_CONT; 452 } 453 454 /* 455 * System Use end 456 */ 457 static int 458 cd9660_rrip_stop(p,ana) 459 ISO_SUSP_HEADER *p; 460 ISO_RRIP_ANALYZE *ana; 461 { 462 return ISO_SUSP_STOP; 463 } 464 465 /* 466 * Extension reference 467 */ 468 static int 469 cd9660_rrip_extref(p,ana) 470 ISO_RRIP_EXTREF *p; 471 ISO_RRIP_ANALYZE *ana; 472 { 473 if (isonum_711(p->len_id) != 10 474 || bcmp((char *)p + 8,"RRIP_1991A",10) 475 || isonum_711(p->version) != 1) 476 return 0; 477 ana->fields &= ~ISO_SUSP_EXTREF; 478 return ISO_SUSP_EXTREF; 479 } 480 481 static int 482 cd9660_rrip_loop(isodir,ana,table) 483 struct iso_directory_record *isodir; 484 ISO_RRIP_ANALYZE *ana; 485 RRIP_TABLE *table; 486 { 487 RRIP_TABLE *ptable; 488 ISO_SUSP_HEADER *phead; 489 ISO_SUSP_HEADER *pend; 490 struct buf *bp = NULL; 491 char *pwhead; 492 u_short c; 493 int result; 494 495 /* 496 * Note: If name length is odd, 497 * it will be padding 1 byte after the name 498 */ 499 pwhead = isodir->name + isonum_711(isodir->name_len); 500 if (!(isonum_711(isodir->name_len)&1)) 501 pwhead++; 502 isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL, 503 ana->imp->im_flags, ana->imp->im_d2l); 504 505 /* If it's not the '.' entry of the root dir obey SP field */ 506 if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 507 pwhead += ana->imp->rr_skip; 508 else 509 pwhead += ana->imp->rr_skip0; 510 511 phead = (ISO_SUSP_HEADER *)pwhead; 512 pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 513 514 result = 0; 515 while (1) { 516 ana->iso_ce_len = 0; 517 /* 518 * Note: "pend" should be more than one SUSP header 519 */ 520 while (pend >= phead + 1) { 521 if (isonum_711(phead->version) == 1) { 522 for (ptable = table; ptable->func; ptable++) { 523 if (*phead->type == *ptable->type 524 && phead->type[1] == ptable->type[1]) { 525 result |= ptable->func(phead,ana); 526 break; 527 } 528 } 529 if (!ana->fields) 530 break; 531 } 532 if (result&ISO_SUSP_STOP) { 533 result &= ~ISO_SUSP_STOP; 534 break; 535 } 536 /* plausibility check */ 537 if (isonum_711(phead->length) < sizeof(*phead)) 538 break; 539 /* 540 * move to next SUSP 541 * Hopefully this works with newer versions, too 542 */ 543 phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 544 } 545 546 if (ana->fields && ana->iso_ce_len) { 547 if (ana->iso_ce_blk >= ana->imp->volume_space_size 548 || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 549 || bread(ana->imp->im_devvp, 550 ana->iso_ce_blk << 551 (ana->imp->im_bshift - DEV_BSHIFT), 552 ana->imp->logical_block_size, NOCRED, &bp)) 553 /* what to do now? */ 554 break; 555 phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 556 pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 557 } else 558 break; 559 } 560 if (bp) 561 brelse(bp); 562 /* 563 * If we don't find the Basic SUSP stuffs, just set default value 564 * (attribute/time stamp) 565 */ 566 for (ptable = table; ptable->func2; ptable++) 567 if (!(ptable->result&result)) 568 ptable->func2(isodir,ana); 569 570 return result; 571 } 572 573 /* 574 * Get Attributes. 575 */ 576 /* 577 * XXX the casts are bogus but will do for now. 578 */ 579 #define BC (rrt_func_t *) 580 static RRIP_TABLE rrip_table_analyze[] = { 581 { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 582 { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 583 { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 584 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 585 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 586 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 587 { "", 0, 0, 0 } 588 }; 589 590 int 591 cd9660_rrip_analyze(isodir,inop,imp) 592 struct iso_directory_record *isodir; 593 struct iso_node *inop; 594 struct iso_mnt *imp; 595 { 596 ISO_RRIP_ANALYZE analyze; 597 598 analyze.inop = inop; 599 analyze.imp = imp; 600 analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 601 602 return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 603 } 604 605 /* 606 * Get Alternate Name. 607 */ 608 static RRIP_TABLE rrip_table_getname[] = { 609 { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 610 { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 611 { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 612 { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 613 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 614 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 615 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 616 { "", 0, 0, 0 } 617 }; 618 619 int 620 cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 621 struct iso_directory_record *isodir; 622 char *outbuf; 623 u_short *outlen; 624 ino_t *inump; 625 struct iso_mnt *imp; 626 { 627 ISO_RRIP_ANALYZE analyze; 628 RRIP_TABLE *tab; 629 u_short c; 630 631 analyze.outbuf = outbuf; 632 analyze.outlen = outlen; 633 analyze.maxlen = NAME_MAX; 634 analyze.inump = inump; 635 analyze.imp = imp; 636 analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 637 *outlen = 0; 638 639 isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 640 imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l); 641 tab = rrip_table_getname; 642 if (c == 0 || c == 1) { 643 cd9660_rrip_defname(isodir,&analyze); 644 645 analyze.fields &= ~ISO_SUSP_ALTNAME; 646 tab++; 647 } 648 649 return cd9660_rrip_loop(isodir,&analyze,tab); 650 } 651 652 /* 653 * Get Symbolic Link. 654 */ 655 static RRIP_TABLE rrip_table_getsymname[] = { 656 { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 657 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 658 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 659 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 660 { "", 0, 0, 0 } 661 }; 662 663 int 664 cd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 665 struct iso_directory_record *isodir; 666 char *outbuf; 667 u_short *outlen; 668 struct iso_mnt *imp; 669 { 670 ISO_RRIP_ANALYZE analyze; 671 672 analyze.outbuf = outbuf; 673 analyze.outlen = outlen; 674 *outlen = 0; 675 analyze.maxlen = MAXPATHLEN; 676 analyze.cont = 1; /* don't start with a slash */ 677 analyze.imp = imp; 678 analyze.fields = ISO_SUSP_SLINK; 679 680 return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 681 } 682 683 static RRIP_TABLE rrip_table_extref[] = { 684 { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 685 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 686 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 687 { "", 0, 0, 0 } 688 }; 689 690 /* 691 * Check for Rock Ridge Extension and return offset of its fields. 692 * Note: We insist on the ER field. 693 */ 694 int 695 cd9660_rrip_offset(isodir,imp) 696 struct iso_directory_record *isodir; 697 struct iso_mnt *imp; 698 { 699 ISO_RRIP_OFFSET *p; 700 ISO_RRIP_ANALYZE analyze; 701 702 imp->rr_skip0 = 0; 703 p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 704 if (bcmp(p,"SP\7\1\276\357",6)) { 705 /* Maybe, it's a CDROM XA disc? */ 706 imp->rr_skip0 = 15; 707 p = (ISO_RRIP_OFFSET *)((char *)p + 15); 708 if (bcmp(p,"SP\7\1\276\357",6)) 709 return -1; 710 } 711 712 analyze.imp = imp; 713 analyze.fields = ISO_SUSP_EXTREF; 714 if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 715 return -1; 716 717 return isonum_711(p->skip); 718 } 719