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