cd9660_rrip.c revision 120492
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 1993, 1994
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software contributed to Berkeley
61541Srgrimes * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
71541Srgrimes * Support code is derived from software contributed to Berkeley
81541Srgrimes * by Atsushi Murai (amurai@spec.co.jp).
91541Srgrimes *
101541Srgrimes * Redistribution and use in source and binary forms, with or without
111541Srgrimes * modification, are permitted provided that the following conditions
121541Srgrimes * are met:
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in the
171541Srgrimes *    documentation and/or other materials provided with the distribution.
181541Srgrimes * 3. All advertising materials mentioning features or use of this software
191541Srgrimes *    must display the following acknowledgement:
201541Srgrimes *	This product includes software developed by the University of
211541Srgrimes *	California, Berkeley and its contributors.
221541Srgrimes * 4. Neither the name of the University nor the names of its contributors
231541Srgrimes *    may be used to endorse or promote products derived from this software
241541Srgrimes *    without specific prior written permission.
251541Srgrimes *
261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361541Srgrimes * SUCH DAMAGE.
371541Srgrimes *
3822521Sdyson *	@(#)cd9660_rrip.c	8.6 (Berkeley) 12/5/94
391541Srgrimes */
401541Srgrimes
41116181Sobrien#include <sys/cdefs.h>
42116181Sobrien__FBSDID("$FreeBSD: head/sys/fs/cd9660/cd9660_rrip.c 120492 2003-09-26 20:26:25Z fjoe $");
43116181Sobrien
441541Srgrimes#include <sys/param.h>
452806Sbde#include <sys/systm.h>
4660041Sphk#include <sys/bio.h>
471541Srgrimes#include <sys/buf.h>
481541Srgrimes#include <sys/vnode.h>
491541Srgrimes#include <sys/mount.h>
501541Srgrimes#include <sys/kernel.h>
511541Srgrimes
521541Srgrimes#include <isofs/cd9660/iso.h>
531541Srgrimes#include <isofs/cd9660/cd9660_node.h>
541541Srgrimes#include <isofs/cd9660/cd9660_rrip.h>
551541Srgrimes#include <isofs/cd9660/iso_rrip.h>
561541Srgrimes
5792765Salfredtypedef int	rrt_func_t(void *, ISO_RRIP_ANALYZE *ana);
5812597Sbde
5912597Sbdetypedef struct {
6012597Sbde	char type[2];
6112597Sbde	rrt_func_t *func;
6292765Salfred	void (*func2)(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana);
6312597Sbde	int result;
6412597Sbde} RRIP_TABLE;
6512597Sbde
6692765Salfredstatic int	cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana);
6792765Salfredstatic int	cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana);
6892765Salfredstatic int	cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana);
6992765Salfredstatic void	cd9660_rrip_defattr(struct iso_directory_record *isodir,
7093075Sbde		    ISO_RRIP_ANALYZE *ana);
7192765Salfredstatic void	cd9660_rrip_defname(struct iso_directory_record *isodir,
7293075Sbde		    ISO_RRIP_ANALYZE *ana);
7392765Salfredstatic void	cd9660_rrip_deftstamp(struct iso_directory_record *isodir,
7493075Sbde		    ISO_RRIP_ANALYZE *ana);
7592765Salfredstatic int	cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana);
7692765Salfredstatic int	cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana);
7792765Salfredstatic int	cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana);
7892765Salfredstatic int	cd9660_rrip_loop(struct iso_directory_record *isodir,
7993075Sbde		    ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table);
8092765Salfredstatic int	cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana);
8192765Salfredstatic int	cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana);
8292765Salfredstatic int	cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana);
8392765Salfredstatic int	cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana);
8492765Salfredstatic int	cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana);
8512597Sbde
861541Srgrimes/*
871541Srgrimes * POSIX file attribute
881541Srgrimes */
891541Srgrimesstatic int
901541Srgrimescd9660_rrip_attr(p,ana)
911541Srgrimes	ISO_RRIP_ATTR *p;
921541Srgrimes	ISO_RRIP_ANALYZE *ana;
931541Srgrimes{
9422521Sdyson	ana->inop->inode.iso_mode = isonum_733(p->mode);
9522521Sdyson	ana->inop->inode.iso_uid = isonum_733(p->uid);
9622521Sdyson	ana->inop->inode.iso_gid = isonum_733(p->gid);
9722521Sdyson	ana->inop->inode.iso_links = isonum_733(p->links);
981541Srgrimes	ana->fields &= ~ISO_SUSP_ATTR;
991541Srgrimes	return ISO_SUSP_ATTR;
1001541Srgrimes}
1011541Srgrimes
1021541Srgrimesstatic void
1031541Srgrimescd9660_rrip_defattr(isodir,ana)
1041541Srgrimes	struct iso_directory_record *isodir;
1051541Srgrimes	ISO_RRIP_ANALYZE *ana;
1061541Srgrimes{
1071541Srgrimes	/* But this is a required field! */
1081541Srgrimes	printf("RRIP without PX field?\n");
1095651Sjoerg	cd9660_defattr(isodir,ana->inop,NULL,ISO_FTYPE_RRIP);
1101541Srgrimes}
1111541Srgrimes
1121541Srgrimes/*
1131541Srgrimes * Symbolic Links
1141541Srgrimes */
1151541Srgrimesstatic int
1161541Srgrimescd9660_rrip_slink(p,ana)
1175651Sjoerg	ISO_RRIP_SLINK	*p;
1181541Srgrimes	ISO_RRIP_ANALYZE *ana;
1191541Srgrimes{
1201541Srgrimes	register ISO_RRIP_SLINK_COMPONENT *pcomp;
1211541Srgrimes	register ISO_RRIP_SLINK_COMPONENT *pcompe;
1221541Srgrimes	int len, wlen, cont;
1231541Srgrimes	char *outbuf, *inbuf;
1248876Srgrimes
1251541Srgrimes	pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
1261541Srgrimes	pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
1271541Srgrimes	len = *ana->outlen;
1281541Srgrimes	outbuf = ana->outbuf;
1291541Srgrimes	cont = ana->cont;
1308876Srgrimes
1311541Srgrimes	/*
1321541Srgrimes	 * Gathering a Symbolic name from each component with path
1331541Srgrimes	 */
1341541Srgrimes	for (;
1351541Srgrimes	     pcomp < pcompe;
1361541Srgrimes	     pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
1371541Srgrimes						  + isonum_711(pcomp->clen))) {
1388876Srgrimes
1391541Srgrimes		if (!cont) {
1401541Srgrimes			if (len < ana->maxlen) {
1411541Srgrimes				len++;
1421541Srgrimes				*outbuf++ = '/';
1431541Srgrimes			}
1441541Srgrimes		}
1451541Srgrimes		cont = 0;
1468876Srgrimes
1471541Srgrimes		inbuf = "..";
1481541Srgrimes		wlen = 0;
1498876Srgrimes
1501541Srgrimes		switch (*pcomp->cflag) {
1518876Srgrimes
1521541Srgrimes		case ISO_SUSP_CFLAG_CURRENT:
1531541Srgrimes			/* Inserting Current */
1541541Srgrimes			wlen = 1;
1551541Srgrimes			break;
1568876Srgrimes
1571541Srgrimes		case ISO_SUSP_CFLAG_PARENT:
1581541Srgrimes			/* Inserting Parent */
1591541Srgrimes			wlen = 2;
1601541Srgrimes			break;
1618876Srgrimes
1621541Srgrimes		case ISO_SUSP_CFLAG_ROOT:
1631541Srgrimes			/* Inserting slash for ROOT */
1641541Srgrimes			/* start over from beginning(?) */
1651541Srgrimes			outbuf -= len;
1661541Srgrimes			len = 0;
1671541Srgrimes			break;
1688876Srgrimes
1691541Srgrimes		case ISO_SUSP_CFLAG_VOLROOT:
1701541Srgrimes			/* Inserting a mount point i.e. "/cdrom" */
1711541Srgrimes			/* same as above */
1721541Srgrimes			outbuf -= len;
1731541Srgrimes			len = 0;
1741541Srgrimes			inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
1751541Srgrimes			wlen = strlen(inbuf);
1761541Srgrimes			break;
1778876Srgrimes
1781541Srgrimes		case ISO_SUSP_CFLAG_HOST:
1791541Srgrimes			/* Inserting hostname i.e. "kurt.tools.de" */
1801541Srgrimes			inbuf = hostname;
18112287Sphk			wlen = strlen(hostname);
1821541Srgrimes			break;
1838876Srgrimes
1841541Srgrimes		case ISO_SUSP_CFLAG_CONTINUE:
1851541Srgrimes			cont = 1;
186102412Scharnier			/* FALLTHROUGH */
1871541Srgrimes		case 0:
1881541Srgrimes			/* Inserting component */
1891541Srgrimes			wlen = isonum_711(pcomp->clen);
1901541Srgrimes			inbuf = pcomp->name;
1911541Srgrimes			break;
1921541Srgrimes		default:
1931541Srgrimes			printf("RRIP with incorrect flags?");
1941541Srgrimes			wlen = ana->maxlen + 1;
1951541Srgrimes			break;
1961541Srgrimes		}
1978876Srgrimes
1981541Srgrimes		if (len + wlen > ana->maxlen) {
1991541Srgrimes			/* indicate error to caller */
2001541Srgrimes			ana->cont = 1;
2011541Srgrimes			ana->fields = 0;
2021541Srgrimes			ana->outbuf -= *ana->outlen;
2031541Srgrimes			*ana->outlen = 0;
2041541Srgrimes			return 0;
2051541Srgrimes		}
2068876Srgrimes
2071541Srgrimes		bcopy(inbuf,outbuf,wlen);
2081541Srgrimes		outbuf += wlen;
2091541Srgrimes		len += wlen;
2108876Srgrimes
2111541Srgrimes	}
2121541Srgrimes	ana->outbuf = outbuf;
2131541Srgrimes	*ana->outlen = len;
2141541Srgrimes	ana->cont = cont;
2158876Srgrimes
2161541Srgrimes	if (!isonum_711(p->flags)) {
2171541Srgrimes		ana->fields &= ~ISO_SUSP_SLINK;
2181541Srgrimes		return ISO_SUSP_SLINK;
2191541Srgrimes	}
2201541Srgrimes	return 0;
2211541Srgrimes}
2221541Srgrimes
2231541Srgrimes/*
2241541Srgrimes * Alternate name
2251541Srgrimes */
2261541Srgrimesstatic int
2271541Srgrimescd9660_rrip_altname(p,ana)
2281541Srgrimes	ISO_RRIP_ALTNAME *p;
2291541Srgrimes	ISO_RRIP_ANALYZE *ana;
2301541Srgrimes{
2311541Srgrimes	char *inbuf;
2321541Srgrimes	int wlen;
2331541Srgrimes	int cont;
2348876Srgrimes
2351541Srgrimes	inbuf = "..";
2361541Srgrimes	wlen = 0;
2371541Srgrimes	cont = 0;
2388876Srgrimes
2391541Srgrimes	switch (*p->flags) {
2401541Srgrimes	case ISO_SUSP_CFLAG_CURRENT:
2411541Srgrimes		/* Inserting Current */
2421541Srgrimes		wlen = 1;
2431541Srgrimes		break;
2448876Srgrimes
2451541Srgrimes	case ISO_SUSP_CFLAG_PARENT:
2461541Srgrimes		/* Inserting Parent */
2471541Srgrimes		wlen = 2;
2481541Srgrimes		break;
2498876Srgrimes
2501541Srgrimes	case ISO_SUSP_CFLAG_HOST:
2511541Srgrimes		/* Inserting hostname i.e. "kurt.tools.de" */
2521541Srgrimes		inbuf = hostname;
25312287Sphk		wlen = strlen(hostname);
2541541Srgrimes		break;
2558876Srgrimes
2561541Srgrimes	case ISO_SUSP_CFLAG_CONTINUE:
2571541Srgrimes		cont = 1;
258102412Scharnier		/* FALLTHROUGH */
2591541Srgrimes	case 0:
2601541Srgrimes		/* Inserting component */
2611541Srgrimes		wlen = isonum_711(p->h.length) - 5;
2621541Srgrimes		inbuf = (char *)p + 5;
2631541Srgrimes		break;
2648876Srgrimes
2651541Srgrimes	default:
2661541Srgrimes		printf("RRIP with incorrect NM flags?\n");
2671541Srgrimes		wlen = ana->maxlen + 1;
2681541Srgrimes		break;
2691541Srgrimes	}
2708876Srgrimes
2711541Srgrimes	if ((*ana->outlen += wlen) > ana->maxlen) {
2721541Srgrimes		/* treat as no name field */
2731541Srgrimes		ana->fields &= ~ISO_SUSP_ALTNAME;
2741541Srgrimes		ana->outbuf -= *ana->outlen - wlen;
2751541Srgrimes		*ana->outlen = 0;
2761541Srgrimes		return 0;
2771541Srgrimes	}
2788876Srgrimes
2791541Srgrimes	bcopy(inbuf,ana->outbuf,wlen);
2801541Srgrimes	ana->outbuf += wlen;
2818876Srgrimes
2821541Srgrimes	if (!cont) {
2831541Srgrimes		ana->fields &= ~ISO_SUSP_ALTNAME;
2841541Srgrimes		return ISO_SUSP_ALTNAME;
2851541Srgrimes	}
2861541Srgrimes	return 0;
2871541Srgrimes}
2881541Srgrimes
2891541Srgrimesstatic void
2901541Srgrimescd9660_rrip_defname(isodir,ana)
2911541Srgrimes	struct iso_directory_record *isodir;
2921541Srgrimes	ISO_RRIP_ANALYZE *ana;
2931541Srgrimes{
29445773Sdcs	isofntrans(isodir->name,isonum_711(isodir->name_len),
29545773Sdcs		   ana->outbuf,ana->outlen,
296120492Sfjoe		   1,isonum_711(isodir->flags)&4, ana->imp->joliet_level,
297120492Sfjoe		   ana->imp->im_flags, ana->imp->im_d2l);
29845773Sdcs	switch (*ana->outbuf) {
2991541Srgrimes	default:
3001541Srgrimes		break;
3011541Srgrimes	case 1:
3021541Srgrimes		*ana->outlen = 2;
303102412Scharnier		/* FALLTHROUGH */
30445773Sdcs	case 0:
30545773Sdcs		/* outlen is 1 already */
30645773Sdcs		strcpy(ana->outbuf,"..");
3071541Srgrimes		break;
3081541Srgrimes	}
3091541Srgrimes}
3101541Srgrimes
3111541Srgrimes/*
3121541Srgrimes * Parent or Child Link
3131541Srgrimes */
3141541Srgrimesstatic int
3151541Srgrimescd9660_rrip_pclink(p,ana)
3165651Sjoerg	ISO_RRIP_CLINK	*p;
3171541Srgrimes	ISO_RRIP_ANALYZE *ana;
3181541Srgrimes{
3191541Srgrimes	*ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
3201541Srgrimes	ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK);
3211541Srgrimes	return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK;
3221541Srgrimes}
3231541Srgrimes
3241541Srgrimes/*
3251541Srgrimes * Relocated directory
3261541Srgrimes */
3271541Srgrimesstatic int
3281541Srgrimescd9660_rrip_reldir(p,ana)
3295651Sjoerg	ISO_RRIP_RELDIR	 *p;
3301541Srgrimes	ISO_RRIP_ANALYZE *ana;
3311541Srgrimes{
3321541Srgrimes	/* special hack to make caller aware of RE field */
3331541Srgrimes	*ana->outlen = 0;
3341541Srgrimes	ana->fields = 0;
3351541Srgrimes	return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
3361541Srgrimes}
3371541Srgrimes
3381541Srgrimesstatic int
3391541Srgrimescd9660_rrip_tstamp(p,ana)
3401541Srgrimes	ISO_RRIP_TSTAMP *p;
3411541Srgrimes	ISO_RRIP_ANALYZE *ana;
3421541Srgrimes{
34322521Sdyson	u_char *ptime;
34422521Sdyson
3451541Srgrimes	ptime = p->time;
3468876Srgrimes
3471541Srgrimes	/* Check a format of time stamp (7bytes/17bytes) */
3481541Srgrimes	if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) {
3491541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
3501541Srgrimes			ptime += 7;
3518876Srgrimes
3521541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
3535651Sjoerg			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime,
3545651Sjoerg					    ISO_FTYPE_RRIP);
3551541Srgrimes			ptime += 7;
3561541Srgrimes		} else
3572806Sbde			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
35822521Sdyson
3591541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
3605651Sjoerg			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime,
3615651Sjoerg					    ISO_FTYPE_RRIP);
3621541Srgrimes			ptime += 7;
3631541Srgrimes		} else
3641541Srgrimes			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
3658876Srgrimes
3661541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
3675651Sjoerg			cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime,
3685651Sjoerg					    ISO_FTYPE_RRIP);
3691541Srgrimes		else
3701541Srgrimes			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
3718876Srgrimes
3721541Srgrimes	} else {
3731541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
3741541Srgrimes			ptime += 17;
3758876Srgrimes
3761541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
3771541Srgrimes			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime);
3781541Srgrimes			ptime += 17;
3791541Srgrimes		} else
3802806Sbde			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
38122521Sdyson
3821541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
3831541Srgrimes			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
3841541Srgrimes			ptime += 17;
3851541Srgrimes		} else
3861541Srgrimes			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
3878876Srgrimes
3881541Srgrimes		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
3891541Srgrimes			cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime);
3901541Srgrimes		else
3911541Srgrimes			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
3928876Srgrimes
3931541Srgrimes	}
3941541Srgrimes	ana->fields &= ~ISO_SUSP_TSTAMP;
3951541Srgrimes	return ISO_SUSP_TSTAMP;
3961541Srgrimes}
3971541Srgrimes
3981541Srgrimesstatic void
3991541Srgrimescd9660_rrip_deftstamp(isodir,ana)
4001541Srgrimes	struct iso_directory_record  *isodir;
4011541Srgrimes	ISO_RRIP_ANALYZE *ana;
4021541Srgrimes{
4035651Sjoerg	cd9660_deftstamp(isodir,ana->inop,NULL,ISO_FTYPE_RRIP);
4041541Srgrimes}
4051541Srgrimes
4061541Srgrimes/*
4071541Srgrimes * POSIX device modes
4081541Srgrimes */
4091541Srgrimesstatic int
4101541Srgrimescd9660_rrip_device(p,ana)
4111541Srgrimes	ISO_RRIP_DEVICE *p;
4121541Srgrimes	ISO_RRIP_ANALYZE *ana;
4131541Srgrimes{
41422521Sdyson	u_int high, low;
41522521Sdyson
41622521Sdyson	high = isonum_733(p->dev_t_high);
41722521Sdyson	low  = isonum_733(p->dev_t_low);
41822521Sdyson
41922521Sdyson	if (high == 0)
42048859Sphk		ana->inop->inode.iso_rdev = makeudev(umajor(low), uminor(low));
42122521Sdyson	else
42248859Sphk		ana->inop->inode.iso_rdev = makeudev(high, uminor(low));
4231541Srgrimes	ana->fields &= ~ISO_SUSP_DEVICE;
4241541Srgrimes	return ISO_SUSP_DEVICE;
4251541Srgrimes}
4261541Srgrimes
4271541Srgrimes/*
4281541Srgrimes * Flag indicating
4291541Srgrimes */
4301541Srgrimesstatic int
4311541Srgrimescd9660_rrip_idflag(p,ana)
4321541Srgrimes	ISO_RRIP_IDFLAG *p;
4331541Srgrimes	ISO_RRIP_ANALYZE *ana;
4341541Srgrimes{
4351541Srgrimes	ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */
4361541Srgrimes	/* special handling of RE field */
4371541Srgrimes	if (ana->fields&ISO_SUSP_RELDIR)
43812597Sbde		return cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p,ana);
4398876Srgrimes
4401541Srgrimes	return ISO_SUSP_IDFLAG;
4411541Srgrimes}
4421541Srgrimes
4431541Srgrimes/*
4441541Srgrimes * Continuation pointer
4451541Srgrimes */
4461541Srgrimesstatic int
4471541Srgrimescd9660_rrip_cont(p,ana)
4481541Srgrimes	ISO_RRIP_CONT *p;
4491541Srgrimes	ISO_RRIP_ANALYZE *ana;
4501541Srgrimes{
4511541Srgrimes	ana->iso_ce_blk = isonum_733(p->location);
4521541Srgrimes	ana->iso_ce_off = isonum_733(p->offset);
4531541Srgrimes	ana->iso_ce_len = isonum_733(p->length);
4541541Srgrimes	return ISO_SUSP_CONT;
4551541Srgrimes}
4561541Srgrimes
4571541Srgrimes/*
4581541Srgrimes * System Use end
4591541Srgrimes */
4601541Srgrimesstatic int
4611541Srgrimescd9660_rrip_stop(p,ana)
4621541Srgrimes	ISO_SUSP_HEADER *p;
4631541Srgrimes	ISO_RRIP_ANALYZE *ana;
4641541Srgrimes{
4651541Srgrimes	return ISO_SUSP_STOP;
4661541Srgrimes}
4671541Srgrimes
4681541Srgrimes/*
4691541Srgrimes * Extension reference
4701541Srgrimes */
4711541Srgrimesstatic int
4721541Srgrimescd9660_rrip_extref(p,ana)
4731541Srgrimes	ISO_RRIP_EXTREF *p;
4741541Srgrimes	ISO_RRIP_ANALYZE *ana;
4751541Srgrimes{
4761541Srgrimes	if (isonum_711(p->len_id) != 10
4771541Srgrimes	    || bcmp((char *)p + 8,"RRIP_1991A",10)
4781541Srgrimes	    || isonum_711(p->version) != 1)
4791541Srgrimes		return 0;
4801541Srgrimes	ana->fields &= ~ISO_SUSP_EXTREF;
4811541Srgrimes	return ISO_SUSP_EXTREF;
4821541Srgrimes}
4831541Srgrimes
4841541Srgrimesstatic int
4851541Srgrimescd9660_rrip_loop(isodir,ana,table)
4861541Srgrimes	struct iso_directory_record *isodir;
4871541Srgrimes	ISO_RRIP_ANALYZE *ana;
4881541Srgrimes	RRIP_TABLE *table;
4891541Srgrimes{
4901541Srgrimes	register RRIP_TABLE *ptable;
4911541Srgrimes	register ISO_SUSP_HEADER *phead;
4921541Srgrimes	register ISO_SUSP_HEADER *pend;
4931541Srgrimes	struct buf *bp = NULL;
4941541Srgrimes	char *pwhead;
495120492Sfjoe	u_short c;
4961541Srgrimes	int result;
4978876Srgrimes
4981541Srgrimes	/*
4991541Srgrimes	 * Note: If name length is odd,
5005651Sjoerg	 *	 it will be padding 1 byte after the name
5011541Srgrimes	 */
5021541Srgrimes	pwhead = isodir->name + isonum_711(isodir->name_len);
5031541Srgrimes	if (!(isonum_711(isodir->name_len)&1))
5041541Srgrimes		pwhead++;
505120492Sfjoe	isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL,
506120492Sfjoe		ana->imp->im_flags, ana->imp->im_d2l);
5078876Srgrimes
5081541Srgrimes	/* If it's not the '.' entry of the root dir obey SP field */
50945773Sdcs	if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
5101541Srgrimes		pwhead += ana->imp->rr_skip;
5111541Srgrimes	else
5121541Srgrimes		pwhead += ana->imp->rr_skip0;
5138876Srgrimes
5141541Srgrimes	phead = (ISO_SUSP_HEADER *)pwhead;
5151541Srgrimes	pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
5168876Srgrimes
5171541Srgrimes	result = 0;
5181541Srgrimes	while (1) {
5191541Srgrimes		ana->iso_ce_len = 0;
5201541Srgrimes		/*
5211541Srgrimes		 * Note: "pend" should be more than one SUSP header
5228876Srgrimes		 */
5231541Srgrimes		while (pend >= phead + 1) {
5241541Srgrimes			if (isonum_711(phead->version) == 1) {
5251541Srgrimes				for (ptable = table; ptable->func; ptable++) {
5261541Srgrimes					if (*phead->type == *ptable->type
5271541Srgrimes					    && phead->type[1] == ptable->type[1]) {
5281541Srgrimes						result |= ptable->func(phead,ana);
5291541Srgrimes						break;
5301541Srgrimes					}
5311541Srgrimes				}
5321541Srgrimes				if (!ana->fields)
5331541Srgrimes					break;
5341541Srgrimes			}
53522521Sdyson			if (result&ISO_SUSP_STOP) {
53622521Sdyson				result &= ~ISO_SUSP_STOP;
53722521Sdyson				break;
53822521Sdyson			}
53922521Sdyson			/* plausibility check */
54022521Sdyson			if (isonum_711(phead->length) < sizeof(*phead))
54122521Sdyson				break;
5421541Srgrimes			/*
5431541Srgrimes			 * move to next SUSP
5441541Srgrimes			 * Hopefully this works with newer versions, too
5451541Srgrimes			 */
5461541Srgrimes			phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
5471541Srgrimes		}
54822521Sdyson
54922521Sdyson		if (ana->fields && ana->iso_ce_len) {
5501541Srgrimes			if (ana->iso_ce_blk >= ana->imp->volume_space_size
5511541Srgrimes			    || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
5521541Srgrimes			    || bread(ana->imp->im_devvp,
55322521Sdyson				     ana->iso_ce_blk <<
55422521Sdyson				     (ana->imp->im_bshift - DEV_BSHIFT),
55522521Sdyson				     ana->imp->logical_block_size, NOCRED, &bp))
5561541Srgrimes				/* what to do now? */
5571541Srgrimes				break;
55822521Sdyson			phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
5591541Srgrimes			pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
5601541Srgrimes		} else
5611541Srgrimes			break;
5621541Srgrimes	}
5631541Srgrimes	if (bp)
5641541Srgrimes		brelse(bp);
5651541Srgrimes	/*
5661541Srgrimes	 * If we don't find the Basic SUSP stuffs, just set default value
56722521Sdyson	 *   (attribute/time stamp)
5681541Srgrimes	 */
5691541Srgrimes	for (ptable = table; ptable->func2; ptable++)
5701541Srgrimes		if (!(ptable->result&result))
5711541Srgrimes			ptable->func2(isodir,ana);
5728876Srgrimes
5731541Srgrimes	return result;
5741541Srgrimes}
5751541Srgrimes
57612597Sbde/*
57722521Sdyson * Get Attributes.
57822521Sdyson */
57922521Sdyson/*
58012597Sbde * XXX the casts are bogus but will do for now.
58112597Sbde */
58212597Sbde#define	BC	(rrt_func_t *)
5831541Srgrimesstatic RRIP_TABLE rrip_table_analyze[] = {
58412597Sbde	{ "PX", BC cd9660_rrip_attr,	cd9660_rrip_defattr,	ISO_SUSP_ATTR },
58512597Sbde	{ "TF", BC cd9660_rrip_tstamp,	cd9660_rrip_deftstamp,	ISO_SUSP_TSTAMP },
58612597Sbde	{ "PN", BC cd9660_rrip_device,	0,			ISO_SUSP_DEVICE },
58712597Sbde	{ "RR", BC cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
58812597Sbde	{ "CE", BC cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
58912597Sbde	{ "ST", BC cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
5901541Srgrimes	{ "",	0,			0,			0 }
5911541Srgrimes};
5921541Srgrimes
5931541Srgrimesint
5941541Srgrimescd9660_rrip_analyze(isodir,inop,imp)
5951541Srgrimes	struct iso_directory_record *isodir;
5961541Srgrimes	struct iso_node *inop;
5971541Srgrimes	struct iso_mnt *imp;
5981541Srgrimes{
5991541Srgrimes	ISO_RRIP_ANALYZE analyze;
6008876Srgrimes
6011541Srgrimes	analyze.inop = inop;
6021541Srgrimes	analyze.imp = imp;
6031541Srgrimes	analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE;
6048876Srgrimes
6051541Srgrimes	return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
6061541Srgrimes}
6071541Srgrimes
60822521Sdyson/*
60922521Sdyson * Get Alternate Name.
6101541Srgrimes */
6111541Srgrimesstatic RRIP_TABLE rrip_table_getname[] = {
61212597Sbde	{ "NM", BC cd9660_rrip_altname,	cd9660_rrip_defname,	ISO_SUSP_ALTNAME },
61312597Sbde	{ "CL", BC cd9660_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
61412597Sbde	{ "PL", BC cd9660_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
61512597Sbde	{ "RE", BC cd9660_rrip_reldir,	0,			ISO_SUSP_RELDIR },
61612597Sbde	{ "RR", BC cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
61712597Sbde	{ "CE", BC cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
61812597Sbde	{ "ST", BC cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
6191541Srgrimes	{ "",	0,			0,			0 }
6201541Srgrimes};
6211541Srgrimes
6221541Srgrimesint
6231541Srgrimescd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
6241541Srgrimes	struct iso_directory_record *isodir;
6251541Srgrimes	char *outbuf;
6261541Srgrimes	u_short *outlen;
6271541Srgrimes	ino_t *inump;
6281541Srgrimes	struct iso_mnt *imp;
6291541Srgrimes{
6301541Srgrimes	ISO_RRIP_ANALYZE analyze;
6311541Srgrimes	RRIP_TABLE *tab;
632120492Sfjoe	u_short c;
6338876Srgrimes
6341541Srgrimes	analyze.outbuf = outbuf;
6351541Srgrimes	analyze.outlen = outlen;
6361541Srgrimes	analyze.maxlen = NAME_MAX;
6371541Srgrimes	analyze.inump = inump;
6381541Srgrimes	analyze.imp = imp;
6391541Srgrimes	analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
6401541Srgrimes	*outlen = 0;
6418876Srgrimes
64245773Sdcs	isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
643120492Sfjoe		imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l);
6441541Srgrimes	tab = rrip_table_getname;
64545773Sdcs	if (c == 0 || c == 1) {
6461541Srgrimes		cd9660_rrip_defname(isodir,&analyze);
6478876Srgrimes
6481541Srgrimes		analyze.fields &= ~ISO_SUSP_ALTNAME;
6491541Srgrimes		tab++;
6501541Srgrimes	}
6518876Srgrimes
6521541Srgrimes	return cd9660_rrip_loop(isodir,&analyze,tab);
6531541Srgrimes}
6541541Srgrimes
65522521Sdyson/*
65622521Sdyson * Get Symbolic Link.
6571541Srgrimes */
6581541Srgrimesstatic RRIP_TABLE rrip_table_getsymname[] = {
65912597Sbde	{ "SL", BC cd9660_rrip_slink,	0,			ISO_SUSP_SLINK },
66012597Sbde	{ "RR", BC cd9660_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
66112597Sbde	{ "CE", BC cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
66212597Sbde	{ "ST", BC cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
6631541Srgrimes	{ "",	0,			0,			0 }
6641541Srgrimes};
6651541Srgrimes
6661541Srgrimesint
6671541Srgrimescd9660_rrip_getsymname(isodir,outbuf,outlen,imp)
6681541Srgrimes	struct iso_directory_record *isodir;
6691541Srgrimes	char *outbuf;
6701541Srgrimes	u_short *outlen;
6711541Srgrimes	struct iso_mnt *imp;
6721541Srgrimes{
6731541Srgrimes	ISO_RRIP_ANALYZE analyze;
6748876Srgrimes
6751541Srgrimes	analyze.outbuf = outbuf;
6761541Srgrimes	analyze.outlen = outlen;
6771541Srgrimes	*outlen = 0;
6781541Srgrimes	analyze.maxlen = MAXPATHLEN;
6791541Srgrimes	analyze.cont = 1;		/* don't start with a slash */
6801541Srgrimes	analyze.imp = imp;
6811541Srgrimes	analyze.fields = ISO_SUSP_SLINK;
6828876Srgrimes
6831541Srgrimes	return (cd9660_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK);
6841541Srgrimes}
6851541Srgrimes
6861541Srgrimesstatic RRIP_TABLE rrip_table_extref[] = {
68712597Sbde	{ "ER", BC cd9660_rrip_extref,	0,			ISO_SUSP_EXTREF },
68812597Sbde	{ "CE", BC cd9660_rrip_cont,	0,			ISO_SUSP_CONT },
68912597Sbde	{ "ST", BC cd9660_rrip_stop,	0,			ISO_SUSP_STOP },
6901541Srgrimes	{ "",	0,			0,			0 }
6911541Srgrimes};
6921541Srgrimes
6931541Srgrimes/*
6941541Srgrimes * Check for Rock Ridge Extension and return offset of its fields.
69522521Sdyson * Note: We insist on the ER field.
6961541Srgrimes */
6971541Srgrimesint
6981541Srgrimescd9660_rrip_offset(isodir,imp)
6991541Srgrimes	struct iso_directory_record *isodir;
7001541Srgrimes	struct iso_mnt *imp;
7011541Srgrimes{
7021541Srgrimes	ISO_RRIP_OFFSET *p;
7031541Srgrimes	ISO_RRIP_ANALYZE analyze;
7048876Srgrimes
7051541Srgrimes	imp->rr_skip0 = 0;
7061541Srgrimes	p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
7071541Srgrimes	if (bcmp(p,"SP\7\1\276\357",6)) {
7081541Srgrimes		/* Maybe, it's a CDROM XA disc? */
7091541Srgrimes		imp->rr_skip0 = 15;
7101541Srgrimes		p = (ISO_RRIP_OFFSET *)((char *)p + 15);
7111541Srgrimes		if (bcmp(p,"SP\7\1\276\357",6))
7121541Srgrimes			return -1;
7131541Srgrimes	}
7148876Srgrimes
7151541Srgrimes	analyze.imp = imp;
7161541Srgrimes	analyze.fields = ISO_SUSP_EXTREF;
7171541Srgrimes	if (!(cd9660_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
7181541Srgrimes		return -1;
7198876Srgrimes
7201541Srgrimes	return isonum_711(p->skip);
7211541Srgrimes}
722