cd9660_rrip.c revision 92765
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.6 (Berkeley) 12/5/94 39 * $FreeBSD: head/sys/fs/cd9660/cd9660_rrip.c 92765 2002-03-20 07:51:46Z alfred $ 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/bio.h> 45#include <sys/buf.h> 46#include <sys/vnode.h> 47#include <sys/mount.h> 48#include <sys/kernel.h> 49 50#include <isofs/cd9660/iso.h> 51#include <isofs/cd9660/cd9660_node.h> 52#include <isofs/cd9660/cd9660_rrip.h> 53#include <isofs/cd9660/iso_rrip.h> 54 55typedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); 56 57typedef struct { 58 char type[2]; 59 rrt_func_t *func; 60 void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); 61 int result; 62} RRIP_TABLE; 63 64static int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); 65static int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); 66static int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); 67static void cd9660_rrip_defattr(struct iso_directory_record *isodir, 68 ISO_RRIP_ANALYZE *ana); 69static void cd9660_rrip_defname(struct iso_directory_record *isodir, 70 ISO_RRIP_ANALYZE *ana); 71static void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, 72 ISO_RRIP_ANALYZE *ana); 73static int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); 74static int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); 75static int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); 76static int cd9660_rrip_loop(struct iso_directory_record *isodir, 77 ISO_RRIP_ANALYZE *ana, 78 RRIP_TABLE *table); 79static int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); 80static int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); 81static int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); 82static int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); 83static int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); 84 85/* 86 * POSIX file attribute 87 */ 88static int 89cd9660_rrip_attr(p,ana) 90 ISO_RRIP_ATTR *p; 91 ISO_RRIP_ANALYZE *ana; 92{ 93 ana->inop->inode.iso_mode = isonum_733(p->mode); 94 ana->inop->inode.iso_uid = isonum_733(p->uid); 95 ana->inop->inode.iso_gid = isonum_733(p->gid); 96 ana->inop->inode.iso_links = isonum_733(p->links); 97 ana->fields &= ~ISO_SUSP_ATTR; 98 return ISO_SUSP_ATTR; 99} 100 101static void 102cd9660_rrip_defattr(isodir,ana) 103 struct iso_directory_record *isodir; 104 ISO_RRIP_ANALYZE *ana; 105{ 106 /* But this is a required field! */ 107 printf("RRIP without PX field?\n"); 108 cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 109} 110 111/* 112 * Symbolic Links 113 */ 114static int 115cd9660_rrip_slink(p,ana) 116 ISO_RRIP_SLINK *p; 117 ISO_RRIP_ANALYZE *ana; 118{ 119 register ISO_RRIP_SLINK_COMPONENT *pcomp; 120 register ISO_RRIP_SLINK_COMPONENT *pcompe; 121 int len, wlen, cont; 122 char *outbuf, *inbuf; 123 124 pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; 125 pcompe = (ISO_RRIP_SLINK_COMPONENT *)((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 = strlen(hostname); 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 bcopy(inbuf,outbuf,wlen); 207 outbuf += wlen; 208 len += wlen; 209 210 } 211 ana->outbuf = outbuf; 212 *ana->outlen = len; 213 ana->cont = cont; 214 215 if (!isonum_711(p->flags)) { 216 ana->fields &= ~ISO_SUSP_SLINK; 217 return ISO_SUSP_SLINK; 218 } 219 return 0; 220} 221 222/* 223 * Alternate name 224 */ 225static int 226cd9660_rrip_altname(p,ana) 227 ISO_RRIP_ALTNAME *p; 228 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 /* fall thru */ 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 printf("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 288static void 289cd9660_rrip_defname(isodir,ana) 290 struct iso_directory_record *isodir; 291 ISO_RRIP_ANALYZE *ana; 292{ 293 isofntrans(isodir->name,isonum_711(isodir->name_len), 294 ana->outbuf,ana->outlen, 295 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level); 296 switch (*ana->outbuf) { 297 default: 298 break; 299 case 1: 300 *ana->outlen = 2; 301 /* FALL THROUGH */ 302 case 0: 303 /* outlen is 1 already */ 304 strcpy(ana->outbuf,".."); 305 break; 306 } 307} 308 309/* 310 * Parent or Child Link 311 */ 312static int 313cd9660_rrip_pclink(p,ana) 314 ISO_RRIP_CLINK *p; 315 ISO_RRIP_ANALYZE *ana; 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 */ 325static int 326cd9660_rrip_reldir(p,ana) 327 ISO_RRIP_RELDIR *p; 328 ISO_RRIP_ANALYZE *ana; 329{ 330 /* special hack to make caller aware of RE field */ 331 *ana->outlen = 0; 332 ana->fields = 0; 333 return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 334} 335 336static int 337cd9660_rrip_tstamp(p,ana) 338 ISO_RRIP_TSTAMP *p; 339 ISO_RRIP_ANALYZE *ana; 340{ 341 u_char *ptime; 342 343 ptime = p->time; 344 345 /* Check a format of time stamp (7bytes/17bytes) */ 346 if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) { 347 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 348 ptime += 7; 349 350 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 351 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime, 352 ISO_FTYPE_RRIP); 353 ptime += 7; 354 } else 355 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 356 357 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 358 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime, 359 ISO_FTYPE_RRIP); 360 ptime += 7; 361 } else 362 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 363 364 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 365 cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime, 366 ISO_FTYPE_RRIP); 367 else 368 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 369 370 } else { 371 if (*p->flags&ISO_SUSP_TSTAMP_CREAT) 372 ptime += 17; 373 374 if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) { 375 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime); 376 ptime += 17; 377 } else 378 bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec)); 379 380 if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) { 381 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime); 382 ptime += 17; 383 } else 384 ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime; 385 386 if (*p->flags&ISO_SUSP_TSTAMP_ATTR) 387 cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime); 388 else 389 ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime; 390 391 } 392 ana->fields &= ~ISO_SUSP_TSTAMP; 393 return ISO_SUSP_TSTAMP; 394} 395 396static void 397cd9660_rrip_deftstamp(isodir,ana) 398 struct iso_directory_record *isodir; 399 ISO_RRIP_ANALYZE *ana; 400{ 401 cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP); 402} 403 404/* 405 * POSIX device modes 406 */ 407static int 408cd9660_rrip_device(p,ana) 409 ISO_RRIP_DEVICE *p; 410 ISO_RRIP_ANALYZE *ana; 411{ 412 u_int high, low; 413 414 high = isonum_733(p->dev_t_high); 415 low = isonum_733(p->dev_t_low); 416 417 if (high == 0) 418 ana->inop->inode.iso_rdev = makeudev(umajor(low), uminor(low)); 419 else 420 ana->inop->inode.iso_rdev = makeudev(high, uminor(low)); 421 ana->fields &= ~ISO_SUSP_DEVICE; 422 return ISO_SUSP_DEVICE; 423} 424 425/* 426 * Flag indicating 427 */ 428static int 429cd9660_rrip_idflag(p,ana) 430 ISO_RRIP_IDFLAG *p; 431 ISO_RRIP_ANALYZE *ana; 432{ 433 ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */ 434 /* special handling of RE field */ 435 if (ana->fields&ISO_SUSP_RELDIR) 436 return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana); 437 438 return ISO_SUSP_IDFLAG; 439} 440 441/* 442 * Continuation pointer 443 */ 444static int 445cd9660_rrip_cont(p,ana) 446 ISO_RRIP_CONT *p; 447 ISO_RRIP_ANALYZE *ana; 448{ 449 ana->iso_ce_blk = isonum_733(p->location); 450 ana->iso_ce_off = isonum_733(p->offset); 451 ana->iso_ce_len = isonum_733(p->length); 452 return ISO_SUSP_CONT; 453} 454 455/* 456 * System Use end 457 */ 458static int 459cd9660_rrip_stop(p,ana) 460 ISO_SUSP_HEADER *p; 461 ISO_RRIP_ANALYZE *ana; 462{ 463 return ISO_SUSP_STOP; 464} 465 466/* 467 * Extension reference 468 */ 469static int 470cd9660_rrip_extref(p,ana) 471 ISO_RRIP_EXTREF *p; 472 ISO_RRIP_ANALYZE *ana; 473{ 474 if (isonum_711(p->len_id) != 10 475 || bcmp((char *)p + 8,"RRIP_1991A",10) 476 || isonum_711(p->version) != 1) 477 return 0; 478 ana->fields &= ~ISO_SUSP_EXTREF; 479 return ISO_SUSP_EXTREF; 480} 481 482static int 483cd9660_rrip_loop(isodir,ana,table) 484 struct iso_directory_record *isodir; 485 ISO_RRIP_ANALYZE *ana; 486 RRIP_TABLE *table; 487{ 488 register RRIP_TABLE *ptable; 489 register ISO_SUSP_HEADER *phead; 490 register ISO_SUSP_HEADER *pend; 491 struct buf *bp = NULL; 492 char *pwhead; 493 u_char c; 494 int result; 495 496 /* 497 * Note: If name length is odd, 498 * it will be padding 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->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 << 551 (ana->imp->im_bshift - DEV_BSHIFT), 552 ana->imp->logical_block_size, NOCRED, &bp)) 553 /* what to do now? */ 554 break; 555 phead = (ISO_SUSP_HEADER *)(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); 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/* 577 * XXX the casts are bogus but will do for now. 578 */ 579#define BC (rrt_func_t *) 580static RRIP_TABLE rrip_table_analyze[] = { 581 { "PX", BC cd9660_rrip_attr, cd9660_rrip_defattr, ISO_SUSP_ATTR }, 582 { "TF", BC cd9660_rrip_tstamp, cd9660_rrip_deftstamp, ISO_SUSP_TSTAMP }, 583 { "PN", BC cd9660_rrip_device, 0, ISO_SUSP_DEVICE }, 584 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 585 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 586 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 587 { "", 0, 0, 0 } 588}; 589 590int 591cd9660_rrip_analyze(isodir,inop,imp) 592 struct iso_directory_record *isodir; 593 struct iso_node *inop; 594 struct iso_mnt *imp; 595{ 596 ISO_RRIP_ANALYZE analyze; 597 598 analyze.inop = inop; 599 analyze.imp = imp; 600 analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE; 601 602 return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze); 603} 604 605/* 606 * Get Alternate Name. 607 */ 608static RRIP_TABLE rrip_table_getname[] = { 609 { "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME }, 610 { "CL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 611 { "PL", BC cd9660_rrip_pclink, 0, ISO_SUSP_CLINK|ISO_SUSP_PLINK }, 612 { "RE", BC cd9660_rrip_reldir, 0, ISO_SUSP_RELDIR }, 613 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 614 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 615 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 616 { "", 0, 0, 0 } 617}; 618 619int 620cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp) 621 struct iso_directory_record *isodir; 622 char *outbuf; 623 u_short *outlen; 624 ino_t *inump; 625 struct iso_mnt *imp; 626{ 627 ISO_RRIP_ANALYZE analyze; 628 RRIP_TABLE *tab; 629 u_char c; 630 631 analyze.outbuf = outbuf; 632 analyze.outlen = outlen; 633 analyze.maxlen = NAME_MAX; 634 analyze.inump = inump; 635 analyze.imp = imp; 636 analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; 637 *outlen = 0; 638 639 isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), 640 imp->joliet_level, &c); 641 tab = rrip_table_getname; 642 if (c == 0 || c == 1) { 643 cd9660_rrip_defname(isodir,&analyze); 644 645 analyze.fields &= ~ISO_SUSP_ALTNAME; 646 tab++; 647 } 648 649 return cd9660_rrip_loop(isodir,&analyze,tab); 650} 651 652/* 653 * Get Symbolic Link. 654 */ 655static RRIP_TABLE rrip_table_getsymname[] = { 656 { "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK }, 657 { "RR", BC cd9660_rrip_idflag, 0, ISO_SUSP_IDFLAG }, 658 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 659 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 660 { "", 0, 0, 0 } 661}; 662 663int 664cd9660_rrip_getsymname(isodir,outbuf,outlen,imp) 665 struct iso_directory_record *isodir; 666 char *outbuf; 667 u_short *outlen; 668 struct iso_mnt *imp; 669{ 670 ISO_RRIP_ANALYZE analyze; 671 672 analyze.outbuf = outbuf; 673 analyze.outlen = outlen; 674 *outlen = 0; 675 analyze.maxlen = MAXPATHLEN; 676 analyze.cont = 1; /* don't start with a slash */ 677 analyze.imp = imp; 678 analyze.fields = ISO_SUSP_SLINK; 679 680 return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK); 681} 682 683static RRIP_TABLE rrip_table_extref[] = { 684 { "ER", BC cd9660_rrip_extref, 0, ISO_SUSP_EXTREF }, 685 { "CE", BC cd9660_rrip_cont, 0, ISO_SUSP_CONT }, 686 { "ST", BC cd9660_rrip_stop, 0, ISO_SUSP_STOP }, 687 { "", 0, 0, 0 } 688}; 689 690/* 691 * Check for Rock Ridge Extension and return offset of its fields. 692 * Note: We insist on the ER field. 693 */ 694int 695cd9660_rrip_offset(isodir,imp) 696 struct iso_directory_record *isodir; 697 struct iso_mnt *imp; 698{ 699 ISO_RRIP_OFFSET *p; 700 ISO_RRIP_ANALYZE analyze; 701 702 imp->rr_skip0 = 0; 703 p = (ISO_RRIP_OFFSET *)(isodir->name + 1); 704 if (bcmp(p,"SP\7\1\276\357",6)) { 705 /* Maybe, it's a CDROM XA disc? */ 706 imp->rr_skip0 = 15; 707 p = (ISO_RRIP_OFFSET *)((char *)p + 15); 708 if (bcmp(p,"SP\7\1\276\357",6)) 709 return -1; 710 } 711 712 analyze.imp = imp; 713 analyze.fields = ISO_SUSP_EXTREF; 714 if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF)) 715 return -1; 716 717 return isonum_711(p->skip); 718} 719