1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley 8 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 9 * Support code is derived from software contributed to Berkeley 10 * by Atsushi Murai (amurai@spec.co.jp). 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94 37 */ 38 39 #include <sys/cdefs.h> 40 __FBSDID("$FreeBSD$"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/bio.h> 45 #include <sys/buf.h> 46 #include <sys/jail.h> 47 #include <sys/vnode.h> 48 #include <sys/mount.h> 49 #include <sys/kernel.h> 50 51 #include <fs/cd9660/iso.h> 52 #include <fs/cd9660/cd9660_node.h> 53 #include <fs/cd9660/cd9660_rrip.h> 54 #include <fs/cd9660/iso_rrip.h> 55 56 typedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 57 58 typedef struct { 59 char type[2]; 60 rrt_func_t *func; 61 void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 62 int result; 63 } RRIP_TABLE; 64 65 static int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 66 static int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 67 static int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 68 static void cd9660_rrip_defattr(struct iso_directory_record *isodir, 69 ISO_RRIP_ANALYZE *ana); 70 static void cd9660_rrip_defname(struct iso_directory_record *isodir, 71 ISO_RRIP_ANALYZE *ana); 72 static void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 73 ISO_RRIP_ANALYZE *ana); 74 static int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 75 static int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 76 static int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 77 static int cd9660_rrip_loop(struct iso_directory_record *isodir, 78 ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table); 79 static int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 80 static int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 81 static int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 82 static int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 83 static int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 84 85 /* 86 * POSIX file attribute 87 */ 88 static int 89 cd9660_rrip_attr(p,ana) 90 ISO_RRIP_ATTR *p; 91 ISO_RRIP_ANALYZE *ana; 92 { 93 ana->inop->inode.iso_mode = isonum_733(p->mode); 94 ana->inop->inode.iso_uid = isonum_733(p->uid); 95 ana->inop->inode.iso_gid = isonum_733(p->gid); 96 ana->inop->inode.iso_links = isonum_733(p->links); 97 ana->fields &= ~ISO_SUSP_ATTR; 98 return ISO_SUSP_ATTR; 99 } 100 101 static void 102 cd9660_rrip_defattr(isodir,ana) 103 struct iso_directory_record *isodir; 104 ISO_RRIP_ANALYZE *ana; 105 { 106 /* But this is a required field! */ 107 printf("RRIP without PX field?\n"); 108 cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 109 } 110 111 /* 112 * Symbolic Links 113 */ 114 static int 115 cd9660_rrip_slink(p,ana) 116 ISO_RRIP_SLINK *p; 117 ISO_RRIP_ANALYZE *ana; 118 { 119 ISO_RRIP_SLINK_COMPONENT *pcomp; 120 ISO_RRIP_SLINK_COMPONENT *pcompe; 121 int len, wlen, cont; 122 char *outbuf, *inbuf; 123 char hostbuf[MAXHOSTNAMELEN]; 124 125 pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 126 pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 127 len = *ana->outlen; 128 outbuf = ana->outbuf; 129 cont = ana->cont; 130 131 /* 132 * Gathering a Symbolic name from each component with path 133 */ 134 for (; 135 pcomp < pcompe; 136 pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 137 + isonum_711(pcomp->clen))) { 138 139 if (!cont) { 140 if (len < ana->maxlen) { 141 len++; 142 *outbuf++ = '/'; 143 } 144 } 145 cont = 0; 146 147 inbuf = ".."; 148 wlen = 0; 149 150 switch (*pcomp->cflag) { 151 152 case ISO_SUSP_CFLAG_CURRENT: 153 /* Inserting Current */ 154 wlen = 1; 155 break; 156 157 case ISO_SUSP_CFLAG_PARENT: 158 /* Inserting Parent */ 159 wlen = 2; 160 break; 161 162 case ISO_SUSP_CFLAG_ROOT: 163 /* Inserting slash for ROOT */ 164 /* Double slash, nothing really to do here. */ 165 break; 166 167 case ISO_SUSP_CFLAG_VOLROOT: 168 /* Inserting a mount point i.e. "/cdrom" */ 169 /* same as above */ 170 outbuf -= len; 171 len = 0; 172 inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 173 wlen = strlen(inbuf); 174 break; 175 176 case ISO_SUSP_CFLAG_HOST: 177 /* Inserting hostname i.e. "kurt.tools.de" */ 178 getcredhostname(curthread->td_ucred, hostbuf, 179 sizeof(hostbuf)); 180 inbuf = hostbuf; 181 wlen = strlen(inbuf); 182 break; 183 184 case ISO_SUSP_CFLAG_CONTINUE: 185 cont = 1; 186 /* FALLTHROUGH */ 187 case 0: 188 /* Inserting component */ 189 wlen = isonum_711(pcomp->clen); 190 inbuf = pcomp->name; 191 break; 192 default: 193 printf("RRIP with incorrect flags?"); 194 wlen = ana->maxlen + 1; 195 break; 196 } 197 198 if (len + wlen > ana->maxlen) { 199 /* indicate error to caller */ 200 ana->cont = 1; 201 ana->fields = 0; 202 ana->outbuf -= *ana->outlen; 203 *ana->outlen = 0; 204 return 0; 205 } 206 207 memcpy(outbuf, inbuf, wlen); 208 outbuf += wlen; 209 len += wlen; 210 211 } 212 ana->outbuf = outbuf; 213 *ana->outlen = len; 214 ana->cont = cont; 215 216 if (!isonum_711(p->flags)) { 217 ana->fields &= ~ISO_SUSP_SLINK; 218 return ISO_SUSP_SLINK; 219 } 220 return 0; 221 } 222 223 /* 224 * Alternate name 225 */ 226 static int 227 cd9660_rrip_altname(p,ana) 228 ISO_RRIP_ALTNAME *p; 229 ISO_RRIP_ANALYZE *ana; 230 { 231 char *inbuf; 232 int wlen; 233 int cont; 234 char hostbuf[MAXHOSTNAMELEN]; 235 236 inbuf = ".."; 237 wlen = 0; 238 cont = 0; 239 240 switch (*p->flags) { 241 case ISO_SUSP_CFLAG_CURRENT: 242 /* Inserting Current */ 243 wlen = 1; 244 break; 245 246 case ISO_SUSP_CFLAG_PARENT: 247 /* Inserting Parent */ 248 wlen = 2; 249 break; 250 251 case ISO_SUSP_CFLAG_HOST: 252 /* Inserting hostname i.e. "kurt.tools.de" */ 253 getcredhostname(curthread->td_ucred, hostbuf, sizeof(hostbuf)); 254 inbuf = hostbuf; 255 wlen = strlen(inbuf); 256 break; 257 258 case ISO_SUSP_CFLAG_CONTINUE: 259 cont = 1; 260 /* FALLTHROUGH */ 261 case 0: 262 /* Inserting component */ 263 wlen = isonum_711(p->h.length) - 5; 264 inbuf = (char *)p + 5; 265 break; 266 267 default: 268 printf("RRIP with incorrect NM flags?\n"); 269 wlen = ana->maxlen + 1; 270 break; 271 } 272 273 if ((*ana->outlen += wlen) > ana->maxlen) { 274 /* treat as no name field */ 275 ana->fields &= ~ISO_SUSP_ALTNAME; 276 ana->outbuf -= *ana->outlen - wlen; 277 *ana->outlen = 0; 278 return 0; 279 } 280 281 memcpy(ana->outbuf, inbuf, wlen); 282 ana->outbuf += wlen; 283 284 if (!cont) { 285 ana->fields &= ~ISO_SUSP_ALTNAME; 286 return ISO_SUSP_ALTNAME; 287 } 288 return 0; 289 } 290 291 static void 292 cd9660_rrip_defname(isodir,ana) 293 struct iso_directory_record *isodir; 294 ISO_RRIP_ANALYZE *ana; 295 { 296 isofntrans(isodir->name,isonum_711(isodir->name_len), 297 ana->outbuf,ana->outlen, 298 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level, 299 ana->imp->im_flags, ana->imp->im_d2l); 300 switch (*ana->outbuf) { 301 default: 302 break; 303 case 1: 304 *ana->outlen = 2; 305 /* FALLTHROUGH */ 306 case 0: 307 /* outlen is 1 already */ 308 strcpy(ana->outbuf,".."); 309 break; 310 } 311 } 312 313 /* 314 * Parent or Child Link 315 */ 316 static int 317 cd9660_rrip_pclink(p,ana) 318 ISO_RRIP_CLINK *p; 319 ISO_RRIP_ANALYZE *ana; 320 { 321 *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 322 ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 323 return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 324 } 325 326 /* 327 * Relocated directory 328 */ 329 static int 330 cd9660_rrip_reldir(p,ana) 331 ISO_RRIP_RELDIR *p; 332 ISO_RRIP_ANALYZE *ana; 333 { 334 /* special hack to make caller aware of RE field */ 335 *ana->outlen = 0; 336 ana->fields = 0; 337 return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 338 } 339 340 static int 341 cd9660_rrip_tstamp(p,ana) 342 ISO_RRIP_TSTAMP *p; 343 ISO_RRIP_ANALYZE *ana; 344 { 345 u_char *ptime; 346 347 ptime = p->time; 348 349 /* Check a format of time stamp (7bytes/17bytes) */ 350 if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 351 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 352 ptime += 7; 353 354 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 355 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 356 ISO_FTYPE_RRIP); 357 ptime += 7; 358 } else 359 memset(&ana->inop->inode.iso_mtime, 0, sizeof(struct timespec)); 360 361 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 362 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 363 ISO_FTYPE_RRIP); 364 ptime += 7; 365 } else 366 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 367 368 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 369 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 370 ISO_FTYPE_RRIP); 371 else 372 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 373 374 } else { 375 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 376 ptime += 17; 377 378 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 379 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 380 ptime += 17; 381 } else 382 memset(&ana->inop->inode.iso_mtime, 0, sizeof(struct timespec)); 383 384 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 385 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 386 ptime += 17; 387 } else 388 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 389 390 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 391 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 392 else 393 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 394 395 } 396 ana->fields &= ~ISO_SUSP_TSTAMP; 397 return ISO_SUSP_TSTAMP; 398 } 399 400 static void 401 cd9660_rrip_deftstamp(isodir,ana) 402 struct iso_directory_record *isodir; 403 ISO_RRIP_ANALYZE *ana; 404 { 405 cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 406 } 407 408 /* 409 * POSIX device modes 410 */ 411 static int 412 cd9660_rrip_device(p,ana) 413 ISO_RRIP_DEVICE *p; 414 ISO_RRIP_ANALYZE *ana; 415 { 416 u_int high, low; 417 418 high = isonum_733(p->dev_t_high); 419 low = isonum_733(p->dev_t_low); 420 421 if (high == 0) 422 ana->inop->inode.iso_rdev = makedev(major(low), minor(low)); 423 else 424 ana->inop->inode.iso_rdev = makedev(high, minor(low)); 425 ana->fields &= ~ISO_SUSP_DEVICE; 426 return ISO_SUSP_DEVICE; 427 } 428 429 /* 430 * Flag indicating 431 */ 432 static int 433 cd9660_rrip_idflag(p,ana) 434 ISO_RRIP_IDFLAG *p; 435 ISO_RRIP_ANALYZE *ana; 436 { 437 ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 438 /* special handling of RE field */ 439 if (ana->fields&ISO_SUSP_RELDIR) 440 return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 441 442 return ISO_SUSP_IDFLAG; 443 } 444 445 /* 446 * Continuation pointer 447 */ 448 static int 449 cd9660_rrip_cont(p,ana) 450 ISO_RRIP_CONT *p; 451 ISO_RRIP_ANALYZE *ana; 452 { 453 ana->iso_ce_blk = isonum_733(p->location); 454 ana->iso_ce_off = isonum_733(p->offset); 455 ana->iso_ce_len = isonum_733(p->length); 456 return ISO_SUSP_CONT; 457 } 458 459 /* 460 * System Use end 461 */ 462 static int 463 cd9660_rrip_stop(p,ana) 464 ISO_SUSP_HEADER *p; 465 ISO_RRIP_ANALYZE *ana; 466 { 467 return ISO_SUSP_STOP; 468 } 469 470 /* 471 * Extension reference 472 */ 473 static int 474 cd9660_rrip_extref(p,ana) 475 ISO_RRIP_EXTREF *p; 476 ISO_RRIP_ANALYZE *ana; 477 { 478 if ( ! ((isonum_711(p->len_id) == 10 479 && bcmp((char *)p + 8,"RRIP_1991A",10) == 0) 480 || (isonum_711(p->len_id) == 10 481 && bcmp((char *)p + 8,"IEEE_P1282",10) == 0) 482 || (isonum_711(p->len_id) == 9 483 && bcmp((char *)p + 8,"IEEE_1282", 9) == 0)) 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 RRIP_TABLE *ptable; 497 ISO_SUSP_HEADER *phead; 498 ISO_SUSP_HEADER *pend; 499 struct buf *bp = NULL; 500 char *pwhead; 501 u_short 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, NULL, 512 ana->imp->im_flags, ana->imp->im_d2l); 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 cd_ino_t *inump; 634 struct iso_mnt *imp; 635 { 636 ISO_RRIP_ANALYZE analyze; 637 RRIP_TABLE *tab; 638 u_short 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, NULL, imp->im_flags, imp->im_d2l); 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