*BSD News Article 35163


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!harbinger.cc.monash.edu.au!bunyip.cc.uq.oz.au!munnari.oz.au!news.Hawaii.Edu!ames!pacbell.com!ihnp4.ucsd.edu!swrinde!cs.utexas.edu!uunet!news.sprintlink.net!demon!minnow.render.com!minnow.render.com!dfr
From: dfr@render.com (Doug Rabson)
Newsgroups: comp.os.386bsd.bugs
Subject: RockRidge fixes for FreeBSD-1.1.5 (long)
Date: 22 Aug 1994 12:31:25 GMT
Organization: RenderMorphics Ltd.
Lines: 6062
Message-ID: <DFR.94Aug22133125@minnow.render.com>
NNTP-Posting-Host: minnow.render.com

I have had a couple of requests for this.  These patches are based on
a patch set which I had for FreeBSD-1.1 which contained a port of
NetBSD's isofs to FreeBSD.

I have minimally tested it and it appears to work for my only
RockRidge CD (X11R6) and several ordinary CDs.  There appears to be a
problem in exporting CDs over NFS.  Some long directories get
truncated.

------------------------------cut here------------------------------
diff -cr sbin/mount_isofs/Makefile /usr/src/sbin/mount_isofs/Makefile
*** sbin/mount_isofs/Makefile	Wed Jul 21 22:57:33 1993
--- /usr/src/sbin/mount_isofs/Makefile	Mon Aug 15 15:17:59 1994
***************
*** 1,4 ****
! #	$Id: Makefile,v 1.3 1993/07/21 21:57:33 rgrimes Exp $
  
  PROG = mount_isofs
  MAN8 = mount_isofs.8
--- 1,4 ----
! #	$Id: Makefile,v 1.5 1993/09/07 15:40:28 ws Exp $
  
  PROG = mount_isofs
  MAN8 = mount_isofs.8
diff -cr sbin/mount_isofs/mount_isofs.8 /usr/src/sbin/mount_isofs/mount_isofs.8
*** sbin/mount_isofs/mount_isofs.8	Mon Feb  7 02:47:56 1994
--- /usr/src/sbin/mount_isofs/mount_isofs.8	Mon Aug 15 15:17:59 1994
***************
*** 14,20 ****
  .\"    must display the following acknowledgement:
  .\"      This product includes software developed by Christopher G. Demetriou.
  .\" 3. The name of the author may not be used to endorse or promote products
! .\"    derived from this software withough specific prior written permission
  .\"
  .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
--- 14,20 ----
  .\"    must display the following acknowledgement:
  .\"      This product includes software developed by Christopher G. Demetriou.
  .\" 3. The name of the author may not be used to endorse or promote products
! .\"    derived from this software without specific prior written permission
  .\"
  .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
***************
*** 27,37 ****
  .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  .\"
! .\"	$Id: mount_isofs.8,v 1.5 1994/02/07 02:47:56 rgrimes Exp $
  .\"
  .Dd July 19, 1993
  .Dt MOUNT_ISOFS 8
! .Os
  .Sh NAME
  .Nm mount_isofs
  .Nd mount an ISO-9660 filesystem
--- 27,37 ----
  .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  .\"
! .\"	$Id: mount_isofs.8,v 1.5 1994/01/29 01:43:37 jtc Exp $
  .\"
  .Dd July 19, 1993
  .Dt MOUNT_ISOFS 8
! .Os NetBSD 0.9
  .Sh NAME
  .Nm mount_isofs
  .Nd mount an ISO-9660 filesystem
***************
*** 39,44 ****
--- 39,46 ----
  .Nm mount_isofs
  .Op Fl F Ar fsoptions
  .Op Fl norrip
+ .Op Fl gen
+ .Op Fl extattr
  .Pa special
  .Pa node
  .Sh DESCRIPTION
***************
*** 51,57 ****
  indicated by
  .Pa node .
  This command is normally executed by
! .Xr mount 8 .
  at boot time.
  .Pp
  If the filesystem includes Rockridge extensions, they are
--- 53,59 ----
  indicated by
  .Pa node .
  This command is normally executed by
! .Xr mount 8
  at boot time.
  .Pp
  If the filesystem includes Rockridge extensions, they are
***************
*** 60,71 ****
  flag is used.  If that option is given to
  .Nm
  then the Rockridge extensions will be ignored.
  .Sh EXAMPLES
  .Bd -literal -offset indent -compact
! mount_isofs /dev/cd0a /cdrom
! mount_isofs \-norrip /dev/cd0a /cdrom
! mount \-t isofs /dev/cd0a /cdrom
! mount \-t isofs \-o \-norrip /dev/cd0a /cdrom
  .Ed
  .Sh SEE ALSO
  .Xr mount 2 ,
--- 62,89 ----
  flag is used.  If that option is given to
  .Nm
  then the Rockridge extensions will be ignored.
+ .Pp
+ Version numbers on files are normally stripped on directory listings.
+ If you want to see those, use the
+ .Fl gen
+ flag.
+ Otherwise, if there are files with different version numbers on the disk,
+ only the last one will be listed.
+ In either case, you may open a file with or without explicitly stating the
+ version number.
+ .Pp
+ If a disk contains extended attributes, they are normally ignored.
+ You can enable the usage of extended attributes with the
+ .Fl extattr
+ flag.
  .Sh EXAMPLES
  .Bd -literal -offset indent -compact
! mount_isofs /dev/cd0d /cdrom
! mount_isofs \-norrip /dev/cd0d /cdrom
! mount_isofs \-norrip \-gen /dev/cd0d /cdrom
! mount \-t isofs /dev/cd0d /cdrom
! mount \-t isofs \-o \-norrip /dev/cd0d /cdrom
! mount \-t isofs \-o \-gen,\-extattr /dev/cd0d /cdrom
  .Ed
  .Sh SEE ALSO
  .Xr mount 2 ,
***************
*** 76,82 ****
  ("CDROM001") format;
  it does not.
  .Pp
! POSIX device nodes are currently not supported.
  .Pp
  The filesystem name might need some rethinking, and some would
  say it should run as a user process.
--- 94,105 ----
  ("CDROM001") format;
  it does not.
  .Pp
! POSIX device node mapping is currently not supported.
! .Pp
! Version numbers are not stripped if Rockridge extensions are in use.
! In this case, accessing files that don't have Rockridge names without
! version numbers gets the one with the lowest version number and not
! the one with the highest.
  .Pp
  The filesystem name might need some rethinking, and some would
  say it should run as a user process.
diff -cr sbin/mount_isofs/mount_isofs.c /usr/src/sbin/mount_isofs/mount_isofs.c
*** sbin/mount_isofs/mount_isofs.c	Sun Oct 24 04:30:08 1993
--- /usr/src/sbin/mount_isofs/mount_isofs.c	Mon Aug 15 16:02:41 1994
***************
*** 1,9 ****
  #ifndef lint
! static char rcsid[] = "$Header: /home/cvs/386BSD/src/sbin/mount_isofs/mount_isofs.c,v 1.3 1993/10/24 04:30:08 rgrimes Exp $";
! #endif
  
  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/mount.h>
  
  void
--- 1,10 ----
  #ifndef lint
! static char rcsid[] = "$Id: mount_isofs.c,v 1.8 1993/10/20 19:53:36 cgd Exp $";
! #endif /* not lint */
  
  #include <stdio.h>
  #include <sys/types.h>
+ #define ISOFS
  #include <sys/mount.h>
  
  void
***************
*** 20,40 ****
  {
  	char *dev;
  	char *dir;
! 	struct ufs_args args;
  	int c;
! 	int opts;
! 
! 	opts = MNT_RDONLY;
  
  	argc--;
  	argv++;
  	while (argc > 2) {
  		if (!strcmp("-F", argv[0])) {
  			argc--; argv++;
! 			opts |= atoi(argv[0]);
  			argc--; argv++;
  		} else if (!strcmp(argv[0], "-norrip")) {
! 			opts |= MNT_NORRIP;
  			argc--; argv++;
  		} else
  			usage();
--- 21,45 ----
  {
  	char *dev;
  	char *dir;
! 	struct iso_args args;
  	int c;
! 	int opts = 0, mntflags = 0;
  
  	argc--;
  	argv++;
  	while (argc > 2) {
  		if (!strcmp("-F", argv[0])) {
  			argc--; argv++;
! 			mntflags |= atoi(argv[0]);
  			argc--; argv++;
  		} else if (!strcmp(argv[0], "-norrip")) {
! 			opts |= ISOFSMNT_NORRIP;
! 			argc--; argv++;
! 		} else if (!strcmp(argv[0], "-gen")) {
! 			opts |= ISOFSMNT_GENS;
! 			argc--; argv++;
! 		} else if (!strcmp(argv[0], "-extattr")) {
! 			opts |= ISOFSMNT_EXTATT;
  			argc--; argv++;
  		} else
  			usage();
***************
*** 44,53 ****
  	dir = argv[1];
  
  	args.fspec = dev;
! 	args.exflags = MNT_EXRDONLY | opts;
  	args.exroot = 0;
  
! 	if (mount (MOUNT_ISOFS, dir, MNT_RDONLY, &args) < 0) {
  		perror ("mount");
  		exit (1);
  	}
--- 49,58 ----
  	dir = argv[1];
  
  	args.fspec = dev;
! 	args.flags = opts;
  	args.exroot = 0;
  
! 	if (mount (MOUNT_ISOFS, dir, mntflags, &args) < 0) {
  		perror ("mount");
  		exit (1);
  	}
diff -cr sys/isofs/TODO /usr/src/sys/isofs/TODO
*** sys/isofs/TODO	Tue Jul 20 04:27:21 1993
--- /usr/src/sys/isofs/TODO	Mon Aug 15 15:17:55 1994
***************
*** 1,4 ****
! #	$Id: TODO,v 1.2 1993/07/20 03:27:21 jkh Exp $
  
   1) should understand "older", original High Sierra ("CDROM001") type
  
--- 1,4 ----
! #	$Id: TODO,v 1.4 1993/09/07 15:40:51 ws Exp $
  
   1) should understand "older", original High Sierra ("CDROM001") type
  
***************
*** 13,34 ****
         o File Attribute 
         o Time stamp
         o uid, gid
  
     Except follows:
  
!        o POSIX device modes
  
!          I have no idea right now, we should check a REAL implementation
!          for 386BSD.....
           
-        o Limitation of 8 level directory( ISO9660 limitation )
- 
-          Rock Ridge Extension are defined with the "CL/PL/RE" for getting
-          rid of this limitation. But as far as I test the cdroms,I'v never 
-          seen this definition and we can access the over 8 level without
-          it. (Another word, this limitation is NOT physical ISO9660's
-          FORMAT limitation for unix stuffs.... I believe... )
- 
   3) should be called cdfs, as there are other ISO file system soon possible
  
     Not yet. Probably we should make another file system when the ECMA draft 
--- 13,28 ----
         o File Attribute 
         o Time stamp
         o uid, gid
+        o Devices
+        o Relocated directories
  
     Except follows:
  
!        o POSIX device number mapping
  
!          There is some preliminary stuff in there that (ab-)uses the mknod
!          system call, but this needs a writable filesystem
           
   3) should be called cdfs, as there are other ISO file system soon possible
  
     Not yet. Probably we should make another file system when the ECMA draft 
***************
*** 48,55 ****
   6) should run as a user process, and not take up kernel space (cdroms
      are slow)
  
!    Not yet. And addition, we should try to avoid a long seek by a absolute path
!    with using the PATH TABLE or other method.
  
   7) ECMA support.
  
--- 42,48 ----
   6) should run as a user process, and not take up kernel space (cdroms
      are slow)
  
!    Not yet.
  
   7) ECMA support.
  
***************
*** 62,66 ****
--- 55,77 ----
     clean. As far as I know, if you export the cdrom by NFS, the client
     can access the 8 bit clean (ie. Solaris Japanese with EUC code )
  
+  9) Access checks in isofs_access
+ 
+    Not yet.
+ 
+  10) Support for generation numbers
+ 
+    Yes. Default is to list only the last file (the one with the highest
+    generation number). If you mount with -gen, all files are shown with
+    their generation numbers. In both cases you can specify the generation
+    number on opening files (if you happen to know it) or leave it off,
+    when it will again find the last file.
+ 
+  11) Support for extended attributes
+ 
+    Yes. Since this requires an extra block buffer for the attributes
+    this must be enabled on mounting with the option -extattr.
+ 
  ----------
  Last update July 19, '93 by Atsushi Murai. (amurai@spec.co.jp)
+ Last update August 19, '93 by Wolfgang Solfrank. (ws@tools.de)
diff -cr sys/isofs/iso.h /usr/src/sys/isofs/iso.h
*** sys/isofs/iso.h	Sun Dec 19 00:51:02 1993
--- /usr/src/sys/isofs/iso.h	Mon Aug 15 15:17:55 1994
***************
*** 1,5 ****
  /*
!  *	$Id: iso.h,v 1.5 1993/12/19 00:51:02 wollman Exp $
   */
  
  #ifndef _ISOFS_ISO_H_
--- 1,5 ----
  /*
!  *	$Id: iso.h,v 1.6 1993/10/28 17:38:42 ws Exp $
   */
  
  #ifndef _ISOFS_ISO_H_
***************
*** 70,105 ****
  	char name_len			[ISODCL (33, 33)]; /* 711 */
  	char name			[0];
  };
  
! /* CD-ROM Fromat type */
! enum ISO_FTYPE  { ISO_FTYPE_9660, ISO_FTYPE_RRIP, ISO_FTYPE_ECMA };
  
  struct iso_mnt {
  	int logical_block_size;
  	int volume_space_size;
  	struct vnode *im_devvp;
  	char im_fsmnt[50];
  	
- 	int im_ronly;
- 	int im_fmod;
  	struct mount *im_mountp;
  	dev_t im_dev;
! 
  	int im_bshift;
  	int im_bmask;
! 	int im_bsize;
! 
  	char root[ISODCL (157, 190)];
  	int root_extent;
  	int root_size;
  	enum ISO_FTYPE  iso_ftype;
  };
  
  #define VFSTOISOFS(mp)	((struct iso_mnt *)((mp)->mnt_data))
  
! #define iso_blkoff(imp, loc) ((loc) & ~(imp)->im_bmask)
  #define iso_lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
! #define iso_blksize(imp, ip, lbn) ((imp)->im_bsize)
  #define iso_lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
  
  
--- 70,133 ----
  	char name_len			[ISODCL (33, 33)]; /* 711 */
  	char name			[0];
  };
+ /* can't take sizeof(iso_directory_record), because of possible alignment
+    of the last entry (34 instead of 33) */
+ #define ISO_DIRECTORY_RECORD_SIZE	33
+ 
+ struct iso_extended_attributes {
+ 	unsigned char owner		[ISODCL (1, 4)]; /* 723 */
+ 	unsigned char group		[ISODCL (5, 8)]; /* 723 */
+ 	unsigned char perm		[ISODCL (9, 10)]; /* 9.5.3 */
+ 	char ctime			[ISODCL (11, 27)]; /* 8.4.26.1 */
+ 	char mtime			[ISODCL (28, 44)]; /* 8.4.26.1 */
+ 	char xtime			[ISODCL (45, 61)]; /* 8.4.26.1 */
+ 	char ftime			[ISODCL (62, 78)]; /* 8.4.26.1 */
+ 	char recfmt			[ISODCL (79, 79)]; /* 711 */
+ 	char recattr			[ISODCL (80, 80)]; /* 711 */
+ 	unsigned char reclen		[ISODCL (81, 84)]; /* 723 */
+ 	char system_id			[ISODCL (85, 116)]; /* achars */
+ 	char system_use			[ISODCL (117, 180)];
+ 	char version			[ISODCL (181, 181)]; /* 711 */
+ 	char len_esc			[ISODCL (182, 182)]; /* 711 */
+ 	char reserved			[ISODCL (183, 246)];
+ 	unsigned char len_au		[ISODCL (247, 250)]; /* 723 */
+ };
+ 
+ /* CD-ROM Format type */
+ enum ISO_FTYPE  { ISO_FTYPE_DEFAULT, ISO_FTYPE_9660, ISO_FTYPE_RRIP, ISO_FTYPE_ECMA };
  
! #ifndef	ISOFSMNT_ROOT
! #define	ISOFSMNT_ROOT	0
! #endif
  
  struct iso_mnt {
+ 	int im_flags;
+ 	
  	int logical_block_size;
  	int volume_space_size;
  	struct vnode *im_devvp;
  	char im_fsmnt[50];
  	
  	struct mount *im_mountp;
  	dev_t im_dev;
! 	
  	int im_bshift;
  	int im_bmask;
! 	
  	char root[ISODCL (157, 190)];
  	int root_extent;
  	int root_size;
  	enum ISO_FTYPE  iso_ftype;
+ 	
+ 	int rr_skip;
+ 	int rr_skip0;
  };
  
  #define VFSTOISOFS(mp)	((struct iso_mnt *)((mp)->mnt_data))
  
! #define iso_blkoff(imp, loc) ((loc) & (imp)->im_bmask)
  #define iso_lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
! #define iso_blksize(imp, ip, lbn) ((imp)->logical_block_size)
  #define iso_lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
  
  
***************
*** 112,129 ****
  int isofs_sync __P((struct mount *mp, int waitfor));
  int isofs_fhtovp __P((struct mount *mp, struct fid *fhp, struct vnode **vpp));
  int isofs_vptofh __P((struct vnode *vp, struct fid *fhp));
! void isofs_init __P((void));
  
! /* From isofs_util.c: */
! extern int isonum_711(char *);
! extern int isonum_712(char *);
! extern int isonum_721(char *);
! extern int isonum_722(char *);
! extern int isonum_723(char *);
! extern int isonum_731(u_char *);
! extern int isonum_732(u_char *);
! extern int isonum_733(u_char *);
! extern int isofncmp(char *, int, char *, int);
! extern void isofntrans(char *, int, char *, int *);
  
  #endif /* _ISOFS_ISO_H_ */
--- 140,222 ----
  int isofs_sync __P((struct mount *mp, int waitfor));
  int isofs_fhtovp __P((struct mount *mp, struct fid *fhp, struct vnode **vpp));
  int isofs_vptofh __P((struct vnode *vp, struct fid *fhp));
! void isofs_init __P(());
  
! struct iso_node;
! int iso_bmap __P((struct iso_node *ip, int lblkno, daddr_t *result)); 
! int iso_blkatoff __P((struct iso_node *ip, off_t offset, struct buf **bpp)); 
! int iso_iget __P((struct iso_node *xp, ino_t ino, int relocated,
! 		  struct iso_node **ipp, struct iso_directory_record *isodir));
! void iso_iput __P((struct iso_node *ip)); 
! void iso_ilock __P((struct iso_node *ip)); 
! void iso_iunlock __P((struct iso_node *ip)); 
! int isofs_mountroot __P((void)); 
! 
! extern inline int
! isonum_711(p)
! 	unsigned char *p;
! {
! 	return *p;
! }
! 
! extern inline int
! isonum_712(p)
! 	char *p;
! {
! 	return *p;
! }
! 
! extern inline int
! isonum_721(p)
! 	unsigned char *p;
! {
! 	return *p|((char)p[1] << 8);
! }
! 
! extern inline int
! isonum_722(p)
! 	unsigned char *p;
! {
! 	return ((char)*p << 8)|p[1];
! }
! 
! extern inline int
! isonum_723(p)
! 	unsigned char *p;
! {
! 	return isonum_721(p);
! }
! 
! extern inline int
! isonum_731(p)
! 	unsigned char *p;
! {
! 	return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
! }
! 
! extern inline int
! isonum_732(p)
! 	unsigned char *p;
! {
! 	return (*p << 24)|(p[1] << 16)|(p[2] << 8)|p[3];
! }
! 
! extern inline int
! isonum_733(p)
! 	unsigned char *p;
! {
! 	return isonum_731(p);
! }
! 
! int isofncmp __P((unsigned char *fn, int fnlen,
! 		  unsigned char *isofn, int isolen));
! void isofntrans __P((unsigned char *infn, int infnlen,
! 		     unsigned char *outfn, unsigned short *outfnlen,
! 		     int original, int assoc));
! 
! /*
!  * Associated files have a leading '='.
!  */
! #define	ASSOCCHAR	'='
  
  #endif /* _ISOFS_ISO_H_ */
