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