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