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