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