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