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