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