diff -cr sys/isofs/iso_rrip.h /usr/src/sys/isofs/iso_rrip.h
*** sys/isofs/iso_rrip.h	Sun Nov  7 17:46:03 1993
--- /usr/src/sys/isofs/iso_rrip.h	Mon Aug 15 15:17:55 1994
***************
*** 29,42 ****
   * SUCH DAMAGE.
   *
   *	from: @(#)iso_rrip.h
!  *	$Id: iso_rrip.h,v 1.4 1993/11/07 17:46:03 wollman Exp $
   */
  
  #ifndef _ISOFS_ISO_RRIP_H_
  #define _ISOFS_ISO_RRIP_H_ 1
  
  /*
!  *	Analyze function flag
   */
  #define	ISO_SUSP_ATTR		0x0001
  #define	ISO_SUSP_DEVICE		0x0002
--- 29,42 ----
   * SUCH DAMAGE.
   *
   *	from: @(#)iso_rrip.h
!  *	$Id: iso_rrip.h,v 1.3 1993/09/07 15:40:53 ws Exp $
   */
  
  #ifndef _ISOFS_ISO_RRIP_H_
  #define _ISOFS_ISO_RRIP_H_ 1
  
  /*
!  *	Analyze function flag (similar to RR field bits)
   */
  #define	ISO_SUSP_ATTR		0x0001
  #define	ISO_SUSP_DEVICE		0x0002
***************
*** 47,60 ****
  #define	ISO_SUSP_RELDIR		0x0040
  #define	ISO_SUSP_TSTAMP		0x0080
  #define	ISO_SUSP_IDFLAG		0x0100
! #define	ISO_SUSP_EXFLAG		0x0200
! #define	ISO_SUSP_UNKNOWN	0x0400
  
  typedef struct {
! 	ISO_RRIP_INODE	inode;
! 	u_short		iso_altlen;	/* Alt Name length */
! 	u_short		iso_symlen;	/* Symbol Name length */
! 	char		*iso_altname;	/* Alt Name (no Null terminated ) */
! 	char		*iso_symname;	/* Symbol Name (no NULL termninated )*/
  } ISO_RRIP_ANALYZE;
  #endif /* _ISOFS_ISO_RRIP_H_ */
--- 47,81 ----
  #define	ISO_SUSP_RELDIR		0x0040
  #define	ISO_SUSP_TSTAMP		0x0080
  #define	ISO_SUSP_IDFLAG		0x0100
! #define	ISO_SUSP_EXTREF		0x0200
! #define	ISO_SUSP_CONT		0x0400
! #define	ISO_SUSP_OFFSET		0x0800
! #define	ISO_SUSP_STOP		0x1000
! #define	ISO_SUSP_UNKNOWN	0x8000
  
  typedef struct {
! 	struct iso_node	*inop;
! 	int		fields;		/* interesting fields in this analysis */
! 	daddr_t		iso_ce_blk;	/* block of continuation area */
! 	off_t		iso_ce_off;	/* offset of continuation area */
! 	int		iso_ce_len;	/* length of continuation area */
! 	struct iso_mnt	*imp;		/* mount structure */
! 	ino_t		*inump;		/* inode number pointer */
! 	char		*outbuf;	/* name/symbolic link output area */
! 	u_short		*outlen;	/* length of above */
! 	u_short		maxlen;		/* maximum length of above */
! 	int		cont;		/* continuation of above */
  } ISO_RRIP_ANALYZE;
+ 
+ int isofs_rrip_analyze __P((struct iso_directory_record *isodir,
+ 			    struct iso_node *inop, struct iso_mnt *imp));
+ int isofs_rrip_getname __P((struct iso_directory_record *isodir,
+ 			    char *outbuf, u_short *outlen,
+ 			    ino_t *inump, struct iso_mnt *imp));
+ int isofs_rrip_getsymname __P((struct iso_directory_record *isodir,
+ 			       char *outbuf, u_short *outlen,
+ 			       struct iso_mnt *imp));
+ int isofs_rrip_offset __P((struct iso_directory_record *isodir,
+ 			   struct iso_mnt *imp));
+ 
  #endif /* _ISOFS_ISO_RRIP_H_ */
diff -cr sys/isofs/isofs_bmap.c /usr/src/sys/isofs/isofs_bmap.c
*** sys/isofs/isofs_bmap.c	Sun Dec 19 00:51:03 1993
--- /usr/src/sys/isofs/isofs_bmap.c	Mon Aug 15 15:17:55 1994
***************
*** 1,25 ****
  /*
!  * 	$Id: isofs_bmap.c,v 1.4 1993/12/19 00:51:03 wollman Exp $
   */
  
! #include "param.h"
! #include "systm.h"
! #include "namei.h"
! #include "buf.h"
! #include "file.h"
! #include "vnode.h"
! #include "mount.h"
  
! #include "iso.h"
! #include "isofs_node.h"
  
  int
  iso_bmap(ip, lblkno, result)
! 	struct iso_node *ip;
! 	int lblkno;
! 	int *result;
  {
! 	*result = (ip->iso_extent + lblkno)
! 		* (ip->i_mnt->im_bsize / DEV_BSIZE);
! 	return (0);
  }
--- 1,24 ----
  /*
!  * 	$Id: isofs_bmap.c,v 1.6 1993/12/18 04:31:28 mycroft Exp $
   */
  
! #include <sys/param.h>
! #include <sys/namei.h>
! #include <sys/buf.h>
! #include <sys/file.h>
! #include <sys/vnode.h>
! #include <sys/mount.h>
  
! #include <isofs/iso.h>
! #include <isofs/isofs_node.h>
  
  int
  iso_bmap(ip, lblkno, result)
! struct iso_node *ip;
! int lblkno;
! daddr_t *result;
  {
! 	*result = (ip->iso_start + lblkno)
! 		  * (ip->i_mnt->logical_block_size / DEV_BSIZE);
! 	return 0;
  }
diff -cr sys/isofs/isofs_lookup.c /usr/src/sys/isofs/isofs_lookup.c
*** sys/isofs/isofs_lookup.c	Thu Nov 25 01:32:22 1993
--- /usr/src/sys/isofs/isofs_lookup.c	Mon Aug 15 15:17:56 1994
***************
*** 34,56 ****
   * SUCH DAMAGE.
   *
   *	from: @(#)ufs_lookup.c	7.33 (Berkeley) 5/19/91
!  *	$Id: isofs_lookup.c,v 1.5 1993/11/25 01:32:22 wollman Exp $
   */
  
! #include "param.h"
! #include "systm.h"
! #include "namei.h"
! #include "buf.h"
! #include "file.h"
! #include "vnode.h"
! #include "mount.h"
  
! #include "iso.h"
! #include "isofs_node.h"
! #include "iso_rrip.h"
! #include "isofs_rrip.h"
! 
! struct	nchstats nchstats;
  
  /*
   * Convert a component of a pathname into a pointer to a locked inode.
--- 34,56 ----
   * SUCH DAMAGE.
   *
   *	from: @(#)ufs_lookup.c	7.33 (Berkeley) 5/19/91
!  *	$Id: isofs_lookup.c,v 1.17 1994/04/25 03:49:27 cgd Exp $
   */
  
! #include <sys/param.h>
! #include <sys/systm.h>
! #include <sys/namei.h>
! #include <sys/buf.h>
! #include <sys/file.h>
! #include <sys/vnode.h>
! #include <sys/mount.h>
! 
! #include <isofs/iso.h>
! #include <isofs/isofs_node.h>
! #include <isofs/iso_rrip.h>
! #include <isofs/isofs_rrip.h>
  
! struct	nchstats iso_nchstats;
  
  /*
   * Convert a component of a pathname into a pointer to a locked inode.
***************
*** 96,123 ****
  	register struct iso_node *dp;	/* the directory we are searching */
  	register struct iso_mnt *imp;	/* file system that directory is in */
  	struct buf *bp = 0;		/* a buffer of directory entries */
! 	register struct iso_directory_record *ep;
! 					/* the current directory entry */
! 	int entryoffsetinblock = 0;	/* offset of ep in bp's buffer */
! 	enum {NONE, COMPACT, FOUND} slotstatus;
! 	int slotoffset = -1;		/* offset of area with free space */
! 	int slotsize;			/* size of area at slotoffset */
! 	int slotfreespace;		/* amount of space free in slot */
! 	int slotneeded;			/* size of the entry we're seeking */
  	int numdirpasses;		/* strategy for directory search */
! 	int endsearch;			/* offset to end directory search */
  	struct iso_node *pdp;		/* saved dp during symlink work */
  	struct iso_node *tdp;		/* returned by iget */
  	int flag;			/* LOOKUP, CREATE, RENAME, or DELETE */
  	int lockparent;			/* 1 => lockparent flag is set */
  	int wantparent;			/* 1 => wantparent or lockparent flag */
  	int error;
! 
  	int reclen;
! 	int namelen;
! 	char altname[251];
! 	int i;
! 
  	ndp->ni_dvp = vdp;
  	ndp->ni_vp = NULL;
  	dp = VTOI(vdp);
--- 96,120 ----
  	register struct iso_node *dp;	/* the directory we are searching */
  	register struct iso_mnt *imp;	/* file system that directory is in */
  	struct buf *bp = 0;		/* a buffer of directory entries */
! 	struct iso_directory_record *ep;/* the current directory entry */
! 	off_t entryoffsetinblock = 0;	/* offset of ep in bp's buffer */
! 	off_t saveoffset = 0;		/* offset of last directory entry in dir */
  	int numdirpasses;		/* strategy for directory search */
! 	off_t endsearch;		/* offset to end directory search */
  	struct iso_node *pdp;		/* saved dp during symlink work */
  	struct iso_node *tdp;		/* returned by iget */
  	int flag;			/* LOOKUP, CREATE, RENAME, or DELETE */
  	int lockparent;			/* 1 => lockparent flag is set */
  	int wantparent;			/* 1 => wantparent or lockparent flag */
  	int error;
! 	ino_t ino = 0;
  	int reclen;
! 	u_short namelen;
! 	char altname[NAME_MAX];
! 	int res;
! 	int assoc, len;
! 	char *name;
! 	
  	ndp->ni_dvp = vdp;
  	ndp->ni_vp = NULL;
  	dp = VTOI(vdp);
***************
*** 125,137 ****
  	lockparent = ndp->ni_nameiop & LOCKPARENT;
  	flag = ndp->ni_nameiop & OPMASK;
  	wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
! 
  	/*
  	 * Check accessiblity of directory.
  	 */
! 	if ((dp->iso_flags & 2) == 0)
! 		return (ENOTDIR);
! 
  	/*
  	 * We now have a segment name to search for, and a directory to search.
  	 *
--- 122,136 ----
  	lockparent = ndp->ni_nameiop & LOCKPARENT;
  	flag = ndp->ni_nameiop & OPMASK;
  	wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
! 	
  	/*
  	 * Check accessiblity of directory.
  	 */
! 	if (vdp->v_type != VDIR)
! 		return ENOTDIR;
! 	if (error = isofs_access(vdp, VEXEC, ndp->ni_cred, p))
! 		return error;
! 	
  	/*
  	 * We now have a segment name to search for, and a directory to search.
  	 *
***************
*** 141,150 ****
  	 */
  	if (error = cache_lookup(ndp)) {
  		int vpid;	/* capability number of vnode */
! 
  		if (error == ENOENT)
  			return (error);
! #ifdef PARANOID
  		if (vdp == ndp->ni_rootdir && ndp->ni_isdotdot)
  			panic("ufs_lookup: .. through root");
  #endif
--- 140,149 ----
  	 */
  	if (error = cache_lookup(ndp)) {
  		int vpid;	/* capability number of vnode */
! 		
  		if (error == ENOENT)
  			return (error);
! #ifdef DIAGNOSTIC
  		if (vdp == ndp->ni_rootdir && ndp->ni_isdotdot)
  			panic("ufs_lookup: .. through root");
  #endif
***************
*** 186,192 ****
  		vdp = ITOV(dp);
  		ndp->ni_vp = NULL;
  	}
! 
  	/*
  	 * If there is cached information on a previous search of
  	 * this directory, pick up where we last left off.
--- 185,201 ----
  		vdp = ITOV(dp);
  		ndp->ni_vp = NULL;
  	}
! 	
! 	len = ndp->ni_namelen;
! 	name = ndp->ni_ptr;
! 	/*
! 	 * A leading `=' means, we are looking for an associated file
! 	 */
! 	if (assoc = (imp->iso_ftype != ISO_FTYPE_RRIP && *name == ASSOCCHAR)) {
! 		len--;
! 		name++;
! 	}
! 	
  	/*
  	 * If there is cached information on a previous search of
  	 * this directory, pick up where we last left off.
***************
*** 205,219 ****
  		ndp->ni_ufs.ufs_offset = dp->i_diroff;
  		entryoffsetinblock = iso_blkoff(imp, ndp->ni_ufs.ufs_offset);
  		if (entryoffsetinblock != 0) {
! 			if (error = iso_blkatoff(dp, ndp->ni_ufs.ufs_offset,
! 			    (char **)0, &bp))
! 				return (error);
  		}
  		numdirpasses = 2;
! 		nchstats.ncs_2passes++;
  	}
! 	endsearch = roundup(dp->i_size, imp->logical_block_size);
! 
  searchloop:
  	while (ndp->ni_ufs.ufs_offset < endsearch) {
  		/*
--- 214,227 ----
  		ndp->ni_ufs.ufs_offset = dp->i_diroff;
  		entryoffsetinblock = iso_blkoff(imp, ndp->ni_ufs.ufs_offset);
  		if (entryoffsetinblock != 0) {
! 			if (error = iso_blkatoff(dp,ndp->ni_ufs.ufs_offset,&bp))
! 				return error;
  		}
  		numdirpasses = 2;
! 		iso_nchstats.ncs_2passes++;
  	}
! 	endsearch = roundup(dp->i_size,imp->logical_block_size);
! 	
  searchloop:
  	while (ndp->ni_ufs.ufs_offset < endsearch) {
  		/*
***************
*** 221,307 ****
  		 * read the next directory block.
  		 * Release previous if it exists.
  		 */
! 		if (iso_blkoff(imp, ndp->ni_ufs.ufs_offset) == 0) {
  			if (bp != NULL)
  				brelse(bp);
! 			if (error = iso_blkatoff(dp, ndp->ni_ufs.ufs_offset,
! 						 (char **)0, &bp))
! 				return (error);
  			entryoffsetinblock = 0;
  		}
  		/*
  		 * Get pointer to next entry.
  		 */
! 
  		ep = (struct iso_directory_record *)
  			(bp->b_un.b_addr + entryoffsetinblock);
! 
  		reclen = isonum_711 (ep->length);
  		if (reclen == 0) {
  			/* skip to next block, if any */
  			ndp->ni_ufs.ufs_offset =
! 				roundup (ndp->ni_ufs.ufs_offset,
! 					 imp->logical_block_size);
  			continue;
  		}
! 
! 		if (reclen < sizeof (struct iso_directory_record))
  			/* illegal entry, stop */
  			break;
! 
! /* 10 Aug 92*/	if (entryoffsetinblock + reclen -1 >= imp->logical_block_size)
  			/* entries are not allowed to cross boundaries */
  			break;
! 
  		/*
  		 * Check for a name match.
  		 */
! 		namelen = isonum_711 (ep->name_len);
! 
! 		if (reclen < sizeof (struct iso_directory_record) + namelen)
  			/* illegal entry, stop */
  			break;
! 
! 		if (namelen == 1
! 		     && ((ndp->ni_namelen == 1
! 			  && ndp->ni_ptr[0] == '.'
! 			  && ep->name[0] == 0)
! 			 || (ndp->ni_isdotdot && ep->name[0] == 1))) {
! 			/*
! 			 * Save directory entry's inode number and
! 			 * reclen in ndp->ni_ufs area, and release
! 			 * directory buffer.
! 			 */
! 			ndp->ni_ufs.ufs_ino = isonum_733 (ep->extent);
! 			brelse(bp);
! 			goto found;
! 		} else {
! 			switch ( imp->iso_ftype ) {
! 				case ISO_FTYPE_9660:
! 				if( ( namelen  >= ndp->ni_namelen ) &&
! 					    ( isofncmp( ndp->ni_ptr, ndp->ni_namelen, ep->name, namelen ) ) ) {
! 						ndp->ni_ufs.ufs_ino = isonum_733 (ep->extent);
! 						brelse(bp);
! 						goto found;
! 					}
! 					break;
! 				case ISO_FTYPE_RRIP:
! 					isofs_rrip_getname( ep, altname, &namelen );
! 					if ( ( namelen == ndp->ni_namelen ) &&
! 					     ( !bcmp( ndp->ni_ptr, altname, ndp->ni_namelen ) ) ) {
! 						ndp->ni_ufs.ufs_ino = isonum_733 (ep->extent);
! 						brelse(bp);
  						goto found;
  					}
! 					break;
! 				default:
! 					break;
  			}
  		}
  		ndp->ni_ufs.ufs_offset += reclen;
  		entryoffsetinblock += reclen;
  	}
! /* notfound: */
  	/*
  	 * If we started in the middle of the directory and failed
  	 * to find our target, we must check the beginning as well.
--- 229,345 ----
  		 * read the next directory block.
  		 * Release previous if it exists.
  		 */
! 		if (iso_blkoff(imp,ndp->ni_ufs.ufs_offset) == 0) {
  			if (bp != NULL)
  				brelse(bp);
! 			if (error = iso_blkatoff(dp,ndp->ni_ufs.ufs_offset,&bp))
! 				return error;
  			entryoffsetinblock = 0;
  		}
  		/*
  		 * Get pointer to next entry.
  		 */
! 		
  		ep = (struct iso_directory_record *)
  			(bp->b_un.b_addr + entryoffsetinblock);
! 		
  		reclen = isonum_711 (ep->length);
  		if (reclen == 0) {
  			/* skip to next block, if any */
  			ndp->ni_ufs.ufs_offset =
! 				roundup(ndp->ni_ufs.ufs_offset,
! 					imp->logical_block_size);
  			continue;
  		}
! 		
! 		if (reclen < ISO_DIRECTORY_RECORD_SIZE)
  			/* illegal entry, stop */
  			break;
! 		
! 		if (entryoffsetinblock + reclen > imp->logical_block_size)
  			/* entries are not allowed to cross boundaries */
  			break;
! 		
  		/*
  		 * Check for a name match.
  		 */
! 		namelen = isonum_711(ep->name_len);
! 		
! 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen)
  			/* illegal entry, stop */
  			break;
! 		
! 		switch (imp->iso_ftype) {
! 		default:
! 			if ((!(isonum_711(ep->flags)&4)) == !assoc) {
! 				if ((len == 1
! 				     && *name == '.')
! 				    || ndp->ni_isdotdot) {
! 					if (namelen == 1
! 					    && ep->name[0] == (ndp->ni_isdotdot ? 1 : 0)) {
! 						/*
! 						 * Save directory entry's inode number and
! 						 * reclen in ndp->ni_ufs area, and release
! 						 * directory buffer.
! 						 */
! 						isodirino(&ndp->ni_ufs.ufs_ino,ep,imp);
  						goto found;
  					}
! 					if (namelen != 1
! 					    || ep->name[0] != 0)
! 						goto notfound;
! 				} else if (!(res = isofncmp(name,len,
! 							    ep->name,namelen))) {
! 					if (isonum_711(ep->flags)&2)
! 						isodirino(&ino,ep,imp);
! 					else
! 						ino = (bp->b_blkno << DEV_BSHIFT)
! 						      + entryoffsetinblock;
! 					saveoffset = ndp->ni_ufs.ufs_offset;
! 				} else if (ino)
! 					goto foundino;
! #ifdef	NOSORTBUG	/* On some CDs directory entries are not sorted correctly */
! 				else if (res < 0)
! 					goto notfound;
! 				else if (res > 0 && numdirpasses == 2)
! 					numdirpasses++;
! #endif
  			}
+ 			break;
+ 		case ISO_FTYPE_RRIP:
+ 			if (isonum_711(ep->flags)&2)
+ 				isodirino(&ino,ep,imp);
+ 			else
+ 				ino = (bp->b_blkno << DEV_BSHIFT) + entryoffsetinblock;
+ 			ndp->ni_ufs.ufs_ino = ino;
+ 			isofs_rrip_getname(ep,altname,&namelen,&ndp->ni_ufs.ufs_ino,imp);
+ 			if (namelen == ndp->ni_namelen
+ 			    && !bcmp(name,altname,namelen))
+ 				goto found;
+ 			ino = 0;
+ 			break;
  		}
  		ndp->ni_ufs.ufs_offset += reclen;
  		entryoffsetinblock += reclen;
  	}
! 	if (ino) {
! foundino:
! 		ndp->ni_ufs.ufs_ino = ino;
! 		if (saveoffset != ndp->ni_ufs.ufs_offset) {
! 			if (iso_lblkno(imp,ndp->ni_ufs.ufs_offset)
! 			    != iso_lblkno(imp,saveoffset)) {
! 				if (bp != NULL)
! 					brelse(bp);
! 				if (error = iso_blkatoff(dp,saveoffset,&bp))
! 					return error;
! 			}
! 			ep = (struct iso_directory_record *)(bp->b_un.b_addr
! 							     + iso_blkoff(imp,saveoffset));
! 			ndp->ni_ufs.ufs_offset = saveoffset;
! 		}
! 		goto found;
! 	}
! notfound:
  	/*
  	 * If we started in the middle of the directory and failed
  	 * to find our target, we must check the beginning as well.
***************
*** 319,330 ****
  	 */
  	if (ndp->ni_makeentry)
  		cache_enter(ndp);
  	return (ENOENT);
! 
  found:
! 	if (numdirpasses == 2)
! 		nchstats.ncs_pass2++;
! 
  	/*
  	 * Found component in pathname.
  	 * If the final component of path name, save information
--- 357,370 ----
  	 */
  	if (ndp->ni_makeentry)
  		cache_enter(ndp);
+ 	if (flag == CREATE || flag == RENAME)
+ 		return EJUSTRETURN;
  	return (ENOENT);
! 	
  found:
! 	if (numdirpasses > 1)
! 		iso_nchstats.ncs_pass2++;
! 	
  	/*
  	 * Found component in pathname.
  	 * If the final component of path name, save information
***************
*** 332,339 ****
  	 */
  	if (*ndp->ni_next == '\0' && flag == LOOKUP)
  		dp->i_diroff = ndp->ni_ufs.ufs_offset;
! 			/* &~ (imp->logical_block_size - 1); */
! 
  	/*
  	 * Step through the translation in the name.  We do not `iput' the
  	 * directory because we may need it again if a symbolic link
--- 372,378 ----
  	 */
  	if (*ndp->ni_next == '\0' && flag == LOOKUP)
  		dp->i_diroff = ndp->ni_ufs.ufs_offset;
! 	
  	/*
  	 * Step through the translation in the name.  We do not `iput' the
  	 * directory because we may need it again if a symbolic link
***************
*** 354,364 ****
  	 * that point backwards in the directory structure.
  	 */
  	pdp = dp;
  	if (ndp->ni_isdotdot) {
  		ISO_IUNLOCK(pdp);	/* race to get the inode */
! 		if (error = iso_iget(dp, ndp->ni_ufs.ufs_ino, &tdp, ep)) {
  			ISO_ILOCK(pdp);
! 			return (error);
  		}
  		if (lockparent && *ndp->ni_next == '\0')
  			ISO_ILOCK(pdp);
--- 393,410 ----
  	 * that point backwards in the directory structure.
  	 */
  	pdp = dp;
+ 	/*
+ 	 * If ino is different from ndp->ni_ufs.ufs_ino,
+ 	 * it's a relocated directory.
+ 	 */
  	if (ndp->ni_isdotdot) {
  		ISO_IUNLOCK(pdp);	/* race to get the inode */
! 		if (error = iso_iget(dp,ndp->ni_ufs.ufs_ino,
! 				     ndp->ni_ufs.ufs_ino != ino,
! 				     &tdp,ep)) {
! 			brelse(bp);
  			ISO_ILOCK(pdp);
! 			return error;
  		}
  		if (lockparent && *ndp->ni_next == '\0')
  			ISO_ILOCK(pdp);
***************
*** 367,388 ****
  		VREF(vdp);	/* we want ourself, ie "." */
  		ndp->ni_vp = vdp;
  	} else {
! 		if (error = iso_iget(dp, ndp->ni_ufs.ufs_ino, &tdp, ep))
! 			return (error);
  		if (!lockparent || *ndp->ni_next != '\0')
  			ISO_IUNLOCK(pdp);
  		ndp->ni_vp = ITOV(tdp);
  	}
! 
  	/*
  	 * Insert name into cache if appropriate.
  	 */
  	if (ndp->ni_makeentry)
  		cache_enter(ndp);
! 	return (0);
  }
  
- 
  /*
   * Return buffer with contents of block "offset"
   * from the beginning of directory "ip".  If "res"
--- 413,439 ----
  		VREF(vdp);	/* we want ourself, ie "." */
  		ndp->ni_vp = vdp;
  	} else {
! 		if (error = iso_iget(dp,ndp->ni_ufs.ufs_ino,
! 				     ndp->ni_ufs.ufs_ino != ino,
! 				     &tdp,ep)) {
! 			brelse(bp);
! 			return error;
! 		}
  		if (!lockparent || *ndp->ni_next != '\0')
  			ISO_IUNLOCK(pdp);
  		ndp->ni_vp = ITOV(tdp);
  	}
! 	
! 	brelse(bp);
! 	
  	/*
  	 * Insert name into cache if appropriate.
  	 */
  	if (ndp->ni_makeentry)
  		cache_enter(ndp);
! 	return 0;
  }
  
  /*
   * Return buffer with contents of block "offset"
   * from the beginning of directory "ip".  If "res"
***************
*** 390,415 ****
   * remaining space in the directory.
   */
  int
! iso_blkatoff(ip, offset, res, bpp)
  	struct iso_node *ip;
  	off_t offset;
- 	char **res;
  	struct buf **bpp;
  {
  	register struct iso_mnt *imp = ip->i_mnt;
! 	daddr_t lbn = iso_lblkno (imp, offset);
! 	int bsize = iso_blksize (imp, ip, lbn);
  	struct buf *bp;
  	int error;
! 
! 	*bpp = 0;
! 	if (error = bread(ITOV(ip), lbn, bsize, NOCRED, &bp)) {
  		brelse(bp);
! 		return (error);
  	}
- 	if (res)
- 		*res = bp->b_un.b_addr + iso_blkoff(imp, offset);
  	*bpp = bp;
! 
! 	return (0);
  }
--- 441,463 ----
   * remaining space in the directory.
   */
  int
! iso_blkatoff(ip, offset, bpp)
  	struct iso_node *ip;
  	off_t offset;
  	struct buf **bpp;
  {
  	register struct iso_mnt *imp = ip->i_mnt;
! 	daddr_t lbn = iso_lblkno(imp,offset);
! 	int bsize = iso_blksize(imp,ip,lbn);
  	struct buf *bp;
  	int error;
! 	
! 	if (error = bread(ITOV(ip),lbn,bsize,NOCRED,&bp)) {
  		brelse(bp);
! 		*bpp = 0;
! 		return error;
  	}
  	*bpp = bp;
! 	
! 	return 0;
  }
