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