xref: /csrg-svn/sys/isofs/cd9660/cd9660_rrip.c (revision 65789)
1*65789Smckusick /*-
2*65789Smckusick  * Copyright (c) 1993, 1994
3*65789Smckusick  *	The Regents of the University of California.  All rights reserved.
4*65789Smckusick  *
5*65789Smckusick  * This code is derived from software contributed to Berkeley
6*65789Smckusick  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
7*65789Smckusick  * Support code is derived from software contributed to Berkeley
8*65789Smckusick  * by Atsushi Murai (amurai@spec.co.jp).
9*65789Smckusick  *
10*65789Smckusick  * %sccs.include.redist.c%
11*65789Smckusick  *
12*65789Smckusick  *	@(#)cd9660_rrip.c	8.1 (Berkeley) 01/21/94
13*65789Smckusick  */
14*65789Smckusick 
15*65789Smckusick #include <sys/param.h>
16*65789Smckusick #include <sys/namei.h>
17*65789Smckusick #include <sys/buf.h>
18*65789Smckusick #include <sys/file.h>
19*65789Smckusick #include <sys/vnode.h>
20*65789Smckusick #include <sys/mount.h>
21*65789Smckusick #include <sys/kernel.h>
22*65789Smckusick #include <sys/stat.h>
23*65789Smckusick #include <sys/types.h>
24*65789Smckusick 
25*65789Smckusick #include <sys/time.h>
26*65789Smckusick 
27*65789Smckusick #include <isofs/cd9660/iso.h>
28*65789Smckusick #include <isofs/cd9660/isofs_node.h>
29*65789Smckusick #include <isofs/cd9660/isofs_rrip.h>
30*65789Smckusick #include <isofs/cd9660/iso_rrip.h>
31*65789Smckusick 
32*65789Smckusick /*
33*65789Smckusick  * POSIX file attribute
34*65789Smckusick  */
35*65789Smckusick static int
36*65789Smckusick isofs_rrip_attr(p,ana)
37*65789Smckusick 	ISO_RRIP_ATTR *p;
38*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
39*65789Smckusick {
40*65789Smckusick 	ana->inop->inode.iso_mode = isonum_731(p->mode_l);
41*65789Smckusick 	ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
42*65789Smckusick 	ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
43*65789Smckusick 	ana->inop->inode.iso_links = isonum_731(p->links_l);
44*65789Smckusick 	ana->fields &= ~ISO_SUSP_ATTR;
45*65789Smckusick 	return ISO_SUSP_ATTR;
46*65789Smckusick }
47*65789Smckusick 
48*65789Smckusick static void
49*65789Smckusick isofs_rrip_defattr(isodir,ana)
50*65789Smckusick 	struct iso_directory_record *isodir;
51*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
52*65789Smckusick {
53*65789Smckusick 	/* But this is a required field! */
54*65789Smckusick 	printf("RRIP without PX field?\n");
55*65789Smckusick 	isofs_defattr(isodir,ana->inop,NULL);
56*65789Smckusick }
57*65789Smckusick 
58*65789Smckusick /*
59*65789Smckusick  * Symbolic Links
60*65789Smckusick  */
61*65789Smckusick static int
62*65789Smckusick isofs_rrip_slink(p,ana)
63*65789Smckusick 	ISO_RRIP_SLINK  *p;
64*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
65*65789Smckusick {
66*65789Smckusick 	register ISO_RRIP_SLINK_COMPONENT *pcomp;
67*65789Smckusick 	register ISO_RRIP_SLINK_COMPONENT *pcompe;
68*65789Smckusick 	int len, wlen, cont;
69*65789Smckusick 	char *outbuf, *inbuf;
70*65789Smckusick 
71*65789Smckusick 	pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
72*65789Smckusick 	pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
73*65789Smckusick 	len = *ana->outlen;
74*65789Smckusick 	outbuf = ana->outbuf;
75*65789Smckusick 	cont = ana->cont;
76*65789Smckusick 
77*65789Smckusick 	/*
78*65789Smckusick 	 * Gathering a Symbolic name from each component with path
79*65789Smckusick 	 */
80*65789Smckusick 	for (;
81*65789Smckusick 	     pcomp < pcompe;
82*65789Smckusick 	     pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
83*65789Smckusick 						  + isonum_711(pcomp->clen))) {
84*65789Smckusick 
85*65789Smckusick 		if (!cont) {
86*65789Smckusick 			if (len < ana->maxlen) {
87*65789Smckusick 				len++;
88*65789Smckusick 				*outbuf++ = '/';
89*65789Smckusick 			}
90*65789Smckusick 		}
91*65789Smckusick 		cont = 0;
92*65789Smckusick 
93*65789Smckusick 		inbuf = "..";
94*65789Smckusick 		wlen = 0;
95*65789Smckusick 
96*65789Smckusick 		switch (*pcomp->cflag) {
97*65789Smckusick 
98*65789Smckusick 		case ISO_SUSP_CFLAG_CURRENT:
99*65789Smckusick 			/* Inserting Current */
100*65789Smckusick 			wlen = 1;
101*65789Smckusick 			break;
102*65789Smckusick 
103*65789Smckusick 		case ISO_SUSP_CFLAG_PARENT:
104*65789Smckusick 			/* Inserting Parent */
105*65789Smckusick 			wlen = 2;
106*65789Smckusick 			break;
107*65789Smckusick 
108*65789Smckusick 		case ISO_SUSP_CFLAG_ROOT:
109*65789Smckusick 			/* Inserting slash for ROOT */
110*65789Smckusick 			/* start over from beginning(?) */
111*65789Smckusick 			outbuf -= len;
112*65789Smckusick 			len = 0;
113*65789Smckusick 			break;
114*65789Smckusick 
115*65789Smckusick 		case ISO_SUSP_CFLAG_VOLROOT:
116*65789Smckusick 			/* Inserting a mount point i.e. "/cdrom" */
117*65789Smckusick 			/* same as above */
118*65789Smckusick 			outbuf -= len;
119*65789Smckusick 			len = 0;
120*65789Smckusick 			inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
121*65789Smckusick 			wlen = strlen(inbuf);
122*65789Smckusick 			break;
123*65789Smckusick 
124*65789Smckusick 		case ISO_SUSP_CFLAG_HOST:
125*65789Smckusick 			/* Inserting hostname i.e. "kurt.tools.de" */
126*65789Smckusick 			inbuf = hostname;
127*65789Smckusick 			wlen = hostnamelen;
128*65789Smckusick 			break;
129*65789Smckusick 
130*65789Smckusick 		case ISO_SUSP_CFLAG_CONTINUE:
131*65789Smckusick 			cont = 1;
132*65789Smckusick 			/* fall thru */
133*65789Smckusick 		case 0:
134*65789Smckusick 			/* Inserting component */
135*65789Smckusick 			wlen = isonum_711(pcomp->clen);
136*65789Smckusick 			inbuf = pcomp->name;
137*65789Smckusick 			break;
138*65789Smckusick 		default:
139*65789Smckusick 			printf("RRIP with incorrect flags?");
140*65789Smckusick 			wlen = ana->maxlen + 1;
141*65789Smckusick 			break;
142*65789Smckusick 		}
143*65789Smckusick 
144*65789Smckusick 		if (len + wlen > ana->maxlen) {
145*65789Smckusick 			/* indicate error to caller */
146*65789Smckusick 			ana->cont = 1;
147*65789Smckusick 			ana->fields = 0;
148*65789Smckusick 			ana->outbuf -= *ana->outlen;
149*65789Smckusick 			*ana->outlen = 0;
150*65789Smckusick 			return 0;
151*65789Smckusick 		}
152*65789Smckusick 
153*65789Smckusick 		bcopy(inbuf,outbuf,wlen);
154*65789Smckusick 		outbuf += wlen;
155*65789Smckusick 		len += wlen;
156*65789Smckusick 
157*65789Smckusick 	}
158*65789Smckusick 	ana->outbuf = outbuf;
159*65789Smckusick 	*ana->outlen = len;
160*65789Smckusick 	ana->cont = cont;
161*65789Smckusick 
162*65789Smckusick 	if (!isonum_711(p->flags)) {
163*65789Smckusick 		ana->fields &= ~ISO_SUSP_SLINK;
164*65789Smckusick 		return ISO_SUSP_SLINK;
165*65789Smckusick 	}
166*65789Smckusick 	return 0;
167*65789Smckusick }
168*65789Smckusick 
169*65789Smckusick /*
170*65789Smckusick  * Alternate name
171*65789Smckusick  */
172*65789Smckusick static int
173*65789Smckusick isofs_rrip_altname(p,ana)
174*65789Smckusick 	ISO_RRIP_ALTNAME *p;
175*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
176*65789Smckusick {
177*65789Smckusick 	char *inbuf;
178*65789Smckusick 	int wlen;
179*65789Smckusick 	int cont;
180*65789Smckusick 
181*65789Smckusick 	inbuf = "..";
182*65789Smckusick 	wlen = 0;
183*65789Smckusick 	cont = 0;
184*65789Smckusick 
185*65789Smckusick 	switch (*p->flags) {
186*65789Smckusick 	case ISO_SUSP_CFLAG_CURRENT:
187*65789Smckusick 		/* Inserting Current */
188*65789Smckusick 		wlen = 1;
189*65789Smckusick 		break;
190*65789Smckusick 
191*65789Smckusick 	case ISO_SUSP_CFLAG_PARENT:
192*65789Smckusick 		/* Inserting Parent */
193*65789Smckusick 		wlen = 2;
194*65789Smckusick 		break;
195*65789Smckusick 
196*65789Smckusick 	case ISO_SUSP_CFLAG_HOST:
197*65789Smckusick 		/* Inserting hostname i.e. "kurt.tools.de" */
198*65789Smckusick 		inbuf = hostname;
199*65789Smckusick 		wlen = hostnamelen;
200*65789Smckusick 		break;
201*65789Smckusick 
202*65789Smckusick 	case ISO_SUSP_CFLAG_CONTINUE:
203*65789Smckusick 		cont = 1;
204*65789Smckusick 		/* fall thru */
205*65789Smckusick 	case 0:
206*65789Smckusick 		/* Inserting component */
207*65789Smckusick 		wlen = isonum_711(p->h.length) - 5;
208*65789Smckusick 		inbuf = (char *)p + 5;
209*65789Smckusick 		break;
210*65789Smckusick 
211*65789Smckusick 	default:
212*65789Smckusick 		printf("RRIP with incorrect NM flags?\n");
213*65789Smckusick 		wlen = ana->maxlen + 1;
214*65789Smckusick 		break;
215*65789Smckusick 	}
216*65789Smckusick 
217*65789Smckusick 	if ((*ana->outlen += wlen) > ana->maxlen) {
218*65789Smckusick 		/* treat as no name field */
219*65789Smckusick 		ana->fields &= ~ISO_SUSP_ALTNAME;
220*65789Smckusick 		ana->outbuf -= *ana->outlen - wlen;
221*65789Smckusick 		*ana->outlen = 0;
222*65789Smckusick 		return 0;
223*65789Smckusick 	}
224*65789Smckusick 
225*65789Smckusick 	bcopy(inbuf,ana->outbuf,wlen);
226*65789Smckusick 	ana->outbuf += wlen;
227*65789Smckusick 
228*65789Smckusick 	if (!cont) {
229*65789Smckusick 		ana->fields &= ~ISO_SUSP_ALTNAME;
230*65789Smckusick 		return ISO_SUSP_ALTNAME;
231*65789Smckusick 	}
232*65789Smckusick 	return 0;
233*65789Smckusick }
234*65789Smckusick 
235*65789Smckusick static void
236*65789Smckusick isofs_rrip_defname(isodir,ana)
237*65789Smckusick 	struct iso_directory_record *isodir;
238*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
239*65789Smckusick {
240*65789Smckusick 	strcpy(ana->outbuf,"..");
241*65789Smckusick 	switch (*isodir->name) {
242*65789Smckusick 	default:
243*65789Smckusick 		isofntrans(isodir->name,isonum_711(isodir->name_len),
244*65789Smckusick 			   ana->outbuf,ana->outlen,
245*65789Smckusick 			   1,isonum_711(isodir->flags)&4);
246*65789Smckusick 		break;
247*65789Smckusick 	case 0:
248*65789Smckusick 		*ana->outlen = 1;
249*65789Smckusick 		break;
250*65789Smckusick 	case 1:
251*65789Smckusick 		*ana->outlen = 2;
252*65789Smckusick 		break;
253*65789Smckusick 	}
254*65789Smckusick }
255*65789Smckusick 
256*65789Smckusick /*
257*65789Smckusick  * Parent or Child Link
258*65789Smckusick  */
259*65789Smckusick static int
260*65789Smckusick isofs_rrip_pclink(p,ana)
261*65789Smckusick 	ISO_RRIP_CLINK  *p;
262*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
263*65789Smckusick {
264*65789Smckusick 	*ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
265*65789Smckusick 	ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK);
266*65789Smckusick 	return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK;
267*65789Smckusick }
268*65789Smckusick 
269*65789Smckusick /*
270*65789Smckusick  * Relocated directory
271*65789Smckusick  */
272*65789Smckusick static int
273*65789Smckusick isofs_rrip_reldir(p,ana)
274*65789Smckusick 	ISO_RRIP_RELDIR  *p;
275*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
276*65789Smckusick {
277*65789Smckusick 	/* special hack to make caller aware of RE field */
278*65789Smckusick 	*ana->outlen = 0;
279*65789Smckusick 	ana->fields = 0;
280*65789Smckusick 	return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
281*65789Smckusick }
282*65789Smckusick 
283*65789Smckusick static int
284*65789Smckusick isofs_rrip_tstamp(p,ana)
285*65789Smckusick 	ISO_RRIP_TSTAMP *p;
286*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
287*65789Smckusick {
288*65789Smckusick 	unsigned char *ptime;
289*65789Smckusick 
290*65789Smckusick 	ptime = p->time;
291*65789Smckusick 
292*65789Smckusick 	/* Check a format of time stamp (7bytes/17bytes) */
293*65789Smckusick 	if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) {
294*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
295*65789Smckusick 			ptime += 7;
296*65789Smckusick 
297*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
298*65789Smckusick 			isofs_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime);
299*65789Smckusick 			ptime += 7;
300*65789Smckusick 		} else
301*65789Smckusick 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval));
302*65789Smckusick 
303*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
304*65789Smckusick 			isofs_tstamp_conv7(ptime,&ana->inop->inode.iso_atime);
305*65789Smckusick 			ptime += 7;
306*65789Smckusick 		} else
307*65789Smckusick 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
308*65789Smckusick 
309*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
310*65789Smckusick 			isofs_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime);
311*65789Smckusick 		else
312*65789Smckusick 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
313*65789Smckusick 
314*65789Smckusick 	} else {
315*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
316*65789Smckusick 			ptime += 17;
317*65789Smckusick 
318*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
319*65789Smckusick 			isofs_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime);
320*65789Smckusick 			ptime += 17;
321*65789Smckusick 		} else
322*65789Smckusick 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval));
323*65789Smckusick 
324*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
325*65789Smckusick 			isofs_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
326*65789Smckusick 			ptime += 17;
327*65789Smckusick 		} else
328*65789Smckusick 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
329*65789Smckusick 
330*65789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
331*65789Smckusick 			isofs_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime);
332*65789Smckusick 		else
333*65789Smckusick 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
334*65789Smckusick 
335*65789Smckusick 	}
336*65789Smckusick 	ana->fields &= ~ISO_SUSP_TSTAMP;
337*65789Smckusick 	return ISO_SUSP_TSTAMP;
338*65789Smckusick }
339*65789Smckusick 
340*65789Smckusick static void
341*65789Smckusick isofs_rrip_deftstamp(isodir,ana)
342*65789Smckusick 	struct iso_directory_record  *isodir;
343*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
344*65789Smckusick {
345*65789Smckusick 	isofs_deftstamp(isodir,ana->inop,NULL);
346*65789Smckusick }
347*65789Smckusick 
348*65789Smckusick /*
349*65789Smckusick  * POSIX device modes
350*65789Smckusick  */
351*65789Smckusick static int
352*65789Smckusick isofs_rrip_device(p,ana)
353*65789Smckusick 	ISO_RRIP_DEVICE *p;
354*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
355*65789Smckusick {
356*65789Smckusick 	unsigned high, low;
357*65789Smckusick 
358*65789Smckusick 	high = isonum_733(p->dev_t_high_l);
359*65789Smckusick 	low  = isonum_733(p->dev_t_low_l);
360*65789Smckusick 
361*65789Smckusick 	if ( high == 0 ) {
362*65789Smckusick 		ana->inop->inode.iso_rdev = makedev( major(low), minor(low) );
363*65789Smckusick 	} else {
364*65789Smckusick 		ana->inop->inode.iso_rdev = makedev( high, minor(low) );
365*65789Smckusick 	}
366*65789Smckusick 	ana->fields &= ~ISO_SUSP_DEVICE;
367*65789Smckusick 	return ISO_SUSP_DEVICE;
368*65789Smckusick }
369*65789Smckusick 
370*65789Smckusick /*
371*65789Smckusick  * Flag indicating
372*65789Smckusick  */
373*65789Smckusick static int
374*65789Smckusick isofs_rrip_idflag(p,ana)
375*65789Smckusick 	ISO_RRIP_IDFLAG *p;
376*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
377*65789Smckusick {
378*65789Smckusick 	ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */
379*65789Smckusick 	/* special handling of RE field */
380*65789Smckusick 	if (ana->fields&ISO_SUSP_RELDIR)
381*65789Smckusick 		return isofs_rrip_reldir(p,ana);
382*65789Smckusick 
383*65789Smckusick 	return ISO_SUSP_IDFLAG;
384*65789Smckusick }
385*65789Smckusick 
386*65789Smckusick /*
387*65789Smckusick  * Continuation pointer
388*65789Smckusick  */
389*65789Smckusick static int
390*65789Smckusick isofs_rrip_cont(p,ana)
391*65789Smckusick 	ISO_RRIP_CONT *p;
392*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
393*65789Smckusick {
394*65789Smckusick 	ana->iso_ce_blk = isonum_733(p->location);
395*65789Smckusick 	ana->iso_ce_off = isonum_733(p->offset);
396*65789Smckusick 	ana->iso_ce_len = isonum_733(p->length);
397*65789Smckusick 	return ISO_SUSP_CONT;
398*65789Smckusick }
399*65789Smckusick 
400*65789Smckusick /*
401*65789Smckusick  * System Use end
402*65789Smckusick  */
403*65789Smckusick static int
404*65789Smckusick isofs_rrip_stop(p,ana)
405*65789Smckusick 	ISO_SUSP_HEADER *p;
406*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
407*65789Smckusick {
408*65789Smckusick 	/* stop analyzing */
409*65789Smckusick 	ana->fields = 0;
410*65789Smckusick 	return ISO_SUSP_STOP;
411*65789Smckusick }
412*65789Smckusick 
413*65789Smckusick /*
414*65789Smckusick  * Extension reference
415*65789Smckusick  */
416*65789Smckusick static int
417*65789Smckusick isofs_rrip_extref(p,ana)
418*65789Smckusick 	ISO_RRIP_EXTREF *p;
419*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
420*65789Smckusick {
421*65789Smckusick 	if (isonum_711(p->len_id) != 10
422*65789Smckusick 	    || bcmp((char *)p + 8,"RRIP_1991A",10)
423*65789Smckusick 	    || isonum_711(p->version) != 1)
424*65789Smckusick 		return 0;
425*65789Smckusick 	ana->fields &= ~ISO_SUSP_EXTREF;
426*65789Smckusick 	return ISO_SUSP_EXTREF;
427*65789Smckusick }
428*65789Smckusick 
429*65789Smckusick typedef struct {
430*65789Smckusick 	char type[2];
431*65789Smckusick 	int (*func)();
432*65789Smckusick 	void (*func2)();
433*65789Smckusick 	int result;
434*65789Smckusick } RRIP_TABLE;
435*65789Smckusick 
436*65789Smckusick static int
437*65789Smckusick isofs_rrip_loop(isodir,ana,table)
438*65789Smckusick 	struct iso_directory_record *isodir;
439*65789Smckusick 	ISO_RRIP_ANALYZE *ana;
440*65789Smckusick 	RRIP_TABLE *table;
441*65789Smckusick {
442*65789Smckusick 	register RRIP_TABLE *ptable;
443*65789Smckusick 	register ISO_SUSP_HEADER *phead;
444*65789Smckusick 	register ISO_SUSP_HEADER *pend;
445*65789Smckusick 	struct buf *bp = NULL;
446*65789Smckusick 	int i;
447*65789Smckusick 	char *pwhead;
448*65789Smckusick 	int result;
449*65789Smckusick 
450*65789Smckusick 	/*
451*65789Smckusick 	 * Note: If name length is odd,
452*65789Smckusick 	 *       it will be padding 1 byte  after the name
453*65789Smckusick 	 */
454*65789Smckusick 	pwhead = isodir->name + isonum_711(isodir->name_len);
455*65789Smckusick 	if (!(isonum_711(isodir->name_len)&1))
456*65789Smckusick 		pwhead++;
457*65789Smckusick 
458*65789Smckusick 	/* If it's not the '.' entry of the root dir obey SP field */
459*65789Smckusick 	if (*isodir->name != 0
460*65789Smckusick 	    || isonum_733(isodir->extent) != ana->imp->root_extent)
461*65789Smckusick 		pwhead += ana->imp->rr_skip;
462*65789Smckusick 	else
463*65789Smckusick 		pwhead += ana->imp->rr_skip0;
464*65789Smckusick 
465*65789Smckusick 	phead = (ISO_SUSP_HEADER *)pwhead;
466*65789Smckusick 	pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
467*65789Smckusick 
468*65789Smckusick 	result = 0;
469*65789Smckusick 	while (1) {
470*65789Smckusick 		ana->iso_ce_len = 0;
471*65789Smckusick 		/*
472*65789Smckusick 		 * Note: "pend" should be more than one SUSP header
473*65789Smckusick 		 */
474*65789Smckusick 		while (pend >= phead + 1) {
475*65789Smckusick 			if (isonum_711(phead->version) == 1) {
476*65789Smckusick 				for (ptable = table; ptable->func; ptable++) {
477*65789Smckusick 					if (*phead->type == *ptable->type
478*65789Smckusick 					    && phead->type[1] == ptable->type[1]) {
479*65789Smckusick 						result |= ptable->func(phead,ana);
480*65789Smckusick 						break;
481*65789Smckusick 					}
482*65789Smckusick 				}
483*65789Smckusick 				if (!ana->fields)
484*65789Smckusick 					break;
485*65789Smckusick 			}
486*65789Smckusick 			/*
487*65789Smckusick 			 * move to next SUSP
488*65789Smckusick 			 * Hopefully this works with newer versions, too
489*65789Smckusick 			 */
490*65789Smckusick 			phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
491*65789Smckusick 		}
492*65789Smckusick 
493*65789Smckusick 		if ( ana->fields && ana->iso_ce_len ) {
494*65789Smckusick 			if (ana->iso_ce_blk >= ana->imp->volume_space_size
495*65789Smckusick 			    || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
496*65789Smckusick 			    || bread(ana->imp->im_devvp,
497*65789Smckusick 				     ana->iso_ce_blk * ana->imp->logical_block_size / DEV_BSIZE,
498*65789Smckusick 				     ana->imp->logical_block_size,NOCRED,&bp))
499*65789Smckusick 				/* what to do now? */
500*65789Smckusick 				break;
501*65789Smckusick 			phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off);
502*65789Smckusick 			pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
503*65789Smckusick 		} else
504*65789Smckusick 			break;
505*65789Smckusick 	}
506*65789Smckusick 	if (bp)
507*65789Smckusick 		brelse(bp);
508*65789Smckusick 	/*
509*65789Smckusick 	 * If we don't find the Basic SUSP stuffs, just set default value
510*65789Smckusick 	 *   ( attribute/time stamp )
511*65789Smckusick 	 */
512*65789Smckusick 	for (ptable = table; ptable->func2; ptable++)
513*65789Smckusick 		if (!(ptable->result&result))
514*65789Smckusick 			ptable->func2(isodir,ana);
515*65789Smckusick 
516*65789Smckusick 	return result;
517*65789Smckusick }
518*65789Smckusick 
519*65789Smckusick static RRIP_TABLE rrip_table_analyze[] = {
520*65789Smckusick 	{ "PX", isofs_rrip_attr,	isofs_rrip_defattr,	ISO_SUSP_ATTR },
521*65789Smckusick 	{ "TF", isofs_rrip_tstamp,	isofs_rrip_deftstamp,	ISO_SUSP_TSTAMP },
522*65789Smckusick 	{ "PN", isofs_rrip_device,	0,			ISO_SUSP_DEVICE },
523*65789Smckusick 	{ "RR", isofs_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
524*65789Smckusick 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
525*65789Smckusick 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
526*65789Smckusick 	{ "",	0,			0,			0 }
527*65789Smckusick };
528*65789Smckusick 
529*65789Smckusick int
530*65789Smckusick isofs_rrip_analyze(isodir,inop,imp)
531*65789Smckusick 	struct iso_directory_record *isodir;
532*65789Smckusick 	struct iso_node *inop;
533*65789Smckusick 	struct iso_mnt *imp;
534*65789Smckusick {
535*65789Smckusick 	ISO_RRIP_ANALYZE analyze;
536*65789Smckusick 
537*65789Smckusick 	analyze.inop = inop;
538*65789Smckusick 	analyze.imp = imp;
539*65789Smckusick 	analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE;
540*65789Smckusick 
541*65789Smckusick 	return isofs_rrip_loop(isodir,&analyze,rrip_table_analyze);
542*65789Smckusick }
543*65789Smckusick 
544*65789Smckusick /*
545*65789Smckusick  * Get Alternate Name from 'AL' record
546*65789Smckusick  * If either no AL record or 0 length,
547*65789Smckusick  *    it will be return the translated ISO9660 name,
548*65789Smckusick  */
549*65789Smckusick static RRIP_TABLE rrip_table_getname[] = {
550*65789Smckusick 	{ "NM", isofs_rrip_altname,	isofs_rrip_defname,	ISO_SUSP_ALTNAME },
551*65789Smckusick 	{ "CL", isofs_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
552*65789Smckusick 	{ "PL", isofs_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
553*65789Smckusick 	{ "RE", isofs_rrip_reldir,	0,			ISO_SUSP_RELDIR },
554*65789Smckusick 	{ "RR", isofs_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
555*65789Smckusick 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
556*65789Smckusick 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
557*65789Smckusick 	{ "",	0,			0,			0 }
558*65789Smckusick };
559*65789Smckusick 
560*65789Smckusick int
561*65789Smckusick isofs_rrip_getname(isodir,outbuf,outlen,inump,imp)
562*65789Smckusick 	struct iso_directory_record *isodir;
563*65789Smckusick 	char *outbuf;
564*65789Smckusick 	u_short *outlen;
565*65789Smckusick 	ino_t *inump;
566*65789Smckusick 	struct iso_mnt *imp;
567*65789Smckusick {
568*65789Smckusick 	ISO_RRIP_ANALYZE analyze;
569*65789Smckusick 	RRIP_TABLE *tab;
570*65789Smckusick 
571*65789Smckusick 	analyze.outbuf = outbuf;
572*65789Smckusick 	analyze.outlen = outlen;
573*65789Smckusick 	analyze.maxlen = NAME_MAX;
574*65789Smckusick 	analyze.inump = inump;
575*65789Smckusick 	analyze.imp = imp;
576*65789Smckusick 	analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
577*65789Smckusick 	*outlen = 0;
578*65789Smckusick 
579*65789Smckusick 	tab = rrip_table_getname;
580*65789Smckusick 	if (*isodir->name == 0
581*65789Smckusick 	    || *isodir->name == 1) {
582*65789Smckusick 		isofs_rrip_defname(isodir,&analyze);
583*65789Smckusick 
584*65789Smckusick 		analyze.fields &= ~ISO_SUSP_ALTNAME;
585*65789Smckusick 		tab++;
586*65789Smckusick 	}
587*65789Smckusick 
588*65789Smckusick 	return isofs_rrip_loop(isodir,&analyze,tab);
589*65789Smckusick }
590*65789Smckusick 
591*65789Smckusick /*
592*65789Smckusick  * Get Symbolic Name from 'SL' record
593*65789Smckusick  *
594*65789Smckusick  * Note: isodir should contains SL record!
595*65789Smckusick  */
596*65789Smckusick static RRIP_TABLE rrip_table_getsymname[] = {
597*65789Smckusick 	{ "SL", isofs_rrip_slink,	0,			ISO_SUSP_SLINK },
598*65789Smckusick 	{ "RR", isofs_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
599*65789Smckusick 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
600*65789Smckusick 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
601*65789Smckusick 	{ "",	0,			0,			0 }
602*65789Smckusick };
603*65789Smckusick 
604*65789Smckusick int
605*65789Smckusick isofs_rrip_getsymname(isodir,outbuf,outlen,imp)
606*65789Smckusick 	struct iso_directory_record *isodir;
607*65789Smckusick 	char *outbuf;
608*65789Smckusick 	u_short *outlen;
609*65789Smckusick 	struct iso_mnt *imp;
610*65789Smckusick {
611*65789Smckusick 	ISO_RRIP_ANALYZE analyze;
612*65789Smckusick 
613*65789Smckusick 	analyze.outbuf = outbuf;
614*65789Smckusick 	analyze.outlen = outlen;
615*65789Smckusick 	*outlen = 0;
616*65789Smckusick 	analyze.maxlen = MAXPATHLEN;
617*65789Smckusick 	analyze.cont = 1;		/* don't start with a slash */
618*65789Smckusick 	analyze.imp = imp;
619*65789Smckusick 	analyze.fields = ISO_SUSP_SLINK;
620*65789Smckusick 
621*65789Smckusick 	return (isofs_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK);
622*65789Smckusick }
623*65789Smckusick 
624*65789Smckusick static RRIP_TABLE rrip_table_extref[] = {
625*65789Smckusick 	{ "ER", isofs_rrip_extref,	0,			ISO_SUSP_EXTREF },
626*65789Smckusick 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
627*65789Smckusick 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
628*65789Smckusick 	{ "",	0,			0,			0 }
629*65789Smckusick };
630*65789Smckusick 
631*65789Smckusick /*
632*65789Smckusick  * Check for Rock Ridge Extension and return offset of its fields.
633*65789Smckusick  * Note: We require the ER field.
634*65789Smckusick  */
635*65789Smckusick int
636*65789Smckusick isofs_rrip_offset(isodir,imp)
637*65789Smckusick 	struct iso_directory_record *isodir;
638*65789Smckusick 	struct iso_mnt *imp;
639*65789Smckusick {
640*65789Smckusick 	ISO_RRIP_OFFSET *p;
641*65789Smckusick 	ISO_RRIP_ANALYZE analyze;
642*65789Smckusick 
643*65789Smckusick 	imp->rr_skip0 = 0;
644*65789Smckusick 	p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
645*65789Smckusick 	if (bcmp(p,"SP\7\1\276\357",6)) {
646*65789Smckusick 		/* Maybe, it's a CDROM XA disc? */
647*65789Smckusick 		imp->rr_skip0 = 15;
648*65789Smckusick 		p = (ISO_RRIP_OFFSET *)((char *)p + 15);
649*65789Smckusick 		if (bcmp(p,"SP\7\1\276\357",6))
650*65789Smckusick 			return -1;
651*65789Smckusick 	}
652*65789Smckusick 
653*65789Smckusick 	analyze.imp = imp;
654*65789Smckusick 	analyze.fields = ISO_SUSP_EXTREF;
655*65789Smckusick 	if (!(isofs_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
656*65789Smckusick 		return -1;
657*65789Smckusick 
658*65789Smckusick 	return isonum_711(p->skip);
659*65789Smckusick }
660