diff -cr sys/isofs/isofs_node.c /usr/src/sys/isofs/isofs_node.c
*** sys/isofs/isofs_node.c	Thu Nov 25 01:32:23 1993
--- /usr/src/sys/isofs/isofs_node.c	Mon Aug 15 15:58:28 1994
***************
*** 30,58 ****
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	from: @(#)isofs_inode.c
!  *	$Id: isofs_node.c,v 1.6 1993/11/25 01:32:23 wollman Exp $
   */
  
! #include "param.h"
! #include "systm.h"
! #include "mount.h"
! #include "proc.h"
! #include "file.h"
! #include "buf.h"
! #include "vnode.h"
! #include "kernel.h"
! #include "malloc.h"
! 
! #include "iso.h"
! #include "isofs_node.h"
! #include "iso_rrip.h"
  
  #define	INOHSZ	512
  #if	((INOHSZ&(INOHSZ-1)) == 0)
! #define	INOHASH(dev,ino)	(((dev)+(ino))&(INOHSZ-1))
  #else
! #define	INOHASH(dev,ino)	(((unsigned)((dev)+(ino)))%INOHSZ)
  #endif
  
  union iso_ihead {
--- 30,65 ----
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	from: @(#)ufs_inode.c (unknown version)
!  *	$Id: isofs_node.c,v 1.12 1994/04/25 03:49:30 cgd Exp $
   */
  
! #include <sys/param.h>
! #include <sys/systm.h>
! #include <sys/mount.h>
! #include <sys/proc.h>
! #include <sys/file.h>
! #include <sys/buf.h>
! #include <sys/vnode.h>
! #include <sys/kernel.h>
! #include <sys/malloc.h>
! #include <sys/stat.h>
! 
! #include <isofs/iso.h>
! #include <isofs/isofs_node.h>
! #include <isofs/iso_rrip.h>
! 
! #define	IFTOVT(mode)	(iftovt_tab[((mode) & 0170000) >> 12])
! static enum vtype iftovt_tab[16] = {
! 	VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
! 	VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
! };
  
  #define	INOHSZ	512
  #if	((INOHSZ&(INOHSZ-1)) == 0)
! #define	INOHASH(dev,ino)	(((dev)+((ino)>>12))&(INOHSZ-1))
  #else
! #define	INOHASH(dev,ino)	(((unsigned)((dev)+((ino)>>12)))%INOHSZ)
  #endif
  
  union iso_ihead {
***************
*** 60,75 ****
  	struct iso_node *ih_chain[2];
  } iso_ihead[INOHSZ];
  
  int prtactive;	/* 1 => print out reclaim of active vnodes */
  
  /*
!  * Initialize hash links for inodes.
   */
  void
  isofs_init()
  {
  	register int i;
  	register union iso_ihead *ih = iso_ihead;
  
  #ifndef lint
  	if (VN_MAXPRIVATE < sizeof(struct iso_node))
--- 67,99 ----
  	struct iso_node *ih_chain[2];
  } iso_ihead[INOHSZ];
  
+ #ifdef	ISODEVMAP
+ #define	DNOHSZ	64
+ #if	((DNOHSZ&(DNOHSZ-1)) == 0)
+ #define	DNOHASH(dev,ino)	(((dev)+((ino)>>12))&(DNOHSZ-1))
+ #else
+ #define	DNOHASH(dev,ino)	(((unsigned)((dev)+((ino)>>12)))%DNOHSZ)
+ #endif
+ 
+ union iso_dhead {
+ 	union  iso_dhead  *dh_head[2];
+ 	struct iso_dnode *dh_chain[2];
+ } iso_dhead[DNOHSZ];
+ #endif
+ 
  int prtactive;	/* 1 => print out reclaim of active vnodes */
  
  /*
!  * Initialize hash links for inodes and dnodes.
   */
  void
  isofs_init()
  {
  	register int i;
  	register union iso_ihead *ih = iso_ihead;
+ #ifdef	ISODEVMAP
+ 	register union iso_dhead *dh = iso_dhead;
+ #endif
  
  #ifndef lint
  	if (VN_MAXPRIVATE < sizeof(struct iso_node))
***************
*** 79,86 ****
--- 103,168 ----
  		ih->ih_head[0] = ih;
  		ih->ih_head[1] = ih;
  	}
+ #ifdef	ISODEVMAP
+ 	for (i = DNOHSZ; --i >= 0; dh++) {
+ 		dh->dh_head[0] = dh;
+ 		dh->dh_head[1] = dh;
+ 	}
+ #endif
  }
  
+ #ifdef	ISODEVMAP
+ /*
+  * Enter a new node into the device hash list
+  */
+ struct iso_dnode *
+ iso_dmap(dev,ino,create)
+ 	dev_t	dev;
+ 	ino_t	ino;
+ 	int	create;
+ {
+ 	struct iso_dnode *dp;
+ 	union iso_dhead *dh;
+ 	
+ 	dh = &iso_dhead[DNOHASH(dev, ino)];
+ 	for (dp = dh->dh_chain[0];
+ 	     dp != (struct iso_dnode *)dh;
+ 	     dp = dp->d_forw)
+ 		if (ino == dp->i_number && dev == dp->i_dev)
+ 			return dp;
+ 
+ 	if (!create)
+ 		return (struct iso_dnode *)0;
+ 
+ 	MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK);
+ 	dp->i_dev = dev;
+ 	dp->i_number = ino;
+ 	insque(dp,dh);
+ 	
+ 	return dp;
+ }
+ 
+ void
+ iso_dunmap(dev)
+ 	dev_t	dev;
+ {
+ 	struct iso_dnode *dp, *dq;
+ 	union iso_dhead *dh;
+ 	
+ 	for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) {
+ 		for (dp = dh->dh_chain[0];
+ 		     dp != (struct iso_dnode *)dh;
+ 		     dp = dq) {
+ 			dq = dp->d_forw;
+ 			if (dev == dp->i_dev) {
+ 				remque(dp);
+ 				FREE(dp,M_CACHE);
+ 			}
+ 		}
+ 	}
+ }
+ #endif
+ 
  /*
   * Look up a ISOFS dinode number to find its incore vnode.
   * If it is not in core, read it in from the specified device.
***************
*** 89,112 ****
   * points must be done by the calling routine.
   */
  int
! iso_iget(xp, ino, ipp, isodir)
  	struct iso_node *xp;
  	ino_t ino;
  	struct iso_node **ipp;
  	struct iso_directory_record *isodir;
  {
  	dev_t dev = xp->i_dev;
  	struct mount *mntp = ITOV(xp)->v_mount;
! 	extern struct vnodeops isofs_vnodeops, spec_inodeops;
  	register struct iso_node *ip, *iq;
  	register struct vnode *vp;
  	struct vnode *nvp;
! 	struct buf *bp;
! 	struct dinode *dp;
  	union iso_ihead *ih;
! 	int i, error, result = 0;
  	struct iso_mnt *imp;
! 
  	ih = &iso_ihead[INOHASH(dev, ino)];
  loop:
  	for (ip = ih->ih_chain[0];
--- 171,197 ----
   * points must be done by the calling routine.
   */
  int
! iso_iget(xp, ino, relocated, ipp, isodir)
  	struct iso_node *xp;
  	ino_t ino;
+         int relocated;
  	struct iso_node **ipp;
  	struct iso_directory_record *isodir;
  {
  	dev_t dev = xp->i_dev;
  	struct mount *mntp = ITOV(xp)->v_mount;
! 	extern struct vnodeops isofs_vnodeops, isofs_spec_inodeops;
  	register struct iso_node *ip, *iq;
  	register struct vnode *vp;
+ 	register struct iso_dnode *dp;
  	struct vnode *nvp;
! 	struct buf *bp = NULL, *bp2 = NULL;
  	union iso_ihead *ih;
! 	union iso_dhead *dh;
! 	int i, error, result;
  	struct iso_mnt *imp;
! 	ino_t defino;
! 	
  	ih = &iso_ihead[INOHASH(dev, ino)];
  loop:
  	for (ip = ih->ih_chain[0];
***************
*** 116,144 ****
  			continue;
  		if ((ip->i_flag&ILOCKED) != 0) {
  			ip->i_flag |= IWANT;
! 			tsleep((caddr_t)ip, PINOD, "isoiget", 0);
  			goto loop;
  		}
  		if (vget(ITOV(ip)))
  			goto loop;
  		*ipp = ip;
! 		return(0);
  	}
  	/*
  	 * Allocate a new inode.
  	 */
  	if (error = getnewvnode(VT_ISOFS, mntp, &isofs_vnodeops, &nvp)) {
  		*ipp = 0;
! 		return (error);
  	}
  	ip = VTOI(nvp);
  	ip->i_vnode = nvp;
  	ip->i_flag = 0;
  	ip->i_devvp = 0;
  	ip->i_diroff = 0;
- 	ip->iso_parent = xp->i_diroff; /* Parent directory's */
- 	ip->iso_parent_ext = xp->iso_extent;
  	ip->i_lockf = 0;
  	/*
  	 * Put it onto its hash chain and lock it so that other requests for
  	 * this inode will block if they arrive while we are sleeping waiting
--- 201,228 ----
  			continue;
  		if ((ip->i_flag&ILOCKED) != 0) {
  			ip->i_flag |= IWANT;
! 			tsleep((caddr_t)ip, PINOD, "iget", 0);
  			goto loop;
  		}
  		if (vget(ITOV(ip)))
  			goto loop;
  		*ipp = ip;
! 		return 0;
  	}
  	/*
  	 * Allocate a new inode.
  	 */
  	if (error = getnewvnode(VT_ISOFS, mntp, &isofs_vnodeops, &nvp)) {
  		*ipp = 0;
! 		return error;
  	}
  	ip = VTOI(nvp);
  	ip->i_vnode = nvp;
  	ip->i_flag = 0;
  	ip->i_devvp = 0;
  	ip->i_diroff = 0;
  	ip->i_lockf = 0;
+ 	
  	/*
  	 * Put it onto its hash chain and lock it so that other requests for
  	 * this inode will block if they arrive while we are sleeping waiting
***************
*** 150,209 ****
  	insque(ip, ih);
  	ISO_ILOCK(ip);
  
- 	ip->iso_reclen = isonum_711 (isodir->length);
- 	ip->iso_extlen = isonum_711 (isodir->ext_attr_length);
- 	ip->iso_extent = isonum_733 (isodir->extent);
- 	ip->i_size = isonum_733 (isodir->size);
- 	ip->iso_flags = isonum_711 (isodir->flags);
- 	ip->iso_unit_size = isonum_711 (isodir->file_unit_size);
- 	ip->iso_interleave_gap = isonum_711 (isodir->interleave);
- 	ip->iso_volume_seq = isonum_723 (isodir->volume_sequence_number);
- 	ip->iso_namelen = isonum_711 (isodir->name_len);
- 
  	imp = VFSTOISOFS (mntp);
  	vp = ITOV(ip);
  	/*
! 	 * Setup time stamp, attribute , if CL or PL, set loc but not yet..
  	 */
! 	switch ( imp->iso_ftype ) {
! 		case ISO_FTYPE_9660:
! 			isofs_rrip_defattr  ( isodir, &(ip->inode) );
! 			isofs_rrip_deftstamp( isodir, &(ip->inode) );
! 			goto FlameOff;
! 			break;  
! 		case ISO_FTYPE_RRIP:
! 			result = isofs_rrip_analyze( isodir, &(ip->inode) );
! 			break;  
! 		default:
! 			printf("unknown iso_ftype.. %d\n", imp->iso_ftype );
! 			break;
  	}
  	/*
  	 * Initialize the associated vnode
  	 */
! 	if ( result & ISO_SUSP_SLINK ) {
! 		vp->v_type = VLNK;	      /* Symbolic Link */
! 	} else {
! FlameOff:
! 		if (ip->iso_flags & 2) {
! 			vp->v_type = VDIR;
! 		} else {
! 			vp->v_type = VREG;
  		}
  	}
! 
! 	imp = VFSTOISOFS (mntp);
! 
! 	if (ino == imp->root_extent)
  		vp->v_flag |= VROOT;
! 	/*
! 	 * Finish inode initialization.
! 	 */
! 	ip->i_mnt = imp;
! 	ip->i_devvp = imp->im_devvp;
! 	VREF(ip->i_devvp);
  	*ipp = ip;
! 	return (0);
  }
  
  /*
--- 234,343 ----
  	insque(ip, ih);
  	ISO_ILOCK(ip);
  
  	imp = VFSTOISOFS (mntp);
+ 	ip->i_mnt = imp;
+ 	ip->i_devvp = imp->im_devvp;
+ 	VREF(ip->i_devvp);
+ 	
+ 	if (relocated) {
+ 		/*
+ 		 * On relocated directories we must
+ 		 * read the `.' entry out of a dir.
+ 		 */
+ 		ip->iso_start = ino >> imp->im_bshift;
+ 		if (error = iso_blkatoff(ip,0,&bp)) {
+ 			vrele(ip->i_devvp);
+ 			remque(ip);
+ 			ip->i_forw = ip;
+ 			ip->i_back = ip;
+ 			iso_iput(ip);
+ 			*ipp = 0;
+ 			return error;
+ 		}
+ 		isodir = (struct iso_directory_record *)bp->b_un.b_addr;
+ 	}
+ 	
+ 	ip->iso_extent = isonum_733(isodir->extent);
+ 	ip->i_size = isonum_733(isodir->size);
+ 	ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
+ 	
  	vp = ITOV(ip);
+ 	
  	/*
! 	 * Setup time stamp, attribute
  	 */
! 	vp->v_type = VNON;
! 	switch (imp->iso_ftype) {
! 	default:	/* ISO_FTYPE_9660 */
! 		if ((imp->im_flags&ISOFSMNT_EXTATT)
! 		    && isonum_711(isodir->ext_attr_length))
! 			iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length),
! 				     &bp2);
! 		isofs_defattr(isodir,ip,bp2 );
! 		isofs_deftstamp(isodir,ip,bp2 );
! 		break;
! 	case ISO_FTYPE_RRIP:
! 		result = isofs_rrip_analyze(isodir,ip,imp);
! 		break;
  	}
+ 	if (bp2)
+ 		brelse(bp2);
+ 	if (bp)
+ 		brelse(bp);
+ 	
  	/*
  	 * Initialize the associated vnode
  	 */
! 	vp->v_type = IFTOVT(ip->inode.iso_mode);
! 	
! 	if ( vp->v_type == VFIFO ) {
! #ifdef	FIFO
! 		extern struct vnodeops isofs_fifo_inodeops;
! 		vp->v_op = &isofs_fifo_inodeops;
! #else
! 		iso_iput(ip);
! 		*ipp = 0;
! 		return EOPNOTSUPP;
! #endif	/* FIFO */
! 	} else if ( vp->v_type == VCHR || vp->v_type == VBLK ) {
! 		/*
! 		 * if device, look at device number table for translation
! 		 */
! #ifdef	ISODEVMAP
! 		if (dp = iso_dmap(dev,ino,0))
! 			ip->inode.iso_rdev = dp->d_dev;
! #endif
! 		vp->v_op = &isofs_spec_inodeops;
! 		if (nvp = checkalias(vp, ip->inode.iso_rdev, mntp)) {
! 			/*
! 			 * Reinitialize aliased inode.
! 			 */
! 			vp = nvp;
! 			iq = VTOI(vp);
! 			iq->i_vnode = vp;
! 			iq->i_flag = 0;
! 			ISO_ILOCK(iq);
! 			iq->i_dev = dev;
! 			iq->i_number = ino;
! 			iq->i_mnt = ip->i_mnt;
! 			bcopy(&ip->iso_extent,&iq->iso_extent,
! 			      (char *)(ip + 1) - (char *)&ip->iso_extent);
! 			insque(iq, ih);
! 			/*
! 			 * Discard unneeded vnode
! 			 * (This introduces the need of INACTIVE modification)
! 			 */
! 			ip->inode.iso_mode = 0;
! 			iso_iput(ip);
! 			ip = iq;
  		}
  	}
! 	
! 	if (ip->iso_extent == imp->root_extent)
  		vp->v_flag |= VROOT;
! 	
  	*ipp = ip;
! 	return 0;
  }
  
  /*
***************
*** 213,219 ****
  iso_iput(ip)
  	register struct iso_node *ip;
  {
! 
  	if ((ip->i_flag & ILOCKED) == 0)
  		panic("iso_iput");
  	ISO_IUNLOCK(ip);
--- 347,353 ----
  iso_iput(ip)
  	register struct iso_node *ip;
  {
! 	
  	if ((ip->i_flag & ILOCKED) == 0)
  		panic("iso_iput");
  	ISO_IUNLOCK(ip);
***************
*** 231,256 ****
  {
  	register struct iso_node *ip = VTOI(vp);
  	int mode, error = 0;
! 
  	if (prtactive && vp->v_usecount != 0)
  		vprint("isofs_inactive: pushing active", vp);
! 
  	ip->i_flag = 0;
  	/*
  	 * If we are done with the inode, reclaim it
  	 * so that it can be reused immediately.
  	 */
! 
! 	/*
! 	 * Purge symlink entries since they cause problems
! 	 * when cached.  Leave other entries alone since flushing
! 	 * them every time is a major performance hit.
! 	 */
! 	if (vp->v_usecount == 0 && vp->v_type == VLNK) {
! /*		printf("Flushing symlink entry\n");*/
  		vgone(vp);
! 	}
! 	return (error);
  }
  
  /*
--- 365,382 ----
  {
  	register struct iso_node *ip = VTOI(vp);
  	int mode, error = 0;
! 	
  	if (prtactive && vp->v_usecount != 0)
  		vprint("isofs_inactive: pushing active", vp);
! 	
  	ip->i_flag = 0;
  	/*
  	 * If we are done with the inode, reclaim it
  	 * so that it can be reused immediately.
  	 */
! 	if (vp->v_usecount == 0 && ip->inode.iso_mode == 0)
  		vgone(vp);
! 	return error;
  }
  
  /*
***************
*** 262,268 ****
  {
  	register struct iso_node *ip = VTOI(vp);
  	int i;
! 
  	if (prtactive && vp->v_usecount != 0)
  		vprint("isofs_reclaim: pushing active", vp);
  	/*
--- 388,394 ----
  {
  	register struct iso_node *ip = VTOI(vp);
  	int i;
! 	
  	if (prtactive && vp->v_usecount != 0)
  		vprint("isofs_reclaim: pushing active", vp);
  	/*
***************
*** 280,286 ****
  		ip->i_devvp = 0;
  	}
  	ip->i_flag = 0;
! 	return (0);
  }
  
  /*
--- 406,412 ----
  		ip->i_devvp = 0;
  	}
  	ip->i_flag = 0;
! 	return 0;
  }
  
  /*
***************
*** 290,302 ****
  iso_ilock(ip)
  	register struct iso_node *ip;
  {
! 
  	while (ip->i_flag & ILOCKED) {
  		ip->i_flag |= IWANT;
  		if (ip->i_spare0 == curproc->p_pid)
  			panic("locking against myself");
  		ip->i_spare1 = curproc->p_pid;
! 		(void) tsleep((caddr_t)ip, PINOD, "isoilck", 0);
  	}
  	ip->i_spare1 = 0;
  	ip->i_spare0 = curproc->p_pid;
--- 416,428 ----
  iso_ilock(ip)
  	register struct iso_node *ip;
  {
! 	
  	while (ip->i_flag & ILOCKED) {
  		ip->i_flag |= IWANT;
  		if (ip->i_spare0 == curproc->p_pid)
  			panic("locking against myself");
  		ip->i_spare1 = curproc->p_pid;
! 		(void) tsleep((caddr_t)ip, PINOD, "ilock", 0);
  	}
  	ip->i_spare1 = 0;
  	ip->i_spare0 = curproc->p_pid;
***************
*** 319,322 ****
--- 445,650 ----
  		ip->i_flag &= ~IWANT;
  		wakeup((caddr_t)ip);
  	}
+ }
+ 
+ /*
+  * File attributes
+  */
+ void
+ isofs_defattr(isodir,inop,bp)
+ 	struct iso_directory_record *isodir;
+ 	struct iso_node *inop;
+ 	struct buf *bp;
+ {
+ 	struct buf *bp2 = NULL;
+ 	struct iso_mnt *imp;
+ 	struct iso_extended_attributes *ap = NULL;
+ 	int off;
+ 	
+ 	if (isonum_711(isodir->flags)&2) {
+ 		inop->inode.iso_mode = S_IFDIR;
+ 		/*
+ 		 * If we return 2, fts() will assume there are no subdirectories
+ 		 * (just links for the path and .), so instead we return 1.
+ 		 */
+ 		inop->inode.iso_links = 1;
+ 	} else {
+ 		inop->inode.iso_mode = S_IFREG;
+ 		inop->inode.iso_links = 1;
+ 	}
+ 	if (!bp
+ 	    && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ 	    && (off = isonum_711(isodir->ext_attr_length))) {
+ 		iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ 		bp = bp2;
+ 	}
+ 	if (bp) {
+ 		ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
+ 		
+ 		if (isonum_711(ap->version) == 1) {
+ 			if (!(ap->perm[0]&0x40))
+ 				inop->inode.iso_mode |= VEXEC >> 6;
+ 			if (!(ap->perm[0]&0x10))
+ 				inop->inode.iso_mode |= VREAD >> 6;
+ 			if (!(ap->perm[0]&4))
+ 				inop->inode.iso_mode |= VEXEC >> 3;
+ 			if (!(ap->perm[0]&1))
+ 				inop->inode.iso_mode |= VREAD >> 3;
+ 			if (!(ap->perm[1]&0x40))
+ 				inop->inode.iso_mode |= VEXEC;
+ 			if (!(ap->perm[1]&0x10))
+ 				inop->inode.iso_mode |= VREAD;
+ 			inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */
+ 			inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */
+ 		} else
+ 			ap = NULL;
+ 	}
+ 	if (!ap) {
+ 		inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6;
+ 		inop->inode.iso_uid = (uid_t)0;
+ 		inop->inode.iso_gid = (gid_t)0;
+ 	}
+ 	if (bp2)
+ 		brelse(bp2);
+ }
+ 
+ /*
+  * Time stamps
+  */
+ void
+ isofs_deftstamp(isodir,inop,bp)
+ 	struct iso_directory_record *isodir;
+ 	struct iso_node *inop;
+ 	struct buf *bp;
+ {
+ 	struct buf *bp2 = NULL;
+ 	struct iso_mnt *imp;
+ 	struct iso_extended_attributes *ap = NULL;
+ 	int off;
+ 	
+ 	if (!bp
+ 	    && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ 	    && (off = isonum_711(isodir->ext_attr_length))) {
+ 		iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ 		bp = bp2;
+ 	}
+ 	if (bp) {
+ 		ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
+ 		
+ 		if (isonum_711(ap->version) == 1) {
+ 			if (!isofs_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
+ 				isofs_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
+ 			if (!isofs_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
+ 				inop->inode.iso_ctime = inop->inode.iso_atime;
+ 			if (!isofs_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime))
+ 				inop->inode.iso_mtime = inop->inode.iso_ctime;
+ 		} else
+ 			ap = NULL;
+ 	}
+ 	if (!ap) {
+ 		isofs_tstamp_conv7(isodir->date,&inop->inode.iso_ctime);
+ 		inop->inode.iso_atime = inop->inode.iso_ctime;
+ 		inop->inode.iso_mtime = inop->inode.iso_ctime;
+ 	}
+ 	if (bp2)
+ 		brelse(bp2);
+ }
+ 
+ int
+ isofs_tstamp_conv7(pi,pu)
+ char *pi;
+ struct timeval *pu;
+ {
+ 	int i;
+ 	int crtime, days;
+ 	int y, m, d, hour, minute, second, tz;
+ 	
+ 	y = pi[0] + 1900;
+ 	m = pi[1];
+ 	d = pi[2];
+ 	hour = pi[3];
+ 	minute = pi[4];
+ 	second = pi[5];
+ 	tz = pi[6];
+ 	
+ 	if (y < 1970) {
+ 		pu->tv_sec  = 0;
+ 		pu->tv_usec = 0;
+ 		return 0;
+ 	} else {
+ #ifdef	ORIGINAL
+ 		/* computes day number relative to Sept. 19th,1989 */
+ 		/* don't even *THINK* about changing formula. It works! */
+ 		days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100;
+ #else
+ 		/*
+ 		 * Changed :-) to make it relative to Jan. 1st, 1970
+ 		 * and to disambiguate negative division
+ 		 */
+ 		days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239;
+ #endif
+ 		crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second;
+ 		
+ 		/* timezone offset is unreliable on some disks */
+ 		if (-48 <= tz && tz <= 52)
+ 			crtime -= tz * 15 * 60;
+ 	}
+ 	pu->tv_sec  = crtime;
+ 	pu->tv_usec = 0;
+ 	return 1;
+ }
+ 
+ static unsigned
+ isofs_chars2ui(begin,len)
+ 	unsigned char *begin;
+ 	int len;
+ {
+ 	unsigned rc;
+ 	
+ 	for (rc = 0; --len >= 0;) {
+ 		rc *= 10;
+ 		rc += *begin++ - '0';
+ 	}
+ 	return rc;
+ }
+ 
+ int
+ isofs_tstamp_conv17(pi,pu)
+ 	unsigned char *pi;
+ 	struct timeval *pu;
+ {
+ 	unsigned char buf[7];
+ 	
+ 	/* year:"0001"-"9999" -> -1900  */
+ 	buf[0] = isofs_chars2ui(pi,4) - 1900;
+ 	
+ 	/* month: " 1"-"12"      -> 1 - 12 */
+ 	buf[1] = isofs_chars2ui(pi + 4,2);
+ 	
+ 	/* day:   " 1"-"31"      -> 1 - 31 */
+ 	buf[2] = isofs_chars2ui(pi + 6,2);
+ 	
+ 	/* hour:  " 0"-"23"      -> 0 - 23 */
+ 	buf[3] = isofs_chars2ui(pi + 8,2);
+ 	
+ 	/* minute:" 0"-"59"      -> 0 - 59 */
+ 	buf[4] = isofs_chars2ui(pi + 10,2);
+ 	
+ 	/* second:" 0"-"59"      -> 0 - 59 */
+ 	buf[5] = isofs_chars2ui(pi + 12,2);
+ 	
+ 	/* difference of GMT */
+ 	buf[6] = pi[16];
+ 	
+ 	return isofs_tstamp_conv7(buf,pu);
+ }
+ 
+ void
+ isodirino(inump,isodir,imp)
+ 	ino_t *inump;
+ 	struct iso_directory_record *isodir;
+ 	struct iso_mnt *imp;
+ {
+ 	*inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
+ 		 * imp->logical_block_size;
  }
diff -cr sys/isofs/isofs_node.h /usr/src/sys/isofs/isofs_node.h
*** sys/isofs/isofs_node.h	Sun Dec 19 00:51:04 1993
--- /usr/src/sys/isofs/isofs_node.h	Mon Aug 15 15:17:56 1994
***************
*** 1,22 ****
  /*
!  *	$Id: isofs_node.h,v 1.5 1993/12/19 00:51:04 wollman Exp $
   */
  
  #ifndef _ISOFS_ISOFS_NODE_H_
  #define _ISOFS_ISOFS_NODE_H_ 1
  
- 
  typedef	struct	{
- 	unsigned	iso_cln;	/* Child link */
- 	unsigned	iso_pln;	/* Parents link */
  	struct timeval	iso_atime;	/* time of last access */
  	struct timeval	iso_mtime;	/* time of last modification */
  	struct timeval	iso_ctime;	/* time file changed */
  	u_short		iso_mode;	/* files access mode and type */
  	uid_t		iso_uid;	/* owner user id */
  	gid_t		iso_gid;	/* owner group id */
  } ISO_RRIP_INODE;
  
  struct iso_node {
  	struct	iso_node *i_chain[2]; /* hash chain, MUST be first */
  	struct	vnode *i_vnode;	/* vnode associated with this inode */
--- 1,35 ----
  /*
!  *	$Id: isofs_node.h,v 1.9 1993/12/23 07:37:42 cgd Exp $
   */
  
  #ifndef _ISOFS_ISOFS_NODE_H_
  #define _ISOFS_ISOFS_NODE_H_ 1
  
  typedef	struct	{
  	struct timeval	iso_atime;	/* time of last access */
  	struct timeval	iso_mtime;	/* time of last modification */
  	struct timeval	iso_ctime;	/* time file changed */
  	u_short		iso_mode;	/* files access mode and type */
  	uid_t		iso_uid;	/* owner user id */
  	gid_t		iso_gid;	/* owner group id */
+ 	short		iso_links;	/* links of file */
+ 	dev_t		iso_rdev;	/* Major/Minor number for special */
  } ISO_RRIP_INODE;
  
+ #ifdef	ISODEVMAP
+ /*
+  * FOr device# (major,minor) translation table
+  */
+ struct iso_dnode {
+ 	struct iso_dnode *d_chain[2];	/* hash chain, MUST be first */
+ 	dev_t		i_dev;		/* device where dnode resides */
+ 	ino_t		i_number;	/* the identity of the inode */
+ 	dev_t		d_dev;		/* device # for translation */
+ };
+ #define	d_forw		d_chain[0]
+ #define	d_back		d_chain[1]
+ #endif
+ 
  struct iso_node {
  	struct	iso_node *i_chain[2]; /* hash chain, MUST be first */
  	struct	vnode *i_vnode;	/* vnode associated with this inode */
***************
*** 24,29 ****
--- 37,43 ----
  	u_long	i_flag;		/* see below */
  	dev_t	i_dev;		/* device where inode resides */
  	ino_t	i_number;	/* the identity of the inode */
+ 				/* we use the actual starting block of the file */
  	struct	iso_mnt *i_mnt;	/* filesystem associated with this inode */
  	struct	lockf *i_lockf;	/* head of byte-level lock list */
  	long	i_diroff;	/* offset in dir, where we found last entry */
***************
*** 31,48 ****
  	long	i_spare0;
  	long	i_spare1;
  
! 
! 	int iso_reclen;
! 	int iso_extlen;
! 	int iso_extent;
! 	int i_size;
! 	int iso_flags;
! 	int iso_unit_size;
! 	int iso_interleave_gap;
! 	int iso_volume_seq;
! 	int iso_namelen;	/* ISO9660/RRIP name len */
! 	int iso_parent;		/* byte offset in beginning of dir record */
! 	int iso_parent_ext;	/* block number of dir record */
  	ISO_RRIP_INODE  inode;
  };
  
--- 45,54 ----
  	long	i_spare0;
  	long	i_spare1;
  
! 	long iso_extent;	/* extent of file */
! 	long i_size;
! 	long iso_start;		/* actual start of data of file (may be different */
! 				/* from iso_extent, if file has extended attributes) */
  	ISO_RRIP_INODE  inode;
  };
  
***************
*** 92,108 ****
  int isofs_strategy __P((struct buf *bp));
  void isofs_print __P((struct vnode *vp));
  int isofs_islocked __P((struct vnode *vp));
! 
! /* From isofs_node.c: */
! struct iso_directory_record;
! extern void isofs_init(void);
! extern int iso_iget(struct iso_node *, ino_t, struct iso_node **, 
! 		    struct iso_directory_record *);
! extern void iso_iput(struct iso_node *);
! extern void iso_ilock(struct iso_node *);
! extern void iso_iunlock(struct iso_node *);
! 
! 
! extern int iso_blkatoff(struct iso_node *, off_t, char **, struct buf **);
  
  #endif /* _ISOFS_ISOFS_NODE_H_ */
--- 98,110 ----
  int isofs_strategy __P((struct buf *bp));
  void isofs_print __P((struct vnode *vp));
  int isofs_islocked __P((struct vnode *vp));
! void isofs_defattr __P((struct iso_directory_record *isodir,
! 			struct iso_node *inop, struct buf *bp));
! void isofs_deftstamp __P((struct iso_directory_record *isodir,
! 			struct iso_node *inop, struct buf *bp));
! #ifdef	ISODEVMAP
! struct iso_dnode *iso_dmap __P((dev_t dev, ino_t ino, int create));
! void iso_dunmap __P((dev_t dev));
! #endif
  
  #endif /* _ISOFS_ISOFS_NODE_H_ */
diff -cr sys/isofs/isofs_rrip.c /usr/src/sys/isofs/isofs_rrip.c
*** sys/isofs/isofs_rrip.c	Mon Jun 13 21:19:35 1994
--- /usr/src/sys/isofs/isofs_rrip.c	Mon Aug 15 15:38:56 1994
***************
*** 28,664 ****
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	$Id: isofs_rrip.c,v 1.6 1994/06/13 20:19:35 jkh Exp $
   */
  
! #include "param.h"
! #include "systm.h"
! #include "namei.h"
! #include "buf.h"
! #include "file.h"
! #include "vnode.h"
! #include "mount.h"
! #include "kernel.h"
! 
! #include "sys/time.h"
! 
! #include "iso.h"
! #include "isofs_node.h"
! #include "isofs_rrip.h"
! #include "iso_rrip.h"
  
  /*
   * POSIX file attribute
   */
! static int isofs_rrip_attr( p, ana )
! 	ISO_RRIP_ATTR	 *p;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	ana->inode.iso_mode  = isonum_731(p->mode_l);
! 	ana->inode.iso_uid   = (uid_t)isonum_731(p->uid_l);
! 	ana->inode.iso_gid   = (gid_t)isonum_731(p->gid_l);
! /*	ana->inode.iso_links = isonum_731(p->links_l); */
! 	return 0;
! }
! 
! int isofs_rrip_defattr(  isodir, ana )
! 	struct iso_directory_record 	*isodir;
! 	ISO_RRIP_ANALYZE 		*ana;
! {
! 	ana->inode.iso_mode  = (VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6);
! 	ana->inode.iso_uid   = (uid_t)0;
! 	ana->inode.iso_gid   = (gid_t)0;
! 	return 0;
  }
  
