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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)cd9660_rrip.c 8.2 (Berkeley) 1/23/94 39 * $Id$ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/namei.h> 44 #include <sys/buf.h> 45 #include <sys/file.h> 46 #include <sys/vnode.h> 47 #include <sys/mount.h> 48 #include <sys/kernel.h> 49 #include <sys/stat.h> 50 #include <sys/types.h> 51 52 #include <sys/time.h> 53 54 #include <isofs/cd9660/iso.h> 55 #include <isofs/cd9660/cd9660_node.h> 56 #include <isofs/cd9660/cd9660_rrip.h> 57 #include <isofs/cd9660/iso_rrip.h> 58 59 /* 60 * POSIX file attribute 61 */ 62 static int 63 cd9660_rrip_attr(p,ana) 64 ISO_RRIP_ATTR *p; 65 ISO_RRIP_ANALYZE *ana; 66 { 67 ana->inop->inode.iso_mode = isonum_731(p->mode_l); 68 ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l); 69 ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l); 70 ana->inop->inode.iso_links = isonum_731(p->links_l); 71 ana->fields &= ~ISO_SUSP_ATTR; 72 return ISO_SUSP_ATTR; 73 } 74 75 static void 76 cd9660_rrip_defattr(isodir,ana) 77 struct iso_directory_record *isodir; 78 ISO_RRIP_ANALYZE *ana; 79 { 80 /* But this is a required field! */ 81 printf("RRIP without PX field?\n"); 82 cd9660_defattr(isodir,ana->inop,NULL); 83 } 84 85 /* 86 * Symbolic Links 87 */ 88 static int 89 cd9660_rrip_slink(p,ana) 90 ISO_RRIP_SLINK *p; 91 ISO_RRIP_ANALYZE *ana; 92 { 93 register ISO_RRIP_SLINK_COMPONENT *pcomp; 94 register ISO_RRIP_SLINK_COMPONENT *pcompe; 95 int len, wlen, cont; 96 char *outbuf, *inbuf; 97 98 pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 99 pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); 100 len = *ana->outlen; 101 outbuf = ana->outbuf; 102 cont = ana->cont; 103 104 /* 105 * Gathering a Symbolic name from each component with path 106 */ 107 for (; 108 pcomp < pcompe; 109 pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ 110 + isonum_711(pcomp->clen))) { 111 112 if (!cont) { 113 if (len < ana->maxlen) { 114 len++; 115 *outbuf++ = '/'; 116 } 117 } 118 cont = 0; 119 120 inbuf = ".."; 121 wlen = 0; 122 123 switch (*pcomp->cflag) { 124 125 case ISO_SUSP_CFLAG_CURRENT: 126 /* Inserting Current */ 127 wlen = 1; 128 break; 129 130 case ISO_SUSP_CFLAG_PARENT: 131 /* Inserting Parent */ 132 wlen = 2; 133 break; 134 135 case ISO_SUSP_CFLAG_ROOT: 136 /* Inserting slash for ROOT */ 137 /* start over from beginning(?) */ 138 outbuf -= len; 139 len = 0; 140 break; 141 142 case ISO_SUSP_CFLAG_VOLROOT: 143 /* Inserting a mount point i.e. "/cdrom" */ 144 /* same as above */ 145 outbuf -= len; 146 len = 0; 147 inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname; 148 wlen = strlen(inbuf); 149 break; 150 151 case ISO_SUSP_CFLAG_HOST: 152 /* Inserting hostname i.e. "kurt.tools.de" */ 153 inbuf = hostname; 154 wlen = hostnamelen; 155 break; 156 157 case ISO_SUSP_CFLAG_CONTINUE: 158 cont = 1; 159 /* fall thru */ 160 case 0: 161 /* Inserting component */ 162 wlen = isonum_711(pcomp->clen); 163 inbuf = pcomp->name; 164 break; 165 default: 166 printf("RRIP with incorrect flags?"); 167 wlen = ana->maxlen + 1; 168 break; 169 } 170 171 if (len + wlen > ana->maxlen) { 172 /* indicate error to caller */ 173 ana->cont = 1; 174 ana->fields = 0; 175 ana->outbuf -= *ana->outlen; 176 *ana->outlen = 0; 177 return 0; 178 } 179 180 bcopy(inbuf,outbuf,wlen); 181 outbuf += wlen; 182 len += wlen; 183 184 } 185 ana->outbuf = outbuf; 186 *ana->outlen = len; 187 ana->cont = cont; 188 189 if (!isonum_711(p->flags)) { 190 ana->fields &= ~ISO_SUSP_SLINK; 191 return ISO_SUSP_SLINK; 192 } 193 return 0; 194 } 195 196 /* 197 * Alternate name 198 */ 199 static int 200 cd9660_rrip_altname(p,ana) 201 ISO_RRIP_ALTNAME *p; 202 ISO_RRIP_ANALYZE *ana; 203 { 204 char *inbuf; 205 int wlen; 206 int cont; 207 208 inbuf = ".."; 209 wlen = 0; 210 cont = 0; 211 212 switch (*p->flags) { 213 case ISO_SUSP_CFLAG_CURRENT: 214 /* Inserting Current */ 215 wlen = 1; 216 break; 217 218 case ISO_SUSP_CFLAG_PARENT: 219 /* Inserting Parent */ 220 wlen = 2; 221 break; 222 223 case ISO_SUSP_CFLAG_HOST: 224 /* Inserting hostname i.e. "kurt.tools.de" */ 225 inbuf = hostname; 226 wlen = hostnamelen; 227 break; 228 229 case ISO_SUSP_CFLAG_CONTINUE: 230 cont = 1; 231 /* fall thru */ 232 case 0: 233 /* Inserting component */ 234 wlen = isonum_711(p->h.length) - 5; 235 inbuf = (char *)p + 5; 236 break; 237 238 default: 239 printf("RRIP with incorrect NM flags?\n"); 240 wlen = ana->maxlen + 1; 241 break; 242 } 243 244 if ((*ana->outlen += wlen) > ana->maxlen) { 245 /* treat as no name field */ 246 ana->fields &= ~ISO_SUSP_ALTNAME; 247 ana->outbuf -= *ana->outlen - wlen; 248 *ana->outlen = 0; 249 return 0; 250 } 251 252 bcopy(inbuf,ana->outbuf,wlen); 253 ana->outbuf += wlen; 254 255 if (!cont) { 256 ana->fields &= ~ISO_SUSP_ALTNAME; 257 return ISO_SUSP_ALTNAME; 258 } 259 return 0; 260 } 261 262 static void 263 cd9660_rrip_defname(isodir,ana) 264 struct iso_directory_record *isodir; 265 ISO_RRIP_ANALYZE *ana; 266 { 267 strcpy(ana->outbuf,".."); 268 switch (*isodir->name) { 269 default: 270 isofntrans(isodir->name,isonum_711(isodir->name_len), 271 ana->outbuf,ana->outlen, 272 1,isonum_711(isodir->flags)&4); 273 break; 274 case 0: 275 *ana->outlen = 1; 276 break; 277 case 1: 278 *ana->outlen = 2; 279 break; 280 } 281 } 282 283 /* 284 * Parent or Child Link 285 */ 286 static int 287 cd9660_rrip_pclink(p,ana) 288 ISO_RRIP_CLINK *p; 289 ISO_RRIP_ANALYZE *ana; 290 { 291 *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; 292 ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK); 293 return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK; 294 } 295 296 /* 297 * Relocated directory 298 */ 299 static int 300 cd9660_rrip_reldir(p,ana) 301 ISO_RRIP_RELDIR *p; 302 ISO_RRIP_ANALYZE *ana; 303 { 304 /* special hack to make caller aware of RE field */ 305 *ana->outlen = 0; 306 ana->fields = 0; 307 return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 308 } 309 310 static int 311 cd9660_rrip_tstamp(p,ana) 312 ISO_RRIP_TSTAMP *p; 313 ISO_RRIP_ANALYZE *ana; 314 { 315 unsigned char *ptime; 316 317 ptime = p->time; 318 319 /* Check a format of time stamp (7bytes/17bytes) */ 320 if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 321 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 322 ptime += 7; 323 324 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 325 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime); 326 ptime += 7; 327 } else 328 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval)); 329 330 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 331 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime); 332 ptime += 7; 333 } else 334 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 335 336 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 337 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime); 338 else 339 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 340 341 } else { 342 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 343 ptime += 17; 344 345 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 346 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 347 ptime += 17; 348 } else 349 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval)); 350 351 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 352 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 353 ptime += 17; 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_conv17(ptime,&ana->inop->inode.iso_ctime); 359 else 360 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 361 362 } 363 ana->fields &= ~ISO_SUSP_TSTAMP; 364 return ISO_SUSP_TSTAMP; 365 } 366 367 static void 368 cd9660_rrip_deftstamp(isodir,ana) 369 struct iso_directory_record *isodir; 370 ISO_RRIP_ANALYZE *ana; 371 { 372 cd9660_deftstamp(isodir,ana->inop,NULL); 373 } 374 375 /* 376 * POSIX device modes 377 */ 378 static int 379 cd9660_rrip_device(p,ana) 380 ISO_RRIP_DEVICE *p; 381 ISO_RRIP_ANALYZE *ana; 382 { 383 unsigned high, low; 384 385 high = isonum_733(p->dev_t_high_l); 386 low = isonum_733(p->dev_t_low_l); 387 388 if ( high == 0 ) { 389 ana->inop->inode.iso_rdev = makedev( major(low), minor(low) ); 390 } else { 391 ana->inop->inode.iso_rdev = makedev( high, minor(low) ); 392 } 393 ana->fields &= ~ISO_SUSP_DEVICE; 394 return ISO_SUSP_DEVICE; 395 } 396 397 /* 398 * Flag indicating 399 */ 400 static int 401 cd9660_rrip_idflag(p,ana) 402 ISO_RRIP_IDFLAG *p; 403 ISO_RRIP_ANALYZE *ana; 404 { 405 ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 406 /* special handling of RE field */ 407 if (ana->fields&ISO_SUSP_RELDIR) 408 return cd9660_rrip_reldir(p,ana); 409 410 return ISO_SUSP_IDFLAG; 411 } 412 413 /* 414 * Continuation pointer 415 */ 416 static int 417 cd9660_rrip_cont(p,ana) 418 ISO_RRIP_CONT *p; 419 ISO_RRIP_ANALYZE *ana; 420 { 421 ana->iso_ce_blk = isonum_733(p->location); 422 ana->iso_ce_off = isonum_733(p->offset); 423 ana->iso_ce_len = isonum_733(p->length); 424 return ISO_SUSP_CONT; 425 } 426 427 /* 428 * System Use end 429 */ 430 static int 431 cd9660_rrip_stop(p,ana) 432 ISO_SUSP_HEADER *p; 433 ISO_RRIP_ANALYZE *ana; 434 { 435 /* stop analyzing */ 436 ana->fields = 0; 437 return ISO_SUSP_STOP; 438 } 439 440 /* 441 * Extension reference 442 */ 443 static int 444 cd9660_rrip_extref(p,ana) 445 ISO_RRIP_EXTREF *p; 446 ISO_RRIP_ANALYZE *ana; 447 { 448 if (isonum_711(p->len_id) != 10 449 || bcmp((char *)p + 8,"RRIP_1991A",10) 450 || isonum_711(p->version) != 1) 451 return 0; 452 ana->fields &= ~ISO_SUSP_EXTREF; 453 return ISO_SUSP_EXTREF; 454 } 455 456 typedef struct { 457 char type[2]; 458 int (*func)(); 459 void (*func2)(); 460 int result; 461 } RRIP_TABLE; 462 463 static int 464 cd9660_rrip_loop(isodir,ana,table) 465 struct iso_directory_record *isodir; 466 ISO_RRIP_ANALYZE *ana; 467 RRIP_TABLE *table; 468 { 469 register RRIP_TABLE *ptable; 470 register ISO_SUSP_HEADER *phead; 471 register ISO_SUSP_HEADER *pend; 472 struct buf *bp = NULL; 473 int i; 474 char *pwhead; 475 int result; 476 477 /* 478 * Note: If name length is odd, 479 * it will be padding 1 byte after the name 480 */ 481 pwhead = isodir->name + isonum_711(isodir->name_len); 482 if (!(isonum_711(isodir->name_len)&1)) 483 pwhead++; 484 485 /* If it's not the '.' entry of the root dir obey SP field */ 486 if (*isodir->name != 0 487 || isonum_733(isodir->extent) != ana->imp->root_extent) 488 pwhead += ana->imp->rr_skip; 489 else 490 pwhead += ana->imp->rr_skip0; 491 492 phead = (ISO_SUSP_HEADER *)pwhead; 493 pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); 494 495 result = 0; 496 while (1) { 497 ana->iso_ce_len = 0; 498 /* 499 * Note: "pend" should be more than one SUSP header 500 */ 501 while (pend >= phead + 1) { 502 if (isonum_711(phead->version) == 1) { 503 for (ptable = table; ptable->func; ptable++) { 504 if (*phead->type == *ptable->type 505 && phead->type[1] == ptable->type[1]) { 506 result |= ptable->func(phead,ana); 507 break; 508 } 509 } 510 if (!ana->fields) 511 break; 512 } 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 > ana->imp->logical_block_size 523 || bread(ana->imp->im_devvp, 524 ana->iso_ce_blk * ana->imp->logical_block_size / DEV_BSIZE, 525 ana->imp->logical_block_size,NOCRED,&bp)) 526 /* what to do now? */ 527 break; 528 phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off); 529 pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len); 530 } else 531 break; 532 } 533 if (bp) 534 brelse(bp); 535 /* 536 * If we don't find the Basic SUSP stuffs, just set default value 537 * ( attribute/time stamp ) 538 */ 539 for (ptable = table; ptable->func2; ptable++) 540 if (!(ptable->result&result)) 541 ptable->func2(isodir,ana); 542 543 return result; 544 } 545 546 static RRIP_TABLE rrip_table_analyze[] = { 547 { "PX", cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 548 { "TF", cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 549 { "PN", cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 550 { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 551 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 552 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 553 { "", 0, 0, 0 } 554 }; 555 556 int 557 cd9660_rrip_analyze(isodir,inop,imp) 558 struct iso_directory_record *isodir; 559 struct iso_node *inop; 560 struct iso_mnt *imp; 561 { 562 ISO_RRIP_ANALYZE analyze; 563 564 analyze.inop = inop; 565 analyze.imp = imp; 566 analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 567 568 return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 569 } 570 571 /* 572 * Get Alternate Name from 'AL' record 573 * If either no AL record or 0 length, 574 * it will be return the translated ISO9660 name, 575 */ 576 static RRIP_TABLE rrip_table_getname[] = { 577 { "NM", cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 578 { "CL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 579 { "PL", cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 580 { "RE", cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 581 { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 582 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 583 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 584 { "", 0, 0, 0 } 585 }; 586 587 int 588 cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 589 struct iso_directory_record *isodir; 590 char *outbuf; 591 u_short *outlen; 592 ino_t *inump; 593 struct iso_mnt *imp; 594 { 595 ISO_RRIP_ANALYZE analyze; 596 RRIP_TABLE *tab; 597 598 analyze.outbuf = outbuf; 599 analyze.outlen = outlen; 600 analyze.maxlen = NAME_MAX; 601 analyze.inump = inump; 602 analyze.imp = imp; 603 analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 604 *outlen = 0; 605 606 tab = rrip_table_getname; 607 if (*isodir->name == 0 608 || *isodir->name == 1) { 609 cd9660_rrip_defname(isodir,&analyze); 610 611 analyze.fields &= ~ISO_SUSP_ALTNAME; 612 tab++; 613 } 614 615 return cd9660_rrip_loop(isodir,&analyze,tab); 616 } 617 618 /* 619 * Get Symbolic Name from 'SL' record 620 * 621 * Note: isodir should contains SL record! 622 */ 623 static RRIP_TABLE rrip_table_getsymname[] = { 624 { "SL", cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 625 { "RR", cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 626 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 627 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 628 { "", 0, 0, 0 } 629 }; 630 631 int 632 cd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 633 struct iso_directory_record *isodir; 634 char *outbuf; 635 u_short *outlen; 636 struct iso_mnt *imp; 637 { 638 ISO_RRIP_ANALYZE analyze; 639 640 analyze.outbuf = outbuf; 641 analyze.outlen = outlen; 642 *outlen = 0; 643 analyze.maxlen = MAXPATHLEN; 644 analyze.cont = 1; /* don't start with a slash */ 645 analyze.imp = imp; 646 analyze.fields = ISO_SUSP_SLINK; 647 648 return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 649 } 650 651 static RRIP_TABLE rrip_table_extref[] = { 652 { "ER", cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 653 { "CE", cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 654 { "ST", cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 655 { "", 0, 0, 0 } 656 }; 657 658 /* 659 * Check for Rock Ridge Extension and return offset of its fields. 660 * Note: We require the ER field. 661 */ 662 int 663 cd9660_rrip_offset(isodir,imp) 664 struct iso_directory_record *isodir; 665 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