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