1 /*- 2 * Copyright (c) 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley 6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7 * Support code is derived from software contributed to Berkeley 8 * by Atsushi Murai (amurai@spec.co.jp). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94 35 * $FreeBSD: src/sys/isofs/cd9660/cd9660_rrip.c,v 1.17 1999/08/28 00:46:06 peter Exp $ 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/buf.h> 41 #include <sys/vnode.h> 42 #include <sys/mount.h> 43 #include <sys/kernel.h> 44 #include <sys/malloc.h> 45 46 #include "iso.h" 47 #include "cd9660_node.h" 48 #include "cd9660_rrip.h" 49 #include "iso_rrip.h" 50 51 #include <sys/buf2.h> 52 53 typedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 54 55 typedef struct { 56 char type[2]; 57 rrt_func_t *func; 58 void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 59 int result; 60 } RRIP_TABLE; 61 62 static int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 63 static int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 64 static int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 65 static void cd9660_rrip_defattr(struct iso_directory_record *isodir, 66 ISO_RRIP_ANALYZE *ana); 67 static void cd9660_rrip_defname(struct iso_directory_record *isodir, 68 ISO_RRIP_ANALYZE *ana); 69 static void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 70 ISO_RRIP_ANALYZE *ana); 71 static int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 72 static int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 73 static int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 74 static int cd9660_rrip_loop(struct iso_directory_record *isodir, 75 ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table); 76 static int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 77 static int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 78 static int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 79 static int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 80 static int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 81 82 /* 83 * POSIX file attribute 84 */ 85 static int 86 cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana) 87 { 88 ana->inop->inode.iso_mode = isonum_733(p->mode); 89 ana->inop->inode.iso_uid = isonum_733(p->uid); 90 ana->inop->inode.iso_gid = isonum_733(p->gid); 91 ana->inop->inode.iso_links = isonum_733(p->links); 92 ana->fields &= ~ISO_SUSP_ATTR; 93 return ISO_SUSP_ATTR; 94 } 95 96 static void 97 cd9660_rrip_defattr(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana) 98 { 99 /* But this is a required field! */ 100 kprintf("RRIP without PX field?\n"); 101 cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 102 } 103 104 /* 105 * Symbolic Links 106 */ 107 static int 108 cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana) 109 { 110 ISO_RRIP_SLINK_COMPONENT *pcomp; 111 ISO_RRIP_SLINK_COMPONENT *pcompe; 112 int error, len, wlen, cont; 113 char *outbuf, *inbuf, *freebuf; 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 freebuf = NULL; 121 122 /* 123 * Gathering a Symbolic name from each component with path 124 */ 125 for (; 126 pcomp < pcompe; 127 pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 128 + isonum_711(pcomp->clen))) { 129 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 143 case ISO_SUSP_CFLAG_CURRENT: 144 /* Inserting Current */ 145 wlen = 1; 146 break; 147 148 case ISO_SUSP_CFLAG_PARENT: 149 /* Inserting Parent */ 150 wlen = 2; 151 break; 152 153 case ISO_SUSP_CFLAG_ROOT: 154 /* Inserting slash for ROOT */ 155 /* start over from beginning(?) */ 156 outbuf -= len; 157 len = 0; 158 break; 159 160 case ISO_SUSP_CFLAG_VOLROOT: 161 /* Inserting a mount point i.e. "/cdrom" */ 162 /* same as above */ 163 outbuf -= len; 164 len = 0; 165 error = cache_fullpath(NULL, &ana->imp->im_mountp->mnt_ncmountpt, NULL, 166 &inbuf, &freebuf, 0); 167 if (error) 168 goto bad; 169 wlen = strlen(inbuf); 170 break; 171 172 case ISO_SUSP_CFLAG_HOST: 173 /* Inserting hostname i.e. "kurt.tools.de" */ 174 inbuf = hostname; 175 wlen = strlen(hostname); 176 break; 177 178 case ISO_SUSP_CFLAG_CONTINUE: 179 cont = 1; 180 /* FALLTHROUGH */ 181 case 0: 182 /* Inserting component */ 183 wlen = isonum_711(pcomp->clen); 184 inbuf = pcomp->name; 185 break; 186 default: 187 kprintf("RRIP with incorrect flags?"); 188 wlen = ana->maxlen + 1; 189 break; 190 } 191 192 if (len + wlen > ana->maxlen) 193 goto bad; 194 195 bcopy(inbuf,outbuf,wlen); 196 outbuf += wlen; 197 len += wlen; 198 199 if (freebuf != NULL) { 200 kfree(freebuf, M_TEMP); 201 freebuf = NULL; 202 } 203 } 204 ana->outbuf = outbuf; 205 *ana->outlen = len; 206 ana->cont = cont; 207 208 if (!isonum_711(p->flags)) { 209 ana->fields &= ~ISO_SUSP_SLINK; 210 return ISO_SUSP_SLINK; 211 } 212 return 0; 213 214 bad: 215 if (freebuf != NULL) 216 kfree(freebuf, M_TEMP); 217 ana->cont = 1; 218 ana->fields = 0; 219 ana->outbuf -= *ana->outlen; 220 *ana->outlen = 0; 221 return 0; 222 } 223 224 /* 225 * Alternate name 226 */ 227 static int 228 cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana) 229 { 230 char *inbuf; 231 int wlen; 232 int cont; 233 234 inbuf = ".."; 235 wlen = 0; 236 cont = 0; 237 238 switch (*p->flags) { 239 case ISO_SUSP_CFLAG_CURRENT: 240 /* Inserting Current */ 241 wlen = 1; 242 break; 243 244 case ISO_SUSP_CFLAG_PARENT: 245 /* Inserting Parent */ 246 wlen = 2; 247 break; 248 249 case ISO_SUSP_CFLAG_HOST: 250 /* Inserting hostname i.e. "kurt.tools.de" */ 251 inbuf = hostname; 252 wlen = strlen(hostname); 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 kprintf("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 bcopy(inbuf,ana->outbuf,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(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana) 290 { 291 isofntrans(isodir->name,isonum_711(isodir->name_len), 292 ana->outbuf,ana->outlen, 293 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level, 294 ana->imp->im_flags, ana->imp->im_d2l); 295 switch (*ana->outbuf) { 296 default: 297 break; 298 case 1: 299 *ana->outlen = 2; 300 /* FALLTHROUGH */ 301 case 0: 302 /* outlen is 1 already */ 303 strcpy(ana->outbuf,".."); 304 break; 305 } 306 } 307 308 /* 309 * Parent or Child Link 310 */ 311 static int 312 cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana) 313 { 314 *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 315 ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 316 return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 317 } 318 319 /* 320 * Relocated directory 321 */ 322 static int 323 cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana) 324 { 325 /* special hack to make caller aware of RE field */ 326 *ana->outlen = 0; 327 ana->fields = 0; 328 return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 329 } 330 331 static int 332 cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana) 333 { 334 u_char *ptime; 335 336 ptime = p->time; 337 338 /* Check a format of time stamp (7bytes/17bytes) */ 339 if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 340 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 341 ptime += 7; 342 343 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 344 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 345 ISO_FTYPE_RRIP); 346 ptime += 7; 347 } else 348 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 349 350 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 351 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 352 ISO_FTYPE_RRIP); 353 ptime += 7; 354 } else 355 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 356 357 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 358 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 359 ISO_FTYPE_RRIP); 360 else 361 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 362 363 } else { 364 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 365 ptime += 17; 366 367 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 368 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 369 ptime += 17; 370 } else 371 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 372 373 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 374 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 375 ptime += 17; 376 } else 377 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 378 379 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 380 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 381 else 382 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 383 384 } 385 ana->fields &= ~ISO_SUSP_TSTAMP; 386 return ISO_SUSP_TSTAMP; 387 } 388 389 static void 390 cd9660_rrip_deftstamp(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana) 391 { 392 cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 393 } 394 395 /* 396 * POSIX device modes 397 */ 398 static int 399 cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana) 400 { 401 u_int high, low; 402 403 high = isonum_733(p->dev_t_high); 404 low = isonum_733(p->dev_t_low); 405 406 if (high == 0) 407 ana->inop->inode.iso_rdev = makeudev(umajor(low), uminor(low)); 408 else 409 ana->inop->inode.iso_rdev = makeudev(high, uminor(low)); 410 ana->fields &= ~ISO_SUSP_DEVICE; 411 return ISO_SUSP_DEVICE; 412 } 413 414 /* 415 * Flag indicating 416 */ 417 static int 418 cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana) 419 { 420 ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 421 /* special handling of RE field */ 422 if (ana->fields&ISO_SUSP_RELDIR) 423 return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 424 425 return ISO_SUSP_IDFLAG; 426 } 427 428 /* 429 * Continuation pointer 430 */ 431 static int 432 cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana) 433 { 434 ana->iso_ce_blk = isonum_733(p->location); 435 ana->iso_ce_off = isonum_733(p->offset); 436 ana->iso_ce_len = isonum_733(p->length); 437 return ISO_SUSP_CONT; 438 } 439 440 /* 441 * System Use end 442 */ 443 static int 444 cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana) 445 { 446 return ISO_SUSP_STOP; 447 } 448 449 /* 450 * Extension reference 451 */ 452 static int 453 cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana) 454 { 455 if (isonum_711(p->len_id) != 10 456 || bcmp((char *)p + 8,"RRIP_1991A",10) 457 || isonum_711(p->version) != 1) 458 return 0; 459 ana->fields &= ~ISO_SUSP_EXTREF; 460 return ISO_SUSP_EXTREF; 461 } 462 463 static int 464 cd9660_rrip_loop(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana, 465 RRIP_TABLE *table) 466 { 467 RRIP_TABLE *ptable; 468 ISO_SUSP_HEADER *phead; 469 ISO_SUSP_HEADER *pend; 470 struct buf *bp = NULL; 471 char *pwhead; 472 u_short c; 473 int result; 474 475 /* 476 * Note: If name length is odd, 477 * it will be padding 1 byte after the name 478 */ 479 pwhead = isodir->name + isonum_711(isodir->name_len); 480 if (!(isonum_711(isodir->name_len)&1)) 481 pwhead++; 482 isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL, 483 ana->imp->im_flags, ana->imp->im_d2l); 484 485 /* If it's not the '.' entry of the root dir obey SP field */ 486 if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent) 487 pwhead += ana->imp->rr_skip; 488 else 489 pwhead += ana->imp->rr_skip0; 490 491 phead = (ISO_SUSP_HEADER *)pwhead; 492 pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 493 494 result = 0; 495 while (1) { 496 ana->iso_ce_len = 0; 497 /* 498 * Note: "pend" should be more than one SUSP header 499 */ 500 while (pend >= phead + 1) { 501 if (isonum_711(phead->version) == 1) { 502 for (ptable = table; ptable->func; ptable++) { 503 if (*phead->type == *ptable->type 504 && phead->type[1] == ptable->type[1]) { 505 result |= ptable->func(phead,ana); 506 break; 507 } 508 } 509 if (!ana->fields) 510 break; 511 } 512 if (result&ISO_SUSP_STOP) { 513 result &= ~ISO_SUSP_STOP; 514 break; 515 } 516 /* plausibility check */ 517 if (isonum_711(phead->length) < sizeof(*phead)) 518 break; 519 /* 520 * move to next SUSP 521 * Hopefully this works with newer versions, too 522 */ 523 phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length)); 524 } 525 526 if (ana->fields && ana->iso_ce_len) { 527 if (ana->iso_ce_blk >= ana->imp->volume_space_size 528 || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size 529 || bread(ana->imp->im_devvp, 530 lblktooff(ana->imp, ana->iso_ce_blk), 531 ana->imp->logical_block_size, &bp)) 532 /* what to do now? */ 533 break; 534 phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off); 535 pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 536 } else 537 break; 538 } 539 if (bp) 540 brelse(bp); 541 /* 542 * If we don't find the Basic SUSP stuffs, just set default value 543 * (attribute/time stamp) 544 */ 545 for (ptable = table; ptable->func2; ptable++) 546 if (!(ptable->result&result)) 547 ptable->func2(isodir,ana); 548 549 return result; 550 } 551 552 /* 553 * Get Attributes. 554 */ 555 /* 556 * XXX the casts are bogus but will do for now. 557 */ 558 #define BC (rrt_func_t *) 559 static RRIP_TABLE rrip_table_analyze[] = { 560 { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 561 { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 562 { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 563 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 564 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 565 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 566 { "", 0, 0, 0 } 567 }; 568 569 int 570 cd9660_rrip_analyze(struct iso_directory_record *isodir, struct iso_node *inop, 571 struct iso_mnt *imp) 572 { 573 ISO_RRIP_ANALYZE analyze; 574 575 analyze.inop = inop; 576 analyze.imp = imp; 577 analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 578 579 return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 580 } 581 582 /* 583 * Get Alternate Name. 584 */ 585 static RRIP_TABLE rrip_table_getname[] = { 586 { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 587 { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 588 { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 589 { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 590 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 591 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 592 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 593 { "", 0, 0, 0 } 594 }; 595 596 int 597 cd9660_rrip_getname(struct iso_directory_record *isodir, char *outbuf, 598 u_short *outlen, ino_t *inump, struct iso_mnt *imp) 599 { 600 ISO_RRIP_ANALYZE analyze; 601 RRIP_TABLE *tab; 602 u_short c; 603 604 analyze.outbuf = outbuf; 605 analyze.outlen = outlen; 606 analyze.maxlen = NAME_MAX; 607 analyze.inump = inump; 608 analyze.imp = imp; 609 analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 610 *outlen = 0; 611 612 isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 613 imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l); 614 tab = rrip_table_getname; 615 if (c == 0 || c == 1) { 616 cd9660_rrip_defname(isodir,&analyze); 617 618 analyze.fields &= ~ISO_SUSP_ALTNAME; 619 tab++; 620 } 621 622 return cd9660_rrip_loop(isodir,&analyze,tab); 623 } 624 625 /* 626 * Get Symbolic Link. 627 */ 628 static RRIP_TABLE rrip_table_getsymname[] = { 629 { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 630 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 631 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 632 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 633 { "", 0, 0, 0 } 634 }; 635 636 int 637 cd9660_rrip_getsymname(struct iso_directory_record *isodir, char *outbuf, 638 u_short *outlen, struct iso_mnt *imp) 639 { 640 ISO_RRIP_ANALYZE analyze; 641 642 analyze.outbuf = outbuf; 643 analyze.outlen = outlen; 644 *outlen = 0; 645 analyze.maxlen = MAXPATHLEN; 646 analyze.cont = 1; /* don't start with a slash */ 647 analyze.imp = imp; 648 analyze.fields = ISO_SUSP_SLINK; 649 650 return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 651 } 652 653 static RRIP_TABLE rrip_table_extref[] = { 654 { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 655 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 656 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 657 { "", 0, 0, 0 } 658 }; 659 660 /* 661 * Check for Rock Ridge Extension and return offset of its fields. 662 * Note: We insist on the ER field. 663 */ 664 int 665 cd9660_rrip_offset(struct iso_directory_record *isodir, struct iso_mnt *imp) 666 { 667 ISO_RRIP_OFFSET *p; 668 ISO_RRIP_ANALYZE analyze; 669 670 imp->rr_skip0 = 0; 671 p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 672 if (bcmp(p,"SP\7\1\276\357",6)) { 673 /* Maybe, it's a CDROM XA disc? */ 674 imp->rr_skip0 = 15; 675 p = (ISO_RRIP_OFFSET *)((char *)p + 15); 676 if (bcmp(p,"SP\7\1\276\357",6)) 677 return -1; 678 } 679 680 analyze.imp = imp; 681 analyze.fields = ISO_SUSP_EXTREF; 682 if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 683 return -1; 684 685 return isonum_711(p->skip); 686 } 687