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