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