! /*
!  * POSIX device modes
!  */
! static int isofs_rrip_device( p, ana )
! 	ISO_RRIP_DEVICE  *p;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	char   buf[3];
! 
! 	buf[0] = p->h.type[0];
! 	buf[1] = p->h.type[1];
! 	buf[2]	= 0x00;
! 
! 	printf("isofs:%s[%d] high=0x%08x, low=0x%08x\n",
! 				buf,
! 				isonum_711(p->h.length),
! 				isonum_731(p->dev_t_high_l),
! 				isonum_731(p->dev_t_low_l)
! 					 );
! 	return 0;
  }
  
  /*
   * Symbolic Links
   */
! static int isofs_rrip_slink( p, ana )
  	ISO_RRIP_SLINK  *p;
  	ISO_RRIP_ANALYZE *ana;
  {
  	return 0;
  }
  
  /*
   * Alternate name
   */
! static int isofs_rrip_altname( p, ana )
  	ISO_RRIP_ALTNAME *p;
  	ISO_RRIP_ANALYZE *ana;
  {
  	return 0;
  }
  
! /*
!  * Child Link
!  */
! static int isofs_rrip_clink( p, ana )
! 	ISO_RRIP_CLINK  *p;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	char   buf[3];
! 	buf[0] = p->h.type[0];
! 	buf[1] = p->h.type[1];
! 	buf[2]	= 0x00;
! 	printf("isofs:%s[%d] loc=%d\n",
! 				buf,
! 				isonum_711(p->h.length),
! 				isonum_733(p->dir_loc)
! 							);
! 	ana->inode.iso_cln = isonum_733(p->dir_loc);
! 	return 0;
  }
  
  /*
!  * Parent Link
   */
! static int isofs_rrip_plink( p, ana )
! ISO_RRIP_PLINK  *p;
! ISO_RRIP_ANALYZE *ana;
! {
! 
! 	char   buf[3];
! 	buf[0] = p->h.type[0];
! 	buf[1] = p->h.type[1];
! 	buf[2]	= 0x00;
! 	printf("isofs:%s[%d] loc=%d\n",
! 				buf,
! 				isonum_711(p->h.length),
! 				isonum_733(p->dir_loc)
! 							);
! 	ana->inode.iso_pln = isonum_733(p->dir_loc);
! 	return 0;
  }
  
  /*
   * Relocated directory
   */
! static int isofs_rrip_reldir( p, ana )
! ISO_RRIP_RELDIR  *p;
! ISO_RRIP_ANALYZE *ana;
  {
! 	char   buf[3];
! 
! 	buf[0] = p->h.type[0];
! 	buf[1] = p->h.type[1];
! 	buf[2]	= 0x00;
! 
! 	printf("isofs:%s[%d]\n",buf, isonum_711(p->h.length) );
! 	return 0;
! }
! 
! /*
!  * Time stamp 
!  */
! static void isofs_rrip_tstamp_conv7(pi, pu)
! char	         *pi;
! struct timeval   *pu;
! {
! 	int	 i;
! 	int	 crtime,days;
! 	int	 year,month,day,hour,minute,second,tz;
! 
! 	year   = pi[0] - 70;
! 	month  = pi[1];
! 	day    = pi[2];
! 	hour   = pi[3];
! 	minute = pi[4];
! 	second = pi[5];
! 	tz     = pi[6];
! 
! 	if (year < 0) {
! 		crtime = 0;
! 	} else {
! 		static int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
! 
! 		days = year * 365;
! 		if (year > 2)
! 			days += (year+2) / 4;
! 		for (i = 1; i < month; i++)
! 			days += monlen[i-1];
! 		if (((year+2) % 4) == 0 && month > 2)
! 			days++;
! 		days += day - 1;
! 		crtime = ((((days * 24) + hour) * 60 + minute) * 60)
! 			+ second;
! 
! 		/* sign extend */
! 		if (tz & 0x80)
! 			tz |= (-1 << 8);
! 
! 		/* timezone offset is unreliable on some disks */
! 		if (-48 <= tz && tz <= 52)
! 			crtime -= tz * 15 * 60;
! 	}
! 	pu->tv_sec  = crtime;
! 	pu->tv_usec = 0;
  }
  
! 
! static unsigned isofs_chars2ui( begin, end )
! unsigned char *begin;
! unsigned char *end;
  {
! 	unsigned rc=0;
! 	int 	 len; 
! 	int 	 wlen;
! 	static   int pow[]={ 1, 10, 100, 1000 };
! 
! 	len = end - begin;
! 	wlen= len;
! 	for (; len >= 0; len -- ) {
! 		rc += ( *(begin+len) * pow[wlen - len] ); 
! 	}
! 	return( rc );
! }
  	
- static void isofs_rrip_tstamp_conv17(pi, pu)
- unsigned char *pi;
- struct timeval   *pu;
- {
- 	unsigned char	buf[7];
- 
-         /* year:"0001"-"9999" -> -1900  */
- 	buf[0]  =  (unsigned char)(isofs_chars2ui( &pi[0], &pi[3]) - 1900 );
- 
- 	/* month: " 1"-"12"      -> 1 - 12 */
- 	buf[1]  =  (unsigned char)isofs_chars2ui( &pi[4], &pi[5]);
- 
- 	/* day:   " 1"-"31"      -> 1 - 31 */
- 	buf[2]  =  isofs_chars2ui( &pi[6], &pi[7]);
- 
-   	/* hour:  " 0"-"23"      -> 0 - 23 */
- 	buf[3]  =  isofs_chars2ui( &pi[8], &pi[9]);
- 
- 	/* minute:" 0"-"59"      -> 0 - 59 */
- 	buf[4]  =  isofs_chars2ui( &pi[10], &pi[11] );
- 
- 	/* second:" 0"-"59"      -> 0 - 59 */
- 	buf[5]  =  isofs_chars2ui( &pi[12], &pi[13] );
- 
- 	/* difference of GMT */
- 	buf[6]  =  pi[16];
- 
- 	isofs_rrip_tstamp_conv7(buf, pu);
- }
- 
- static int isofs_rrip_tstamp( p, ana )
- ISO_RRIP_TSTAMP  *p;
- ISO_RRIP_ANALYZE *ana;
- {
- 	unsigned char *ptime;	
- 
  	ptime = p->time;
! 
  	/* Check a format of time stamp (7bytes/17bytes) */
! 	if ( !(*p->flags & ISO_SUSP_TSTAMP_FORM17 ) ) {
!         		isofs_rrip_tstamp_conv7(ptime,    &ana->inode.iso_ctime );
! 
! 			if ( *p->flags & ISO_SUSP_TSTAMP_MODIFY )
!         			isofs_rrip_tstamp_conv7(ptime+7,    &ana->inode.iso_mtime );
! 			else
!         			ana->inode.iso_mtime = ana->inode.iso_ctime;
! 
! 			if ( *p->flags & ISO_SUSP_TSTAMP_ACCESS )
!         			isofs_rrip_tstamp_conv7(ptime+14,   &ana->inode.iso_atime );
! 			else
!         			ana->inode.iso_atime = ana->inode.iso_ctime;
  	} else {
!         		isofs_rrip_tstamp_conv17(ptime,    &ana->inode.iso_ctime );
! 			
! 			if ( *p->flags & ISO_SUSP_TSTAMP_MODIFY )
!         			isofs_rrip_tstamp_conv17(ptime+17, &ana->inode.iso_mtime );
! 			else
!         			ana->inode.iso_mtime = ana->inode.iso_ctime;
! 
! 			if ( *p->flags & ISO_SUSP_TSTAMP_ACCESS )
!         			isofs_rrip_tstamp_conv17(ptime+34, &ana->inode.iso_atime );
! 			else
!         			ana->inode.iso_atime = ana->inode.iso_ctime;
  	}
! 	return 0;
  }
  
! int isofs_rrip_deftstamp( isodir, ana )
  	struct iso_directory_record  *isodir;
  	ISO_RRIP_ANALYZE *ana;
  {
!        	isofs_rrip_tstamp_conv7(isodir->date, &ana->inode.iso_ctime );
! 	ana->inode.iso_atime = ana->inode.iso_ctime;
! 	ana->inode.iso_mtime = ana->inode.iso_ctime;
! 	return 0;
  }
  
  
  /*
   * Flag indicating
-  *   Nothing to do....
   */
! static int isofs_rrip_idflag( p, ana )
! ISO_RRIP_IDFLAG  *p;
! ISO_RRIP_ANALYZE *ana;
! {
! 	char   buf[3];
! 
! 	buf[0] = p->h.type[0];
! 	buf[1] = p->h.type[1];
! 	buf[2]	= 0x00;
! 
! 	printf("isofs:%s[%d] idflag=0x%x\n",
! 				buf,
! 				isonum_711(p->h.length),
! 				p->flags );
! 	return 0;
  }
  
  /*
!  * Extension reference
!  *   Nothing to do....
   */
! static int isofs_rrip_exflag( p, ana )
! ISO_RRIP_EXFLAG  *p;
! ISO_RRIP_ANALYZE *ana;
! {
! 	char   buf[3];
! 
! 	buf[0] = p->h.type[0];
! 	buf[1] = p->h.type[1];
! 	buf[2]	= 0x00;
! 
! 	printf("isofs:%s[%d] exflag=0x%x",
! 				buf,
! 				isonum_711(p->h.length),
! 				p->flags );
! 	return 0;
  }
  
  /*
!  * Unknown ...
!  *   Nothing to do....
   */
! static int isofs_rrip_unknown( p, ana )
! 	ISO_RRIP_EXFLAG  *p;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	return 0;
  }
  
  typedef struct {
! 	char	 type[2];
! 	int	 (*func)();
! 	int	 (*func2)();
! 	int	 result;
  } RRIP_TABLE;
  
! static RRIP_TABLE rrip_table [] = {
!              { 'P', 'X', isofs_rrip_attr,   isofs_rrip_defattr,   ISO_SUSP_ATTR    },
! 	     { 'T', 'F', isofs_rrip_tstamp, isofs_rrip_deftstamp, ISO_SUSP_TSTAMP  },
! 	     { 'N', 'M', isofs_rrip_altname,0,                    ISO_SUSP_ALTNAME },
! 	     { 'C', 'L', isofs_rrip_clink,  0,                    ISO_SUSP_CLINK   },
! 	     { 'P', 'L', isofs_rrip_plink,  0,                    ISO_SUSP_PLINK   },
! 	     { 'S', 'L', isofs_rrip_slink,  0,                    ISO_SUSP_SLINK   },
! 	     { 'R', 'E', isofs_rrip_reldir, 0,                    ISO_SUSP_RELDIR  },
! 	     { 'P', 'N', isofs_rrip_device, 0,                    ISO_SUSP_DEVICE  },
! 	     { 'R', 'R', isofs_rrip_idflag, 0,                    ISO_SUSP_IDFLAG  },
! 	     { 'E', 'R', isofs_rrip_exflag, 0,                    ISO_SUSP_EXFLAG  },
! 	     { 'S', 'P', isofs_rrip_unknown,0,                    ISO_SUSP_UNKNOWN },
! 	     { 'C', 'E', isofs_rrip_unknown,0,                    ISO_SUSP_UNKNOWN }
! };
! 
! int isofs_rrip_analyze ( isodir, analyze )
! struct iso_directory_record 	*isodir;
! ISO_RRIP_ANALYZE		*analyze;
! {	
! 	register RRIP_TABLE	 *ptable;
  	register ISO_SUSP_HEADER *phead;
  	register ISO_SUSP_HEADER *pend;
! 	int	found;
! 	int	i;
! 	char	*pwhead;
! 	int	result;
! 
  	/*
!          * Note: If name length is odd,
  	 *       it will be padding 1 byte  after the name
  	 */
! 	pwhead 	=  isodir->name + isonum_711(isodir->name_len);
! 	if ( !(isonum_711(isodir->name_len) & 0x0001) )
! 		pwhead ++;
! 	phead 	= (ISO_SUSP_HEADER *)pwhead;
! 	pend 	= (ISO_SUSP_HEADER *)( (char *)isodir + isonum_711(isodir->length) );
! 
  	result = 0;
! 	if ( pend == phead ) {
! 		goto setdefault;
! 	}
! 	/*
! 	 * Note: "pend" should be more than one SUSP header
! 	 */ 
! 	while ( pend >= phead + 1) {
! 		found   = 0;
! 		for ( ptable=&rrip_table[0];ptable < &rrip_table[sizeof(rrip_table)/sizeof(RRIP_TABLE)]; ptable ++) {
! 			if ( bcmp( phead->type, ptable->type, 2 ) == 0 ) {
! 				found = 1;
! 				ptable->func( phead, analyze );
! 				result |= ptable->result;
! 				break;
  			}
! 		}
! 		if ( found == 0 ) {
! 			printf("isofs: name '");
! 			for ( i =0; i < isonum_711(isodir->name_len) ;i++) {
! 				printf("%c", *(isodir->name + i) );
  			}
! 			printf("'");
! 			printf(" - type %c%c [%08x/%08x]...not found\n",
! 				phead->type[0], phead->type[1], phead, pend );
! 			isofs_hexdump( phead, (int)( (char *)pend - (char *)phead ) );
! 		 	break;
! 		}
! 
! 		/*
! 		 * move to next SUSP
! 		 */
! 		phead  = (ISO_SUSP_HEADER *) ((unsigned)isonum_711(phead->length) + (char *)phead);
  	}
! 
! setdefault:
  	/*
  	 * If we don't find the Basic SUSP stuffs, just set default value
!          *   ( attribute/time stamp )
  	 */
! 	for ( ptable=&rrip_table[0];ptable < &rrip_table[2]; ptable ++) {
! 		if ( ptable->func2 != 0 && !(ptable->result & result) ) {
! 			ptable->func2( isodir, analyze );
! 		}
! 	}
! 	return ( result );
  }
  
! /* 
!  * Get Alternate Name from 'AL' record 
!  * If either no AL record nor 0 lenght, 
!  *    it will be return the translated ISO9660 name,
   */
! int	isofs_rrip_getname( isodir, outbuf, outlen )
  	struct iso_directory_record *isodir;
! 	char *outbuf;
! 	int *outlen;
  {
! 	ISO_SUSP_HEADER  *phead, *pend;
! 	ISO_RRIP_ALTNAME *p;
! 	char		 *pwhead;
! 	int		 found;
! 
! 	/*
!          * Note: If name length is odd,
! 	 *       it will be padding 1 byte  after the name
! 	 */
! 	pwhead 	=  isodir->name + isonum_711(isodir->name_len);
! 	if ( !(isonum_711(isodir->name_len) & 0x0001) )
! 		pwhead ++;
! 	phead 	= (ISO_SUSP_HEADER *)pwhead;
! 	pend 	= (ISO_SUSP_HEADER *)( (char *)isodir + isonum_711(isodir->length) );
! 
! 	found   = 0;
! 	if ( pend != phead ) {
! 		while ( pend >= phead + 1) {
! 			if ( bcmp( phead->type, "NM", 2 ) == 0 ) {
! 				found = 1;
! 				break;
! 			}
! 			phead  = (ISO_SUSP_HEADER *) ((unsigned)isonum_711(phead->length) + (char *)phead);
! 		}
! 	}
! 	if ( found == 1 ) {
! 		p = (ISO_RRIP_ALTNAME *)phead;
! 		*outlen = isonum_711( p->h.length ) - sizeof( ISO_RRIP_ALTNAME );
! 		bcopy( (char *)( &p->flags + 1 ), outbuf, *outlen );
! 	} else {
! 		isofntrans(isodir->name, isonum_711(isodir->name_len), outbuf, outlen );
! 		if ( *outlen == 1) {
! 			switch ( outbuf[0] ) {
! 			case 0:
! 				outbuf[0] = '.';
! 				break;
! 			case 1:
! 				outbuf[0] = '.';
! 				outbuf[1] = '.';
! 				*outlen = 2;
! 			}
! 		}
! 	}
! 	return( found );
  }
  
  /* 
!  * Get Symbolic Name from 'SL' record 
!  *
!  * Note: isodir should contains SL record!
!  */
! int	isofs_rrip_getsymname( vp, isodir, outbuf, outlen )
! struct vnode			*vp;
! struct iso_directory_record 	*isodir;
! char				*outbuf;
! int				*outlen;
! {
! 	register ISO_RRIP_SLINK_COMPONENT *pcomp;
! 	register ISO_SUSP_HEADER  *phead, *pend;
! 	register ISO_RRIP_SLINK_COMPONENT *pcompe;
! 	ISO_RRIP_SLINK   *p;
! 	char		 *pwhead;
! 	int		 found;
! 	int		 slash;
! 	int 	  	 wlen;
  
! 	/*
!          * Note: If name length is odd,
! 	 *       it will be padding 1 byte  after the name
! 	 */
! 	pwhead 	=  isodir->name + isonum_711(isodir->name_len);
! 	if ( !(isonum_711(isodir->name_len) & 0x0001) )
! 		pwhead ++;
! 	phead 	= (ISO_SUSP_HEADER *)pwhead;
! 	pend 	= (ISO_SUSP_HEADER *)( (char *)isodir + isonum_711(isodir->length) );
! 
! 	found   = 0;
! 	if ( pend != phead ) {
! 		while ( pend >= phead + 1) {
! 			if ( bcmp( phead->type, "SL", 2 ) == 0 ) {
! 				found = 1;
! 				break;
! 			}
! 			phead  = (ISO_SUSP_HEADER *) ((unsigned)isonum_711(phead->length) + (char *)phead);
! 		}
  	}
- 	if ( found == 0 ) {
- 		*outlen = 0;
- 		return( found );
- 	} 
- 
- 	p	= (ISO_RRIP_SLINK *)phead;
- 	pcomp	= (ISO_RRIP_SLINK_COMPONENT *)p->component;
- 	pcompe  = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
  	
! 	/*
!          * Gathering a Symbolic name from each component with path
!          */
! 	*outlen = 0; 
! 	slash   = 0;
! 	while ( pcomp < pcompe ) {
! 
! 		/* Inserting Current */
! 		if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_CURRENT ) {
! 			bcopy("./",	outbuf+*outlen, 2);
! 			*outlen += 2;
! 			slash   = 0;
! 		}
  
! 		/* Inserting Parent */
! 		if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_PARENT ) {
! 			bcopy("../",	outbuf+*outlen, 3);
! 			*outlen += 3;
! 			slash   = 0;
! 		}
  
