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