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