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