1 /*- 2 * Copyright (c) 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley 6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7 * Support code is derived from software contributed to Berkeley 8 * by Atsushi Murai (amurai@spec.co.jp). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94 39 * $Id: cd9660_rrip.c,v 1.14 1999/04/18 10:58:01 dcs Exp $ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/buf.h> 45 #include <sys/vnode.h> 46 #include <sys/mount.h> 47 #include <sys/kernel.h> 48 49 #include <isofs/cd9660/iso.h> 50 #include <isofs/cd9660/cd9660_node.h> 51 #include <isofs/cd9660/cd9660_rrip.h> 52 #include <isofs/cd9660/iso_rrip.h> 53 54 typedef int rrt_func_t __P((void *, ISO_RRIP_ANALYZE *ana)); 55 56 typedef struct { 57 char type[2]; 58 rrt_func_t *func; 59 void (*func2) __P((struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana)); 60 int result; 61 } RRIP_TABLE; 62 63 static int cd9660_rrip_altname __P((ISO_RRIP_ALTNAME *p, 64 ISO_RRIP_ANALYZE *ana)); 65 static int cd9660_rrip_attr __P((ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana)); 66 static int cd9660_rrip_cont __P((ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana)); 67 static void cd9660_rrip_defattr __P((struct iso_directory_record *isodir, 68 ISO_RRIP_ANALYZE *ana)); 69 static void cd9660_rrip_defname __P((struct iso_directory_record *isodir, 70 ISO_RRIP_ANALYZE *ana)); 71 static void cd9660_rrip_deftstamp __P((struct iso_directory_record *isodir, 72 ISO_RRIP_ANALYZE *ana)); 73 static int cd9660_rrip_device __P((ISO_RRIP_DEVICE *p, 74 ISO_RRIP_ANALYZE *ana)); 75 static int cd9660_rrip_extref __P((ISO_RRIP_EXTREF *p, 76 ISO_RRIP_ANALYZE *ana)); 77 static int cd9660_rrip_idflag __P((ISO_RRIP_IDFLAG *p, 78 ISO_RRIP_ANALYZE *ana)); 79 static int cd9660_rrip_loop __P((struct iso_directory_record *isodir, 80 ISO_RRIP_ANALYZE *ana, 81 RRIP_TABLE *table)); 82 static int cd9660_rrip_pclink __P((ISO_RRIP_CLINK *p, 83 ISO_RRIP_ANALYZE *ana)); 84 static int cd9660_rrip_reldir __P((ISO_RRIP_RELDIR *p, 85 ISO_RRIP_ANALYZE *ana)); 86 static int cd9660_rrip_slink __P((ISO_RRIP_SLINK *p, 87 ISO_RRIP_ANALYZE *ana)); 88 static int cd9660_rrip_stop __P((ISO_SUSP_HEADER *p, 89 ISO_RRIP_ANALYZE *ana)); 90 static int cd9660_rrip_tstamp __P((ISO_RRIP_TSTAMP *p, 91 ISO_RRIP_ANALYZE *ana)); 92 93 /* 94 * POSIX file attribute 95 */ 96 static int 97 cd9660_rrip_attr(p,ana) 98 ISO_RRIP_ATTR *p; 99 ISO_RRIP_ANALYZE *ana; 100 { 101 ana->inop->inode.iso_mode = isonum_733(p->mode); 102 ana->inop->inode.iso_uid = isonum_733(p->uid); 103 ana->inop->inode.iso_gid = isonum_733(p->gid); 104 ana->inop->inode.iso_links = isonum_733(p->links); 105 ana->fields &= ~ISO_SUSP_ATTR; 106 return ISO_SUSP_ATTR; 107 } 108 109 static void 110 cd9660_rrip_defattr(isodir,ana) 111 struct iso_directory_record *isodir; 112 ISO_RRIP_ANALYZE *ana; 113 { 114 /* But this is a required field! */ 115 printf("RRIP without PX field?\n"); 116 cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 117 } 118 119 /* 120 * Symbolic Links 121 */ 122 static int 123 cd9660_rrip_slink(p,ana) 124 ISO_RRIP_SLINK *p; 125 ISO_RRIP_ANALYZE *ana; 126 { 127 register ISO_RRIP_SLINK_COMPONENT *pcomp; 128 register ISO_RRIP_SLINK_COMPONENT *pcompe; 129 int len, wlen, cont; 130 char *outbuf, *inbuf; 131 132 pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 133 pcompe = (ISO_RRIP_SLINK_COMPONENT *)((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 = strlen(hostname); 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 bcopy(inbuf,outbuf,wlen); 215 outbuf += wlen; 216 len += wlen; 217 218 } 219 ana->outbuf = outbuf; 220 *ana->outlen = len; 221 ana->cont = cont; 222 223 if (!isonum_711(p->flags)) { 224 ana->fields &= ~ISO_SUSP_SLINK; 225 return ISO_SUSP_SLINK; 226 } 227 return 0; 228 } 229 230 /* 231 * Alternate name 232 */ 233 static int 234 cd9660_rrip_altname(p,ana) 235 ISO_RRIP_ALTNAME *p; 236 ISO_RRIP_ANALYZE *ana; 237 { 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 = strlen(hostname); 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 bcopy(inbuf,ana->outbuf,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(isodir,ana) 298 struct iso_directory_record *isodir; 299 ISO_RRIP_ANALYZE *ana; 300 { 301 isofntrans(isodir->name,isonum_711(isodir->name_len), 302 ana->outbuf,ana->outlen, 303 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level); 304 switch (*ana->outbuf) { 305 default: 306 break; 307 case 1: 308 *ana->outlen = 2; 309 /* FALL THROUGH */ 310 case 0: 311 /* outlen is 1 already */ 312 strcpy(ana->outbuf,".."); 313 break; 314 } 315 } 316 317 /* 318 * Parent or Child Link 319 */ 320 static int 321 cd9660_rrip_pclink(p,ana) 322 ISO_RRIP_CLINK *p; 323 ISO_RRIP_ANALYZE *ana; 324 { 325 *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 326 ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 327 return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 328 } 329 330 /* 331 * Relocated directory 332 */ 333 static int 334 cd9660_rrip_reldir(p,ana) 335 ISO_RRIP_RELDIR *p; 336 ISO_RRIP_ANALYZE *ana; 337 { 338 /* special hack to make caller aware of RE field */ 339 *ana->outlen = 0; 340 ana->fields = 0; 341 return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 342 } 343 344 static int 345 cd9660_rrip_tstamp(p,ana) 346 ISO_RRIP_TSTAMP *p; 347 ISO_RRIP_ANALYZE *ana; 348 { 349 u_char *ptime; 350 351 ptime = p->time; 352 353 /* Check a format of time stamp (7bytes/17bytes) */ 354 if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 355 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 356 ptime += 7; 357 358 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 359 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 360 ISO_FTYPE_RRIP); 361 ptime += 7; 362 } else 363 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 364 365 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 366 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 367 ISO_FTYPE_RRIP); 368 ptime += 7; 369 } else 370 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 371 372 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 373 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 374 ISO_FTYPE_RRIP); 375 else 376 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 377 378 } else { 379 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 380 ptime += 17; 381 382 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 383 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 384 ptime += 17; 385 } else 386 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 387 388 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 389 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 390 ptime += 17; 391 } else 392 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 393 394 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 395 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 396 else 397 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 398 399 } 400 ana->fields &= ~ISO_SUSP_TSTAMP; 401 return ISO_SUSP_TSTAMP; 402 } 403 404 static void 405 cd9660_rrip_deftstamp(isodir,ana) 406 struct iso_directory_record *isodir; 407 ISO_RRIP_ANALYZE *ana; 408 { 409 cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 410 } 411 412 /* 413 * POSIX device modes 414 */ 415 static int 416 cd9660_rrip_device(p,ana) 417 ISO_RRIP_DEVICE *p; 418 ISO_RRIP_ANALYZE *ana; 419 { 420 u_int high, low; 421 422 high = isonum_733(p->dev_t_high); 423 low = isonum_733(p->dev_t_low); 424 425 if (high == 0) 426 ana->inop->inode.iso_rdev = umakedev(umajor(low), uminor(low)); 427 else 428 ana->inop->inode.iso_rdev = umakedev(high, uminor(low)); 429 ana->fields &= ~ISO_SUSP_DEVICE; 430 return ISO_SUSP_DEVICE; 431 } 432 433 /* 434 * Flag indicating 435 */ 436 static int 437 cd9660_rrip_idflag(p,ana) 438 ISO_RRIP_IDFLAG *p; 439 ISO_RRIP_ANALYZE *ana; 440 { 441 ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 442 /* special handling of RE field */ 443 if (ana->fields&ISO_SUSP_RELDIR) 444 return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 445 446 return ISO_SUSP_IDFLAG; 447 } 448 449 /* 450 * Continuation pointer 451 */ 452 static int 453 cd9660_rrip_cont(p,ana) 454 ISO_RRIP_CONT *p; 455 ISO_RRIP_ANALYZE *ana; 456 { 457 ana->iso_ce_blk = isonum_733(p->location); 458 ana->iso_ce_off = isonum_733(p->offset); 459 ana->iso_ce_len = isonum_733(p->length); 460 return ISO_SUSP_CONT; 461 } 462 463 /* 464 * System Use end 465 */ 466 static int 467 cd9660_rrip_stop(p,ana) 468 ISO_SUSP_HEADER *p; 469 ISO_RRIP_ANALYZE *ana; 470 { 471 return ISO_SUSP_STOP; 472 } 473 474 /* 475 * Extension reference 476 */ 477 static int 478 cd9660_rrip_extref(p,ana) 479 ISO_RRIP_EXTREF *p; 480 ISO_RRIP_ANALYZE *ana; 481 { 482 if (isonum_711(p->len_id) != 10 483 || bcmp((char *)p + 8,"RRIP_1991A",10) 484 || isonum_711(p->version) != 1) 485 return 0; 486 ana->fields &= ~ISO_SUSP_EXTREF; 487 return ISO_SUSP_EXTREF; 488 } 489 490 static int 491 cd9660_rrip_loop(isodir,ana,table) 492 struct iso_directory_record *isodir; 493 ISO_RRIP_ANALYZE *ana; 494 RRIP_TABLE *table; 495 { 496 register RRIP_TABLE *ptable; 497 register ISO_SUSP_HEADER *phead; 498 register ISO_SUSP_HEADER *pend; 499 struct buf *bp = NULL; 500 char *pwhead; 501 u_char c; 502 int result; 503 504 /* 505 * Note: If name length is odd, 506 * it will be padding 1 byte after the name 507 */ 508 pwhead = isodir->name + isonum_711(isodir->name_len); 509 if (!(isonum_711(isodir->name_len)&1)) 510 pwhead++; 511 isochar(isodir->name, pwhead, ana->imp->joliet_level, &c); 512 513 /* If it's not the '.' entry of the root dir obey SP field */ 514 if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 515 pwhead += ana->imp->rr_skip; 516 else 517 pwhead += ana->imp->rr_skip0; 518 519 phead = (ISO_SUSP_HEADER *)pwhead; 520 pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 521 522 result = 0; 523 while (1) { 524 ana->iso_ce_len = 0; 525 /* 526 * Note: "pend" should be more than one SUSP header 527 */ 528 while (pend >= phead + 1) { 529 if (isonum_711(phead->version) == 1) { 530 for (ptable = table; ptable->func; ptable++) { 531 if (*phead->type == *ptable->type 532 && phead->type[1] == ptable->type[1]) { 533 result |= 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 *)((char *)phead + isonum_711(phead->length)); 552 } 553 554 if (ana->fields && ana->iso_ce_len) { 555 if (ana->iso_ce_blk >= ana->imp->volume_space_size 556 || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 557 || bread(ana->imp->im_devvp, 558 ana->iso_ce_blk << 559 (ana->imp->im_bshift - DEV_BSHIFT), 560 ana->imp->logical_block_size, NOCRED, &bp)) 561 /* what to do now? */ 562 break; 563 phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 564 pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 565 } else 566 break; 567 } 568 if (bp) 569 brelse(bp); 570 /* 571 * If we don't find the Basic SUSP stuffs, just set default value 572 * (attribute/time stamp) 573 */ 574 for (ptable = table; ptable->func2; ptable++) 575 if (!(ptable->result&result)) 576 ptable->func2(isodir,ana); 577 578 return result; 579 } 580 581 /* 582 * Get Attributes. 583 */ 584 /* 585 * XXX the casts are bogus but will do for now. 586 */ 587 #define BC (rrt_func_t *) 588 static RRIP_TABLE rrip_table_analyze[] = { 589 { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 590 { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 591 { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 592 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 593 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 594 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 595 { "", 0, 0, 0 } 596 }; 597 598 int 599 cd9660_rrip_analyze(isodir,inop,imp) 600 struct iso_directory_record *isodir; 601 struct iso_node *inop; 602 struct iso_mnt *imp; 603 { 604 ISO_RRIP_ANALYZE analyze; 605 606 analyze.inop = inop; 607 analyze.imp = imp; 608 analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 609 610 return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 611 } 612 613 /* 614 * Get Alternate Name. 615 */ 616 static RRIP_TABLE rrip_table_getname[] = { 617 { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 618 { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 619 { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 620 { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 621 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 622 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 623 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 624 { "", 0, 0, 0 } 625 }; 626 627 int 628 cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 629 struct iso_directory_record *isodir; 630 char *outbuf; 631 u_short *outlen; 632 ino_t *inump; 633 struct iso_mnt *imp; 634 { 635 ISO_RRIP_ANALYZE analyze; 636 RRIP_TABLE *tab; 637 u_char c; 638 639 analyze.outbuf = outbuf; 640 analyze.outlen = outlen; 641 analyze.maxlen = NAME_MAX; 642 analyze.inump = inump; 643 analyze.imp = imp; 644 analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 645 *outlen = 0; 646 647 isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 648 imp->joliet_level, &c); 649 tab = rrip_table_getname; 650 if (c == 0 || c == 1) { 651 cd9660_rrip_defname(isodir,&analyze); 652 653 analyze.fields &= ~ISO_SUSP_ALTNAME; 654 tab++; 655 } 656 657 return cd9660_rrip_loop(isodir,&analyze,tab); 658 } 659 660 /* 661 * Get Symbolic Link. 662 */ 663 static RRIP_TABLE rrip_table_getsymname[] = { 664 { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 665 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 666 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 667 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 668 { "", 0, 0, 0 } 669 }; 670 671 int 672 cd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 673 struct iso_directory_record *isodir; 674 char *outbuf; 675 u_short *outlen; 676 struct iso_mnt *imp; 677 { 678 ISO_RRIP_ANALYZE analyze; 679 680 analyze.outbuf = outbuf; 681 analyze.outlen = outlen; 682 *outlen = 0; 683 analyze.maxlen = MAXPATHLEN; 684 analyze.cont = 1; /* don't start with a slash */ 685 analyze.imp = imp; 686 analyze.fields = ISO_SUSP_SLINK; 687 688 return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 689 } 690 691 static RRIP_TABLE rrip_table_extref[] = { 692 { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 693 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 694 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 695 { "", 0, 0, 0 } 696 }; 697 698 /* 699 * Check for Rock Ridge Extension and return offset of its fields. 700 * Note: We insist on the ER field. 701 */ 702 int 703 cd9660_rrip_offset(isodir,imp) 704 struct iso_directory_record *isodir; 705 struct iso_mnt *imp; 706 { 707 ISO_RRIP_OFFSET *p; 708 ISO_RRIP_ANALYZE analyze; 709 710 imp->rr_skip0 = 0; 711 p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 712 if (bcmp(p,"SP\7\1\276\357",6)) { 713 /* Maybe, it's a CDROM XA disc? */ 714 imp->rr_skip0 = 15; 715 p = (ISO_RRIP_OFFSET *)((char *)p + 15); 716 if (bcmp(p,"SP\7\1\276\357",6)) 717 return -1; 718 } 719 720 analyze.imp = imp; 721 analyze.fields = ISO_SUSP_EXTREF; 722 if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 723 return -1; 724 725 return isonum_711(p->skip); 726 } 727