xref: /openbsd-src/sys/isofs/cd9660/cd9660_rrip.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: cd9660_rrip.c,v 1.13 2015/03/14 03:38:50 jsg Exp $	*/
2 /*	$NetBSD: cd9660_rrip.c,v 1.17 1997/01/24 00:27:32 cgd Exp $	*/
3 
4 /*-
5  * Copyright (c) 1993, 1994
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley
9  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
10  * Support code is derived from software contributed to Berkeley
11  * by Atsushi Murai (amurai@spec.co.jp).
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)cd9660_rrip.c	8.6 (Berkeley) 12/5/94
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/namei.h>
43 #include <sys/buf.h>
44 #include <sys/vnode.h>
45 #include <sys/lock.h>
46 #include <sys/mount.h>
47 #include <sys/kernel.h>
48 #include <sys/stat.h>
49 #include <sys/types.h>
50 #include <sys/time.h>
51 
52 #include <isofs/cd9660/iso.h>
53 #include <isofs/cd9660/cd9660_extern.h>
54 #include <isofs/cd9660/cd9660_node.h>
55 #include <isofs/cd9660/cd9660_rrip.h>
56 #include <isofs/cd9660/iso_rrip.h>
57 
58 typedef struct {
59 	char type[2];
60 	int (*func)(void *, ISO_RRIP_ANALYZE *);
61 	void (*func2)(void *, ISO_RRIP_ANALYZE *);
62 	int result;
63 } RRIP_TABLE;
64 
65 static int cd9660_rrip_attr(void *, ISO_RRIP_ANALYZE *);
66 static void cd9660_rrip_defattr(void *, ISO_RRIP_ANALYZE *);
67 static int cd9660_rrip_slink(void *, ISO_RRIP_ANALYZE *);
68 static int cd9660_rrip_altname(void *, ISO_RRIP_ANALYZE *);
69 static void cd9660_rrip_defname(void *, ISO_RRIP_ANALYZE *);
70 static int cd9660_rrip_pclink(void *, ISO_RRIP_ANALYZE *);
71 static int cd9660_rrip_reldir(void *, ISO_RRIP_ANALYZE *);
72 static int cd9660_rrip_tstamp(void *, ISO_RRIP_ANALYZE *);
73 static void cd9660_rrip_deftstamp(void *, ISO_RRIP_ANALYZE *);
74 static int cd9660_rrip_device(void *, ISO_RRIP_ANALYZE *);
75 static int cd9660_rrip_idflag(void *, ISO_RRIP_ANALYZE *);
76 static int cd9660_rrip_cont(void *, ISO_RRIP_ANALYZE *);
77 static int cd9660_rrip_stop(void *, ISO_RRIP_ANALYZE *);
78 static int cd9660_rrip_extref(void *, ISO_RRIP_ANALYZE *);
79 static int cd9660_rrip_loop(struct iso_directory_record *,
80     ISO_RRIP_ANALYZE *, RRIP_TABLE *);
81 /*
82  * POSIX file attribute
83  */
84 static int
85 cd9660_rrip_attr(v, ana)
86 	void *v;
87 	ISO_RRIP_ANALYZE *ana;
88 {
89 	ISO_RRIP_ATTR *p = v;
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 
99 static void
100 cd9660_rrip_defattr(v, ana)
101 	void *v;
102 	ISO_RRIP_ANALYZE *ana;
103 {
104 	struct iso_directory_record *isodir = v;
105 
106 	/* But this is a required field! */
107 	printf("RRIP without PX field?\n");
108 	cd9660_defattr(isodir, ana->inop, NULL);
109 }
110 
111 /*
112  * Symbolic Links
113  */
114 static int
115 cd9660_rrip_slink(v, ana)
116 	void *v;
117 	ISO_RRIP_ANALYZE *ana;
118 {
119 	ISO_RRIP_SLINK  *p = v;
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 =
127 	    (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
128 	len = *ana->outlen;
129 	outbuf = ana->outbuf;
130 	cont = ana->cont;
131 
132 	/*
133 	 * Gathering a Symbolic name from each component with path
134 	 */
135 	for (; pcomp < pcompe;
136 	    pcomp = (ISO_RRIP_SLINK_COMPONENT *)
137 	    ((char *)pcomp + ISO_RRIP_SLSIZ + 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 = hostnamelen;
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 	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  */
225 static int
226 cd9660_rrip_altname(v, ana)
227 	void *v;
228 	ISO_RRIP_ANALYZE *ana;
229 {
230 	ISO_RRIP_ALTNAME *p = v;
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 = hostnamelen;
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 
289 static void
290 cd9660_rrip_defname(v, ana)
291 	void *v;
292 	ISO_RRIP_ANALYZE *ana;
293 {
294 	struct iso_directory_record *isodir = v;
295 
296 	strlcpy(ana->outbuf, "..", ana->maxlen - *ana->outlen);
297 	switch (*isodir->name) {
298 	default:
299 		isofntrans(isodir->name, isonum_711(isodir->name_len),
300 		    ana->outbuf, ana->outlen, 1,
301 		    isonum_711(isodir->flags) & 4, ana->imp->joliet_level);
302 		break;
303 	case 0:
304 		*ana->outlen = 1;
305 		break;
306 	case 1:
307 		*ana->outlen = 2;
308 		break;
309 	}
310 }
311 
312 /*
313  * Parent or Child Link
314  */
315 static int
316 cd9660_rrip_pclink(v, ana)
317 	void *v;
318 	ISO_RRIP_ANALYZE *ana;
319 {
320 	ISO_RRIP_CLINK  *p = v;
321 
322 	*ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
323 	ana->fields &= ~(ISO_SUSP_CLINK | ISO_SUSP_PLINK);
324 	return (*p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK);
325 }
326 
327 /*
328  * Relocated directory
329  */
330 /*ARGSUSED*/
331 static int
332 cd9660_rrip_reldir(v, ana)
333 	void *v;
334 	ISO_RRIP_ANALYZE *ana;
335 {
336 	/* special hack to make caller aware of RE field */
337 	*ana->outlen = 0;
338 	ana->fields = 0;
339 	return (ISO_SUSP_RELDIR | ISO_SUSP_ALTNAME | ISO_SUSP_CLINK |
340 	    ISO_SUSP_PLINK);
341 }
342 
343 static int
344 cd9660_rrip_tstamp(v, ana)
345 	void *v;
346 	ISO_RRIP_ANALYZE *ana;
347 {
348 	ISO_RRIP_TSTAMP *p = v;
349 	u_char *ptime;
350 
351 	ptime = p->time;
352 
353 	/* Check a format of time stamp (7bytes/17bytes) */
354 	if (!(*p->flags & ISO_SUSP_TSTAMP_FORM17)) {
355 		if (*p->flags & ISO_SUSP_TSTAMP_CREAT)
356 			ptime += 7;
357 
358 		if (*p->flags & ISO_SUSP_TSTAMP_MODIFY) {
359 			cd9660_tstamp_conv7(ptime,
360 			    &ana->inop->inode.iso_mtime);
361 			ptime += 7;
362 		} else
363 			bzero(&ana->inop->inode.iso_mtime,
364 			    sizeof(struct timespec));
365 
366 		if (*p->flags & ISO_SUSP_TSTAMP_ACCESS) {
367 			cd9660_tstamp_conv7(ptime,
368 			    &ana->inop->inode.iso_atime);
369 			ptime += 7;
370 		} else
371 			ana->inop->inode.iso_atime =
372 			    ana->inop->inode.iso_mtime;
373 
374 		if (*p->flags & ISO_SUSP_TSTAMP_ATTR)
375 			cd9660_tstamp_conv7(ptime,
376 			    &ana->inop->inode.iso_ctime);
377 		else
378 			ana->inop->inode.iso_ctime =
379 			    ana->inop->inode.iso_mtime;
380 
381 	} else {
382 		if (*p->flags & ISO_SUSP_TSTAMP_CREAT)
383 			ptime += 17;
384 
385 		if (*p->flags & ISO_SUSP_TSTAMP_MODIFY) {
386 			cd9660_tstamp_conv17(ptime,
387 			    &ana->inop->inode.iso_mtime);
388 			ptime += 17;
389 		} else
390 			bzero(&ana->inop->inode.iso_mtime,
391 			    sizeof(struct timespec));
392 
393 		if (*p->flags & ISO_SUSP_TSTAMP_ACCESS) {
394 			cd9660_tstamp_conv17(ptime,
395 			    &ana->inop->inode.iso_atime);
396 			ptime += 17;
397 		} else
398 			ana->inop->inode.iso_atime =
399 			    ana->inop->inode.iso_mtime;
400 
401 		if (*p->flags & ISO_SUSP_TSTAMP_ATTR)
402 			cd9660_tstamp_conv17(ptime,
403 			    &ana->inop->inode.iso_ctime);
404 		else
405 			ana->inop->inode.iso_ctime =
406 			    ana->inop->inode.iso_mtime;
407 
408 	}
409 	ana->fields &= ~ISO_SUSP_TSTAMP;
410 	return (ISO_SUSP_TSTAMP);
411 }
412 
413 static void
414 cd9660_rrip_deftstamp(v, ana)
415 	void *v;
416 	ISO_RRIP_ANALYZE *ana;
417 {
418 	struct iso_directory_record  *isodir = v;
419 
420 	cd9660_deftstamp(isodir, ana->inop, NULL);
421 }
422 
423 /*
424  * POSIX device modes
425  */
426 static int
427 cd9660_rrip_device(v, ana)
428 	void *v;
429 	ISO_RRIP_ANALYZE *ana;
430 {
431 	ISO_RRIP_DEVICE *p = v;
432 	u_int high, low;
433 
434 	high = isonum_733(p->dev_t_high);
435 	low  = isonum_733(p->dev_t_low);
436 
437 	if (high == 0)
438 		ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
439 	else
440 		ana->inop->inode.iso_rdev = makedev(high, minor(low));
441 	ana->fields &= ~ISO_SUSP_DEVICE;
442 	return (ISO_SUSP_DEVICE);
443 }
444 
445 /*
446  * Flag indicating
447  */
448 static int
449 cd9660_rrip_idflag(v, ana)
450 	void *v;
451 	ISO_RRIP_ANALYZE *ana;
452 {
453 	ISO_RRIP_IDFLAG *p = v;
454 
455 	/* don't touch high bits */
456 	ana->fields &= isonum_711(p->flags) | ~0xff;
457 	/* special handling of RE field */
458 	if (ana->fields & ISO_SUSP_RELDIR)
459 		return (cd9660_rrip_reldir(p, ana));
460 
461 	return (ISO_SUSP_IDFLAG);
462 }
463 
464 /*
465  * Continuation pointer
466  */
467 static int
468 cd9660_rrip_cont(v, ana)
469 	void *v;
470 	ISO_RRIP_ANALYZE *ana;
471 {
472 	ISO_RRIP_CONT *p = v;
473 
474 	ana->iso_ce_blk = isonum_733(p->location);
475 	ana->iso_ce_off = isonum_733(p->offset);
476 	ana->iso_ce_len = isonum_733(p->length);
477 	return (ISO_SUSP_CONT);
478 }
479 
480 /*
481  * System Use end
482  */
483 static int
484 cd9660_rrip_stop(v, ana)
485 	void *v;
486 	ISO_RRIP_ANALYZE *ana;
487 {
488 	return (ISO_SUSP_STOP);
489 }
490 
491 /*
492  * Extension reference
493  */
494 static int
495 cd9660_rrip_extref(v, ana)
496 	void *v;
497 	ISO_RRIP_ANALYZE *ana;
498 {
499 	ISO_RRIP_EXTREF *p = v;
500 
501 	if (isonum_711(p->version) != 1)
502 		return (0);
503 	if (isonum_711(p->len_id) != 9 &&
504 	    isonum_711(p->len_id) != 10)
505 		return (0);
506 	if (isonum_711(p->len_id) == 9 &&
507 	    bcmp((char *)p + 8, "IEEE_1282", 9))
508 		return (0);
509 	if (isonum_711(p->len_id) == 10 &&
510 	    bcmp((char *)p + 8, "IEEE_P1282", 10) &&
511 	    bcmp((char *)p + 8, "RRIP_1991A", 10))
512 		return (0);
513 	ana->fields &= ~ISO_SUSP_EXTREF;
514 	return (ISO_SUSP_EXTREF);
515 }
516 
517 
518 static int
519 cd9660_rrip_loop(isodir, ana, table)
520 	struct iso_directory_record *isodir;
521 	ISO_RRIP_ANALYZE *ana;
522 	RRIP_TABLE *table;
523 {
524 	register RRIP_TABLE *ptable;
525 	register ISO_SUSP_HEADER *phead;
526 	register ISO_SUSP_HEADER *pend;
527 	struct buf *bp = NULL;
528 	char *pwhead;
529 	u_char c;
530 	int result;
531 
532 	/*
533 	 * Note: If name length is odd,
534 	 *       it will be padded by 1 byte after the name
535 	 */
536 	pwhead = isodir->name + isonum_711(isodir->name_len);
537 	if (!(isonum_711(isodir->name_len) & 1))
538 		pwhead++;
539 	isochar(isodir->name, pwhead, ana->imp->joliet_level, &c);
540 
541 	/* If it's not the '.' entry of the root dir obey SP field */
542 	if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
543 		pwhead += ana->imp->rr_skip;
544 	else
545 		pwhead += ana->imp->rr_skip0;
546 
547 	phead = (ISO_SUSP_HEADER *)pwhead;
548 	pend =
549 	    (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
550 
551 	result = 0;
552 	while (1) {
553 		ana->iso_ce_len = 0;
554 		/*
555 		 * Note: "pend" should be more than one SUSP header
556 		 */
557 		while (pend >= phead + 1) {
558 			if (isonum_711(phead->version) == 1) {
559 				for (ptable = table; ptable->func; ptable++) {
560 					if (*phead->type == *ptable->type &&
561 					    phead->type[1] == ptable->type[1])
562 					    {
563 						result |=
564 						    ptable->func(phead, ana);
565 						break;
566 					}
567 				}
568 				if (!ana->fields)
569 					break;
570 			}
571 			if (result & ISO_SUSP_STOP) {
572 				result &= ~ISO_SUSP_STOP;
573 				break;
574 			}
575 			/* plausibility check */
576 			if (isonum_711(phead->length) < sizeof(*phead))
577 				break;
578 			/*
579 			 * move to next SUSP
580 			 * Hopefully this works with newer versions, too
581 			 */
582 			phead = (ISO_SUSP_HEADER *)
583 			    ((char *)phead + isonum_711(phead->length));
584 		}
585 
586 		if (ana->fields && ana->iso_ce_len) {
587 			if (ana->iso_ce_blk >= ana->imp->volume_space_size ||
588 			    ana->iso_ce_off + ana->iso_ce_len >
589 			    ana->imp->logical_block_size ||
590 			    bread(ana->imp->im_devvp, ana->iso_ce_blk <<
591 			    (ana->imp->im_bshift - DEV_BSHIFT),
592 			    ana->imp->logical_block_size, &bp))
593 				/* what to do now? */
594 				break;
595 			phead =
596 			    (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
597 			pend = (ISO_SUSP_HEADER *)
598 			    ((char *)phead + ana->iso_ce_len);
599 		} else
600 			break;
601 	}
602 	if (bp)
603 		brelse(bp);
604 	/*
605 	 * If we don't find the Basic SUSP stuffs, just set default value
606 	 *   (attribute/time stamp)
607 	 */
608 	for (ptable = table; ptable->func2; ptable++)
609 		if (!(ptable->result & result))
610 			ptable->func2(isodir, ana);
611 
612 	return (result);
613 }
614 
615 /*
616  * Get Attributes.
617  */
618 static RRIP_TABLE rrip_table_analyze[] = {
619 	{ "PX", cd9660_rrip_attr,	cd9660_rrip_defattr,
620 	    ISO_SUSP_ATTR },
621 	{ "TF", cd9660_rrip_tstamp,	cd9660_rrip_deftstamp,
622 	    ISO_SUSP_TSTAMP },
623 	{ "PN", cd9660_rrip_device,	0,
624 	    ISO_SUSP_DEVICE },
625 	{ "RR", cd9660_rrip_idflag,	0,
626 	    ISO_SUSP_IDFLAG },
627 	{ "CE", cd9660_rrip_cont,	0,
628 	    ISO_SUSP_CONT },
629 	{ "ST", cd9660_rrip_stop,	0,
630 	    ISO_SUSP_STOP },
631 	{ "",	0,			0,
632 	    0 }
633 };
634 
635 int
636 cd9660_rrip_analyze(isodir, inop, imp)
637 	struct iso_directory_record *isodir;
638 	struct iso_node *inop;
639 	struct iso_mnt *imp;
640 {
641 	ISO_RRIP_ANALYZE analyze;
642 
643 	analyze.inop = inop;
644 	analyze.imp = imp;
645 	analyze.fields = ISO_SUSP_ATTR | ISO_SUSP_TSTAMP | ISO_SUSP_DEVICE;
646 
647 	return (cd9660_rrip_loop(isodir, &analyze, rrip_table_analyze));
648 }
649 
650 /*
651  * Get Alternate Name.
652  */
653 static RRIP_TABLE rrip_table_getname[] = {
654 	{ "NM", cd9660_rrip_altname,	cd9660_rrip_defname,
655 	    ISO_SUSP_ALTNAME },
656 	{ "CL", cd9660_rrip_pclink,	0,
657 	    ISO_SUSP_CLINK|ISO_SUSP_PLINK },
658 	{ "PL", cd9660_rrip_pclink,	0,
659 	    ISO_SUSP_CLINK|ISO_SUSP_PLINK },
660 	{ "RE", cd9660_rrip_reldir,	0,
661 	    ISO_SUSP_RELDIR },
662 	{ "RR", cd9660_rrip_idflag,	0,
663 	    ISO_SUSP_IDFLAG },
664 	{ "CE", cd9660_rrip_cont,	0,
665 	    ISO_SUSP_CONT },
666 	{ "ST", cd9660_rrip_stop,	0,
667 	    ISO_SUSP_STOP },
668 	{ "",	0,			0,
669 	    0 }
670 };
671 
672 int
673 cd9660_rrip_getname(isodir, outbuf, outlen, inump, imp)
674 	struct iso_directory_record *isodir;
675 	char *outbuf;
676 	u_short *outlen;
677 	cdino_t *inump;
678 	struct iso_mnt *imp;
679 {
680 	ISO_RRIP_ANALYZE analyze;
681 	RRIP_TABLE *tab;
682 	u_char c;
683 
684 	analyze.outbuf = outbuf;
685 	analyze.outlen = outlen;
686 	analyze.maxlen = NAME_MAX;
687 	analyze.inump = inump;
688 	analyze.imp = imp;
689 	analyze.fields = ISO_SUSP_ALTNAME | ISO_SUSP_RELDIR | ISO_SUSP_CLINK |
690 	    ISO_SUSP_PLINK;
691 	*outlen = 0;
692 
693 	isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
694 	    imp->joliet_level, &c);
695 	tab = rrip_table_getname;
696 	if (c == 0 || c == 1) {
697 		cd9660_rrip_defname(isodir, &analyze);
698 
699 		analyze.fields &= ~ISO_SUSP_ALTNAME;
700 		tab++;
701 	}
702 
703 	return (cd9660_rrip_loop(isodir, &analyze, tab));
704 }
705 
706 /*
707  * Get Symbolic Link.
708  */
709 static RRIP_TABLE rrip_table_getsymname[] = {
710 	{ "SL", cd9660_rrip_slink,	0,	ISO_SUSP_SLINK },
711 	{ "RR", cd9660_rrip_idflag,	0,	ISO_SUSP_IDFLAG },
712 	{ "CE", cd9660_rrip_cont,	0,	ISO_SUSP_CONT },
713 	{ "ST", cd9660_rrip_stop,	0,	ISO_SUSP_STOP },
714 	{ "",	0,			0,	0 }
715 };
716 
717 int
718 cd9660_rrip_getsymname(isodir, outbuf, outlen, imp)
719 	struct iso_directory_record *isodir;
720 	char *outbuf;
721 	u_short *outlen;
722 	struct iso_mnt *imp;
723 {
724 	ISO_RRIP_ANALYZE analyze;
725 
726 	analyze.outbuf = outbuf;
727 	analyze.outlen = outlen;
728 	*outlen = 0;
729 	analyze.maxlen = MAXPATHLEN;
730 	analyze.cont = 1;		/* don't start with a slash */
731 	analyze.imp = imp;
732 	analyze.fields = ISO_SUSP_SLINK;
733 
734 	return (cd9660_rrip_loop(isodir, &analyze, rrip_table_getsymname) &
735 	    ISO_SUSP_SLINK);
736 }
737 
738 static RRIP_TABLE rrip_table_extref[] = {
739 	{ "ER", cd9660_rrip_extref,	0,	ISO_SUSP_EXTREF },
740 	{ "CE", cd9660_rrip_cont,	0,	ISO_SUSP_CONT },
741 	{ "ST", cd9660_rrip_stop,	0,	ISO_SUSP_STOP },
742 	{ "",	0,			0,	0 }
743 };
744 
745 /*
746  * Check for Rock Ridge Extension and return offset of its fields.
747  * Note: We insist on the ER field.
748  */
749 int
750 cd9660_rrip_offset(isodir, imp)
751 	struct iso_directory_record *isodir;
752 	struct iso_mnt *imp;
753 {
754 	ISO_RRIP_OFFSET *p;
755 	ISO_RRIP_ANALYZE analyze;
756 
757 	imp->rr_skip0 = 0;
758 	p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
759 	if (bcmp(p, "SP\7\1\276\357", 6)) {
760 		/* Maybe, it's a CDROM XA disc? */
761 		imp->rr_skip0 = 15;
762 		p = (ISO_RRIP_OFFSET *)((char *)p + 15);
763 		if (bcmp(p, "SP\7\1\276\357", 6))
764 			return (-1);
765 	}
766 
767 	analyze.imp = imp;
768 	analyze.fields = ISO_SUSP_EXTREF;
769 	if (!(cd9660_rrip_loop(isodir, &analyze, rrip_table_extref) &
770 	    ISO_SUSP_EXTREF))
771 		return (-1);
772 
773 	return (isonum_711(p->skip));
774 }
775