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