! 		/* Inserting slash for ROOT */
! 		if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_ROOT ) {
! 			bcopy("/",	outbuf+*outlen, 1);
! 			*outlen += 1;
! 			slash   = 0;
! 		}
  
! 		/* Inserting a mount point i.e. "/cdrom" */
! 		if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_VOLROOT ) {
!                         wlen = strlen(vp->v_mount->mnt_stat.f_mntonname);
! 			bcopy(vp->v_mount->mnt_stat.f_mntonname,outbuf+*outlen, wlen);
! 			*outlen += wlen;
! 			slash   = 1;
! 		}
  
! 		/* Inserting hostname i.e. "tama:" */
! 		if ( pcomp->cflag[0] & ISO_SUSP_CFLAG_HOST ) {
! 			bcopy(hostname, outbuf+*outlen, hostnamelen);
! 			*(outbuf+hostnamelen) = ':';
! 			*outlen += (hostnamelen + 1);
! 			slash   = 0;	/* Uuum Should we insert a slash ? */
! 		}
  	
! 		/* Inserting slash for next component */
! 		if ( slash == 1 ) {
! 			outbuf[*outlen] = '/';
! 			*outlen  += 1;
! 			slash   =  0;
! 		}
! 
! 		/* Inserting component */
! 		wlen = isonum_711(pcomp->clen);
! 		if ( wlen != 0 ) {
! 			bcopy( pcomp->name, outbuf + *outlen, wlen );
! 			*outlen += wlen;
! 			slash   = 1;
! 		}
! 			
! 		/*
!                  * Move to next component...
! 		 */	
! 		pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp
! 			+ sizeof(ISO_RRIP_SLINK_COMPONENT) - 1 
! 			+ isonum_711(pcomp->clen));
! 	}
! 	return( found );
! }
! /* Hexdump routine for debug*/
! int isofs_hexdump( p, size )
! 	unsigned char *p;
! 	int  size;
! {	
! 	int i,j,k;
! 	unsigned char *wp;
! 
! 	for ( i = 0; i < size; i += 16 ) {
! 		printf("isofs: ");
! 		wp = p;
! 		k = ( (size - i) > 16 ? 16 : size - i );
! 		for ( j =0; j < k; j ++ ){
! 			printf("%02x ", *p );
! 			p++;
! 		}
! 		printf(" : ");
! 		p = wp;
! 		for ( j =0; j < k; j ++ ){
! 			if ( (*p > 0x20) && (*p < 0x7f) ) 
! 				printf("%c", *p );
! 			else
! 				printf(" ");
! 			p++;
! 		}
! 		printf("\n");
  	}
! 	printf("\n");
! 	return 0;
  }
--- 28,681 ----
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
!  *	$Id: isofs_rrip.c,v 1.8 1994/03/13 17:24:23 ws Exp $
   */
  
! #include <sys/param.h>
! #include <sys/systm.h>
! #include <sys/namei.h>
! #include <sys/buf.h>
! #include <sys/file.h>
! #include <sys/vnode.h>
! #include <sys/mount.h>
! #include <sys/kernel.h>
! #include <sys/stat.h>
! #include <sys/types.h>
! #include <sys/time.h>
! 
! #include <isofs/iso.h>
! #include <isofs/isofs_node.h>
! #include <isofs/isofs_rrip.h>
! #include <isofs/iso_rrip.h>
  
  /*
   * POSIX file attribute
   */
! static int
! isofs_rrip_attr(p,ana)
! 	ISO_RRIP_ATTR *p;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	ana->inop->inode.iso_mode = isonum_731(p->mode_l);
! 	ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
! 	ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
! 	ana->inop->inode.iso_links = isonum_731(p->links_l);
! 	ana->fields &= ~ISO_SUSP_ATTR;
! 	return ISO_SUSP_ATTR;
  }
  
! static void
! isofs_rrip_defattr(isodir,ana)
! 	struct iso_directory_record *isodir;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	/* But this is a required field! */
! 	printf("RRIP without PX field?\n");
! 	isofs_defattr(isodir,ana->inop,NULL);
  }
  
  /*
   * Symbolic Links
   */
! static int
! isofs_rrip_slink(p,ana)
  	ISO_RRIP_SLINK  *p;
  	ISO_RRIP_ANALYZE *ana;
  {
+ 	register ISO_RRIP_SLINK_COMPONENT *pcomp;
+ 	register ISO_RRIP_SLINK_COMPONENT *pcompe;
+ 	int len, wlen, cont;
+ 	char *outbuf, *inbuf;
+ 	
+ 	pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
+ 	pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
+ 	len = *ana->outlen;
+ 	outbuf = ana->outbuf;
+ 	cont = ana->cont;
+ 	
+ 	/*
+ 	 * Gathering a Symbolic name from each component with path
+ 	 */
+ 	for (;
+ 	     pcomp < pcompe;
+ 	     pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
+ 						  + isonum_711(pcomp->clen))) {
+ 		
+ 		if (!cont) {
+ 			if (len < ana->maxlen) {
+ 				len++;
+ 				*outbuf++ = '/';
+ 			}
+ 		}
+ 		cont = 0;
+ 		
+ 		inbuf = "..";
+ 		wlen = 0;
+ 		
+ 		switch (*pcomp->cflag) {
+ 			
+ 		case ISO_SUSP_CFLAG_CURRENT:
+ 			/* Inserting Current */
+ 			wlen = 1;
+ 			break;
+ 			
+ 		case ISO_SUSP_CFLAG_PARENT:
+ 			/* Inserting Parent */
+ 			wlen = 2;
+ 			break;
+ 			
+ 		case ISO_SUSP_CFLAG_ROOT:
+ 			/* Inserting slash for ROOT */
+ 			/* start over from beginning(?) */
+ 			outbuf -= len;
+ 			len = 0;
+ 			break;
+ 			
+ 		case ISO_SUSP_CFLAG_VOLROOT:
+ 			/* Inserting a mount point i.e. "/cdrom" */
+ 			/* same as above */
+ 			outbuf -= len;
+ 			len = 0;
+ 			inbuf = ana->imp->im_mountp->mnt_stat.f_mntonname;
+ 			wlen = strlen(inbuf);
+ 			break;
+ 			
+ 		case ISO_SUSP_CFLAG_HOST:
+ 			/* Inserting hostname i.e. "kurt.tools.de" */
+ 			inbuf = hostname;
+ 			wlen = hostnamelen;
+ 			break;
+ 			
+ 		case ISO_SUSP_CFLAG_CONTINUE:
+ 			cont = 1;
+ 			/* fall thru */
+ 		case 0:
+ 			/* Inserting component */
+ 			wlen = isonum_711(pcomp->clen);
+ 			inbuf = pcomp->name;
+ 			break;
+ 		default:
+ 			printf("RRIP with incorrect flags?");
+ 			wlen = ana->maxlen + 1;
+ 			break;
+ 		}
+ 		
+ 		if (len + wlen > ana->maxlen) {
+ 			/* indicate error to caller */
+ 			ana->cont = 1;
+ 			ana->fields = 0;
+ 			ana->outbuf -= *ana->outlen;
+ 			*ana->outlen = 0;
+ 			return 0;
+ 		}
+ 		
+ 		bcopy(inbuf,outbuf,wlen);
+ 		outbuf += wlen;
+ 		len += wlen;
+ 		
+ 	}
+ 	ana->outbuf = outbuf;
+ 	*ana->outlen = len;
+ 	ana->cont = cont;
+ 	
+ 	if (!isonum_711(p->flags)) {
+ 		ana->fields &= ~ISO_SUSP_SLINK;
+ 		return ISO_SUSP_SLINK;
+ 	}
  	return 0;
  }
  
  /*
   * Alternate name
   */
! static int
! isofs_rrip_altname(p,ana)
  	ISO_RRIP_ALTNAME *p;
  	ISO_RRIP_ANALYZE *ana;
  {
+ 	char *inbuf;
+ 	int wlen;
+ 	int cont;
+ 	
+ 	inbuf = "..";
+ 	wlen = 0;
+ 	cont = 0;
+ 	
+ 	switch (*p->flags) {
+ 	case ISO_SUSP_CFLAG_CURRENT:
+ 		/* Inserting Current */
+ 		wlen = 1;
+ 		break;
+ 		
+ 	case ISO_SUSP_CFLAG_PARENT:
+ 		/* Inserting Parent */
+ 		wlen = 2;
+ 		break;
+ 		
+ 	case ISO_SUSP_CFLAG_HOST:
+ 		/* Inserting hostname i.e. "kurt.tools.de" */
+ 		inbuf = hostname;
+ 		wlen = hostnamelen;
+ 		break;
+ 		
+ 	case ISO_SUSP_CFLAG_CONTINUE:
+ 		cont = 1;
+ 		/* fall thru */
+ 	case 0:
+ 		/* Inserting component */
+ 		wlen = isonum_711(p->h.length) - 5;
+ 		inbuf = (char *)p + 5;
+ 		break;
+ 		
+ 	default:
+ 		printf("RRIP with incorrect NM flags?\n");
+ 		wlen = ana->maxlen + 1;
+ 		break;
+ 	}
+ 	
+ 	if ((*ana->outlen += wlen) > ana->maxlen) {
+ 		/* treat as no name field */
+ 		ana->fields &= ~ISO_SUSP_ALTNAME;
+ 		ana->outbuf -= *ana->outlen - wlen;
+ 		*ana->outlen = 0;
+ 		return 0;
+ 	}
+ 	
+ 	bcopy(inbuf,ana->outbuf,wlen);
+ 	ana->outbuf += wlen;
+ 	
+ 	if (!cont) {
+ 		ana->fields &= ~ISO_SUSP_ALTNAME;
+ 		return ISO_SUSP_ALTNAME;
+ 	}
  	return 0;
  }
  
! static void
! isofs_rrip_defname(isodir,ana)
! 	struct iso_directory_record *isodir;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	strcpy(ana->outbuf,"..");
! 	switch (*isodir->name) {
! 	default:
! 		isofntrans(isodir->name,isonum_711(isodir->name_len),
! 			   ana->outbuf,ana->outlen,
! 			   1,isonum_711(isodir->flags)&4);
! 		break;
! 	case 0:
! 		*ana->outlen = 1;
! 		break;
! 	case 1:
! 		*ana->outlen = 2;
! 		break;
! 	}
  }
  
  /*
!  * Parent or Child Link
   */
! static int
! isofs_rrip_pclink(p,ana)
! 	ISO_RRIP_CLINK  *p;
! 	ISO_RRIP_ANALYZE *ana;
! {
! 	*ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift;
! 	ana->fields &= ~(ISO_SUSP_CLINK|ISO_SUSP_PLINK);
! 	return *p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK;
  }
  
  /*
   * Relocated directory
   */
! static int
! isofs_rrip_reldir(p,ana)
! 	ISO_RRIP_RELDIR  *p;
! 	ISO_RRIP_ANALYZE *ana;
  {
! 	/* special hack to make caller aware of RE field */
! 	*ana->outlen = 0;
! 	ana->fields = 0;
! 	return ISO_SUSP_RELDIR|ISO_SUSP_ALTNAME|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
  }
  
! static int
! isofs_rrip_tstamp(p,ana)
! 	ISO_RRIP_TSTAMP *p;
! 	ISO_RRIP_ANALYZE *ana;
  {
! 	unsigned char *ptime;
  	
  	ptime = p->time;
! 	
  	/* Check a format of time stamp (7bytes/17bytes) */
! 	if (!(*p->flags&ISO_SUSP_TSTAMP_FORM17)) {
! 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
! 			ptime += 7;
! 		
! 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
! 			isofs_tstamp_conv7(ptime,&ana->inop->inode.iso_mtime);
! 			ptime += 7;
! 		} else
! 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval));
! 		
! 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
! 			isofs_tstamp_conv7(ptime,&ana->inop->inode.iso_atime);
! 			ptime += 7;
! 		} else
! 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
! 		
! 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
! 			isofs_tstamp_conv7(ptime,&ana->inop->inode.iso_ctime);
! 		else
! 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
! 		
  	} else {
! 		if (*p->flags&ISO_SUSP_TSTAMP_CREAT)
! 			ptime += 17;
! 		
! 		if (*p->flags&ISO_SUSP_TSTAMP_MODIFY) {
! 			isofs_tstamp_conv17(ptime,&ana->inop->inode.iso_mtime);
! 			ptime += 17;
! 		} else
! 			bzero(&ana->inop->inode.iso_mtime,sizeof(struct timeval));
! 		
! 		if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
! 			isofs_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
! 			ptime += 17;
! 		} else
! 			ana->inop->inode.iso_atime = ana->inop->inode.iso_mtime;
! 		
! 		if (*p->flags&ISO_SUSP_TSTAMP_ATTR)
! 			isofs_tstamp_conv17(ptime,&ana->inop->inode.iso_ctime);
! 		else
! 			ana->inop->inode.iso_ctime = ana->inop->inode.iso_mtime;
! 		
  	}
! 	ana->fields &= ~ISO_SUSP_TSTAMP;
! 	return ISO_SUSP_TSTAMP;
  }
  
! static void
! isofs_rrip_deftstamp(isodir,ana)
  	struct iso_directory_record  *isodir;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	isofs_deftstamp(isodir,ana->inop,NULL);
  }
  
+ /*
+  * POSIX device modes
+  */
+ static int
+ isofs_rrip_device(p,ana)
+ 	ISO_RRIP_DEVICE *p;
+ 	ISO_RRIP_ANALYZE *ana;
+ {
+ 	unsigned high, low;
+ 	
+ 	high = isonum_733(p->dev_t_high_l);
+ 	low  = isonum_733(p->dev_t_low_l);
+ 	
+ 	if (high == 0)
+ 		ana->inop->inode.iso_rdev = makedev(major(low),minor(low));
+ 	else
+ 		ana->inop->inode.iso_rdev = makedev(high,minor(low));
+ 	ana->fields &= ~ISO_SUSP_DEVICE;
+ 	return ISO_SUSP_DEVICE;
+ }
  
  /*
   * Flag indicating
   */
! static int
! isofs_rrip_idflag(p,ana)
! 	ISO_RRIP_IDFLAG *p;
! 	ISO_RRIP_ANALYZE *ana;
! {
! 	ana->fields &= isonum_711(p->flags)|~0xff; /* don't touch high bits */
! 	/* special handling of RE field */
! 	if (ana->fields&ISO_SUSP_RELDIR)
! 		return isofs_rrip_reldir(p,ana);
! 	
! 	return ISO_SUSP_IDFLAG;
  }
  
  /*
!  * Continuation pointer
   */
! static int
! isofs_rrip_cont(p,ana)
! 	ISO_RRIP_CONT *p;
! 	ISO_RRIP_ANALYZE *ana;
! {
! 	ana->iso_ce_blk = isonum_733(p->location);
! 	ana->iso_ce_off = isonum_733(p->offset);
! 	ana->iso_ce_len = isonum_733(p->length);
! 	return ISO_SUSP_CONT;
  }
  
  /*
!  * System Use end
   */
! static int
! isofs_rrip_stop(p,ana)
! 	ISO_SUSP_HEADER *p;
  	ISO_RRIP_ANALYZE *ana;
  {
! 	return ISO_SUSP_STOP;
! }
! 
! /*
!  * Extension reference
!  */
! static int
! isofs_rrip_extref(p,ana)
! 	ISO_RRIP_EXTREF *p;
! 	ISO_RRIP_ANALYZE *ana;
! {
! 	if (isonum_711(p->len_id) != 10
! 	    || bcmp((char *)p + 8,"RRIP_1991A",10)
! 	    || isonum_711(p->version) != 1)
! 		return 0;
! 	ana->fields &= ~ISO_SUSP_EXTREF;
! 	return ISO_SUSP_EXTREF;
  }
  
  typedef struct {
! 	char type[2];
! 	int (*func)();
! 	void (*func2)();
! 	int result;
  } RRIP_TABLE;
  
! static int
! isofs_rrip_loop(isodir,ana,table)
! 	struct iso_directory_record *isodir;
! 	ISO_RRIP_ANALYZE *ana;
! 	RRIP_TABLE *table;
! {
! 	register RRIP_TABLE *ptable;
  	register ISO_SUSP_HEADER *phead;
  	register ISO_SUSP_HEADER *pend;
! 	struct buf *bp = NULL;
! 	int i;
! 	char *pwhead;
! 	int result;
! 	
  	/*
! 	 * Note: If name length is odd,
  	 *       it will be padding 1 byte  after the name
  	 */
! 	pwhead = isodir->name + isonum_711(isodir->name_len);
! 	if (!(isonum_711(isodir->name_len)&1))
! 		pwhead++;
! 	
! 	/* If it's not the '.' entry of the root dir obey SP field */
! 	if (*isodir->name != 0
! 	    || isonum_733(isodir->extent) != ana->imp->root_extent)
! 		pwhead += ana->imp->rr_skip;
! 	else
! 		pwhead += ana->imp->rr_skip0;
! 	
! 	phead = (ISO_SUSP_HEADER *)pwhead;
! 	pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length));
! 	
  	result = 0;
! 	while (1) {
! 		ana->iso_ce_len = 0;
! 		/*
! 		 * Note: "pend" should be more than one SUSP header
! 		 */ 
! 		while (pend >= phead + 1) {
! 			if (isonum_711(phead->version) == 1) {
! 				for (ptable = table; ptable->func; ptable++) {
! 					if (*phead->type == *ptable->type
! 					    && phead->type[1] == ptable->type[1]) {
! 						result |= ptable->func(phead,ana);
! 						break;
! 					}
! 				}
! 				if (!ana->fields)
! 					break;
  			}
! 			if (result&ISO_SUSP_STOP) {
! 				result &= ~ISO_SUSP_STOP;
! 				break;
  			}
! 			/* plausibility check */
! 			if (isonum_711(phead->length) < sizeof(*phead))
! 				break;
! 			/*
! 			 * move to next SUSP
! 			 * Hopefully this works with newer versions, too
! 			 */
! 			phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
! 		}
! 		
! 		if (ana->fields && ana->iso_ce_len) {
! 			if (ana->iso_ce_blk >= ana->imp->volume_space_size
! 			    || ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
! 			    || bread(ana->imp->im_devvp,
! 				     ana->iso_ce_blk * ana->imp->logical_block_size / DEV_BSIZE,
! 				     ana->imp->logical_block_size,NOCRED,&bp))
! 				/* what to do now? */
! 				break;
! 			phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off);
! 			pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
! 		} else
! 			break;
  	}
! 	if (bp)
! 		brelse(bp);
  	/*
  	 * If we don't find the Basic SUSP stuffs, just set default value
! 	 *   (attribute/time stamp)
  	 */
! 	for (ptable = table; ptable->func2; ptable++)
! 		if (!(ptable->result&result))
! 			ptable->func2(isodir,ana);
! 	
! 	return result;
  }
  
! /*
!  * Get Attributes.
   */
