xref: /csrg-svn/sys/isofs/cd9660/cd9660_rrip.c (revision 68049)
165789Smckusick /*-
265789Smckusick  * Copyright (c) 1993, 1994
365789Smckusick  *	The Regents of the University of California.  All rights reserved.
465789Smckusick  *
565789Smckusick  * This code is derived from software contributed to Berkeley
665789Smckusick  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
765789Smckusick  * Support code is derived from software contributed to Berkeley
865789Smckusick  * by Atsushi Murai (amurai@spec.co.jp).
965789Smckusick  *
1065789Smckusick  * %sccs.include.redist.c%
1165789Smckusick  *
12*68049Smckusick  *	@(#)cd9660_rrip.c	8.6 (Berkeley) 12/05/94
1365789Smckusick  */
1465789Smckusick 
1565789Smckusick #include <sys/param.h>
16*68049Smckusick #include <sys/systm.h>
1765789Smckusick #include <sys/namei.h>
1865789Smckusick #include <sys/buf.h>
1965789Smckusick #include <sys/file.h>
2065789Smckusick #include <sys/vnode.h>
2165789Smckusick #include <sys/mount.h>
2265789Smckusick #include <sys/kernel.h>
2365789Smckusick #include <sys/stat.h>
2465789Smckusick #include <sys/types.h>
2565789Smckusick 
2665789Smckusick #include <sys/time.h>
2765789Smckusick 
2865789Smckusick #include <isofs/cd9660/iso.h>
2965855Smckusick #include <isofs/cd9660/cd9660_node.h>
3065855Smckusick #include <isofs/cd9660/cd9660_rrip.h>
3165789Smckusick #include <isofs/cd9660/iso_rrip.h>
3265789Smckusick 
3365789Smckusick /*
3465789Smckusick  * POSIX file attribute
3565789Smckusick  */
3665789Smckusick static int
cd9660_rrip_attr(p,ana)3765855Smckusick cd9660_rrip_attr(p,ana)
3865789Smckusick 	ISO_RRIP_ATTR *p;
3965789Smckusick 	ISO_RRIP_ANALYZE *ana;
4065789Smckusick {
41*68049Smckusick 	ana->inop->inode.iso_mode = isonum_733(p->mode);
42*68049Smckusick 	ana->inop->inode.iso_uid = isonum_733(p->uid);
43*68049Smckusick 	ana->inop->inode.iso_gid = isonum_733(p->gid);
44*68049Smckusick 	ana->inop->inode.iso_links = isonum_733(p->links);
4565789Smckusick 	ana->fields &= ~ISO_SUSP_ATTR;
4665789Smckusick 	return ISO_SUSP_ATTR;
4765789Smckusick }
4865789Smckusick 
4965789Smckusick static void
cd9660_rrip_defattr(isodir,ana)5065855Smckusick cd9660_rrip_defattr(isodir,ana)
5165789Smckusick 	struct iso_directory_record *isodir;
5265789Smckusick 	ISO_RRIP_ANALYZE *ana;
5365789Smckusick {
5465789Smckusick 	/* But this is a required field! */
5565789Smckusick 	printf("RRIP without PX field?\n");
5665855Smckusick 	cd9660_defattr(isodir,ana->inop,NULL);
5765789Smckusick }
5865789Smckusick 
5965789Smckusick /*
6065789Smckusick  * Symbolic Links
6165789Smckusick  */
6265789Smckusick static int
cd9660_rrip_slink(p,ana)6365855Smckusick cd9660_rrip_slink(p,ana)
6465789Smckusick 	ISO_RRIP_SLINK  *p;
6565789Smckusick 	ISO_RRIP_ANALYZE *ana;
6665789Smckusick {
6765789Smckusick 	register ISO_RRIP_SLINK_COMPONENT *pcomp;
6865789Smckusick 	register ISO_RRIP_SLINK_COMPONENT *pcompe;
6965789Smckusick 	int len, wlen, cont;
7065789Smckusick 	char *outbuf, *inbuf;
7165789Smckusick 
7265789Smckusick 	pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
7365789Smckusick 	pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
7465789Smckusick 	len = *ana->outlen;
7565789Smckusick 	outbuf = ana->outbuf;
7665789Smckusick 	cont = ana->cont;
7765789Smckusick 
7865789Smckusick 	/*
7965789Smckusick 	 * Gathering a Symbolic name from each component with path
8065789Smckusick 	 */
8165789Smckusick 	for (;
8265789Smckusick 	     pcomp < pcompe;
8365789Smckusick 	     pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
8465789Smckusick 						  + isonum_711(pcomp->clen))) {
8565789Smckusick 
8665789Smckusick 		if (!cont) {
8765789Smckusick 			if (len < ana->maxlen) {
8865789Smckusick 				len++;
8965789Smckusick 				*outbuf++ = '/';
9065789Smckusick 			}
9165789Smckusick 		}
9265789Smckusick 		cont = 0;
9365789Smckusick 
9465789Smckusick 		inbuf = "..";
9565789Smckusick 		wlen = 0;
9665789Smckusick 
9765789Smckusick 		switch (*pcomp->cflag) {
9865789Smckusick 
9965789Smckusick 		case ISO_SUSP_CFLAG_CURRENT:
10065789Smckusick 			/* Inserting Current */
10165789Smckusick 			wlen = 1;
10265789Smckusick 			break;
10365789Smckusick 
10465789Smckusick 		case ISO_SUSP_CFLAG_PARENT:
10565789Smckusick 			/* Inserting Parent */
10665789Smckusick 			wlen = 2;
10765789Smckusick 			break;
10865789Smckusick 
10965789Smckusick 		case ISO_SUSP_CFLAG_ROOT:
11065789Smckusick 			/* Inserting slash for ROOT */
11165789Smckusick 			/* start over from beginning(?) */
11265789Smckusick 			outbuf -= len;
11365789Smckusick 			len = 0;
11465789Smckusick 			break;
11565789Smckusick 
11665789Smckusick 		case ISO_SUSP_CFLAG_VOLROOT:
11765789Smckusick 			/* Inserting a mount point i.e. "/cdrom" */
11865789Smckusick 			/* same as above */
11965789Smckusick 			outbuf -= len;
12065789Smckusick 			len = 0;
12165789Smckusick 			inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
12265789Smckusick 			wlen = strlen(inbuf);
12365789Smckusick 			break;
12465789Smckusick 
12565789Smckusick 		case ISO_SUSP_CFLAG_HOST:
12665789Smckusick 			/* Inserting hostname i.e. "kurt.tools.de" */
12765789Smckusick 			inbuf = hostname;
12865789Smckusick 			wlen = hostnamelen;
12965789Smckusick 			break;
13065789Smckusick 
13165789Smckusick 		case ISO_SUSP_CFLAG_CONTINUE:
13265789Smckusick 			cont = 1;
13365789Smckusick 			/* fall thru */
13465789Smckusick 		case 0:
13565789Smckusick 			/* Inserting component */
13665789Smckusick 			wlen = isonum_711(pcomp->clen);
13765789Smckusick 			inbuf = pcomp->name;
13865789Smckusick 			break;
13965789Smckusick 		default:
14065789Smckusick 			printf("RRIP with incorrect flags?");
14165789Smckusick 			wlen = ana->maxlen + 1;
14265789Smckusick 			break;
14365789Smckusick 		}
14465789Smckusick 
14565789Smckusick 		if (len + wlen > ana->maxlen) {
14665789Smckusick 			/* indicate error to caller */
14765789Smckusick 			ana->cont = 1;
14865789Smckusick 			ana->fields = 0;
14965789Smckusick 			ana->outbuf -= *ana->outlen;
15065789Smckusick 			*ana->outlen = 0;
15165789Smckusick 			return 0;
15265789Smckusick 		}
15365789Smckusick 
15465789Smckusick 		bcopy(inbuf,outbuf,wlen);
15565789Smckusick 		outbuf += wlen;
15665789Smckusick 		len += wlen;
15765789Smckusick 
15865789Smckusick 	}
15965789Smckusick 	ana->outbuf = outbuf;
16065789Smckusick 	*ana->outlen = len;
16165789Smckusick 	ana->cont = cont;
16265789Smckusick 
16365789Smckusick 	if (!isonum_711(p->flags)) {
16465789Smckusick 		ana->fields &= ~ISO_SUSP_SLINK;
16565789Smckusick 		return ISO_SUSP_SLINK;
16665789Smckusick 	}
16765789Smckusick 	return 0;
16865789Smckusick }
16965789Smckusick 
17065789Smckusick /*
17165789Smckusick  * Alternate name
17265789Smckusick  */
17365789Smckusick static int
cd9660_rrip_altname(p,ana)17465855Smckusick cd9660_rrip_altname(p,ana)
17565789Smckusick 	ISO_RRIP_ALTNAME *p;
17665789Smckusick 	ISO_RRIP_ANALYZE *ana;
17765789Smckusick {
17865789Smckusick 	char *inbuf;
17965789Smckusick 	int wlen;
18065789Smckusick 	int cont;
18165789Smckusick 
18265789Smckusick 	inbuf = "..";
18365789Smckusick 	wlen = 0;
18465789Smckusick 	cont = 0;
18565789Smckusick 
18665789Smckusick 	switch (*p->flags) {
18765789Smckusick 	case ISO_SUSP_CFLAG_CURRENT:
18865789Smckusick 		/* Inserting Current */
18965789Smckusick 		wlen = 1;
19065789Smckusick 		break;
19165789Smckusick 
19265789Smckusick 	case ISO_SUSP_CFLAG_PARENT:
19365789Smckusick 		/* Inserting Parent */
19465789Smckusick 		wlen = 2;
19565789Smckusick 		break;
19665789Smckusick 
19765789Smckusick 	case ISO_SUSP_CFLAG_HOST:
19865789Smckusick 		/* Inserting hostname i.e. "kurt.tools.de" */
19965789Smckusick 		inbuf = hostname;
20065789Smckusick 		wlen = hostnamelen;
20165789Smckusick 		break;
20265789Smckusick 
20365789Smckusick 	case ISO_SUSP_CFLAG_CONTINUE:
20465789Smckusick 		cont = 1;
20565789Smckusick 		/* fall thru */
20665789Smckusick 	case 0:
20765789Smckusick 		/* Inserting component */
20865789Smckusick 		wlen = isonum_711(p->h.length) - 5;
20965789Smckusick 		inbuf = (char *)p + 5;
21065789Smckusick 		break;
21165789Smckusick 
21265789Smckusick 	default:
21365789Smckusick 		printf("RRIP with incorrect NM flags?\n");
21465789Smckusick 		wlen = ana->maxlen + 1;
21565789Smckusick 		break;
21665789Smckusick 	}
21765789Smckusick 
21865789Smckusick 	if ((*ana->outlen += wlen) > ana->maxlen) {
21965789Smckusick 		/* treat as no name field */
22065789Smckusick 		ana->fields &= ~ISO_SUSP_ALTNAME;
22165789Smckusick 		ana->outbuf -= *ana->outlen - wlen;
22265789Smckusick 		*ana->outlen = 0;
22365789Smckusick 		return 0;
22465789Smckusick 	}
22565789Smckusick 
22665789Smckusick 	bcopy(inbuf,ana->outbuf,wlen);
22765789Smckusick 	ana->outbuf += wlen;
22865789Smckusick 
22965789Smckusick 	if (!cont) {
23065789Smckusick 		ana->fields &= ~ISO_SUSP_ALTNAME;
23165789Smckusick 		return ISO_SUSP_ALTNAME;
23265789Smckusick 	}
23365789Smckusick 	return 0;
23465789Smckusick }
23565789Smckusick 
23665789Smckusick static void
cd9660_rrip_defname(isodir,ana)23765855Smckusick cd9660_rrip_defname(isodir,ana)
23865789Smckusick 	struct iso_directory_record *isodir;
23965789Smckusick 	ISO_RRIP_ANALYZE *ana;
24065789Smckusick {
24165789Smckusick 	strcpy(ana->outbuf,"..");
24265789Smckusick 	switch (*isodir->name) {
24365789Smckusick 	default:
24465789Smckusick 		isofntrans(isodir->name,isonum_711(isodir->name_len),
24565789Smckusick 			   ana->outbuf,ana->outlen,
24665789Smckusick 			   1,isonum_711(isodir->flags)&4);
24765789Smckusick 		break;
24865789Smckusick 	case 0:
24965789Smckusick 		*ana->outlen = 1;
25065789Smckusick 		break;
25165789Smckusick 	case 1:
25265789Smckusick 		*ana->outlen = 2;
25365789Smckusick 		break;
25465789Smckusick 	}
25565789Smckusick }
25665789Smckusick 
25765789Smckusick /*
25865789Smckusick  * Parent or Child Link
25965789Smckusick  */
26065789Smckusick static int
cd9660_rrip_pclink(p,ana)26165855Smckusick cd9660_rrip_pclink(p,ana)
26265789Smckusick 	ISO_RRIP_CLINK  *p;
26365789Smckusick 	ISO_RRIP_ANALYZE *ana;
26465789Smckusick {
26565789Smckusick 	*ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
26665789Smckusick 	ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK);
26765789Smckusick 	return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK;
26865789Smckusick }
26965789Smckusick 
27065789Smckusick /*
27165789Smckusick  * Relocated directory
27265789Smckusick  */
27365789Smckusick static int
cd9660_rrip_reldir(p,ana)27465855Smckusick cd9660_rrip_reldir(p,ana)
27565789Smckusick 	ISO_RRIP_RELDIR  *p;
27665789Smckusick 	ISO_RRIP_ANALYZE *ana;
27765789Smckusick {
27865789Smckusick 	/* special hack to make caller aware of RE field */
27965789Smckusick 	*ana->outlen = 0;
28065789Smckusick 	ana->fields = 0;
28165789Smckusick 	return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
28265789Smckusick }
28365789Smckusick 
28465789Smckusick static int
cd9660_rrip_tstamp(p,ana)28565855Smckusick cd9660_rrip_tstamp(p,ana)
28665789Smckusick 	ISO_RRIP_TSTAMP *p;
28765789Smckusick 	ISO_RRIP_ANALYZE *ana;
28865789Smckusick {
289*68049Smckusick 	u_char *ptime;
29065789Smckusick 
29165789Smckusick 	ptime = p->time;
29265789Smckusick 
29365789Smckusick 	/* Check a format of time stamp (7bytes/17bytes) */
29465789Smckusick 	if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) {
29565789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
29665789Smckusick 			ptime += 7;
29765789Smckusick 
29865789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
29965855Smckusick 			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime);
30065789Smckusick 			ptime += 7;
30165789Smckusick 		} else
302*68049Smckusick 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
30365789Smckusick 
30465789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
30565855Smckusick 			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime);
30665789Smckusick 			ptime += 7;
30765789Smckusick 		} else
30865789Smckusick 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
30965789Smckusick 
31065789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
31165855Smckusick 			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime);
31265789Smckusick 		else
31365789Smckusick 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
31465789Smckusick 
31565789Smckusick 	} else {
31665789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
31765789Smckusick 			ptime += 17;
31865789Smckusick 
31965789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
32065855Smckusick 			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime);
32165789Smckusick 			ptime += 17;
32265789Smckusick 		} else
323*68049Smckusick 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
32465789Smckusick 
32565789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
32665855Smckusick 			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
32765789Smckusick 			ptime += 17;
32865789Smckusick 		} else
32965789Smckusick 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
33065789Smckusick 
33165789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
33265855Smckusick 			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime);
33365789Smckusick 		else
33465789Smckusick 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
33565789Smckusick 
33665789Smckusick 	}
33765789Smckusick 	ana->fields &= ~ISO_SUSP_TSTAMP;
33865789Smckusick 	return ISO_SUSP_TSTAMP;
33965789Smckusick }
34065789Smckusick 
34165789Smckusick static void
cd9660_rrip_deftstamp(isodir,ana)34265855Smckusick cd9660_rrip_deftstamp(isodir,ana)
34365789Smckusick 	struct iso_directory_record  *isodir;
34465789Smckusick 	ISO_RRIP_ANALYZE *ana;
34565789Smckusick {
34665855Smckusick 	cd9660_deftstamp(isodir,ana->inop,NULL);
34765789Smckusick }
34865789Smckusick 
34965789Smckusick /*
35065789Smckusick  * POSIX device modes
35165789Smckusick  */
35265789Smckusick static int
cd9660_rrip_device(p,ana)35365855Smckusick cd9660_rrip_device(p,ana)
35465789Smckusick 	ISO_RRIP_DEVICE *p;
35565789Smckusick 	ISO_RRIP_ANALYZE *ana;
35665789Smckusick {
357*68049Smckusick 	u_int high, low;
35865789Smckusick 
359*68049Smckusick 	high = isonum_733(p->dev_t_high);
360*68049Smckusick 	low  = isonum_733(p->dev_t_low);
36165789Smckusick 
36267377Smkm 	if (high == 0)
36367377Smkm 		ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
36467377Smkm 	else
36567377Smkm 		ana->inop->inode.iso_rdev = makedev(high, minor(low));
36665789Smckusick 	ana->fields &= ~ISO_SUSP_DEVICE;
36765789Smckusick 	return ISO_SUSP_DEVICE;
36865789Smckusick }
36965789Smckusick 
37065789Smckusick /*
37165789Smckusick  * Flag indicating
37265789Smckusick  */
37365789Smckusick static int
cd9660_rrip_idflag(p,ana)37465855Smckusick cd9660_rrip_idflag(p,ana)
37565789Smckusick 	ISO_RRIP_IDFLAG *p;
37665789Smckusick 	ISO_RRIP_ANALYZE *ana;
37765789Smckusick {
37865789Smckusick 	ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */
37965789Smckusick 	/* special handling of RE field */
38065789Smckusick 	if (ana->fields&ISO_SUSP_RELDIR)
38165855Smckusick 		return cd9660_rrip_reldir(p,ana);
38265789Smckusick 
38365789Smckusick 	return ISO_SUSP_IDFLAG;
38465789Smckusick }
38565789Smckusick 
38665789Smckusick /*
38765789Smckusick  * Continuation pointer
38865789Smckusick  */
38965789Smckusick static int
cd9660_rrip_cont(p,ana)39065855Smckusick cd9660_rrip_cont(p,ana)
39165789Smckusick 	ISO_RRIP_CONT *p;
39265789Smckusick 	ISO_RRIP_ANALYZE *ana;
39365789Smckusick {
39465789Smckusick 	ana->iso_ce_blk = isonum_733(p->location);
39565789Smckusick 	ana->iso_ce_off = isonum_733(p->offset);
39665789Smckusick 	ana->iso_ce_len = isonum_733(p->length);
39765789Smckusick 	return ISO_SUSP_CONT;
39865789Smckusick }
39965789Smckusick 
40065789Smckusick /*
40165789Smckusick  * System Use end
40265789Smckusick  */
40365789Smckusick static int
cd9660_rrip_stop(p,ana)40465855Smckusick cd9660_rrip_stop(p,ana)
40565789Smckusick 	ISO_SUSP_HEADER *p;
40665789Smckusick 	ISO_RRIP_ANALYZE *ana;
40765789Smckusick {
40865789Smckusick 	return ISO_SUSP_STOP;
40965789Smckusick }
41065789Smckusick 
41165789Smckusick /*
41265789Smckusick  * Extension reference
41365789Smckusick  */
41465789Smckusick static int
cd9660_rrip_extref(p,ana)41565855Smckusick cd9660_rrip_extref(p,ana)
41665789Smckusick 	ISO_RRIP_EXTREF *p;
41765789Smckusick 	ISO_RRIP_ANALYZE *ana;
41865789Smckusick {
41965789Smckusick 	if (isonum_711(p->len_id) != 10
42065789Smckusick 	    || bcmp((char *)p + 8,"RRIP_1991A",10)
42165789Smckusick 	    || isonum_711(p->version) != 1)
42265789Smckusick 		return 0;
42365789Smckusick 	ana->fields &= ~ISO_SUSP_EXTREF;
42465789Smckusick 	return ISO_SUSP_EXTREF;
42565789Smckusick }
42665789Smckusick 
42765789Smckusick typedef struct {
42865789Smckusick 	char type[2];
42965789Smckusick 	int (*func)();
43065789Smckusick 	void (*func2)();
43165789Smckusick 	int result;
43265789Smckusick } RRIP_TABLE;
43365789Smckusick 
43465789Smckusick static int
cd9660_rrip_loop(isodir,ana,table)43565855Smckusick cd9660_rrip_loop(isodir,ana,table)
43665789Smckusick 	struct iso_directory_record *isodir;
43765789Smckusick 	ISO_RRIP_ANALYZE *ana;
43865789Smckusick 	RRIP_TABLE *table;
43965789Smckusick {
44065789Smckusick 	register RRIP_TABLE *ptable;
44165789Smckusick 	register ISO_SUSP_HEADER *phead;
44265789Smckusick 	register ISO_SUSP_HEADER *pend;
44365789Smckusick 	struct buf *bp = NULL;
44465789Smckusick 	int i;
44565789Smckusick 	char *pwhead;
44665789Smckusick 	int result;
44765789Smckusick 
44865789Smckusick 	/*
44965789Smckusick 	 * Note: If name length is odd,
45065789Smckusick 	 *       it will be padding 1 byte  after the name
45165789Smckusick 	 */
45265789Smckusick 	pwhead = isodir->name + isonum_711(isodir->name_len);
45365789Smckusick 	if (!(isonum_711(isodir->name_len)&1))
45465789Smckusick 		pwhead++;
45565789Smckusick 
45665789Smckusick 	/* If it's not the '.' entry of the root dir obey SP field */
45765789Smckusick 	if (*isodir->name != 0
45865789Smckusick 	    || isonum_733(isodir->extent) != ana->imp->root_extent)
45965789Smckusick 		pwhead += ana->imp->rr_skip;
46065789Smckusick 	else
46165789Smckusick 		pwhead += ana->imp->rr_skip0;
46265789Smckusick 
46365789Smckusick 	phead = (ISO_SUSP_HEADER *)pwhead;
46465789Smckusick 	pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
46565789Smckusick 
46665789Smckusick 	result = 0;
46765789Smckusick 	while (1) {
46865789Smckusick 		ana->iso_ce_len = 0;
46965789Smckusick 		/*
47065789Smckusick 		 * Note: "pend" should be more than one SUSP header
47165789Smckusick 		 */
47265789Smckusick 		while (pend >= phead + 1) {
47365789Smckusick 			if (isonum_711(phead->version) == 1) {
47465789Smckusick 				for (ptable = table; ptable->func; ptable++) {
47565789Smckusick 					if (*phead->type == *ptable->type
47665789Smckusick 					    && phead->type[1] == ptable->type[1]) {
47765789Smckusick 						result |= ptable->func(phead,ana);
47865789Smckusick 						break;
47965789Smckusick 					}
48065789Smckusick 				}
48165789Smckusick 				if (!ana->fields)
48265789Smckusick 					break;
48365789Smckusick 			}
48467377Smkm 			if (result&ISO_SUSP_STOP) {
48567377Smkm 				result &= ~ISO_SUSP_STOP;
48667377Smkm 				break;
48767377Smkm 			}
48867377Smkm 			/* plausibility check */
48967377Smkm 			if (isonum_711(phead->length) < sizeof(*phead))
49067377Smkm 				break;
49165789Smckusick 			/*
49265789Smckusick 			 * move to next SUSP
49365789Smckusick 			 * Hopefully this works with newer versions, too
49465789Smckusick 			 */
49565789Smckusick 			phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
49665789Smckusick 		}
49765789Smckusick 
49867377Smkm 		if (ana->fields && ana->iso_ce_len) {
49965789Smckusick 			if (ana->iso_ce_blk >= ana->imp->volume_space_size
50065789Smckusick 			    || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
50165789Smckusick 			    || bread(ana->imp->im_devvp,
502*68049Smckusick 				     ana->iso_ce_blk <<
503*68049Smckusick 				     (ana->imp->im_bshift - DEV_BSHIFT),
504*68049Smckusick 				     ana->imp->logical_block_size, NOCRED, &bp))
50565789Smckusick 				/* what to do now? */
50665789Smckusick 				break;
507*68049Smckusick 			phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
50865789Smckusick 			pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
50965789Smckusick 		} else
51065789Smckusick 			break;
51165789Smckusick 	}
51265789Smckusick 	if (bp)
51365789Smckusick 		brelse(bp);
51465789Smckusick 	/*
51565789Smckusick 	 * If we don't find the Basic SUSP stuffs, just set default value
51667377Smkm 	 *   (attribute/time stamp)
51765789Smckusick 	 */
51865789Smckusick 	for (ptable = table; ptable->func2; ptable++)
51965789Smckusick 		if (!(ptable->result&result))
52065789Smckusick 			ptable->func2(isodir,ana);
52165789Smckusick 
52265789Smckusick 	return result;
52365789Smckusick }
52465789Smckusick 
52567377Smkm /*
52667377Smkm  * Get Attributes.
52767377Smkm  */
52865789Smckusick static RRIP_TABLE rrip_table_analyze[] = {
52965855Smckusick 	{ "PX", cd9660_rrip_attr,	cd9660_rrip_defattr,	ISO_SUSP_ATTR },
53065855Smckusick 	{ "TF", cd9660_rrip_tstamp,	cd9660_rrip_deftstamp,	ISO_SUSP_TSTAMP },
53165855Smckusick 	{ "PN", cd9660_rrip_device,	0,			ISO_SUSP_DEVICE },
53265855Smckusick 	{ "RR", cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
53365855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
53465855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
53565789Smckusick 	{ "",	0,			0,			0 }
53665789Smckusick };
53765789Smckusick 
53865789Smckusick int
cd9660_rrip_analyze(isodir,inop,imp)53965855Smckusick cd9660_rrip_analyze(isodir,inop,imp)
54065789Smckusick 	struct iso_directory_record *isodir;
54165789Smckusick 	struct iso_node *inop;
54265789Smckusick 	struct iso_mnt *imp;
54365789Smckusick {
54465789Smckusick 	ISO_RRIP_ANALYZE analyze;
54565789Smckusick 
54665789Smckusick 	analyze.inop = inop;
54765789Smckusick 	analyze.imp = imp;
54865789Smckusick 	analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE;
54965789Smckusick 
55065855Smckusick 	return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
55165789Smckusick }
55265789Smckusick 
55365789Smckusick /*
55467377Smkm  * Get Alternate Name.
55565789Smckusick  */
55665789Smckusick static RRIP_TABLE rrip_table_getname[] = {
55765855Smckusick 	{ "NM", cd9660_rrip_altname,	cd9660_rrip_defname,	ISO_SUSP_ALTNAME },
55865855Smckusick 	{ "CL", cd9660_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
55965855Smckusick 	{ "PL", cd9660_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
56065855Smckusick 	{ "RE", cd9660_rrip_reldir,	0,			ISO_SUSP_RELDIR },
56165855Smckusick 	{ "RR", cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
56265855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
56365855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
56465789Smckusick 	{ "",	0,			0,			0 }
56565789Smckusick };
56665789Smckusick 
56765789Smckusick int
cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)56865855Smckusick cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
56965789Smckusick 	struct iso_directory_record *isodir;
57065789Smckusick 	char *outbuf;
57165789Smckusick 	u_short *outlen;
57265789Smckusick 	ino_t *inump;
57365789Smckusick 	struct iso_mnt *imp;
57465789Smckusick {
57565789Smckusick 	ISO_RRIP_ANALYZE analyze;
57665789Smckusick 	RRIP_TABLE *tab;
57765789Smckusick 
57865789Smckusick 	analyze.outbuf = outbuf;
57965789Smckusick 	analyze.outlen = outlen;
58065789Smckusick 	analyze.maxlen = NAME_MAX;
58165789Smckusick 	analyze.inump = inump;
58265789Smckusick 	analyze.imp = imp;
58365789Smckusick 	analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
58465789Smckusick 	*outlen = 0;
58565789Smckusick 
58665789Smckusick 	tab = rrip_table_getname;
58765789Smckusick 	if (*isodir->name == 0
58865789Smckusick 	    || *isodir->name == 1) {
58965855Smckusick 		cd9660_rrip_defname(isodir,&analyze);
59065789Smckusick 
59165789Smckusick 		analyze.fields &= ~ISO_SUSP_ALTNAME;
59265789Smckusick 		tab++;
59365789Smckusick 	}
59465789Smckusick 
59565855Smckusick 	return cd9660_rrip_loop(isodir,&analyze,tab);
59665789Smckusick }
59765789Smckusick 
59865789Smckusick /*
59967377Smkm  * Get Symbolic Link.
60065789Smckusick  */
60165789Smckusick static RRIP_TABLE rrip_table_getsymname[] = {
60265855Smckusick 	{ "SL", cd9660_rrip_slink,	0,			ISO_SUSP_SLINK },
60365855Smckusick 	{ "RR", cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
60465855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
60565855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
60665789Smckusick 	{ "",	0,			0,			0 }
60765789Smckusick };
60865789Smckusick 
60965789Smckusick int
cd9660_rrip_getsymname(isodir,outbuf,outlen,imp)61065855Smckusick cd9660_rrip_getsymname(isodir,outbuf,outlen,imp)
61165789Smckusick 	struct iso_directory_record *isodir;
61265789Smckusick 	char *outbuf;
61365789Smckusick 	u_short *outlen;
61465789Smckusick 	struct iso_mnt *imp;
61565789Smckusick {
61665789Smckusick 	ISO_RRIP_ANALYZE analyze;
61765789Smckusick 
61865789Smckusick 	analyze.outbuf = outbuf;
61967699Smckusick 	analyze.outlen = outlen;
62065789Smckusick 	*outlen = 0;
62165789Smckusick 	analyze.maxlen = MAXPATHLEN;
62265789Smckusick 	analyze.cont = 1;		/* don't start with a slash */
62365789Smckusick 	analyze.imp = imp;
62465789Smckusick 	analyze.fields = ISO_SUSP_SLINK;
62565789Smckusick 
62665855Smckusick 	return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK);
62765789Smckusick }
62865789Smckusick 
62965789Smckusick static RRIP_TABLE rrip_table_extref[] = {
63065855Smckusick 	{ "ER", cd9660_rrip_extref,	0,			ISO_SUSP_EXTREF },
63165855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
63265855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
63365789Smckusick 	{ "",	0,			0,			0 }
63465789Smckusick };
63565789Smckusick 
63665789Smckusick /*
63765789Smckusick  * Check for Rock Ridge Extension and return offset of its fields.
63867377Smkm  * Note: We insist on the ER field.
63965789Smckusick  */
64065789Smckusick int
cd9660_rrip_offset(isodir,imp)64165855Smckusick cd9660_rrip_offset(isodir,imp)
64265789Smckusick 	struct iso_directory_record *isodir;
64365789Smckusick 	struct iso_mnt *imp;
64465789Smckusick {
64565789Smckusick 	ISO_RRIP_OFFSET *p;
64665789Smckusick 	ISO_RRIP_ANALYZE analyze;
64765789Smckusick 
64865789Smckusick 	imp->rr_skip0 = 0;
64965789Smckusick 	p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
65065789Smckusick 	if (bcmp(p,"SP\7\1\276\357",6)) {
65165789Smckusick 		/* Maybe, it's a CDROM XA disc? */
65265789Smckusick 		imp->rr_skip0 = 15;
65365789Smckusick 		p = (ISO_RRIP_OFFSET *)((char *)p + 15);
65465789Smckusick 		if (bcmp(p,"SP\7\1\276\357",6))
65565789Smckusick 			return -1;
65665789Smckusick 	}
65765789Smckusick 
65865789Smckusick 	analyze.imp = imp;
65965789Smckusick 	analyze.fields = ISO_SUSP_EXTREF;
66065855Smckusick 	if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
66165789Smckusick 		return -1;
66265789Smckusick 
66365789Smckusick 	return isonum_711(p->skip);
66465789Smckusick }
665