1 /* $NetBSD: cd9660_rrip.c,v 1.10 2006/05/14 21:31:52 elad 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.10 2006/05/14 21:31:52 elad 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(v, ana) 340 void *v; 341 ISO_RRIP_ANALYZE *ana; 342 { 343 /* special hack to make caller aware of RE field */ 344 *ana->outlen = 0; 345 ana->fields = 0; 346 return ISO_SUSP_RELDIR | ISO_SUSP_ALTNAME 347 | ISO_SUSP_CLINK | ISO_SUSP_PLINK; 348 } 349 350 static int 351 cd9660_rrip_tstamp(v, ana) 352 void *v; 353 ISO_RRIP_ANALYZE *ana; 354 { 355 ISO_RRIP_TSTAMP *p = v; 356 u_char *ptime; 357 358 ptime = p->time; 359 360 /* Check a format of time stamp (7bytes/17bytes) */ 361 if (!(*p->flags & ISO_SUSP_TSTAMP_FORM17)) { 362 if (*p->flags & ISO_SUSP_TSTAMP_CREAT) 363 ptime += 7; 364 365 if (*p->flags & ISO_SUSP_TSTAMP_MODIFY) { 366 cd9660_tstamp_conv7(ptime, &ana->inop->inode.iso_mtime); 367 ptime += 7; 368 } else 369 memset(&ana->inop->inode.iso_mtime, 0, sizeof(struct timespec)); 370 371 if (*p->flags & ISO_SUSP_TSTAMP_ACCESS) { 372 cd9660_tstamp_conv7(ptime, &ana->inop->inode.iso_atime); 373 ptime += 7; 374 } else 375 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 376 377 if (*p->flags & ISO_SUSP_TSTAMP_ATTR) 378 cd9660_tstamp_conv7(ptime, &ana->inop->inode.iso_ctime); 379 else 380 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 381 382 } else { 383 if (*p->flags & ISO_SUSP_TSTAMP_CREAT) 384 ptime += 17; 385 386 if (*p->flags & ISO_SUSP_TSTAMP_MODIFY) { 387 cd9660_tstamp_conv17(ptime, &ana->inop->inode.iso_mtime); 388 ptime += 17; 389 } else 390 memset(&ana->inop->inode.iso_mtime, 0, sizeof(struct timespec)); 391 392 if (*p->flags & ISO_SUSP_TSTAMP_ACCESS) { 393 cd9660_tstamp_conv17(ptime, &ana->inop->inode.iso_atime); 394 ptime += 17; 395 } else 396 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 397 398 if (*p->flags & ISO_SUSP_TSTAMP_ATTR) 399 cd9660_tstamp_conv17(ptime, &ana->inop->inode.iso_ctime); 400 else 401 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 402 403 } 404 ana->fields &= ~ISO_SUSP_TSTAMP; 405 return ISO_SUSP_TSTAMP; 406 } 407 408 static void 409 cd9660_rrip_deftstamp(v, ana) 410 void *v; 411 ISO_RRIP_ANALYZE *ana; 412 { 413 struct iso_directory_record *isodir = v; 414 415 cd9660_deftstamp(isodir, ana->inop, NULL); 416 } 417 418 /* 419 * POSIX device modes 420 */ 421 static int 422 cd9660_rrip_device(v, ana) 423 void *v; 424 ISO_RRIP_ANALYZE *ana; 425 { 426 ISO_RRIP_DEVICE *p = v; 427 u_int high, low; 428 429 high = isonum_733(p->dev_t_high); 430 low = isonum_733(p->dev_t_low); 431 432 if (high == 0) 433 ana->inop->inode.iso_rdev = makedev(major(low), minor(low)); 434 else 435 ana->inop->inode.iso_rdev = makedev(high, minor(low)); 436 ana->fields &= ~ISO_SUSP_DEVICE; 437 return ISO_SUSP_DEVICE; 438 } 439 440 /* 441 * Flag indicating 442 */ 443 static int 444 cd9660_rrip_idflag(v, ana) 445 void *v; 446 ISO_RRIP_ANALYZE *ana; 447 { 448 ISO_RRIP_IDFLAG *p = v; 449 450 ana->fields &= isonum_711(p->flags) | ~0xff; /* don't touch high bits */ 451 /* special handling of RE field */ 452 if (ana->fields & ISO_SUSP_RELDIR) 453 return cd9660_rrip_reldir(p, ana); 454 455 return ISO_SUSP_IDFLAG; 456 } 457 458 /* 459 * Continuation pointer 460 */ 461 static int 462 cd9660_rrip_cont(v, ana) 463 void *v; 464 ISO_RRIP_ANALYZE *ana; 465 { 466 ISO_RRIP_CONT *p = v; 467 468 ana->iso_ce_blk = isonum_733(p->location); 469 ana->iso_ce_off = isonum_733(p->offset); 470 ana->iso_ce_len = isonum_733(p->length); 471 return ISO_SUSP_CONT; 472 } 473 474 /* 475 * System Use end 476 */ 477 static int 478 cd9660_rrip_stop(v, ana) 479 void *v; 480 ISO_RRIP_ANALYZE *ana; 481 { 482 return ISO_SUSP_STOP; 483 } 484 485 /* 486 * Extension reference 487 */ 488 static int 489 cd9660_rrip_extref(v, ana) 490 void *v; 491 ISO_RRIP_ANALYZE *ana; 492 { 493 ISO_RRIP_EXTREF *p = v; 494 495 if (isonum_711(p->version) != 1) 496 return 0; 497 if (isonum_711(p->len_id) != 9 498 && isonum_711(p->len_id) != 10) 499 return 0; 500 if (isonum_711(p->len_id) == 9 501 && memcmp((char *)p + 8, "IEEE_1282", 9)) 502 return 0; 503 if (isonum_711(p->len_id) == 10 504 && memcmp((char *)p + 8, "IEEE_P1282", 10) 505 && memcmp((char *)p + 8, "RRIP_1991A", 10)) 506 return 0; 507 ana->fields &= ~ISO_SUSP_EXTREF; 508 return ISO_SUSP_EXTREF; 509 } 510 511 512 static int 513 cd9660_rrip_loop(isodir, ana, table) 514 struct iso_directory_record *isodir; 515 ISO_RRIP_ANALYZE *ana; 516 const RRIP_TABLE *table; 517 { 518 const RRIP_TABLE *ptable; 519 ISO_SUSP_HEADER *phead; 520 ISO_SUSP_HEADER *pend; 521 struct buf *bp = NULL; 522 char *pwhead; 523 u_int16_t c; 524 int result; 525 526 /* 527 * Note: If name length is odd, 528 * it will be padded by 1 byte after the name 529 */ 530 pwhead = isodir->name + isonum_711(isodir->name_len); 531 if (!(isonum_711(isodir->name_len) & 1)) 532 pwhead++; 533 isochar(isodir->name, pwhead, ana->imp->im_joliet_level, &c); 534 535 /* If it's not the '.' entry of the root dir obey SP field */ 536 if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 537 pwhead += ana->imp->rr_skip; 538 else 539 pwhead += ana->imp->rr_skip0; 540 541 phead = (ISO_SUSP_HEADER *)pwhead; 542 pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 543 544 result = 0; 545 while (1) { 546 ana->iso_ce_len = 0; 547 /* 548 * Note: "pend" should be more than one SUSP header 549 */ 550 while (pend >= phead + 1) { 551 if (isonum_711(phead->version) == 1) { 552 for (ptable = table; ptable->func; ptable++) { 553 if (*phead->type == *ptable->type 554 && phead->type[1] == ptable->type[1]) { 555 result |= ptable->func(phead, ana); 556 break; 557 } 558 } 559 if (!ana->fields) 560 break; 561 } 562 if (result & ISO_SUSP_STOP) { 563 result &= ~ISO_SUSP_STOP; 564 break; 565 } 566 /* plausibility check */ 567 if (isonum_711(phead->length) < sizeof(*phead)) 568 break; 569 /* 570 * move to next SUSP 571 * Hopefully this works with newer versions, too 572 */ 573 phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 574 } 575 576 if (ana->fields && ana->iso_ce_len) { 577 if (ana->iso_ce_blk >= ana->imp->volume_space_size 578 || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 579 || bread(ana->imp->im_devvp, 580 ana->iso_ce_blk << (ana->imp->im_bshift - DEV_BSHIFT), 581 ana->imp->logical_block_size, NOCRED, &bp)) 582 /* what to do now? */ 583 break; 584 phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 585 pend = (ISO_SUSP_HEADER *)((char *)phead + ana->iso_ce_len); 586 } else 587 break; 588 } 589 if (bp) 590 brelse(bp); 591 /* 592 * If we don't find the Basic SUSP stuffs, just set default value 593 * (attribute/time stamp) 594 */ 595 for (ptable = table; ptable->func2; ptable++) 596 if (!(ptable->result & result)) 597 ptable->func2(isodir, ana); 598 599 return result; 600 } 601 602 /* 603 * Get Attributes. 604 */ 605 static const RRIP_TABLE rrip_table_analyze[] = { 606 { "PX", cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 607 { "TF", cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 608 { "PN", cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 609 { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 610 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 611 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 612 { "", 0, 0, 0 } 613 }; 614 615 int 616 cd9660_rrip_analyze(isodir, inop, imp) 617 struct iso_directory_record *isodir; 618 struct iso_node *inop; 619 struct iso_mnt *imp; 620 { 621 ISO_RRIP_ANALYZE analyze; 622 623 analyze.inop = inop; 624 analyze.imp = imp; 625 analyze.fields = ISO_SUSP_ATTR | ISO_SUSP_TSTAMP | ISO_SUSP_DEVICE; 626 627 return cd9660_rrip_loop(isodir, &analyze, rrip_table_analyze); 628 } 629 630 /* 631 * Get Alternate Name. 632 */ 633 static const RRIP_TABLE rrip_table_getname[] = { 634 { "NM", cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 635 { "CL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 636 { "PL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 637 { "RE", cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 638 { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 639 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 640 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 641 { "", 0, 0, 0 } 642 }; 643 644 int 645 cd9660_rrip_getname(isodir, outbuf, outlen, inump, imp) 646 struct iso_directory_record *isodir; 647 char *outbuf; 648 u_short *outlen; 649 ino_t *inump; 650 struct iso_mnt *imp; 651 { 652 ISO_RRIP_ANALYZE analyze; 653 const RRIP_TABLE *tab; 654 u_int16_t c; 655 656 analyze.outbuf = outbuf; 657 analyze.outlen = outlen; 658 analyze.maxlen = NAME_MAX; 659 analyze.inump = inump; 660 analyze.imp = imp; 661 analyze.fields = ISO_SUSP_ALTNAME | ISO_SUSP_RELDIR | ISO_SUSP_CLINK | ISO_SUSP_PLINK; 662 *outlen = 0; 663 664 isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 665 imp->im_joliet_level, &c); 666 tab = rrip_table_getname; 667 if (c == 0 || c == 1) { 668 cd9660_rrip_defname(isodir, &analyze); 669 670 analyze.fields &= ~ISO_SUSP_ALTNAME; 671 tab++; 672 } 673 674 return cd9660_rrip_loop(isodir, &analyze, tab); 675 } 676 677 /* 678 * Get Symbolic Link. 679 */ 680 static const RRIP_TABLE rrip_table_getsymname[] = { 681 { "SL", cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 682 { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 683 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 684 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 685 { "", 0, 0, 0 } 686 }; 687 688 int 689 cd9660_rrip_getsymname(isodir, outbuf, outlen, imp) 690 struct iso_directory_record *isodir; 691 char *outbuf; 692 u_short *outlen; 693 struct iso_mnt *imp; 694 { 695 ISO_RRIP_ANALYZE analyze; 696 697 analyze.outbuf = outbuf; 698 analyze.outlen = outlen; 699 *outlen = 0; 700 analyze.maxlen = MAXPATHLEN; 701 analyze.cont = 1; /* don't start with a slash */ 702 analyze.imp = imp; 703 analyze.fields = ISO_SUSP_SLINK; 704 705 return cd9660_rrip_loop(isodir, &analyze, rrip_table_getsymname) & ISO_SUSP_SLINK; 706 } 707 708 static const RRIP_TABLE rrip_table_extref[] = { 709 { "ER", cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 710 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 711 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 712 { "", 0, 0, 0 } 713 }; 714 715 /* 716 * Check for Rock Ridge Extension and return offset of its fields. 717 * Note: We insist on the ER field. 718 */ 719 int 720 cd9660_rrip_offset(isodir, imp) 721 struct iso_directory_record *isodir; 722 struct iso_mnt *imp; 723 { 724 ISO_RRIP_OFFSET *p; 725 ISO_RRIP_ANALYZE analyze; 726 727 imp->rr_skip0 = 0; 728 p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 729 if (memcmp(p, "SP\7\1\276\357", 6)) { 730 /* Maybe, it's a CDROM XA disc? */ 731 imp->rr_skip0 = 15; 732 p = (ISO_RRIP_OFFSET *)((char *)p + 15); 733 if (memcmp(p, "SP\7\1\276\357", 6)) 734 return -1; 735 } 736 737 analyze.imp = imp; 738 analyze.fields = ISO_SUSP_EXTREF; 739 if (!(cd9660_rrip_loop(isodir, &analyze, rrip_table_extref) & ISO_SUSP_EXTREF)) 740 return -1; 741 742 return isonum_711(p->skip); 743 } 744