! static RRIP_TABLE rrip_table_analyze[] = {
! 	{ "PX", isofs_rrip_attr,	isofs_rrip_defattr,	ISO_SUSP_ATTR },
! 	{ "TF", isofs_rrip_tstamp,	isofs_rrip_deftstamp,	ISO_SUSP_TSTAMP },
! 	{ "PN", isofs_rrip_device,	0,			ISO_SUSP_DEVICE },
! 	{ "RR", isofs_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
! 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
! 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
! 	{ "",	0,			0,			0 }
! };
! 
! int
! isofs_rrip_analyze(isodir,inop,imp)
  	struct iso_directory_record *isodir;
! 	struct iso_node *inop;
! 	struct iso_mnt *imp;
  {
! 	ISO_RRIP_ANALYZE analyze;
! 	
! 	analyze.inop = inop;
! 	analyze.imp = imp;
! 	analyze.fields = ISO_SUSP_ATTR|ISO_SUSP_TSTAMP|ISO_SUSP_DEVICE;
! 	
! 	return isofs_rrip_loop(isodir,&analyze,rrip_table_analyze);
  }
  
  /* 
!  * Get Alternate Name.
!  */
! static RRIP_TABLE rrip_table_getname[] = {
! 	{ "NM", isofs_rrip_altname,	isofs_rrip_defname,	ISO_SUSP_ALTNAME },
! 	{ "CL", isofs_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
! 	{ "PL", isofs_rrip_pclink,	0,			ISO_SUSP_CLINK|ISO_SUSP_PLINK },
! 	{ "RE", isofs_rrip_reldir,	0,			ISO_SUSP_RELDIR },
! 	{ "RR", isofs_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
! 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
! 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
! 	{ "",	0,			0,			0 }
! };
  
! int
! isofs_rrip_getname(isodir,outbuf,outlen,inump,imp)
! 	struct iso_directory_record *isodir;
! 	char *outbuf;
! 	u_short *outlen;
! 	ino_t *inump;
! 	struct iso_mnt *imp;
! {
! 	ISO_RRIP_ANALYZE analyze;
! 	RRIP_TABLE *tab;
! 	
! 	analyze.outbuf = outbuf;
! 	analyze.outlen = outlen;
! 	analyze.maxlen = NAME_MAX;
! 	analyze.inump = inump;
! 	analyze.imp = imp;
! 	analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
! 	*outlen = 0;
! 	
! 	tab = rrip_table_getname;
! 	if (*isodir->name == 0
! 	    || *isodir->name == 1) {
! 		isofs_rrip_defname(isodir,&analyze);
! 		
! 		analyze.fields &= ~ISO_SUSP_ALTNAME;
! 		tab++;
  	}
  	
! 	return isofs_rrip_loop(isodir,&analyze,tab);
! }
  
! /* 
!  * Get Symbolic Link.
!  */
! static RRIP_TABLE rrip_table_getsymname[] = {
! 	{ "SL", isofs_rrip_slink,	0,			ISO_SUSP_SLINK },
! 	{ "RR", isofs_rrip_idflag,	0,			ISO_SUSP_IDFLAG },
! 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
! 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
! 	{ "",	0,			0,			0 }
! };
  
! int
! isofs_rrip_getsymname(isodir,outbuf,outlen,imp)
! 	struct iso_directory_record *isodir;
! 	char *outbuf;
! 	u_short *outlen;
! 	struct iso_mnt *imp;
! {
! 	ISO_RRIP_ANALYZE analyze;
! 	
! 	analyze.outbuf = outbuf;
! 	analyze.outlen = outlen;
! 	*outlen = 0;
! 	analyze.maxlen = MAXPATHLEN;
! 	analyze.cont = 1;		/* don't start with a slash */
! 	analyze.imp = imp;
! 	analyze.fields = ISO_SUSP_SLINK;
! 	
! 	return (isofs_rrip_loop(isodir,&analyze,rrip_table_getsymname)&ISO_SUSP_SLINK);
! }
  
! static RRIP_TABLE rrip_table_extref[] = {
! 	{ "ER", isofs_rrip_extref,	0,			ISO_SUSP_EXTREF },
! 	{ "CE", isofs_rrip_cont,	0,			ISO_SUSP_CONT },
! 	{ "ST", isofs_rrip_stop,	0,			ISO_SUSP_STOP },
! 	{ "",	0,			0,			0 }
! };
  
! /*
!  * Check for Rock Ridge Extension and Return Offset of its Fields.
!  * Note: We insist on the ER field.
!  */
! int
! isofs_rrip_offset(isodir,imp)
! 	struct iso_directory_record *isodir;
! 	struct iso_mnt *imp;
! {
! 	ISO_RRIP_OFFSET *p;
! 	ISO_RRIP_ANALYZE analyze;
  	
! 	imp->rr_skip0 = 0;
! 	p = (ISO_RRIP_OFFSET *)(isodir->name + 1);
! 	if (bcmp(p,"SP\7\1\276\357",6)) {
! 		/* Maybe, it's a CDROM XA disc? */
! 		imp->rr_skip0 = 15;
! 		p = (ISO_RRIP_OFFSET *)((char *)p + 15);
! 		if (bcmp(p,"SP\7\1\276\357",6))
! 			return -1;
  	}
! 	
! 	analyze.imp = imp;
! 	analyze.fields = ISO_SUSP_EXTREF;
! 	if (!(isofs_rrip_loop(isodir,&analyze,rrip_table_extref)&ISO_SUSP_EXTREF))
! 		return -1;
! 	
! 	return isonum_711(p->skip);
  }
diff -cr sys/isofs/isofs_rrip.h /usr/src/sys/isofs/isofs_rrip.h
*** sys/isofs/isofs_rrip.h	Sun Nov  7 17:46:05 1993
--- /usr/src/sys/isofs/isofs_rrip.h	Mon Aug 15 15:17:57 1994
***************
*** 29,35 ****
   * SUCH DAMAGE.
   *
   *	from: @(#)isofs_rrip.h
!  *	$Id: isofs_rrip.h,v 1.3 1993/11/07 17:46:05 wollman Exp $
   */
  
  #ifndef _ISOFS_ISOFS_RRIP_H_
--- 29,35 ----
   * SUCH DAMAGE.
   *
   *	from: @(#)isofs_rrip.h
!  *	$Id: isofs_rrip.h,v 1.3 1993/09/07 15:40:58 ws Exp $
   */
  
  #ifndef _ISOFS_ISOFS_RRIP_H_
***************
*** 71,78 ****
  typedef struct {
  	u_char cflag			[ISODCL (  1,    1)];
  	u_char clen			[ISODCL (  2,    2)];
! 	u_char name			[ISODCL (  3,    3)];
  } ISO_RRIP_SLINK_COMPONENT;
  
  typedef struct {
  	ISO_SUSP_HEADER			h;
--- 71,79 ----
  typedef struct {
  	u_char cflag			[ISODCL (  1,    1)];
  	u_char clen			[ISODCL (  2,    2)];
! 	u_char name			[0];
  } ISO_RRIP_SLINK_COMPONENT;
+ #define	ISO_RRIP_SLSIZ	2
  
  typedef struct {
  	ISO_SUSP_HEADER			h;
***************
*** 122,128 ****
  
  typedef struct {
  	ISO_SUSP_HEADER			h;
! 	unsigned char flags		[ISODCL (  4,    4)];
! } ISO_RRIP_EXFLAG;
  
  #endif /* _ISOFS_ISOFS_RRIP_H_ */
--- 123,145 ----
  
  typedef struct {
  	ISO_SUSP_HEADER			h;
! 	char len_id			[ISODCL (  4,    4)];
! 	char len_des			[ISODCL (  5,	 5)];
! 	char len_src			[ISODCL (  6,	 6)];
! 	char version			[ISODCL (  7,	 7)];
! } ISO_RRIP_EXTREF;
! 
! typedef struct {
! 	ISO_SUSP_HEADER			h;
! 	char check			[ISODCL (  4,	 5)];
! 	char skip			[ISODCL (  6,	 6)];
! } ISO_RRIP_OFFSET;
! 
! typedef struct {
! 	ISO_SUSP_HEADER			h;
! 	char location			[ISODCL (  4,	11)];
! 	char offset			[ISODCL ( 12,	19)];
! 	char length			[ISODCL ( 20,	27)];
! } ISO_RRIP_CONT;
  
  #endif /* _ISOFS_ISOFS_RRIP_H_ */
diff -cr sys/isofs/isofs_util.c /usr/src/sys/isofs/isofs_util.c
*** sys/isofs/isofs_util.c	Sun Dec 19 00:51:06 1993
--- /usr/src/sys/isofs/isofs_util.c	Mon Aug 15 15:17:57 1994
***************
*** 1,139 ****
  /*
!  *	$Id: isofs_util.c,v 1.4 1993/12/19 00:51:06 wollman Exp $
   */
  
! #include "param.h"
! #include "systm.h"
  
  int
  isonum_711 (p)
! char *p;
  {
! 	return (*p & 0xff);
  }
  
  int
  isonum_712 (p)
! 	char *p;
  {
! 	int val;
! 
! 	val = *p;
! 	if (val & 0x80)
! 		val |= ~0xff;
! 	return (val);
  }
  
  int
  isonum_721 (p)
! 	char *p;
  {
! 	return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
  }
  
  int
  isonum_722 (p)
! char *p;
  {
! 	return (((p[0] & 0xff) << 8) | (p[1] & 0xff));
  }
  
  int
  isonum_723 (p)
! char *p;
  {
! #if 0
! 	if (p[0] != p[3] || p[1] != p[2]) {
! 		fprintf (stderr, "invalid format 7.2.3 number\n");
! 		exit (1);
! 	}
  #endif
- 	return (isonum_721 (p));
  }
  
  int
  isonum_731 (p)
  unsigned char *p;
  {
! 	return ((p[0] & 0xff)
! 		| ((p[1] & 0xff) << 8)
! 		| ((p[2] & 0xff) << 16)
! 		| ((p[3] & 0xff) << 24));
  }
  
  int
  isonum_732 (p)
  unsigned char *p;
  {
! 	return (((p[0] & 0xff) << 24)
! 		| ((p[1] & 0xff) << 16)
! 		| ((p[2] & 0xff) << 8)
! 		| (p[3] & 0xff));
  }
  
  int
  isonum_733 (p)
  unsigned char *p;
  {
! 	int i;
! 
! #if 0
! 	for (i = 0; i < 4; i++) {
! 		if (p[i] != p[7-i]) {
! 			fprintf (stderr, "bad format 7.3.3 number\n");
! 			exit (1);
! 		}
! 	}
  #endif
- 	return (isonum_731 (p));
  }
  
  /*
   * translate and compare a filename
   */
  int
! isofncmp(char *fn, int fnlen, char *isofn, int isolen) {
! 	int fnidx;
! 
! 	fnidx = 0;
! 	for (fnidx = 0; fnidx < isolen; fnidx++, fn++) {
! 		char c = *isofn++;
! 
! 		if (fnidx > fnlen)
! 			return (0);
! 
! 		if (c >= 'A' && c <= 'Z') {
! 			if (c + ('a' - 'A') !=  *fn)
! 				return(0);
! 			else
! 				continue;
  		}
- 		if (c == ';')
- 			return ((fnidx == fnlen));
- 		if (c != *fn)
- 			return (0);
  	}
! 	return (1);
  }
  
  /*
   * translate a filename
   */
  void
! isofntrans(char *infn, int infnlen, char *outfn, short *outfnlen) {
! 	int fnidx;
! 
! 	fnidx = 0;
! 	for (fnidx = 0; fnidx < infnlen; fnidx++) {
  		char c = *infn++;
! 
! 		if (c >= 'A' && c <= 'Z')
  			*outfn++ = c + ('a' - 'A');
! 		else if (c == ';') {
! 			*outfnlen = fnidx;
! 			return;
! 		} else
  			*outfn++ = c;
  	}
! 	*outfnlen = infnlen;
  }
--- 1,203 ----
  /*
!  *	$Id: isofs_util.c,v 1.10 1994/05/07 01:22:26 cgd Exp $
   */
  
! #include <sys/param.h>
! #include <sys/systm.h>
! #include <sys/namei.h>
! #include <sys/resourcevar.h>
! #include <sys/kernel.h>
! #include <sys/file.h>
! #include <sys/stat.h>
! #include <sys/buf.h>
! #include <sys/proc.h>
! #include <sys/conf.h>
! #include <sys/mount.h>
! #include <sys/vnode.h>
! #include <sys/malloc.h>
! #include <sys/dir.h>
  
+ #include <sys/specdev.h> /* XXX */
+ #include <sys/fifo.h> /* XXX */
+ 
+ #include <isofs/iso.h>
+ 
+ #include <machine/endian.h>
+ 
+ #ifdef	__notanymore__
  int
  isonum_711 (p)
! unsigned char *p;
  {
! 	return (*p);
  }
  
  int
  isonum_712 (p)
! signed char *p;
  {
! 	return (*p);
  }
  
  int
  isonum_721 (p)
! unsigned char *p;
  {
! 	/* little endian short */
! #if BYTE_ORDER != LITTLE_ENDIAN
! 	printf ("isonum_721 called on non little-endian machine!\n");
! #endif
! 
! 	return *(short *)p;
  }
  
  int
  isonum_722 (p)
! unsigned char *p;
  {
!         /* big endian short */
! #if BYTE_ORDER != BIG_ENDIAN
!         printf ("isonum_722 called on non big-endian machine!\n");
! #endif
! 
! 	return *(short *)p;
  }
  
  int
  isonum_723 (p)
! unsigned char *p;
  {
! #if BYTE_ORDER == BIG_ENDIAN
!         return isonum_722 (p + 2);
! #elif BYTE_ORDER == LITTLE_ENDIAN
! 	return isonum_721 (p);
! #else
! 	printf ("isonum_723 unsupported byte order!\n");
! 	return 0;
  #endif
  }
  
  int
  isonum_731 (p)
  unsigned char *p;
  {
!         /* little endian long */
! #if BYTE_ORDER != LITTLE_ENDIAN
!         printf ("isonum_731 called on non little-endian machine!\n");
! #endif
! 
! 	return *(long *)p;
  }
  
  int
  isonum_732 (p)
  unsigned char *p;
  {
!         /* big endian long */
! #if BYTE_ORDER != BIG_ENDIAN
!         printf ("isonum_732 called on non big-endian machine!\n");
! #endif
! 
! 	return *(long *)p;
  }
  
  int
  isonum_733 (p)
  unsigned char *p;
  {
! #if BYTE_ORDER == BIG_ENDIAN
!         return isonum_732 (p + 4);
! #elif BYTE_ORDER == LITTLE_ENDIAN
! 	return isonum_731 (p);
! #else
! 	printf ("isonum_733 unsupported byte order!\n");
! 	return 0;
  #endif
  }
+ #endif	/* __notanymore__ */
  
  /*
   * translate and compare a filename
+  * Note: Version number plus ';' may be omitted.
   */
  int
! isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
! {
! 	int i, j;
! 	unsigned char c;
! 	
! 	while (--fnlen >= 0) {
! 		if (--isolen < 0)
! 			return *fn;
! 		if ((c = *isofn++) == ';') {
! 			switch (*fn++) {
! 			default:
! 				return *--fn;
! 			case 0:
! 				return 0;
! 			case ';':
! 				break;
! 			}
! 			for (i = 0; --fnlen >= 0; i = i * 10 + *fn++ - '0') {
! 				if (*fn < '0' || *fn > '9') {
! 					return -1;
! 				}
! 			}
! 			for (j = 0; --isolen >= 0; j = j * 10 + *isofn++ - '0');
! 			return i - j;
! 		}
! 		if (c != *fn) {
! 			if (c >= 'A' && c <= 'Z') {
! 				if (c + ('a' - 'A') != *fn) {
! 					if (*fn >= 'a' && *fn <= 'z')
! 						return *fn - ('a' - 'A') - c;
! 					else
! 						return *fn - c;
! 				}
! 			} else
! 				return *fn - c;
! 		}
! 		fn++;
! 	}
! 	if (isolen > 0) {
! 		switch (*isofn) {
! 		default:
! 			return -1;
! 		case '.':
! 			if (isofn[1] != ';')
! 				return -1;
! 		case ';':
! 			return 0;
  		}
  	}
! 	return 0;
  }
  
  /*
   * translate a filename
   */
  void
! isofntrans(unsigned char *infn,int infnlen,
! 	   unsigned char *outfn,unsigned short *outfnlen,
! 	   int original,int assoc)
! {
! 	int fnidx = 0;
! 	
! 	if (assoc) {
! 		*outfn++ = ASSOCCHAR;
! 		fnidx++;
! 	}
! 	for (; fnidx < infnlen; fnidx++) {
  		char c = *infn++;
! 		
! 		if (!original && c >= 'A' && c <= 'Z')
  			*outfn++ = c + ('a' - 'A');
! 		else if (!original && c == '.' && *infn == ';')
! 			break;
! 		else if (!original && c == ';')
! 			break;
! 		else
  			*outfn++ = c;
  	}
! 	*outfnlen = fnidx;
  }
diff -cr sys/isofs/isofs_vfsops.c /usr/src/sys/isofs/isofs_vfsops.c
*** sys/isofs/isofs_vfsops.c	Thu Jun  2 07:48:34 1994
--- /usr/src/sys/isofs/isofs_vfsops.c	Tue Aug 16 16:26:34 1994
***************
*** 1,25 ****
  /*
   *	$Id: isofs_vfsops.c,v 1.6 1994/06/02 06:48:34 swallace Exp $
   */
  
! #include "param.h"
! #include "systm.h"
! #include "namei.h"
! #include "proc.h"
! #include "kernel.h"
! #include "vnode.h"
! #include "specdev.h"
! #include "mount.h"
! #include "buf.h"
! #include "file.h"
! #include "dkbad.h"
! #include "disklabel.h"
! #include "ioctl.h"
! #include "errno.h"
! #include "malloc.h"
! 
! #include "iso.h"
! #include "isofs_node.h"
  
  extern int enodev ();
  
--- 1,25 ----
  /*
   *	$Id: isofs_vfsops.c,v 1.6 1994/06/02 06:48:34 swallace Exp $
   */
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/namei.h>
+ #include <sys/proc.h>
+ #include <sys/kernel.h>
+ #include <sys/vnode.h>
+ #include <sys/mount.h>
+ #include <sys/buf.h>
+ #include <sys/file.h>
+ #include <sys/dkbad.h>
+ #include <sys/disklabel.h>
+ #include <sys/ioctl.h>
+ #include <sys/errno.h>
+ #include <sys/malloc.h>
+   
+ #include <sys/specdev.h> /* XXX */
  
! #include <isofs/iso.h>
! #include <isofs/isofs_node.h>
  
  extern int enodev ();
  
***************
*** 37,49 ****
  };
  
  /*
!  * Called by vfs_mountroot when ufs is going to be mounted as root.
   *
   * Name is updated by mount(8) after booting.
   */
  #define ROOTNAME	"root_device"
  
! static int iso_mountfs(struct vnode *, struct mount *, struct proc *);
  
  int
  isofs_mountroot()
--- 37,49 ----
  };
  
  /*
!  * Called by vfs_mountroot when iso is going to be mounted as root.
   *
   * Name is updated by mount(8) after booting.
   */
  #define ROOTNAME	"root_device"
  
! static iso_mountfs();
  
  int
  isofs_mountroot()
***************
*** 55,76 ****
  	register struct fs *fs;
  	u_int size;
  	int error;
! 
  	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
  		M_MOUNT, M_WAITOK);
! 	mp->mnt_op = &isofs_vfsops;
  	mp->mnt_flag = MNT_RDONLY;
  	mp->mnt_exroot = 0;
  	mp->mnt_mounth = NULLVP;
! 	error = iso_mountfs(rootvp, mp, p);
  	if (error) {
  		free((caddr_t)mp, M_MOUNT);
! 		return (error);
  	}
  	if (error = vfs_lock(mp)) {
  		(void)isofs_unmount(mp, 0, p);
  		free((caddr_t)mp, M_MOUNT);
! 		return (error);
  	}
  	rootfs = mp;
  	mp->mnt_next = mp;
--- 55,78 ----
  	register struct fs *fs;
  	u_int size;
  	int error;
! 	struct iso_args args;
! 	
  	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
  		M_MOUNT, M_WAITOK);
! 	mp->mnt_op = (struct vfsops *)&isofs_vfsops;
  	mp->mnt_flag = MNT_RDONLY;
  	mp->mnt_exroot = 0;
  	mp->mnt_mounth = NULLVP;
! 	args.flags = ISOFSMNT_ROOT;
! 	error = iso_mountfs(rootvp, mp, p, &args);
  	if (error) {
  		free((caddr_t)mp, M_MOUNT);
! 		return error;
  	}
  	if (error = vfs_lock(mp)) {
  		(void)isofs_unmount(mp, 0, p);
  		free((caddr_t)mp, M_MOUNT);
! 		return error;
  	}
  	rootfs = mp;
  	mp->mnt_next = mp;
***************
*** 86,101 ****
  	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  	(void) isofs_statfs(mp, &mp->mnt_stat, p);
  	vfs_unlock(mp);
! 	return (0);
  }
  
  /*
!  * Flag to allow forcible unmounting.
   */
  int iso_doforce = 1;
  
  /*
!  * VFS Operations.
   *
   * mount system call
   */
--- 88,104 ----
  	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  	(void) isofs_statfs(mp, &mp->mnt_stat, p);
  	vfs_unlock(mp);
! 	return 0;
  }
  
+ 
  /*
!  * flag to allow forcible unmounting.
   */
  int iso_doforce = 1;
  
  /*
!  * vfs operations.
   *
   * mount system call
   */
***************
*** 108,133 ****
  	struct proc *p;
  {
  	struct vnode *devvp;
! 	struct ufs_args args;
  	u_int size;
  	int error;
! 	struct iso_mnt *imp = 0;
! 
! 	if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
! 		return (error);
! 
  	if ((mp->mnt_flag & MNT_RDONLY) == 0)
! 		return (EROFS);
! 
  	/*
! 	 * Process export requests.
  	 */
! 	if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
! 		if (args.exflags & MNT_EXPORTED)
  			mp->mnt_flag |= MNT_EXPORTED;
  		else
  			mp->mnt_flag &= ~MNT_EXPORTED;
! 		if (args.exflags & MNT_EXRDONLY)
  			mp->mnt_flag |= MNT_EXRDONLY;
  		else
  			mp->mnt_flag &= ~MNT_EXRDONLY;
--- 111,136 ----
  	struct proc *p;
  {
  	struct vnode *devvp;
! 	struct iso_args args;
  	u_int size;
  	int error;
! 	struct iso_mnt *imp;
! 	
! 	if (error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))
! 		return error;
! 	
  	if ((mp->mnt_flag & MNT_RDONLY) == 0)
! 		return EROFS;
! 	
  	/*
!  	 * Process export requests.
  	 */
! 	if ((args.flags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
! 		if (args.flags & MNT_EXPORTED)
  			mp->mnt_flag |= MNT_EXPORTED;
  		else
  			mp->mnt_flag &= ~MNT_EXPORTED;
! 		if (args.flags & MNT_EXRDONLY)
  			mp->mnt_flag |= MNT_EXRDONLY;
  		else
  			mp->mnt_flag &= ~MNT_EXRDONLY;
***************
*** 138,146 ****
  	 * read/write; if there is no device name, that's all we do.
  	 */
  	if (mp->mnt_flag & MNT_UPDATE) {
- 		imp = VFSTOISOFS(mp);
  		if (args.fspec == 0)
! 			return (0);
  	}
  	/*
  	 * Not an update, or updating the name: look up the name
--- 141,148 ----
  	 * read/write; if there is no device name, that's all we do.
  	 */
  	if (mp->mnt_flag & MNT_UPDATE) {
  		if (args.fspec == 0)
! 			return 0;
  	}
  	/*
  	 * Not an update, or updating the name: look up the name
***************
*** 150,169 ****
  	ndp->ni_segflg = UIO_USERSPACE;
  	ndp->ni_dirp = args.fspec;
  	if (error = namei(ndp, p))
! 		return (error);
  	devvp = ndp->ni_vp;
  	if (devvp->v_type != VBLK) {
  		vrele(devvp);
! 		return (ENOTBLK);
  	}
  	if (major(devvp->v_rdev) >= nblkdev) {
  		vrele(devvp);
! 		return (ENXIO);
  	}
! 
! 	if ((mp->mnt_flag & MNT_UPDATE) == 0)
! 		error = iso_mountfs(devvp, mp, p);
! 	else {
  		if (devvp != imp->im_devvp)
  			error = EINVAL;	/* needs translation */
  		else
--- 152,172 ----
  	ndp->ni_segflg = UIO_USERSPACE;
  	ndp->ni_dirp = args.fspec;
  	if (error = namei(ndp, p))
! 		return error;
  	devvp = ndp->ni_vp;
  	if (devvp->v_type != VBLK) {
  		vrele(devvp);
! 		return ENOTBLK;
  	}
  	if (major(devvp->v_rdev) >= nblkdev) {
  		vrele(devvp);
! 		return ENXIO;
  	}
! 	
! 	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
! 		error = iso_mountfs(devvp, mp, p, &args);
! 	} else {
! 		imp = VFSTOISOFS(mp);
  		if (devvp != imp->im_devvp)
  			error = EINVAL;	/* needs translation */
  		else
***************
*** 171,208 ****
  	}
  	if (error) {
  		vrele(devvp);
! 		return (error);
  	}
  	imp = VFSTOISOFS(mp);
! 
! 	/* Check the Rock Ridge Extention support */
! 	if ( args.exflags & MNT_NORRIP ) {
! 		imp->iso_ftype = ISO_FTYPE_9660;
! 		mp->mnt_flag  |= MNT_NORRIP;
! 	} else {
! 		imp->iso_ftype = ISO_FTYPE_RRIP;
! 		mp->mnt_flag  &= ~MNT_NORRIP;
! 	}
! 
  	(void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size);
  	bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size);
  	bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
  	    MNAMELEN);
! 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 
  	    &size);
  	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  	(void) isofs_statfs(mp, &mp->mnt_stat, p);
! 	return (0);
  }
  
  /*
   * Common code for mount and mountroot
   */
! static int
! iso_mountfs(devvp, mp, p)
  	register struct vnode *devvp;
  	struct mount *mp;
  	struct proc *p;
  {
  	register struct iso_mnt *isomp = (struct iso_mnt *)0;
  	struct buf *bp = NULL;
--- 174,202 ----
  	}
  	if (error) {
  		vrele(devvp);
! 		return error;
  	}
  	imp = VFSTOISOFS(mp);
! 	
  	(void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size);
  	bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size);
  	bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
  	    MNAMELEN);
! 	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
  	    &size);
  	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  	(void) isofs_statfs(mp, &mp->mnt_stat, p);
! 	return 0;
  }
  
  /*
   * Common code for mount and mountroot
   */
! static int iso_mountfs(devvp, mp, p, argp)
  	register struct vnode *devvp;
  	struct mount *mp;
  	struct proc *p;
+ 	struct iso_args *argp;
  {
  	register struct iso_mnt *isomp = (struct iso_mnt *)0;
  	struct buf *bp = NULL;
***************
*** 220,310 ****
  	struct iso_primary_descriptor *pri;
  	struct iso_directory_record *rootp;
  	int logical_block_size;
! 
  	if (!ronly)
! 		return (EROFS);
! 
  	/*
  	 * Disallow multiple mounts of the same device.
  	 * Disallow mounting of a device that is currently in use
  	 * (except for root, which might share swap device for miniroot).
  	 * Flush out any old buffers remaining from a previous use.
  	 */
! 	if (error = iso_mountedon(devvp))
! 		return (error);
  	if (vcount(devvp) > 1 && devvp != rootvp)
! 		return (EBUSY);
  	vinvalbuf(devvp, 1);
  	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
! 		return (error);
  	needclose = 1;
! 
  	/* This is the "logical sector size".  The standard says this
  	 * should be 2048 or the physical sector size on the device,
  	 * whichever is greater.  For now, we'll just use a constant.
  	 */
  	iso_bsize = 2048;
! 
  	for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
  		if (error = bread (devvp, iso_blknum * iso_bsize / DEV_BSIZE,
  				   iso_bsize, NOCRED, &bp))
  			goto out;
! 
  		vdp = (struct iso_volume_descriptor *)bp->b_un.b_addr;
  		if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
  			error = EINVAL;
  			goto out;
  		}
! 
  		if (isonum_711 (vdp->type) == ISO_VD_END) {
  			error = EINVAL;
  			goto out;
  		}
! 
  		if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
  			break;
  		brelse(bp);
  	}
! 
  	if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) {
  		error = EINVAL;
  		goto out;
  	}
  	
  	pri = (struct iso_primary_descriptor *)vdp;
! 
  	logical_block_size = isonum_723 (pri->logical_block_size);
! 
  	if (logical_block_size < DEV_BSIZE
  	    || logical_block_size >= MAXBSIZE
  	    || (logical_block_size & (logical_block_size - 1)) != 0) {
  		error = EINVAL;
  		goto out;
  	}
! 
  	rootp = (struct iso_directory_record *)pri->root_directory_record;
! 
  	isomp = (struct iso_mnt *)malloc(sizeof *isomp,M_ISOFSMNT,M_WAITOK);
  	isomp->logical_block_size = logical_block_size;
  	isomp->volume_space_size = isonum_733 (pri->volume_space_size);
  	bcopy (rootp, isomp->root, sizeof isomp->root);
  	isomp->root_extent = isonum_733 (rootp->extent);
  	isomp->root_size = isonum_733 (rootp->size);
! 
! 	isomp->im_bsize = logical_block_size;
! 	isomp->im_bmask = ~(isomp->im_bsize - 1);
  	isomp->im_bshift = 0;
! 	while ((1 << isomp->im_bshift) < isomp->im_bsize)
  		isomp->im_bshift++;
! 
! 	bp->b_flags |= B_INVAL;
  	brelse(bp);
  	bp = NULL;
! 
! 	isomp->im_ronly = ronly;
! 	if (ronly == 0)
! 		isomp->im_fmod = 1;
! 
  	mp->mnt_data = (qaddr_t)isomp;
  	mp->mnt_stat.f_fsid.val[0] = (long)dev;
  	mp->mnt_stat.f_fsid.val[1] = MOUNT_ISOFS;
--- 214,299 ----
  	struct iso_primary_descriptor *pri;
  	struct iso_directory_record *rootp;
  	int logical_block_size;
! 	
  	if (!ronly)
! 		return EROFS;
! 	
  	/*
  	 * Disallow multiple mounts of the same device.
  	 * Disallow mounting of a device that is currently in use
  	 * (except for root, which might share swap device for miniroot).
  	 * Flush out any old buffers remaining from a previous use.
  	 */
! 	if (error = mountedon(devvp))
! 		return error;
  	if (vcount(devvp) > 1 && devvp != rootvp)
