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