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