! 		return EBUSY;
  	vinvalbuf(devvp, 1);
  	if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
! 		return error;
  	needclose = 1;
! 	
  	/* This is the "logical sector size".  The standard says this
  	 * should be 2048 or the physical sector size on the device,
  	 * whichever is greater.  For now, we'll just use a constant.
  	 */
  	iso_bsize = 2048;
! 	
  	for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
  		if (error = bread (devvp, iso_blknum * iso_bsize / DEV_BSIZE,
  				   iso_bsize, NOCRED, &bp))
  			goto out;
! 		
  		vdp = (struct iso_volume_descriptor *)bp->b_un.b_addr;
  		if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
  			error = EINVAL;
  			goto out;
  		}
! 		
  		if (isonum_711 (vdp->type) == ISO_VD_END) {
  			error = EINVAL;
  			goto out;
  		}
! 		
  		if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
  			break;
  		brelse(bp);
  	}
! 	
  	if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) {
  		error = EINVAL;
  		goto out;
  	}
  	
  	pri = (struct iso_primary_descriptor *)vdp;
! 	
  	logical_block_size = isonum_723 (pri->logical_block_size);
! 	
  	if (logical_block_size < DEV_BSIZE
  	    || logical_block_size >= MAXBSIZE
  	    || (logical_block_size & (logical_block_size - 1)) != 0) {
  		error = EINVAL;
  		goto out;
  	}
! 	
  	rootp = (struct iso_directory_record *)pri->root_directory_record;
! 	
  	isomp = (struct iso_mnt *)malloc(sizeof *isomp,M_ISOFSMNT,M_WAITOK);
  	isomp->logical_block_size = logical_block_size;
  	isomp->volume_space_size = isonum_733 (pri->volume_space_size);
  	bcopy (rootp, isomp->root, sizeof isomp->root);
  	isomp->root_extent = isonum_733 (rootp->extent);
  	isomp->root_size = isonum_733 (rootp->size);
! 	
! 	isomp->im_bmask = logical_block_size - 1;
  	isomp->im_bshift = 0;
! 	while ((1 << isomp->im_bshift) < isomp->logical_block_size)
  		isomp->im_bshift++;
! 	
! 	bp->b_flags |= B_AGE;
  	brelse(bp);
  	bp = NULL;
! 	
  	mp->mnt_data = (qaddr_t)isomp;
  	mp->mnt_stat.f_fsid.val[0] = (long)dev;
  	mp->mnt_stat.f_fsid.val[1] = MOUNT_ISOFS;
***************
*** 312,321 ****
  	isomp->im_mountp = mp;
  	isomp->im_dev = dev;
  	isomp->im_devvp = devvp;
! 
  	devvp->v_specflags |= SI_MOUNTEDON;
! 
! 	return (0);
  out:
  	if (bp)
  		brelse(bp);
--- 301,347 ----
  	isomp->im_mountp = mp;
  	isomp->im_dev = dev;
  	isomp->im_devvp = devvp;
! 	
  	devvp->v_specflags |= SI_MOUNTEDON;
! 	
! 	/* Check the Rock Ridge Extention support */
! 	if (!(argp->flags & ISOFSMNT_NORRIP)) {
! 		if (error = bread (isomp->im_devvp,
! 				   (isomp->root_extent + isonum_711(rootp->ext_attr_length))
! 				   * isomp->logical_block_size / DEV_BSIZE,
! 				   isomp->logical_block_size,NOCRED,&bp))
! 		    goto out;
! 		
! 		rootp = (struct iso_directory_record *)bp->b_un.b_addr;
! 		
! 		if ((isomp->rr_skip = isofs_rrip_offset(rootp,isomp)) < 0) {
! 		    argp->flags  |= ISOFSMNT_NORRIP;
! 		} else {
! 		    argp->flags  &= ~ISOFSMNT_GENS;
! 		}
! 		
! 		/*
! 		 * The contents are valid,
! 		 * but they will get reread as part of another vnode, so...
! 		 */
! 		bp->b_flags |= B_AGE;
! 		brelse(bp);
! 		bp = NULL;
! 	}
! 	isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT);
! 	switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) {
! 	default:
! 	    isomp->iso_ftype = ISO_FTYPE_DEFAULT;
! 	    break;
! 	case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
! 	    isomp->iso_ftype = ISO_FTYPE_9660;
! 	    break;
! 	case 0:
! 	    isomp->iso_ftype = ISO_FTYPE_RRIP;
! 	    break;
! 	}
! 	
! 	return 0;
  out:
  	if (bp)
  		brelse(bp);
***************
*** 325,331 ****
  		free((caddr_t)isomp, M_ISOFSMNT);
  		mp->mnt_data = (qaddr_t)0;
  	}
! 	return (error);
  }
  
  /*
--- 351,357 ----
  		free((caddr_t)isomp, M_ISOFSMNT);
  		mp->mnt_data = (qaddr_t)0;
  	}
! 	return error;
  }
  
  /*
***************
*** 339,346 ****
  	int flags;
  	struct proc *p;
  {
! 
! 	return (0);
  }
  
  /*
--- 365,371 ----
  	int flags;
  	struct proc *p;
  {
! 	return 0;
  }
  
  /*
***************
*** 354,404 ****
  {
  	register struct iso_mnt *isomp;
  	int i, error, ronly, flags = 0;
! 
  	if (mntflags & MNT_FORCE) {
  		if (!iso_doforce || mp == rootfs)
! 			return (EINVAL);
  		flags |= FORCECLOSE;
  	}
  	mntflushbuf(mp, 0);
  	if (mntinvalbuf(mp))
! 		return (EBUSY);
  	isomp = VFSTOISOFS(mp);
! 
  	if (error = vflush(mp, NULLVP, flags))
! 		return (error);
! 	ronly = !isomp->im_ronly;
  	isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
! 	error = VOP_CLOSE(isomp->im_devvp, ronly ? FREAD : FREAD|FWRITE,
! 		NOCRED, p);
  	vrele(isomp->im_devvp);
  	free((caddr_t)isomp, M_ISOFSMNT);
  	mp->mnt_data = (qaddr_t)0;
  	mp->mnt_flag &= ~MNT_LOCAL;
! 	return (error);
! }
! 
! /*
!  * Check to see if a filesystem is mounted on a block device.
!  */
! int
! iso_mountedon(vp)
! 	register struct vnode *vp;
! {
! 	register struct vnode *vq;
! 
! 	if (vp->v_specflags & SI_MOUNTEDON)
! 		return (EBUSY);
! 	if (vp->v_flag & VALIASED) {
! 		for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
! 			if (vq->v_rdev != vp->v_rdev ||
! 			    vq->v_type != vp->v_type)
! 				continue;
! 			if (vq->v_specflags & SI_MOUNTEDON)
! 				return (EBUSY);
! 		}
! 	}
! 	return (0);
  }
  
  /*
--- 379,409 ----
  {
  	register struct iso_mnt *isomp;
  	int i, error, ronly, flags = 0;
! 	
  	if (mntflags & MNT_FORCE) {
  		if (!iso_doforce || mp == rootfs)
! 			return EINVAL;
  		flags |= FORCECLOSE;
  	}
  	mntflushbuf(mp, 0);
  	if (mntinvalbuf(mp))
! 		return EBUSY;
  	isomp = VFSTOISOFS(mp);
! 	
  	if (error = vflush(mp, NULLVP, flags))
! 		return error;
! #ifdef	ISODEVMAP
! 	if (isomp->iso_ftype == ISO_FTYPE_RRIP)
! 		iso_dunmap(isomp->im_dev);
! #endif
! 	
  	isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
! 	error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
  	vrele(isomp->im_devvp);
  	free((caddr_t)isomp, M_ISOFSMNT);
  	mp->mnt_data = (qaddr_t)0;
  	mp->mnt_flag &= ~MNT_LOCAL;
! 	return error;
  }
  
  /*
***************
*** 414,432 ****
  	struct vnode tvp;
  	int error;
  	struct iso_mnt *imp = VFSTOISOFS (mp);
! 
  	tvp.v_mount = mp;
  	ip = VTOI(&tvp);
  	ip->i_vnode = &tvp;
  	ip->i_dev = imp->im_dev;
  	ip->i_diroff = 0;
! 	ip->iso_extent = imp->root_extent;
! 	error = iso_iget(ip, imp->root_extent, &nip,
! 			 (struct iso_directory_record *) imp->root);
  	if (error)
! 		return (error);
  	*vpp = ITOV(nip);
! 	return (0);
  }
  
  /*
--- 419,445 ----
  	struct vnode tvp;
  	int error;
  	struct iso_mnt *imp = VFSTOISOFS (mp);
! 	struct iso_directory_record *dp;
! 	
  	tvp.v_mount = mp;
  	ip = VTOI(&tvp);
  	ip->i_vnode = &tvp;
  	ip->i_dev = imp->im_dev;
  	ip->i_diroff = 0;
! 	dp = (struct iso_directory_record *)imp->root;
! 	isodirino(&ip->i_number,dp,imp);
! 	
! 	/*
! 	 * With RRIP we must use the `.' entry of the root directory.
! 	 * Simply tell iget, that it's a relocated directory.
! 	 */
! 	error = iso_iget(ip,ip->i_number,
! 			 imp->iso_ftype == ISO_FTYPE_RRIP,
! 			 &nip,dp);
  	if (error)
! 		return error;
  	*vpp = ITOV(nip);
! 	return 0;
  }
  
  /*
***************
*** 457,463 ****
  		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
  			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
  	}
! 	return (0);
  }
  
  int
--- 470,480 ----
  		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
  			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
  	}
! #if 0
! 	/* Use the first spare for flags: */
! 	sbp->f_spare[0] = isomp->im_flags;
! #endif
! 	return 0;
  }
  
  int
***************
*** 465,471 ****
  	struct mount *mp;
  	int waitfor;
  {
! 	return (0);
  }
  
  /*
--- 482,488 ----
  	struct mount *mp;
  	int waitfor;
  {
! 	return 0;
  }
  
  /*
***************
*** 478,490 ****
   * - check that the generation number matches
   */
  
- 
  struct ifid {
  	ushort	ifid_len;
  	ushort	ifid_pad;
- 	int	ifid_lbn;
- 	int	ifid_offset;
  	int	ifid_ino;
  };
  
  int
--- 495,505 ----
   * - check that the generation number matches
   */
  
  struct ifid {
  	ushort	ifid_len;
  	ushort	ifid_pad;
  	int	ifid_ino;
+ 	off_t	ifid_start;
  };
  
  int
***************
*** 502,563 ****
  	struct buf			*bp;
  	struct iso_directory_record	*dirp;
  	struct iso_node 		*ip, *nip;
! 	struct proc 			*p;
! 
  	ifhp = (struct ifid *)fhp;
  	imp = VFSTOISOFS (mp);
! 
  #ifdef	ISOFS_DBG
! 	printf("fhtovp: lbn %d, off %d, ino %d\n",
! 			ifhp->ifid_lbn, ifhp->ifid_offset, ifhp->ifid_ino);
  #endif
! 
! 	lbn = ifhp->ifid_lbn;
! 	off = ifhp->ifid_offset;
! 	ifhp->ifid_lbn += (ifhp->ifid_offset >> 11);
! 	ifhp->ifid_offset &= 0x7ff;
! 
! 	if (ifhp->ifid_lbn >= imp->volume_space_size)
! 		return (EINVAL);
! 
! 	if (ifhp->ifid_offset + sizeof (struct iso_directory_record)
! 	    > imp->im_bsize)
! 		return (EINVAL);
! 
! 	if (error = bread (imp->im_devvp,
! 		 (ifhp->ifid_lbn * imp->im_bsize / DEV_BSIZE), imp->im_bsize,
! 								 NOCRED, &bp)) {
! 		printf("fhtovp: bread error %d\n", error);
! 		return(EINVAL);
  	}
! 
! 	dirp = (struct iso_directory_record *)
! 				 (bp->b_un.b_addr + ifhp->ifid_offset);
! 
! 	if (ifhp->ifid_offset + isonum_711 (dirp->length) > imp->im_bsize) {
! 		brelse (bp);
! 		return (EINVAL);
  	}
! 	if (isonum_733(dirp->extent) != ifhp->ifid_ino) {
  		brelse(bp);
! 		return(EINVAL);
  	}
! 
  	tvp.v_mount = mp;
  	ip = VTOI(&tvp);
  	ip->i_vnode = &tvp;
  	ip->i_dev = imp->im_dev;
! 	ip->i_diroff = off;
! 	ip->iso_extent = lbn;
! 	if (error = iso_iget(ip, ifhp->ifid_ino, &nip, dirp)) {
  		*vpp = NULLVP;
! 		brelse (bp);
! 		return (error);
  	}
  	ip = nip;
  	*vpp = ITOV(ip);
! 	brelse (bp);
! 	return (0);
  }
  
  /*
--- 517,585 ----
  	struct buf			*bp;
  	struct iso_directory_record	*dirp;
  	struct iso_node 		*ip, *nip;
! 	
  	ifhp = (struct ifid *)fhp;
  	imp = VFSTOISOFS (mp);
! 	
  #ifdef	ISOFS_DBG
! 	printf("fhtovp: ino %d, start %ld\n",ifhp->ifid_ino,ifhp->ifid_start);
  #endif
! 	
! 	lbn = ifhp->ifid_ino >> imp->im_bshift;
! 	off = ifhp->ifid_ino & imp->im_bmask;
! 	
! 	if (lbn >= imp->volume_space_size) {
! 		printf("fhtovp: lbn exceed volume space %d\n",lbn);
! 		return EINVAL;
  	}
! 	
! 	if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
! 		printf("fhtovp: across the block boundary %d\n",
! 		       off + ISO_DIRECTORY_RECORD_SIZE);
! 		return EINVAL;
  	}
! 	
! 	if (error = bread(imp->im_devvp,
! 			  lbn * imp->logical_block_size / DEV_BSIZE,
! 			  imp->logical_block_size,
! 			  NOCRED,&bp)) {
! 		printf("fhtovp: bread error %d\n",error);
  		brelse(bp);
! 		return EINVAL;
  	}
! 	
! 	dirp = (struct iso_directory_record *)(bp->b_un.b_addr + off);
! 	
! 	if (off + isonum_711(dirp->length) > imp->logical_block_size) {
! 		brelse(bp);
! 		printf("fhtovp: directory across the block boundary %d[off=%d/len=%d]\n",
! 		       off + isonum_711(dirp->length),off,isonum_711(dirp->length));
! 		return EINVAL;
! 	}
! 	
! 	if (isonum_733(dirp->extent) + isonum_711(dirp->ext_attr_length)
! 	    != ifhp->ifid_start) {
! 		brelse(bp);
! 		printf("fhtovp: file start miss %d vs %d\n",
! 		       isonum_733(dirp->extent) + isonum_711(dirp->ext_attr_length),
! 		       ifhp->ifid_start);
! 		return EINVAL;
! 	}
! 	
  	tvp.v_mount = mp;
  	ip = VTOI(&tvp);
  	ip->i_vnode = &tvp;
  	ip->i_dev = imp->im_dev;
! 	if (error = iso_iget(ip,ifhp->ifid_ino,0,&nip,dirp)) {
  		*vpp = NULLVP;
! 		brelse(bp);
! 		printf("fhtovp: failed to get ino\n");
! 		return error;
  	}
  	ip = nip;
  	*vpp = ITOV(ip);
! 	brelse(bp);
! 	return 0;
  }
  
  /*
***************
*** 572,593 ****
  	register struct iso_node *ip = VTOI(vp);
  	register struct ifid *ifhp;
  	register struct iso_mnt *mp = ip->i_mnt;
! 
  	ifhp = (struct ifid *)fhp;
  	ifhp->ifid_len = sizeof(struct ifid);
! 
! 	ifhp->ifid_lbn = ip->iso_parent_ext;
! 	ifhp->ifid_offset = ip->iso_parent;
  	ifhp->ifid_ino = ip->i_number;
! 
! 	if(ip->i_number == mp->root_extent) {
! 		ifhp->ifid_lbn = ip->i_number;
! 		ifhp->ifid_offset = 0;
! 	}
! 
  #ifdef	ISOFS_DBG
! 	printf("vptofh: lbn %d, off %d, ino %d\n",
! 			ifhp->ifid_lbn, ifhp->ifid_offset, ifhp->ifid_ino);
  #endif
! 	return (0);
  }
--- 594,609 ----
  	register struct iso_node *ip = VTOI(vp);
  	register struct ifid *ifhp;
  	register struct iso_mnt *mp = ip->i_mnt;
! 	
  	ifhp = (struct ifid *)fhp;
  	ifhp->ifid_len = sizeof(struct ifid);
! 	
  	ifhp->ifid_ino = ip->i_number;
! 	ifhp->ifid_start = ip->iso_start;
! 	
  #ifdef	ISOFS_DBG
! 	printf("vptofh: ino %d, start %ld\n",
! 	       ifhp->ifid_ino,ifhp->ifid_start);
  #endif
! 	return 0;
  }
diff -cr sys/isofs/isofs_vnops.c /usr/src/sys/isofs/isofs_vnops.c
*** sys/isofs/isofs_vnops.c	Sun Jun 12 05:05:29 1994
--- /usr/src/sys/isofs/isofs_vnops.c	Mon Aug 15 15:43:52 1994
***************
*** 1,26 ****
  /*
   *	$Id: isofs_vnops.c,v 1.6 1994/06/12 04:05:29 davidg Exp $
   */
! #include "param.h"
! #include "systm.h"
! #include "namei.h"
! #include "resourcevar.h"
! #include "kernel.h"
! #include "file.h"
! #include "stat.h"
! #include "buf.h"
! #include "proc.h"
! #include "conf.h"
! #include "mount.h"
! #include "vnode.h"
! #include "specdev.h"
! #include "fifo.h"
! #include "malloc.h"
! #include "dir.h"
! 
! #include "iso.h"
! #include "isofs_node.h"
! #include "iso_rrip.h"
  
  /*
   * Open called.
--- 1,84 ----
  /*
   *	$Id: isofs_vnops.c,v 1.6 1994/06/12 04:05:29 davidg Exp $
   */
! 
! #include <sys/param.h>
! #include <sys/systm.h>
! #include <sys/namei.h>
! #include <sys/resourcevar.h>
! #include <sys/kernel.h>
! #include <sys/file.h>
! #include <sys/stat.h>
! #include <sys/buf.h>
! #include <sys/proc.h>
! #include <sys/conf.h>
! #include <sys/mount.h>
! #include <sys/vnode.h>
! #include <sys/malloc.h>
! #include <sys/dir.h>
! 
! #include <sys/specdev.h> /* XXX */
! #include <sys/fifo.h> /* XXX */
! 
! #include <isofs/iso.h>
! #include <isofs/isofs_node.h>
! #include <isofs/iso_rrip.h>
! 
! /*
!  * Mknod vnode call
!  *  Actually remap the device number
!  */
! /* ARGSUSED */
! int
! isofs_mknod(ndp, vap, cred, p)
! 	struct nameidata *ndp;
! 	struct ucred *cred;
! 	struct vattr *vap;
! 	struct proc *p;
! {
! #ifndef	ISODEVMAP
! 	free(ndp->ni_pnbuf, M_NAMEI);
! 	vput(ndp->ni_dvp);
! 	vput(ndp->ni_vp);
! 	return EINVAL;
! #else
! 	register struct vnode *vp;
! 	struct iso_node *ip;
! 	struct iso_dnode *dp;
! 	int error;
! 	
! 	vp = ndp->ni_vp;
! 	ip = VTOI(vp);
! 	
! 	if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
! 	    || vap->va_type != vp->v_type
! 	    || (vap->va_type != VCHR && vap->va_type != VBLK)) {
! 		free(ndp->ni_pnbuf, M_NAMEI);
! 		vput(ndp->ni_dvp);
! 		vput(ndp->ni_vp);
! 		return EINVAL;
! 	}
! 	
! 	dp = iso_dmap(ip->i_dev,ip->i_number,1);
! 	if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
! 		/* same as the unmapped one, delete the mapping */
! 		remque(dp);
! 		FREE(dp,M_CACHE);
! 	} else
! 		/* enter new mapping */
! 		dp->d_dev = vap->va_rdev;
! 	
! 	/*
! 	 * Remove inode so that it will be reloaded by iget and
! 	 * checked to see if it is an alias of an existing entry
! 	 * in the inode cache.
! 	 */
! 	vput(vp);
! 	vp->v_type = VNON;
! 	vgone(vp);
! 	return (0);
! #endif
! }
  
  /*
   * Open called.
***************
*** 66,72 ****
  	struct ucred *cred;
  	struct proc *p;
  {
! 	return (0);
  }
  
  /* ARGSUSED */
--- 124,146 ----
  	struct ucred *cred;
  	struct proc *p;
  {
! 	register struct iso_node *ip = VTOI(vp);
! 	register gid_t *gp;
! 	int i;
! 	
! 	if (cred->cr_uid == 0)
! 		return 0;
! 	if (cred->cr_uid != ip->inode.iso_uid) {
! 		mode >>= 3;
! 		gp = cred->cr_groups;
! 		for (i = 0; i < cred->cr_ngroups; i++, gp++)
! 			if (ip->inode.iso_gid == *gp)
! 				goto found;
! 		mode >>= 3;
! found:
! 		;
! 	}
! 	return (ip->inode.iso_mode & mode) == mode ? 0 : EACCES;
  }
  
  /* ARGSUSED */
***************
*** 82,109 ****
  
  	vap->va_fsid = ip->i_dev;
  	vap->va_fileid = ip->i_number;
- 	/*
- 	 * This should be set properly if a RR filesystem, but this is
- 	 * the safest value for now. Note that previously this was conditionally
- 	 * set to 2 if the file is a directory, but this causes problems
- 	 * with find.
- 	 */
- 	vap->va_nlink = 1;
  
! 	vap->va_mode = ip->inode.iso_mode;
! 	vap->va_uid  = ip->inode.iso_uid;
! 	vap->va_gid  = ip->inode.iso_gid;
  	vap->va_atime= ip->inode.iso_atime;
  	vap->va_mtime= ip->inode.iso_mtime;
  	vap->va_ctime= ip->inode.iso_ctime;
  
! 	vap->va_rdev = 0;
! 	vap->va_size = ip->i_size;
  	vap->va_size_rsv = 0;
! 	vap->va_flags = 0;
  	vap->va_gen = 1;
  	vap->va_blocksize = ip->i_mnt->logical_block_size;
! 	vap->va_bytes = ip->i_size;
  	vap->va_bytes_rsv = 0;
  	vap->va_type = vp->v_type;
  	return (0);
--- 156,178 ----
  
  	vap->va_fsid = ip->i_dev;
  	vap->va_fileid = ip->i_number;
  
! 	vap->va_mode	= ip->inode.iso_mode;
! 	vap->va_nlink	= ip->inode.iso_links;
! 	vap->va_uid	= ip->inode.iso_uid;
! 	vap->va_gid	= ip->inode.iso_gid;
! 
  	vap->va_atime= ip->inode.iso_atime;
  	vap->va_mtime= ip->inode.iso_mtime;
  	vap->va_ctime= ip->inode.iso_ctime;
  
! 	vap->va_rdev	= ip->inode.iso_rdev;
! 	vap->va_size	= ip->i_size;
  	vap->va_size_rsv = 0;
! 	vap->va_flags	= 0;
  	vap->va_gen = 1;
  	vap->va_blocksize = ip->i_mnt->logical_block_size;
! 	vap->va_bytes	= ip->i_size;
  	vap->va_bytes_rsv = 0;
  	vap->va_type = vp->v_type;
  	return (0);
***************
*** 126,139 ****
  	daddr_t lbn, bn, rablock;
  	int size, diff, error = 0;
  	long n, on, type;
! 
! #ifdef DIAGNOSTICx
! 	if (uio->uio_rw != UIO_READ)
! 		panic("isofs_read mode");
! 	type = ip->i_mode & IFMT;
! 	if (type != IFDIR && type != IFREG && type != IFLNK)
! 		panic("isofs_read type");
! #endif
  	if (uio->uio_resid == 0)
  		return (0);
  	if (uio->uio_offset < 0)
--- 195,201 ----
  	daddr_t lbn, bn, rablock;
  	int size, diff, error = 0;
  	long n, on, type;
! 	
  	if (uio->uio_resid == 0)
  		return (0);
  	if (uio->uio_offset < 0)
