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