xref: /csrg-svn/sys/isofs/cd9660/cd9660_rrip.c (revision 67699)
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*67699Smckusick  *	@(#)cd9660_rrip.c	8.5 (Berkeley) 08/17/94
1365789Smckusick  */
1465789Smckusick 
1565789Smckusick #include <sys/param.h>
1665789Smckusick #include <sys/namei.h>
1765789Smckusick #include <sys/buf.h>
1865789Smckusick #include <sys/file.h>
1965789Smckusick #include <sys/vnode.h>
2065789Smckusick #include <sys/mount.h>
2165789Smckusick #include <sys/kernel.h>
2265789Smckusick #include <sys/stat.h>
2365789Smckusick #include <sys/types.h>
2465789Smckusick 
2565789Smckusick #include <sys/time.h>
2665789Smckusick 
2765789Smckusick #include <isofs/cd9660/iso.h>
2865855Smckusick #include <isofs/cd9660/cd9660_node.h>
2965855Smckusick #include <isofs/cd9660/cd9660_rrip.h>
3065789Smckusick #include <isofs/cd9660/iso_rrip.h>
3165789Smckusick 
3265789Smckusick /*
3365789Smckusick  * POSIX file attribute
3465789Smckusick  */
3565789Smckusick static int
3665855Smckusick cd9660_rrip_attr(p,ana)
3765789Smckusick 	ISO_RRIP_ATTR *p;
3865789Smckusick 	ISO_RRIP_ANALYZE *ana;
3965789Smckusick {
4065789Smckusick 	ana->inop->inode.iso_mode = isonum_731(p->mode_l);
4165789Smckusick 	ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
4265789Smckusick 	ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
4365789Smckusick 	ana->inop->inode.iso_links = isonum_731(p->links_l);
4465789Smckusick 	ana->fields &= ~ISO_SUSP_ATTR;
4565789Smckusick 	return ISO_SUSP_ATTR;
4665789Smckusick }
4765789Smckusick 
4865789Smckusick static void
4965855Smckusick cd9660_rrip_defattr(isodir,ana)
5065789Smckusick 	struct iso_directory_record *isodir;
5165789Smckusick 	ISO_RRIP_ANALYZE *ana;
5265789Smckusick {
5365789Smckusick 	/* But this is a required field! */
5465789Smckusick 	printf("RRIP without PX field?\n");
5565855Smckusick 	cd9660_defattr(isodir,ana->inop,NULL);
5665789Smckusick }
5765789Smckusick 
5865789Smckusick /*
5965789Smckusick  * Symbolic Links
6065789Smckusick  */
6165789Smckusick static int
6265855Smckusick cd9660_rrip_slink(p,ana)
6365789Smckusick 	ISO_RRIP_SLINK  *p;
6465789Smckusick 	ISO_RRIP_ANALYZE *ana;
6565789Smckusick {
6665789Smckusick 	register ISO_RRIP_SLINK_COMPONENT *pcomp;
6765789Smckusick 	register ISO_RRIP_SLINK_COMPONENT *pcompe;
6865789Smckusick 	int len, wlen, cont;
6965789Smckusick 	char *outbuf, *inbuf;
7065789Smckusick 
7165789Smckusick 	pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
7265789Smckusick 	pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
7365789Smckusick 	len = *ana->outlen;
7465789Smckusick 	outbuf = ana->outbuf;
7565789Smckusick 	cont = ana->cont;
7665789Smckusick 
7765789Smckusick 	/*
7865789Smckusick 	 * Gathering a Symbolic name from each component with path
7965789Smckusick 	 */
8065789Smckusick 	for (;
8165789Smckusick 	     pcomp < pcompe;
8265789Smckusick 	     pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
8365789Smckusick 						  + isonum_711(pcomp->clen))) {
8465789Smckusick 
8565789Smckusick 		if (!cont) {
8665789Smckusick 			if (len < ana->maxlen) {
8765789Smckusick 				len++;
8865789Smckusick 				*outbuf++ = '/';
8965789Smckusick 			}
9065789Smckusick 		}
9165789Smckusick 		cont = 0;
9265789Smckusick 
9365789Smckusick 		inbuf = "..";
9465789Smckusick 		wlen = 0;
9565789Smckusick 
9665789Smckusick 		switch (*pcomp->cflag) {
9765789Smckusick 
9865789Smckusick 		case ISO_SUSP_CFLAG_CURRENT:
9965789Smckusick 			/* Inserting Current */
10065789Smckusick 			wlen = 1;
10165789Smckusick 			break;
10265789Smckusick 
10365789Smckusick 		case ISO_SUSP_CFLAG_PARENT:
10465789Smckusick 			/* Inserting Parent */
10565789Smckusick 			wlen = 2;
10665789Smckusick 			break;
10765789Smckusick 
10865789Smckusick 		case ISO_SUSP_CFLAG_ROOT:
10965789Smckusick 			/* Inserting slash for ROOT */
11065789Smckusick 			/* start over from beginning(?) */
11165789Smckusick 			outbuf -= len;
11265789Smckusick 			len = 0;
11365789Smckusick 			break;
11465789Smckusick 
11565789Smckusick 		case ISO_SUSP_CFLAG_VOLROOT:
11665789Smckusick 			/* Inserting a mount point i.e. "/cdrom" */
11765789Smckusick 			/* same as above */
11865789Smckusick 			outbuf -= len;
11965789Smckusick 			len = 0;
12065789Smckusick 			inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
12165789Smckusick 			wlen = strlen(inbuf);
12265789Smckusick 			break;
12365789Smckusick 
12465789Smckusick 		case ISO_SUSP_CFLAG_HOST:
12565789Smckusick 			/* Inserting hostname i.e. "kurt.tools.de" */
12665789Smckusick 			inbuf = hostname;
12765789Smckusick 			wlen = hostnamelen;
12865789Smckusick 			break;
12965789Smckusick 
13065789Smckusick 		case ISO_SUSP_CFLAG_CONTINUE:
13165789Smckusick 			cont = 1;
13265789Smckusick 			/* fall thru */
13365789Smckusick 		case 0:
13465789Smckusick 			/* Inserting component */
13565789Smckusick 			wlen = isonum_711(pcomp->clen);
13665789Smckusick 			inbuf = pcomp->name;
13765789Smckusick 			break;
13865789Smckusick 		default:
13965789Smckusick 			printf("RRIP with incorrect flags?");
14065789Smckusick 			wlen = ana->maxlen + 1;
14165789Smckusick 			break;
14265789Smckusick 		}
14365789Smckusick 
14465789Smckusick 		if (len + wlen > ana->maxlen) {
14565789Smckusick 			/* indicate error to caller */
14665789Smckusick 			ana->cont = 1;
14765789Smckusick 			ana->fields = 0;
14865789Smckusick 			ana->outbuf -= *ana->outlen;
14965789Smckusick 			*ana->outlen = 0;
15065789Smckusick 			return 0;
15165789Smckusick 		}
15265789Smckusick 
15365789Smckusick 		bcopy(inbuf,outbuf,wlen);
15465789Smckusick 		outbuf += wlen;
15565789Smckusick 		len += wlen;
15665789Smckusick 
15765789Smckusick 	}
15865789Smckusick 	ana->outbuf = outbuf;
15965789Smckusick 	*ana->outlen = len;
16065789Smckusick 	ana->cont = cont;
16165789Smckusick 
16265789Smckusick 	if (!isonum_711(p->flags)) {
16365789Smckusick 		ana->fields &= ~ISO_SUSP_SLINK;
16465789Smckusick 		return ISO_SUSP_SLINK;
16565789Smckusick 	}
16665789Smckusick 	return 0;
16765789Smckusick }
16865789Smckusick 
16965789Smckusick /*
17065789Smckusick  * Alternate name
17165789Smckusick  */
17265789Smckusick static int
17365855Smckusick cd9660_rrip_altname(p,ana)
17465789Smckusick 	ISO_RRIP_ALTNAME *p;
17565789Smckusick 	ISO_RRIP_ANALYZE *ana;
17665789Smckusick {
17765789Smckusick 	char *inbuf;
17865789Smckusick 	int wlen;
17965789Smckusick 	int cont;
18065789Smckusick 
18165789Smckusick 	inbuf = "..";
18265789Smckusick 	wlen = 0;
18365789Smckusick 	cont = 0;
18465789Smckusick 
18565789Smckusick 	switch (*p->flags) {
18665789Smckusick 	case ISO_SUSP_CFLAG_CURRENT:
18765789Smckusick 		/* Inserting Current */
18865789Smckusick 		wlen = 1;
18965789Smckusick 		break;
19065789Smckusick 
19165789Smckusick 	case ISO_SUSP_CFLAG_PARENT:
19265789Smckusick 		/* Inserting Parent */
19365789Smckusick 		wlen = 2;
19465789Smckusick 		break;
19565789Smckusick 
19665789Smckusick 	case ISO_SUSP_CFLAG_HOST:
19765789Smckusick 		/* Inserting hostname i.e. "kurt.tools.de" */
19865789Smckusick 		inbuf = hostname;
19965789Smckusick 		wlen = hostnamelen;
20065789Smckusick 		break;
20165789Smckusick 
20265789Smckusick 	case ISO_SUSP_CFLAG_CONTINUE:
20365789Smckusick 		cont = 1;
20465789Smckusick 		/* fall thru */
20565789Smckusick 	case 0:
20665789Smckusick 		/* Inserting component */
20765789Smckusick 		wlen = isonum_711(p->h.length) - 5;
20865789Smckusick 		inbuf = (char *)p + 5;
20965789Smckusick 		break;
21065789Smckusick 
21165789Smckusick 	default:
21265789Smckusick 		printf("RRIP with incorrect NM flags?\n");
21365789Smckusick 		wlen = ana->maxlen + 1;
21465789Smckusick 		break;
21565789Smckusick 	}
21665789Smckusick 
21765789Smckusick 	if ((*ana->outlen += wlen) > ana->maxlen) {
21865789Smckusick 		/* treat as no name field */
21965789Smckusick 		ana->fields &= ~ISO_SUSP_ALTNAME;
22065789Smckusick 		ana->outbuf -= *ana->outlen - wlen;
22165789Smckusick 		*ana->outlen = 0;
22265789Smckusick 		return 0;
22365789Smckusick 	}
22465789Smckusick 
22565789Smckusick 	bcopy(inbuf,ana->outbuf,wlen);
22665789Smckusick 	ana->outbuf += wlen;
22765789Smckusick 
22865789Smckusick 	if (!cont) {
22965789Smckusick 		ana->fields &= ~ISO_SUSP_ALTNAME;
23065789Smckusick 		return ISO_SUSP_ALTNAME;
23165789Smckusick 	}
23265789Smckusick 	return 0;
23365789Smckusick }
23465789Smckusick 
23565789Smckusick static void
23665855Smckusick cd9660_rrip_defname(isodir,ana)
23765789Smckusick 	struct iso_directory_record *isodir;
23865789Smckusick 	ISO_RRIP_ANALYZE *ana;
23965789Smckusick {
24065789Smckusick 	strcpy(ana->outbuf,"..");
24165789Smckusick 	switch (*isodir->name) {
24265789Smckusick 	default:
24365789Smckusick 		isofntrans(isodir->name,isonum_711(isodir->name_len),
24465789Smckusick 			   ana->outbuf,ana->outlen,
24565789Smckusick 			   1,isonum_711(isodir->flags)&4);
24665789Smckusick 		break;
24765789Smckusick 	case 0:
24865789Smckusick 		*ana->outlen = 1;
24965789Smckusick 		break;
25065789Smckusick 	case 1:
25165789Smckusick 		*ana->outlen = 2;
25265789Smckusick 		break;
25365789Smckusick 	}
25465789Smckusick }
25565789Smckusick 
25665789Smckusick /*
25765789Smckusick  * Parent or Child Link
25865789Smckusick  */
25965789Smckusick static int
26065855Smckusick cd9660_rrip_pclink(p,ana)
26165789Smckusick 	ISO_RRIP_CLINK  *p;
26265789Smckusick 	ISO_RRIP_ANALYZE *ana;
26365789Smckusick {
26465789Smckusick 	*ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
26565789Smckusick 	ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK);
26665789Smckusick 	return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK;
26765789Smckusick }
26865789Smckusick 
26965789Smckusick /*
27065789Smckusick  * Relocated directory
27165789Smckusick  */
27265789Smckusick static int
27365855Smckusick cd9660_rrip_reldir(p,ana)
27465789Smckusick 	ISO_RRIP_RELDIR  *p;
27565789Smckusick 	ISO_RRIP_ANALYZE *ana;
27665789Smckusick {
27765789Smckusick 	/* special hack to make caller aware of RE field */
27865789Smckusick 	*ana->outlen = 0;
27965789Smckusick 	ana->fields = 0;
28065789Smckusick 	return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
28165789Smckusick }
28265789Smckusick 
28365789Smckusick static int
28465855Smckusick cd9660_rrip_tstamp(p,ana)
28565789Smckusick 	ISO_RRIP_TSTAMP *p;
28665789Smckusick 	ISO_RRIP_ANALYZE *ana;
28765789Smckusick {
28865789Smckusick 	unsigned char *ptime;
28965789Smckusick 
29065789Smckusick 	ptime = p->time;
29165789Smckusick 
29265789Smckusick 	/* Check a format of time stamp (7bytes/17bytes) */
29365789Smckusick 	if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) {
29465789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
29565789Smckusick 			ptime += 7;
29665789Smckusick 
29765789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
29865855Smckusick 			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime);
29965789Smckusick 			ptime += 7;
30065789Smckusick 		} else
30165789Smckusick 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval));
30265789Smckusick 
30365789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
30465855Smckusick 			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime);
30565789Smckusick 			ptime += 7;
30665789Smckusick 		} else
30765789Smckusick 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
30865789Smckusick 
30965789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
31065855Smckusick 			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime);
31165789Smckusick 		else
31265789Smckusick 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
31365789Smckusick 
31465789Smckusick 	} else {
31565789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
31665789Smckusick 			ptime += 17;
31765789Smckusick 
31865789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
31965855Smckusick 			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime);
32065789Smckusick 			ptime += 17;
32165789Smckusick 		} else
32265789Smckusick 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval));
32365789Smckusick 
32465789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
32565855Smckusick 			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
32665789Smckusick 			ptime += 17;
32765789Smckusick 		} else
32865789Smckusick 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
32965789Smckusick 
33065789Smckusick 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
33165855Smckusick 			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime);
33265789Smckusick 		else
33365789Smckusick 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
33465789Smckusick 
33565789Smckusick 	}
33665789Smckusick 	ana->fields &= ~ISO_SUSP_TSTAMP;
33765789Smckusick 	return ISO_SUSP_TSTAMP;
33865789Smckusick }
33965789Smckusick 
34065789Smckusick static void
34165855Smckusick cd9660_rrip_deftstamp(isodir,ana)
34265789Smckusick 	struct iso_directory_record  *isodir;
34365789Smckusick 	ISO_RRIP_ANALYZE *ana;
34465789Smckusick {
34565855Smckusick 	cd9660_deftstamp(isodir,ana->inop,NULL);
34665789Smckusick }
34765789Smckusick 
34865789Smckusick /*
34965789Smckusick  * POSIX device modes
35065789Smckusick  */
35165789Smckusick static int
35265855Smckusick cd9660_rrip_device(p,ana)
35365789Smckusick 	ISO_RRIP_DEVICE *p;
35465789Smckusick 	ISO_RRIP_ANALYZE *ana;
35565789Smckusick {
35665789Smckusick 	unsigned high, low;
35765789Smckusick 
35865789Smckusick 	high = isonum_733(p->dev_t_high_l);
35965789Smckusick 	low  = isonum_733(p->dev_t_low_l);
36065789Smckusick 
36167377Smkm 	if (high == 0)
36267377Smkm 		ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
36367377Smkm 	else
36467377Smkm 		ana->inop->inode.iso_rdev = makedev(high, minor(low));
36565789Smckusick 	ana->fields &= ~ISO_SUSP_DEVICE;
36665789Smckusick 	return ISO_SUSP_DEVICE;
36765789Smckusick }
36865789Smckusick 
36965789Smckusick /*
37065789Smckusick  * Flag indicating
37165789Smckusick  */
37265789Smckusick static int
37365855Smckusick cd9660_rrip_idflag(p,ana)
37465789Smckusick 	ISO_RRIP_IDFLAG *p;
37565789Smckusick 	ISO_RRIP_ANALYZE *ana;
37665789Smckusick {
37765789Smckusick 	ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */
37865789Smckusick 	/* special handling of RE field */
37965789Smckusick 	if (ana->fields&ISO_SUSP_RELDIR)
38065855Smckusick 		return cd9660_rrip_reldir(p,ana);
38165789Smckusick 
38265789Smckusick 	return ISO_SUSP_IDFLAG;
38365789Smckusick }
38465789Smckusick 
38565789Smckusick /*
38665789Smckusick  * Continuation pointer
38765789Smckusick  */
38865789Smckusick static int
38965855Smckusick cd9660_rrip_cont(p,ana)
39065789Smckusick 	ISO_RRIP_CONT *p;
39165789Smckusick 	ISO_RRIP_ANALYZE *ana;
39265789Smckusick {
39365789Smckusick 	ana->iso_ce_blk = isonum_733(p->location);
39465789Smckusick 	ana->iso_ce_off = isonum_733(p->offset);
39565789Smckusick 	ana->iso_ce_len = isonum_733(p->length);
39665789Smckusick 	return ISO_SUSP_CONT;
39765789Smckusick }
39865789Smckusick 
39965789Smckusick /*
40065789Smckusick  * System Use end
40165789Smckusick  */
40265789Smckusick static int
40365855Smckusick cd9660_rrip_stop(p,ana)
40465789Smckusick 	ISO_SUSP_HEADER *p;
40565789Smckusick 	ISO_RRIP_ANALYZE *ana;
40665789Smckusick {
40765789Smckusick 	return ISO_SUSP_STOP;
40865789Smckusick }
40965789Smckusick 
41065789Smckusick /*
41165789Smckusick  * Extension reference
41265789Smckusick  */
41365789Smckusick static int
41465855Smckusick cd9660_rrip_extref(p,ana)
41565789Smckusick 	ISO_RRIP_EXTREF *p;
41665789Smckusick 	ISO_RRIP_ANALYZE *ana;
41765789Smckusick {
41865789Smckusick 	if (isonum_711(p->len_id) != 10
41965789Smckusick 	    || bcmp((char *)p + 8,"RRIP_1991A",10)
42065789Smckusick 	    || isonum_711(p->version) != 1)
42165789Smckusick 		return 0;
42265789Smckusick 	ana->fields &= ~ISO_SUSP_EXTREF;
42365789Smckusick 	return ISO_SUSP_EXTREF;
42465789Smckusick }
42565789Smckusick 
42665789Smckusick typedef struct {
42765789Smckusick 	char type[2];
42865789Smckusick 	int (*func)();
42965789Smckusick 	void (*func2)();
43065789Smckusick 	int result;
43165789Smckusick } RRIP_TABLE;
43265789Smckusick 
43365789Smckusick static int
43465855Smckusick cd9660_rrip_loop(isodir,ana,table)
43565789Smckusick 	struct iso_directory_record *isodir;
43665789Smckusick 	ISO_RRIP_ANALYZE *ana;
43765789Smckusick 	RRIP_TABLE *table;
43865789Smckusick {
43965789Smckusick 	register RRIP_TABLE *ptable;
44065789Smckusick 	register ISO_SUSP_HEADER *phead;
44165789Smckusick 	register ISO_SUSP_HEADER *pend;
44265789Smckusick 	struct buf *bp = NULL;
44365789Smckusick 	int i;
44465789Smckusick 	char *pwhead;
44565789Smckusick 	int result;
44665789Smckusick 
44765789Smckusick 	/*
44865789Smckusick 	 * Note: If name length is odd,
44965789Smckusick 	 *       it will be padding 1 byte  after the name
45065789Smckusick 	 */
45165789Smckusick 	pwhead = isodir->name + isonum_711(isodir->name_len);
45265789Smckusick 	if (!(isonum_711(isodir->name_len)&1))
45365789Smckusick 		pwhead++;
45465789Smckusick 
45565789Smckusick 	/* If it's not the '.' entry of the root dir obey SP field */
45665789Smckusick 	if (*isodir->name != 0
45765789Smckusick 	    || isonum_733(isodir->extent) != ana->imp->root_extent)
45865789Smckusick 		pwhead += ana->imp->rr_skip;
45965789Smckusick 	else
46065789Smckusick 		pwhead += ana->imp->rr_skip0;
46165789Smckusick 
46265789Smckusick 	phead = (ISO_SUSP_HEADER *)pwhead;
46365789Smckusick 	pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
46465789Smckusick 
46565789Smckusick 	result = 0;
46665789Smckusick 	while (1) {
46765789Smckusick 		ana->iso_ce_len = 0;
46865789Smckusick 		/*
46965789Smckusick 		 * Note: "pend" should be more than one SUSP header
47065789Smckusick 		 */
47165789Smckusick 		while (pend >= phead + 1) {
47265789Smckusick 			if (isonum_711(phead->version) == 1) {
47365789Smckusick 				for (ptable = table; ptable->func; ptable++) {
47465789Smckusick 					if (*phead->type == *ptable->type
47565789Smckusick 					    && phead->type[1] == ptable->type[1]) {
47665789Smckusick 						result |= ptable->func(phead,ana);
47765789Smckusick 						break;
47865789Smckusick 					}
47965789Smckusick 				}
48065789Smckusick 				if (!ana->fields)
48165789Smckusick 					break;
48265789Smckusick 			}
48367377Smkm 			if (result&ISO_SUSP_STOP) {
48467377Smkm 				result &= ~ISO_SUSP_STOP;
48567377Smkm 				break;
48667377Smkm 			}
48767377Smkm 			/* plausibility check */
48867377Smkm 			if (isonum_711(phead->length) < sizeof(*phead))
48967377Smkm 				break;
49065789Smckusick 			/*
49165789Smckusick 			 * move to next SUSP
49265789Smckusick 			 * Hopefully this works with newer versions, too
49365789Smckusick 			 */
49465789Smckusick 			phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
49565789Smckusick 		}
49665789Smckusick 
49767377Smkm 		if (ana->fields && ana->iso_ce_len) {
49865789Smckusick 			if (ana->iso_ce_blk >= ana->imp->volume_space_size
49965789Smckusick 			    || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
50065789Smckusick 			    || bread(ana->imp->im_devvp,
50165789Smckusick 				     ana->iso_ce_blk * ana->imp->logical_block_size / DEV_BSIZE,
50265789Smckusick 				     ana->imp->logical_block_size,NOCRED,&bp))
50365789Smckusick 				/* what to do now? */
50465789Smckusick 				break;
50565789Smckusick 			phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off);
50665789Smckusick 			pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
50765789Smckusick 		} else
50865789Smckusick 			break;
50965789Smckusick 	}
51065789Smckusick 	if (bp)
51165789Smckusick 		brelse(bp);
51265789Smckusick 	/*
51365789Smckusick 	 * If we don't find the Basic SUSP stuffs, just set default value
51467377Smkm 	 *   (attribute/time stamp)
51565789Smckusick 	 */
51665789Smckusick 	for (ptable = table; ptable->func2; ptable++)
51765789Smckusick 		if (!(ptable->result&result))
51865789Smckusick 			ptable->func2(isodir,ana);
51965789Smckusick 
52065789Smckusick 	return result;
52165789Smckusick }
52265789Smckusick 
52367377Smkm /*
52467377Smkm  * Get Attributes.
52567377Smkm  */
52665789Smckusick static RRIP_TABLE rrip_table_analyze[] = {
52765855Smckusick 	{ "PX", cd9660_rrip_attr,	cd9660_rrip_defattr,	ISO_SUSP_ATTR },
52865855Smckusick 	{ "TF", cd9660_rrip_tstamp,	cd9660_rrip_deftstamp,	ISO_SUSP_TSTAMP },
52965855Smckusick 	{ "PN", cd9660_rrip_device,	0,			ISO_SUSP_DEVICE },
53065855Smckusick 	{ "RR", cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
53165855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
53265855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
53365789Smckusick 	{ "",	0,			0,			0 }
53465789Smckusick };
53565789Smckusick 
53665789Smckusick int
53765855Smckusick cd9660_rrip_analyze(isodir,inop,imp)
53865789Smckusick 	struct iso_directory_record *isodir;
53965789Smckusick 	struct iso_node *inop;
54065789Smckusick 	struct iso_mnt *imp;
54165789Smckusick {
54265789Smckusick 	ISO_RRIP_ANALYZE analyze;
54365789Smckusick 
54465789Smckusick 	analyze.inop = inop;
54565789Smckusick 	analyze.imp = imp;
54665789Smckusick 	analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE;
54765789Smckusick 
54865855Smckusick 	return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
54965789Smckusick }
55065789Smckusick 
55165789Smckusick /*
55267377Smkm  * Get Alternate Name.
55365789Smckusick  */
55465789Smckusick static RRIP_TABLE rrip_table_getname[] = {
55565855Smckusick 	{ "NM", cd9660_rrip_altname,	cd9660_rrip_defname,	ISO_SUSP_ALTNAME },
55665855Smckusick 	{ "CL", cd9660_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
55765855Smckusick 	{ "PL", cd9660_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
55865855Smckusick 	{ "RE", cd9660_rrip_reldir,	0,			ISO_SUSP_RELDIR },
55965855Smckusick 	{ "RR", cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
56065855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
56165855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
56265789Smckusick 	{ "",	0,			0,			0 }
56365789Smckusick };
56465789Smckusick 
56565789Smckusick int
56665855Smckusick cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
56765789Smckusick 	struct iso_directory_record *isodir;
56865789Smckusick 	char *outbuf;
56965789Smckusick 	u_short *outlen;
57065789Smckusick 	ino_t *inump;
57165789Smckusick 	struct iso_mnt *imp;
57265789Smckusick {
57365789Smckusick 	ISO_RRIP_ANALYZE analyze;
57465789Smckusick 	RRIP_TABLE *tab;
57565789Smckusick 
57665789Smckusick 	analyze.outbuf = outbuf;
57765789Smckusick 	analyze.outlen = outlen;
57865789Smckusick 	analyze.maxlen = NAME_MAX;
57965789Smckusick 	analyze.inump = inump;
58065789Smckusick 	analyze.imp = imp;
58165789Smckusick 	analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
58265789Smckusick 	*outlen = 0;
58365789Smckusick 
58465789Smckusick 	tab = rrip_table_getname;
58565789Smckusick 	if (*isodir->name == 0
58665789Smckusick 	    || *isodir->name == 1) {
58765855Smckusick 		cd9660_rrip_defname(isodir,&analyze);
58865789Smckusick 
58965789Smckusick 		analyze.fields &= ~ISO_SUSP_ALTNAME;
59065789Smckusick 		tab++;
59165789Smckusick 	}
59265789Smckusick 
59365855Smckusick 	return cd9660_rrip_loop(isodir,&analyze,tab);
59465789Smckusick }
59565789Smckusick 
59665789Smckusick /*
59767377Smkm  * Get Symbolic Link.
59865789Smckusick  */
59965789Smckusick static RRIP_TABLE rrip_table_getsymname[] = {
60065855Smckusick 	{ "SL", cd9660_rrip_slink,	0,			ISO_SUSP_SLINK },
60165855Smckusick 	{ "RR", cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
60265855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
60365855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
60465789Smckusick 	{ "",	0,			0,			0 }
60565789Smckusick };
60665789Smckusick 
60765789Smckusick int
60865855Smckusick cd9660_rrip_getsymname(isodir,outbuf,outlen,imp)
60965789Smckusick 	struct iso_directory_record *isodir;
61065789Smckusick 	char *outbuf;
61165789Smckusick 	u_short *outlen;
61265789Smckusick 	struct iso_mnt *imp;
61365789Smckusick {
61465789Smckusick 	ISO_RRIP_ANALYZE analyze;
61565789Smckusick 
61665789Smckusick 	analyze.outbuf = outbuf;
617*67699Smckusick 	analyze.outlen = outlen;
61865789Smckusick 	*outlen = 0;
61965789Smckusick 	analyze.maxlen = MAXPATHLEN;
62065789Smckusick 	analyze.cont = 1;		/* don't start with a slash */
62165789Smckusick 	analyze.imp = imp;
62265789Smckusick 	analyze.fields = ISO_SUSP_SLINK;
62365789Smckusick 
62465855Smckusick 	return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK);
62565789Smckusick }
62665789Smckusick 
62765789Smckusick static RRIP_TABLE rrip_table_extref[] = {
62865855Smckusick 	{ "ER", cd9660_rrip_extref,	0,			ISO_SUSP_EXTREF },
62965855Smckusick 	{ "CE", cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
63065855Smckusick 	{ "ST", cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
63165789Smckusick 	{ "",	0,			0,			0 }
63265789Smckusick };
63365789Smckusick 
63465789Smckusick /*
63565789Smckusick  * Check for Rock Ridge Extension and return offset of its fields.
63667377Smkm  * Note: We insist on the ER field.
63765789Smckusick  */
63865789Smckusick int
63965855Smckusick cd9660_rrip_offset(isodir,imp)
64065789Smckusick 	struct iso_directory_record *isodir;
64165789Smckusick 	struct iso_mnt *imp;
64265789Smckusick {
64365789Smckusick 	ISO_RRIP_OFFSET *p;
64465789Smckusick 	ISO_RRIP_ANALYZE analyze;
64565789Smckusick 
64665789Smckusick 	imp->rr_skip0 = 0;
64765789Smckusick 	p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
64865789Smckusick 	if (bcmp(p,"SP\7\1\276\357",6)) {
64965789Smckusick 		/* Maybe, it's a CDROM XA disc? */
65065789Smckusick 		imp->rr_skip0 = 15;
65165789Smckusick 		p = (ISO_RRIP_OFFSET *)((char *)p + 15);
65265789Smckusick 		if (bcmp(p,"SP\7\1\276\357",6))
65365789Smckusick 			return -1;
65465789Smckusick 	}
65565789Smckusick 
65665789Smckusick 	analyze.imp = imp;
65765789Smckusick 	analyze.fields = ISO_SUSP_EXTREF;
65865855Smckusick 	if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
65965789Smckusick 		return -1;
66065789Smckusick 
66165789Smckusick 	return isonum_711(p->skip);
66265789Smckusick }
663