***************
*** 143,149 ****
  	do {
  		lbn = iso_lblkno(imp, uio->uio_offset);
  		on = iso_blkoff(imp, uio->uio_offset);
! 		n = MIN((unsigned)(imp->im_bsize - on), uio->uio_resid);
  		diff = ip->i_size - uio->uio_offset;
  		if (diff <= 0)
  			return (0);
--- 205,211 ----
  	do {
  		lbn = iso_lblkno(imp, uio->uio_offset);
  		on = iso_blkoff(imp, uio->uio_offset);
! 		n = min((unsigned)(imp->logical_block_size - on), uio->uio_resid);
  		diff = ip->i_size - uio->uio_offset;
  		if (diff <= 0)
  			return (0);
***************
*** 180,185 ****
--- 242,248 ----
  	struct ucred *cred;
  	struct proc *p;
  {
+ 	printf("You did ioctl for isofs !!\n");
  	return (ENOTTY);
  }
  
***************
*** 232,237 ****
--- 295,386 ----
  }
  
  /*
+  * Structure for reading directories
+  */
+ struct isoreaddir {
+ 	struct dirent saveent;
+ 	struct dirent assocent;
+ 	struct dirent current;
+ 	off_t saveoff;
+ 	off_t assocoff;
+ 	off_t curroff;
+ 	struct uio *uio;
+ 	off_t uio_off;
+ 	int eof;
+ };
+ 
+ static int
+ iso_uiodir(idp,dp,off)
+ 	struct isoreaddir *idp;
+ 	struct dirent *dp;
+ 	off_t off;
+ {
+ 	int error;
+ 	
+ 	dp->d_name[dp->d_namlen] = 0;
+ 	dp->d_reclen = DIRSIZ(dp);
+ 	
+ 	if (idp->uio->uio_resid < dp->d_reclen) {
+ 		idp->eof = 0;
+ 		return -1;
+ 	}
+ 	
+ 	if (error = uiomove(dp,dp->d_reclen,idp->uio))
+ 		return error;
+ 	idp->uio_off = off;
+ 	return 0;
+ }
+ 
+ static int
+ iso_shipdir(idp)
+ 	struct isoreaddir *idp;
+ {
+ 	struct dirent *dp;
+ 	int cl, sl, assoc;
+ 	int error;
+ 	char *cname, *sname;
+ 	
+ 	cl = idp->current.d_namlen;
+ 	cname = idp->current.d_name;
+ 	if (assoc = cl > 1 && *cname == ASSOCCHAR) {
+ 		cl--;
+ 		cname++;
+ 	}
+ 	
+ 	dp = &idp->saveent;
+ 	sname = dp->d_name;
+ 	if (!(sl = dp->d_namlen)) {
+ 		dp = &idp->assocent;
+ 		sname = dp->d_name + 1;
+ 		sl = dp->d_namlen - 1;
+ 	}
+ 	if (sl > 0) {
+ 		if (sl != cl
+ 		    || bcmp(sname,cname,sl)) {
+ 			if (idp->assocent.d_namlen) {
+ 				if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
+ 					return error;
+ 				idp->assocent.d_namlen = 0;
+ 			}
+ 			if (idp->saveent.d_namlen) {
+ 				if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
+ 					return error;
+ 				idp->saveent.d_namlen = 0;
+ 			}
+ 		}
+ 	}
+ 	idp->current.d_reclen = DIRSIZ(&idp->current);
+ 	if (assoc) {
+ 		idp->assocoff = idp->curroff;
+ 		bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
+ 	} else {
+ 		idp->saveoff = idp->curroff;
+ 		bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
+ 	}
+ 	return 0;
+ }
+ 
+ /*
   * Vnode op for readdir
   */
  int
***************
*** 241,248 ****
  	struct ucred *cred;
  	int *eofflagp;
  {
! 	struct dirent dirent;
! 	int iso_offset;
  	int entryoffsetinblock;
  	int error = 0;
  	int endsearch;
--- 390,396 ----
  	struct ucred *cred;
  	int *eofflagp;
  {
! 	struct isoreaddir *idp;
  	int entryoffsetinblock;
  	int error = 0;
  	int endsearch;
***************
*** 251,460 ****
  	struct iso_mnt *imp;
  	struct iso_node *ip;
  	struct buf *bp = NULL;
! 	int i;
! 	int end_flag = 0;
! 	ISO_RRIP_ANALYZE ana;
! 
  	ip = VTOI (vp);
  	imp = ip->i_mnt;
! 
! 	iso_offset = uio->uio_offset;
! 
! 	entryoffsetinblock = iso_blkoff(imp, iso_offset);
  	if (entryoffsetinblock != 0) {
! 		if (error = iso_blkatoff(ip, iso_offset, (char **)0, &bp))
  			return (error);
  	}
! 
  	endsearch = ip->i_size;
! 
! 	while (iso_offset < endsearch && uio->uio_resid > 0) {
  		/*
  		 * If offset is on a block boundary,
  		 * read the next directory block.
  		 * Release previous if it exists.
  		 */
! 
! 		if (iso_blkoff(imp, iso_offset) == 0) {
  			if (bp != NULL)
  				brelse(bp);
! 			if (error = iso_blkatoff(ip, iso_offset,
! 						 (char **)0, &bp))
! 				return (error);
  			entryoffsetinblock = 0;
  		}
  		/*
  		 * Get pointer to next entry.
  		 */
! 
  		ep = (struct iso_directory_record *)
  			(bp->b_un.b_addr + entryoffsetinblock);
! 
  		reclen = isonum_711 (ep->length);
  		if (reclen == 0) {
  			/* skip to next block, if any */
! 			iso_offset = roundup (iso_offset,
! 					      imp->logical_block_size);
  			continue;
  		}
! 
! 		if (reclen < sizeof (struct iso_directory_record))
  			/* illegal entry, stop */
  			break;
! 
! /* 10 Aug 92*/	if (entryoffsetinblock + reclen -1 >= imp->logical_block_size)
  			/* illegal directory, so stop looking */
  			break;
! 
! 		dirent.d_fileno = isonum_733 (ep->extent);
! 		dirent.d_namlen = isonum_711 (ep->name_len);
! 
! 		if (reclen < sizeof (struct iso_directory_record)
! 		    + dirent.d_namlen)
  			/* illegal entry, stop */
  			break;
! 
  		/*
  		 *
  		 */
! 		switch (ep->name[0]) {
! 		case 0:
! 			dirent.d_name[0] = '.';
! 			dirent.d_namlen = 1;
! 			break;
! 		case 1:
! 			dirent.d_name[0] = '.';
! 			dirent.d_name[1] = '.';
! 			dirent.d_namlen = 2;
  			break;
! 		default:
! 			switch ( imp->iso_ftype ) {
! 			case ISO_FTYPE_RRIP:
! 				isofs_rrip_getname( ep, dirent.d_name, &dirent.d_namlen );
  				break;
! 			case ISO_FTYPE_9660:
! 			{
! 				int namelen = dirent.d_namlen;
! 				isofntrans(ep->name, dirent.d_namlen,
! 					   dirent.d_name, &namelen);
! 				dirent.d_namlen = namelen;
  				break;
- 			}
  			default:
  				break;
  			}
- 			break;
  		}
! 
! 		dirent.d_name[dirent.d_namlen] = 0;
! 		dirent.d_reclen = DIRSIZ (&dirent);
! 
! 		if (uio->uio_resid < dirent.d_reclen)
! 			break;
! 
! 		if (error = uiomove (&dirent, dirent.d_reclen, uio))
  			break;
! 
! 		iso_offset += reclen;
  		entryoffsetinblock += reclen;
  	}
! 			
  	if (bp)
  		brelse (bp);
  
! 	if (end_flag || (VTOI(vp)->i_size - iso_offset) <= 0)
! 		*eofflagp = 1;
! 	else
! 		*eofflagp = 0;
! 
! 	uio->uio_offset = iso_offset;
! 
  	return (error);
  }
  
  /*
   * Return target name of a symbolic link
   */
  typedef struct iso_directory_record ISODIR;
  typedef struct iso_node             ISONODE;
  typedef struct iso_mnt              ISOMNT;
  int isofs_readlink(vp, uio, cred)
! struct vnode *vp;
! struct uio   *uio;
! struct ucred *cred;
! {
!         ISONODE *ip;
!         ISODIR  *dirp;                   
!         ISOMNT  *imp;
!         struct  buf *bp;
!         int     symlen;
!         int     error;
!         char    symname[NAME_MAX];
! 
!         ip  = VTOI( vp );
!         imp = ip->i_mnt;
!         /*
!          * Get parents directory record block that this inode included.
!          */
!         error = bread(  imp->im_devvp,
!                         (daddr_t)(( ip->iso_parent_ext + (ip->iso_parent >> 11 ) )
!                         * imp->im_bsize / DEV_BSIZE ),
!                         imp->im_bsize,
!                         NOCRED,
!                         &bp );
!         if ( error ) {
!                 return( EINVAL );
!         }
! 
!         /*
!          * Setup the directory pointer for this inode
!          */
  
!         dirp = (ISODIR *)(bp->b_un.b_addr + ( ip->iso_parent & 0x7ff ) );
  #ifdef DEBUG
!         printf("lbn=%d[base=%d,off=%d,bsize=%d,DEV_BSIZE=%d], dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n",
!                                 (daddr_t)(( ip->iso_parent_ext + (ip->iso_parent >> 12 ) ) * imp->im_bsize / DEV_BSIZE ),
!                                 ip->iso_parent_ext,
!                                 (ip->iso_parent >> 11 ),
!                                 imp->im_bsize,
!                                 DEV_BSIZE,
!                                 dirp,
!                                 bp->b_un.b_addr,
!                                 ip->iso_parent,
!                                 ip->iso_parent & 0x7ff );
  #endif
! 
!         /*
!          * Just make sure, we have a right one....
!          *   1: Check not cross boundary on block
!          *   2: Check number of inode
!          */
!         if ( (ip->iso_parent & 0x7ff) + isonum_711( dirp->length ) >=
!                                                 imp->im_bsize )         {
!                 brelse ( bp );
!                 return( EINVAL );
!         }
!         if ( isonum_733(dirp->extent) != ip->i_number ) {
!                 brelse ( bp );
!                 return( EINVAL );
!         }
! 
!         /*
!          * Ok, we just gathering a Symbolick name in SL record.
!          */
!         if ( isofs_rrip_getsymname( vp, dirp, symname, &symlen ) == 0 ) {
!                 brelse ( bp );
!                 return( EINVAL );
!         }
!         /*
!          * Don't forget before you leave from home ;-)
!          */
!         brelse( bp );
! 
!         /*
!          * return with the Symbolick name to caller's.
!          */
!         return ( uiomove( symname, symlen, uio ) );
  }
  
  /*
--- 399,632 ----
  	struct iso_mnt *imp;
  	struct iso_node *ip;
  	struct buf *bp = NULL;
! 	
  	ip = VTOI (vp);
  	imp = ip->i_mnt;
! 	
! 	MALLOC(idp,struct isoreaddir *,sizeof(*idp),M_TEMP,M_WAITOK);
! 	idp->saveent.d_namlen = 0;
! 	idp->assocent.d_namlen = 0;
! 	idp->uio = uio;
! 	idp->curroff = uio->uio_offset;
! 	idp->eof = 1;
! 	
! 	entryoffsetinblock = iso_blkoff(imp, idp->curroff);
  	if (entryoffsetinblock != 0) {
! 		if (error = iso_blkatoff(ip, idp->curroff, &bp)) {
! 			FREE(idp,M_TEMP);
  			return (error);
+ 		}
  	}
! 	
  	endsearch = ip->i_size;
! 	
! 	while (idp->curroff < endsearch) {
  		/*
  		 * If offset is on a block boundary,
  		 * read the next directory block.
  		 * Release previous if it exists.
  		 */
! 		
! 		if (iso_blkoff(imp, idp->curroff) == 0) {
  			if (bp != NULL)
  				brelse(bp);
! 			if (error = iso_blkatoff(ip, idp->curroff, &bp))
! 				break;
  			entryoffsetinblock = 0;
  		}
  		/*
  		 * Get pointer to next entry.
  		 */
! 		
  		ep = (struct iso_directory_record *)
  			(bp->b_un.b_addr + entryoffsetinblock);
! 		
  		reclen = isonum_711 (ep->length);
  		if (reclen == 0) {
  			/* skip to next block, if any */
! 			idp->curroff = roundup (idp->curroff,
! 						imp->logical_block_size);
  			continue;
  		}
! 		
! 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
! 			error = EINVAL;
  			/* illegal entry, stop */
  			break;
! 		}
! 		
! 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
! 			error = EINVAL;
  			/* illegal directory, so stop looking */
  			break;
! 		}
! 		
! 		idp->current.d_namlen = isonum_711 (ep->name_len);
! 		if (isonum_711(ep->flags)&2)
! 			isodirino(&idp->current.d_fileno,ep,imp);
! 		else
! 			idp->current.d_fileno = (bp->b_blkno << DEV_BSHIFT) + idp->curroff;
! 		
! 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
! 			error = EINVAL;
  			/* illegal entry, stop */
  			break;
! 		}
! 		
! 		idp->curroff += reclen;
  		/*
  		 *
  		 */
! 		switch (imp->iso_ftype) {
! 		case ISO_FTYPE_RRIP:
! 			isofs_rrip_getname(ep,idp->current.d_name,
! 					   &idp->current.d_namlen,
! 					   &idp->current.d_fileno,imp);
! 			if (idp->current.d_namlen)
! 				error = iso_uiodir(idp,&idp->current,idp->curroff);
  			break;
! 		default:	/* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
! 			strcpy(idp->current.d_name,"..");
! 			switch (ep->name[0]) {
! 			case 0:
! 				idp->current.d_namlen = 1;
! 				error = iso_uiodir(idp,&idp->current,idp->curroff);
  				break;
! 			case 1:
! 				idp->current.d_namlen = 2;
! 				error = iso_uiodir(idp,&idp->current,idp->curroff);
  				break;
  			default:
+ 				isofntrans(ep->name,idp->current.d_namlen,
+ 					   idp->current.d_name,&idp->current.d_namlen,
+ 					   imp->iso_ftype == ISO_FTYPE_9660,
+ 					   isonum_711(ep->flags)&4);
+ 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
+ 					error = iso_shipdir(idp);
+ 				else
+ 					error = iso_uiodir(idp,&idp->current,idp->curroff);
  				break;
  			}
  		}
! 		if (error)
  			break;
! 		
  		entryoffsetinblock += reclen;
  	}
! 	
! 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
! 		idp->current.d_namlen = 0;
! 		error = iso_shipdir(idp);
! 	}
! 	if (error < 0)
! 		error = 0;
! 	
  	if (bp)
  		brelse (bp);
  
! 	uio->uio_offset = idp->uio_off;
! 	*eofflagp = idp->eof;
! 	
! 	FREE(idp,M_TEMP);
! 	
  	return (error);
  }
  
  /*
   * Return target name of a symbolic link
+  * Shouldn't we get the parent vnode and read the data from there?
+  * This could eventually result in deadlocks in isofs_lookup.
+  * But otherwise the block read here is in the block buffer two times.
   */
  typedef struct iso_directory_record ISODIR;
  typedef struct iso_node             ISONODE;
  typedef struct iso_mnt              ISOMNT;
  int isofs_readlink(vp, uio, cred)
! 	struct vnode *vp;
! 	struct uio   *uio;
! 	struct ucred *cred;
! {
! 	ISONODE	*ip;
! 	ISODIR	*dirp;                   
! 	ISOMNT	*imp;
! 	struct	buf *bp;
! 	u_short	symlen;
! 	int	error;
! 	char	*symname;
! 	ino_t	ino;
! 	
! 	ip  = VTOI(vp);
! 	imp = ip->i_mnt;
! 	
! 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
! 		return EINVAL;
! 	
! 	/*
! 	 * Get parents directory record block that this inode included.
! 	 */
! 	error = bread(imp->im_devvp,
! 		      (daddr_t)((ip->i_number&~imp->im_bmask) / DEV_BSIZE),
! 		      imp->logical_block_size,
! 		      NOCRED,
! 		      &bp);
! 	if (error) {
! 		brelse(bp);
! 		return EINVAL;
! 	}
  
! 	/*
! 	 * Setup the directory pointer for this inode
! 	 */
! 	dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask));
  #ifdef DEBUG
! 	printf("lbn=%d,off=%d,bsize=%d,DEV_BSIZE=%d, dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n",
! 	       (daddr_t)(ip->i_number >> imp->im_bshift),
! 	       ip->i_number & imp->im_bmask,
! 	       imp->logical_block_size,
! 	       DEV_BSIZE,
! 	       dirp,
! 	       bp->b_un.b_addr,
! 	       ip->i_number,
! 	       ip->i_number & imp->im_bmask );
  #endif
! 	
! 	/*
! 	 * Just make sure, we have a right one....
! 	 *   1: Check not cross boundary on block
! 	 */
! 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
! 	    > imp->logical_block_size) {
! 		brelse(bp);
! 		return EINVAL;
! 	}
! 	
! 	/*
! 	 * Now get a buffer
! 	 * Abuse a namei buffer for now.
! 	 */
! 	MALLOC(symname,char *,MAXPATHLEN,M_NAMEI,M_WAITOK);
! 	
! 	/*
! 	 * Ok, we just gathering a symbolic name in SL record.
! 	 */
! 	if (isofs_rrip_getsymname(dirp,symname,&symlen,imp) == 0) {
! 		FREE(symname,M_NAMEI);
! 		brelse(bp);
! 		return EINVAL;
! 	}
! 	/*
! 	 * Don't forget before you leave from home ;-)
! 	 */
! 	brelse(bp);
! 	
! 	/*
! 	 * return with the symbolic name to caller's.
! 	 */
! 	error = uiomove(symname,symlen,uio);
! 	
! 	FREE(symname,M_NAMEI);
! 	
! 	return error;
  }
  
  /*
***************
*** 469,475 ****
  
  	if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
  		FREE(ndp->ni_pnbuf, M_NAMEI);
! 	return (0);
  }
  
  /*
--- 641,647 ----
  
  	if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
  		FREE(ndp->ni_pnbuf, M_NAMEI);
! 	return 0;
  }
  
  /*
***************
*** 482,488 ****
  	register struct iso_node *ip = VTOI(vp);
  
  	ISO_ILOCK(ip);
! 	return (0);
  }
  
  /*
--- 654,660 ----
  	register struct iso_node *ip = VTOI(vp);
  
  	ISO_ILOCK(ip);
! 	return 0;
  }
  
  /*
***************
*** 497,503 ****
  	if (!(ip->i_flag & ILOCKED))
  		panic("isofs_unlock NOT LOCKED");
  	ISO_IUNLOCK(ip);
! 	return (0);
  }
  
  /*
--- 669,675 ----
  	if (!(ip->i_flag & ILOCKED))
  		panic("isofs_unlock NOT LOCKED");
  	ISO_IUNLOCK(ip);
! 	return 0;
  }
  
  /*
***************
*** 509,516 ****
  {
  
  	if (VTOI(vp)->i_flag & ILOCKED)
! 		return (1);
! 	return (0);
  }
  
  /*
--- 681,688 ----
  {
  
  	if (VTOI(vp)->i_flag & ILOCKED)
! 		return 1;
! 	return 0;
  }
  
  /*
***************
*** 530,547 ****
  		panic("isofs_strategy: spec");
  	if (bp->b_blkno == bp->b_lblkno) {
  		if (error = iso_bmap(ip, bp->b_lblkno, &bp->b_blkno))
! 			return (error);
  		if ((long)bp->b_blkno == -1)
  			clrbuf(bp);
  	}
  	if ((long)bp->b_blkno == -1) {
  		biodone(bp);
! 		return (0);
  	}
  	vp = ip->i_devvp;
  	bp->b_dev = vp->v_rdev;
  	(*(vp->v_op->vop_strategy))(bp);
! 	return (0);
  }
  
  /*
--- 702,719 ----
  		panic("isofs_strategy: spec");
  	if (bp->b_blkno == bp->b_lblkno) {
  		if (error = iso_bmap(ip, bp->b_lblkno, &bp->b_blkno))
! 			return error;
  		if ((long)bp->b_blkno == -1)
  			clrbuf(bp);
  	}
  	if ((long)bp->b_blkno == -1) {
  		biodone(bp);
! 		return 0;
  	}
  	vp = ip->i_devvp;
  	bp->b_dev = vp->v_rdev;
  	(*(vp->v_op->vop_strategy))(bp);
! 	return 0;
  }
  
  /*
***************
*** 551,557 ****
  isofs_print(vp)
  	struct vnode *vp;
  {
! 	printf ("tag VT_ISOFS, isofs vnode\n");
  }
  
  extern int enodev ();
--- 723,729 ----
  isofs_print(vp)
  	struct vnode *vp;
  {
! 	printf("tag VT_ISOFS, isofs vnode\n");
  }
  
  extern int enodev ();
***************
*** 594,596 ****
--- 766,842 ----
  	isofs_islocked,		/* islocked */
  	(void *)enodev,		/* advlock */
  };
+ 
+ struct vnodeops isofs_spec_inodeops = {
+ 	spec_lookup,		/* lookup */
+ 	(void *)enodev,		/* create */
+ 	(void *)enodev,		/* mknod */
+ 	spec_open,		/* open */
+ 	spec_close,		/* close */
+ 	isofs_access,		/* access */
+ 	isofs_getattr,		/* getattr */
+ 	(void *)enodev,		/* setattr */
+ 	spec_read,		/* read */
+ 	spec_write,		/* write */
+ 	spec_ioctl,		/* ioctl */
+ 	spec_select,		/* select */
+ 	spec_mmap,		/* mmap */
+ 	spec_fsync,		/* fsync */
+ 	spec_seek,		/* seek */
+ 	(void *)enodev,		/* remove */
+ 	(void *)enodev,		/* link */
+ 	(void *)enodev,		/* rename */
+ 	(void *)enodev,		/* mkdir */
+ 	(void *)enodev,		/* rmdir */
+ 	(void *)enodev,		/* symlink */
+ 	spec_readdir,		/* readdir */
+ 	spec_readlink,		/* readlink */
+ 	spec_abortop,		/* abortop */
+ 	isofs_inactive,		/* inactive */
+ 	isofs_reclaim,		/* reclaim */
+ 	isofs_lock,		/* lock */
+ 	isofs_unlock,		/* unlock */
+ 	(void *)enodev,		/* bmap */
+ 	spec_strategy,		/* strategy */
+ 	isofs_print,		/* print */
+ 	isofs_islocked,		/* islocked */
+ 	spec_advlock,		/* advlock */
+ };
+ 
+ #ifdef	FIFO
+ struct vnodeops isofs_fifo_inodeops = {
+ 	fifo_lookup,		/* lookup */
+ 	(void *)enodev,		/* create */
+ 	(void *)enodev,		/* mknod */
+ 	fifo_open,		/* open */
+ 	fifo_close,		/* close */
+ 	isofs_access,		/* access */
+ 	isofs_getattr,		/* getattr */
+ 	(void *)enodev,		/* setattr */
+ 	fifo_read,		/* read */
+ 	fifo_write,		/* write */
+ 	fifo_ioctl,		/* ioctl */
+ 	fifo_select,		/* select */
+ 	fifo_mmap,		/* mmap */
+ 	fifo_fsync,		/* fsync */
+ 	fifo_seek,		/* seek */
+ 	(void *)enodev,		/* remove */
+ 	(void *)enodev,		/* link */
+ 	(void *)enodev,		/* rename */
+ 	(void *)enodev,		/* mkdir */
+ 	(void *)enodev,		/* rmdir */
+ 	(void *)enodev,		/* symlink */
+ 	fifo_readdir,		/* readdir */
+ 	fifo_readlink,		/* readlink */
+ 	fifo_abortop,		/* abortop */
+ 	isofs_inactive,		/* inactive */
+ 	isofs_reclaim,		/* reclaim */
+ 	isofs_lock,		/* lock */
+ 	isofs_unlock,		/* unlock */
+ 	(void *)enodev,		/* bmap */
+ 	fifo_strategy,		/* strategy */
+ 	isofs_print,		/* print */
+ 	isofs_islocked,		/* islocked */
+ 	fifo_advlock,		/* advlock */
+ };
+ #endif	/* FIFO */
diff -cr sys/sys/mount.h /usr/src/sys/sys/mount.h
*** sys/sys/mount.h	Mon Mar  7 11:39:02 1994
--- /usr/src/sys/sys/mount.h	Mon Aug 15 15:47:20 1994
***************
*** 286,291 ****
--- 286,306 ----
  };
  #endif /* PCFS */
  
+ #ifdef ISOFS
+ /*
+  * Arguments to mount ISO 9660 filesystems.
+  */
+ struct iso_args {
+ 	char *fspec;		/* block special holding the fs to mount */
+ 	int flags;		/* mounting flags, see below */
+ 	uid_t exroot;		/* mapping for root uid			*/
+ };
+ #define ISOFSMNT_NORRIP	0x00000001	/* disable Rock Ridge Ext.*/
+ #define	ISOFSMNT_GENS	0x00000002	/* enable usage of generation numbers */
+ #define	ISOFSMNT_EXTATT	0x00000004	/* enable usage of extended attributes */
+ #endif /* ISOFS */
+ 
+ 
  #ifdef KERNEL
  /*
   * exported vnode operations
--
Doug Rabson, RenderMorphics Ltd.	Mail:  dfr@render.com
					Phone: +44 71 251 4411
					FAX:   +44 71 251 0939