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