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