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