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