Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 Oct 1998 15:00:01 -0800 (PST)
From:      Alex Vasylenko <lxv@nest.org>
To:        freebsd-bugs@FreeBSD.ORG
Subject:   Re: kern/5038: FreeBSD can't read MS Joliet CDs.
Message-ID:  <199810312300.PAA06804@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/5038; it has been noted by GNATS.

From: Alex Vasylenko <lxv@nest.org>
To: freebsd-gnats-submit@freebsd.org,
        Joachim Kuebart <joki@kuebart.stuttgart.netsurf.de>
Cc:  Subject: Re: kern/5038: FreeBSD can't read MS Joliet CDs.
Date: Sat, 31 Oct 1998 14:53:34 -0800

 hi,
 
 below is a diff from -stable (as of 10/30) sources to support Joliet
 extensions to cd9660 filesystem (author Joachim Kuebart 
 <joki@kuebart.stuttgart.netsurf.de>) ...
 
 --Alex.
 
 
 ===== ~/s/src/sys/isofs/cd9660
 diff -u orig/cd9660_lookup.c ./cd9660_lookup.c
 --- orig/cd9660_lookup.c	Sun Aug 17 06:28:32 1997
 +++ ./cd9660_lookup.c	Fri Oct 30 23:41:48 1998
 @@ -308,8 +308,7 @@
  					if (namelen != 1
  					    || ep->name[0] != 0)
  						goto notfound;
 -				} else if (!(res = isofncmp(name,len,
 -							    ep->name,namelen))) {
 +				} else if (!(res = isofncmp(name,len,ep->name,namelen,imp->joliet_level))) {
  					if (isoflags & 2)
  						isodirino(&ino,ep,imp);
  					else
 diff -u orig/cd9660_mount.h ./cd9660_mount.h
 --- orig/cd9660_mount.h	Sun Aug 17 06:28:33 1997
 +++ ./cd9660_mount.h	Fri Oct 30 23:45:01 1998
 @@ -50,3 +50,4 @@
  #define	ISOFSMNT_NORRIP	0x00000001	/* disable Rock Ridge Ext.*/
  #define	ISOFSMNT_GENS	0x00000002	/* enable generation numbers */
  #define	ISOFSMNT_EXTATT	0x00000004	/* enable extended attributes */
 +#define	ISOFSMNT_NOJOLIET 0x00000008	/* disable Joliet Ext. */
 diff -u orig/cd9660_rrip.c ./cd9660_rrip.c
 --- orig/cd9660_rrip.c	Sun Aug 17 06:28:37 1997
 +++ ./cd9660_rrip.c	Fri Oct 30 23:48:14 1998
 @@ -306,18 +306,19 @@
  	struct iso_directory_record *isodir;
  	ISO_RRIP_ANALYZE *ana;
  {
 -	strcpy(ana->outbuf,"..");
 -	switch (*isodir->name) {
 +	isofntrans(isodir->name,isonum_711(isodir->name_len),
 +		   ana->outbuf,ana->outlen,
 +		   1,isonum_711(isodir->flags)&4,
 +		   ana->imp->joliet_level);
 +	switch (*ana->outbuf) {
  	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;
 +		/* fall through */
 +	case 0:
 +		/* outlen is 1 already */
 +		strcpy(ana->outbuf,"..");
  		break;
  	}
  }
 @@ -509,6 +510,7 @@
  	register ISO_SUSP_HEADER *pend;
  	struct buf *bp = NULL;
  	char *pwhead;
 +	u_char c;
  	int result;
  
  	/*
 @@ -516,12 +518,11 @@
  	 *	 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++;
 +	isochar(isodir->name, pwhead, ana->imp->joliet_level, &c);
 +	pwhead += isonum_711(isodir->name_len) & 1;
  
  	/* 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)
 +	if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
  		pwhead += ana->imp->rr_skip;
  	else
  		pwhead += ana->imp->rr_skip0;
 @@ -635,6 +636,7 @@
  {
  	ISO_RRIP_ANALYZE analyze;
  	RRIP_TABLE *tab;
 +	u_char c;
  
  	analyze.outbuf = outbuf;
  	analyze.outlen = outlen;
 @@ -644,9 +646,10 @@
  	analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK;
  	*outlen = 0;
  
 +	isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
 +		imp->joliet_level, &c);
  	tab = rrip_table_getname;
 -	if (*isodir->name == 0
 -	    || *isodir->name == 1) {
 +	if (c == 0 || c == 1) {
  		cd9660_rrip_defname(isodir,&analyze);
  
  		analyze.fields &= ~ISO_SUSP_ALTNAME;
 diff -u orig/cd9660_util.c ./cd9660_util.c
 --- orig/cd9660_util.c	Sun Aug 17 06:28:39 1997
 +++ ./cd9660_util.c	Sat Oct 31 01:26:58 1998
 @@ -5,7 +5,8 @@
   * This code is derived from software contributed to Berkeley
   * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
   * Support code is derived from software contributed to Berkeley
 - * by Atsushi Murai (amurai@spec.co.jp).
 + * by Atsushi Murai (amurai@spec.co.jp). Joliet support was added by
 + * Joachim Kuebart (joki@kuebart.stuttgart.netsurf.de).
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
 @@ -153,33 +154,63 @@
  #endif	/* __notanymore__ */
  
  /*
 + * Get one character out of an iso filename
 + * Obey joliet_level
 + * Return number of bytes consumed
 + */
 +int
 +isochar(isofn, isoend, joliet_level, c)
 +	u_char *isofn;
 +	u_char *isoend;
 +	int joliet_level;
 +	u_char *c;
 +{
 +	*c = *isofn++;
 +	if (joliet_level == 0 || isofn == isoend)
 +		/* (00) and (01) are one byte in Joliet, too */
 +		return 1;
 +
 +	/* No Unicode support yet :-( */
 +	switch (*c) {
 +	default:
 +		*c = '?';
 +		break;
 +	case '\0':
 +		*c = *isofn;
 +		break;
 +	}
 +	return 2;
 +}
 +
 +/*
   * translate and compare a filename
 + * returns (fn - isofn)
   * Note: Version number plus ';' may be omitted.
   */
  int
 -isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
 +isofncmp(fn, fnlen, isofn, isolen, joliet_level)
 +	u_char *fn;
 +	int fnlen;
 +	u_char *isofn;
 +	int isolen;
 +	int joliet_level;
  {
  	int i, j;
 -	unsigned char c;
 +	u_char c, *fnend = fn + fnlen, *isoend = isofn + isolen;
  
 -	while (--fnlen >= 0) {
 -		if (--isolen < 0)
 +	for (; fn != fnend; fn++) {
 +		if (isofn == isoend)
  			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') {
 +		isofn += isochar(isofn, isoend, joliet_level, &c);
 +		if (c == ';') {
 +			if (*fn++ != ';')
 +				return fn[-1];
 +			for (i = 0; fn != fnend; i = i * 10 + *fn++ - '0')
 +				if (*fn < '0' || *fn > '9')
  					return -1;
 -				}
 -			}
 -			for (j = 0; --isolen >= 0; j = j * 10 + *isofn++ - '0');
 +			for (j = 0; isofn != isoend; j = j * 10 + c - '0')
 +				isofn += isochar(isofn, isoend,
 +					joliet_level, &c);
  			return i - j;
  		}
  		if (c != *fn) {
 @@ -193,15 +224,19 @@
  			} else
  				return *fn - c;
  		}
 -		fn++;
  	}
 -	if (isolen > 0) {
 -		switch (*isofn) {
 +	if (isofn != isoend) {
 +		isofn += isochar(isofn, isoend, joliet_level, &c);
 +		switch (c) {
  		default:
 -			return -1;
 +			return -c;
  		case '.':
 -			if (isofn[1] != ';')
 -				return -1;
 +			if (isofn != isoend) {
 +				isochar(isofn, isoend, joliet_level, &c);
 +				if (c == ';')
 +					return 0;
 +			}
 +			return -1;
  		case ';':
  			return 0;
  		}
 @@ -210,31 +245,36 @@
  }
  
  /*
 - * translate a filename
 + * translate a filename of length > 0
   */
  void
 -isofntrans(unsigned char *infn,int infnlen,
 -	   unsigned char *outfn,unsigned short *outfnlen,
 -	   int original,int assoc)
 +isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
 +	u_char *infn;
 +	int infnlen;
 +	u_char *outfn;
 +	u_short *outfnlen;
 +	int original;
 +	int assoc;
 +	int joliet_level;
  {
  	int fnidx = 0;
 +	u_char c, d = '\0', *infnend = infn + infnlen;
  
  	if (assoc) {
  		*outfn++ = ASSOCCHAR;
  		fnidx++;
 -		infnlen++;
  	}
 -	for (; fnidx < infnlen; fnidx++) {
 -		char c = *infn++;
 +	for (; infn != infnend; fnidx++) {
 +		infn += isochar(infn, infnend, joliet_level, &c);
  
  		if (!original && c >= 'A' && c <= 'Z')
  			*outfn++ = c + ('a' - 'A');
 -		else if (!original && c == '.' && *infn == ';')
 -			break;
 -		else if (!original && c == ';')
 +		else if (!original && c == ';') {
 +			fnidx -= (d == '.');
  			break;
 -		else
 +		} else
  			*outfn++ = c;
 +		d = c;
  	}
  	*outfnlen = fnidx;
  }
 diff -u orig/cd9660_vfsops.c ./cd9660_vfsops.c
 --- orig/cd9660_vfsops.c	Sun Mar 29 03:10:36 1998
 +++ ./cd9660_vfsops.c	Sat Oct 31 00:31:56 1998
 @@ -294,9 +294,12 @@
  	int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  	int iso_bsize;
  	int iso_blknum;
 -	struct iso_volume_descriptor *vdp;
 +	int pri_blknum;
 +	int joliet_level;
 +	struct iso_volume_descriptor *vdp = 0;
  	struct iso_primary_descriptor *pri;
  	struct iso_sierra_primary_descriptor *pri_sierra;
 +	struct iso_supplementary_descriptor *supp;
  	struct iso_directory_record *rootp;
  	int logical_block_size;
  
 @@ -326,6 +329,8 @@
  	 */
  	iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
  
 +	joliet_level = 0;
 +	pri_blknum = -1;
  	for (iso_blknum = 16 + argp->ssector;
  	     iso_blknum < 100 + argp->ssector;
  	     iso_blknum++) {
 @@ -343,19 +348,42 @@
  				high_sierra = 1;
  		}
  
 -		if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_END) {
 -			error = EINVAL;
 -			goto out;
 -		}
 +		if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_END)
 +			break;
  
  		if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_PRIMARY)
 -			break;
 +			pri_blknum = iso_blknum;
 +
 +		if (!(argp->flags & ISOFSMNT_NOJOLIET) &&
 +		    isonum_711 (high_sierra? vdp->type_sierra: vdp->type) == ISO_VD_SUPPLEMENTARY) {
 +			supp = (struct iso_supplementary_descriptor *)vdp;
 +			if (bcmp(supp->escape, "%/@", 3) == 0)
 +				joliet_level = 1;
 +			if (bcmp(supp->escape, "%/C", 3) == 0)
 +				joliet_level = 2;
 +			if (bcmp(supp->escape, "%/E", 3) == 0)
 +				joliet_level = 3;
 +			if (isonum_711 (supp->flags) & 1)
 +				joliet_level = 0;
 +			if (joliet_level)
 +				break;
 +		}
 +			
  		brelse(bp);
  	}
  
 -	if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) != ISO_VD_PRIMARY) {
 -		error = EINVAL;
 -		goto out;
 +	if (isonum_711 (high_sierra? vdp->type_sierra: vdp->type) != ISO_VD_SUPPLEMENTARY) {
 +		if (pri_blknum == -1) {
 +			error = EINVAL;
 +			goto out;
 +		}
 +
 +		brelse(bp);
 +		if (error = bread(devvp, pri_blknum * btodb(iso_bsize),
 +				  iso_bsize, NOCRED, &bp))
 +			goto out;
 +		vdp = (struct iso_volume_descriptor *)bp->b_data;
 +		argp->flags |= ISOFSMNT_NOJOLIET;
  	}
  
  	pri = (struct iso_primary_descriptor *)vdp;
 @@ -384,6 +412,7 @@
  		isonum_733 (high_sierra?
  			    pri_sierra->volume_space_size:
  			    pri->volume_space_size);
 +	isomp->joliet_level = joliet_level;
  	/*
  	 * Since an ISO9660 multi-session CD can also access previous
  	 * sessions, we have to include them into the space consider-
 @@ -398,9 +427,7 @@
  	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++;
 +	isomp->im_bshift = ffs(logical_block_size) - 1;
  
  	bp->b_flags |= B_AGE;
  	brelse(bp);
 @@ -441,7 +468,8 @@
  		brelse(bp);
  		bp = NULL;
  	}
 -	isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT);
 +	isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
 +					ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
  
  	if(high_sierra)
  		/* this effectively ignores all the mount flags */
 diff -u orig/cd9660_vnops.c ./cd9660_vnops.c
 --- orig/cd9660_vnops.c	Sun Aug 17 06:28:42 1997
 +++ ./cd9660_vnops.c	Sat Oct 31 01:23:04 1998
 @@ -679,26 +679,23 @@
  			break;
  		default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/
  			strcpy(idp->current.d_name,"..");
 -			switch (ep->name[0]) {
 -			case 0:
 +			if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
  				idp->current.d_namlen = 1;
  				error = iso_uiodir(idp,&idp->current,idp->curroff);
 -				break;
 -			case 1:
 +			} else if (idp->current.d_namlen == 1 && ep->name[0] == 1) {
  				idp->current.d_namlen = 2;
  				error = iso_uiodir(idp,&idp->current,idp->curroff);
 -				break;
 -			default:
 +			} else {
  				isofntrans(ep->name,idp->current.d_namlen,
  					   idp->current.d_name, &elen,
  					   imp->iso_ftype == ISO_FTYPE_9660,
 -					   isoflags & 4);
 +					   isoflags & 4,
 +					   imp->joliet_level);
  				idp->current.d_namlen = (u_char)elen;
  				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
  					error = iso_shipdir(idp);
  				else
  					error = iso_uiodir(idp,&idp->current,idp->curroff);
 -				break;
  			}
  		}
  		if (error)
 diff -u orig/iso.h ./iso.h
 --- orig/iso.h	Tue Jul  7 11:11:16 1998
 +++ ./iso.h	Sat Oct 31 01:39:39 1998
 @@ -54,6 +54,7 @@
  
  /* volume descriptor types */
  #define ISO_VD_PRIMARY 1
 +#define ISO_VD_SUPPLEMENTARY 2
  #define ISO_VD_END 255
  
  #define ISO_STANDARD_ID "CD001"
 @@ -135,6 +136,42 @@
  	char unused4			[ISODCL (856, 2048)];
  };
  
 +struct iso_supplementary_descriptor {
 +	char type			[ISODCL (  1,	1)]; /* 711 */
 +	char id				[ISODCL (  2,	6)];
 +	char version			[ISODCL (  7,	7)]; /* 711 */
 +	char flags			[ISODCL (  8,	8)]; /* 711? */
 +	char system_id			[ISODCL (  9,  40)]; /* achars */
 +	char volume_id			[ISODCL ( 41,  72)]; /* dchars */
 +	char unused2			[ISODCL ( 73,  80)];
 +	char volume_space_size		[ISODCL ( 81,  88)]; /* 733 */
 +	char escape			[ISODCL ( 89, 120)];
 +	char volume_set_size		[ISODCL (121, 124)]; /* 723 */
 +	char volume_sequence_number	[ISODCL (125, 128)]; /* 723 */
 +	char logical_block_size		[ISODCL (129, 132)]; /* 723 */
 +	char path_table_size		[ISODCL (133, 140)]; /* 733 */
 +	char type_l_path_table		[ISODCL (141, 144)]; /* 731 */
 +	char opt_type_l_path_table	[ISODCL (145, 148)]; /* 731 */
 +	char type_m_path_table		[ISODCL (149, 152)]; /* 732 */
 +	char opt_type_m_path_table	[ISODCL (153, 156)]; /* 732 */
 +	char root_directory_record	[ISODCL (157, 190)]; /* 9.1 */
 +	char volume_set_id		[ISODCL (191, 318)]; /* dchars */
 +	char publisher_id		[ISODCL (319, 446)]; /* achars */
 +	char preparer_id		[ISODCL (447, 574)]; /* achars */
 +	char application_id		[ISODCL (575, 702)]; /* achars */
 +	char copyright_file_id		[ISODCL (703, 739)]; /* 7.5 dchars */
 +	char abstract_file_id		[ISODCL (740, 776)]; /* 7.5 dchars */
 +	char bibliographic_file_id	[ISODCL (777, 813)]; /* 7.5 dchars */
 +	char creation_date		[ISODCL (814, 830)]; /* 8.4.26.1 */
 +	char modification_date		[ISODCL (831, 847)]; /* 8.4.26.1 */
 +	char expiration_date		[ISODCL (848, 864)]; /* 8.4.26.1 */
 +	char effective_date		[ISODCL (865, 881)]; /* 8.4.26.1 */
 +	char file_structure_version	[ISODCL (882, 882)]; /* 711 */
 +	char unused4			[ISODCL (883, 883)];
 +	char application_data		[ISODCL (884, 1395)];
 +	char unused5			[ISODCL (1396, 2048)];
 +};
 +
  struct iso_directory_record {
  	char length			[ISODCL (1, 1)]; /* 711 */
  	char ext_attr_length		[ISODCL (2, 2)]; /* 711 */
 @@ -203,6 +240,8 @@
  
  	int rr_skip;
  	int rr_skip0;
 +
 +	int joliet_level;
  };
  
  #define VFSTOISOFS(mp)	((struct iso_mnt *)((mp)->mnt_data))
 @@ -227,9 +266,9 @@
  
  extern vop_t **cd9660_vnodeop_p;
  
 -int isofncmp __P((unsigned char *, int, unsigned char *, int));
 -void isofntrans __P((unsigned char *, int, unsigned char *, unsigned short *,
 -		     int, int));
 +int isochar __P((u_char *, u_char *, int, u_char *));
 +int isofncmp __P((u_char *, int, u_char *, int, int));
 +void isofntrans __P((u_char *, int, u_char *, u_short *, int, int, int));
  
  #endif /* KERNEL */
  
 ===== ~/s/src/sys/sys
 diff -u orig/mount.h ./mount.h
 --- orig/mount.h	Tue Jul 21 10:50:37 1998
 +++ ./mount.h	Sat Oct 31 10:36:45 1998
 @@ -420,6 +420,7 @@
  #define ISOFSMNT_NORRIP		0x00000001 /* disable Rock Ridge Ext.*/
  #define ISOFSMNT_GENS		0x00000002 /* enable generation numbers */
  #define ISOFSMNT_EXTATT		0x00000004 /* enable extended attributes */
 +#define ISOFSMNT_NOJOLIET	0x00000008 /* disable Joliet Ext. */
  #endif /* CD9660 */
  
  #ifdef NFS
 ===== ~/s/src/sbin/mount_cd9660
 diff -u orig/mount_cd9660.8 ./mount_cd9660.8
 --- orig/mount_cd9660.8	Tue Jul 21 10:48:07 1998
 +++ ./mount_cd9660.8	Sat Oct 31 01:48:25 1998
 @@ -67,6 +67,8 @@
  only the last one will be listed.)
  In either case, files may be opened without explicitly stating a
  version number.
 +.It Fl j
 +Do not use any Joliet extensions included in the filesystem.
  .It Fl o
  Options are specified with a
  .Fl o
 diff -u orig/mount_cd9660.c ./mount_cd9660.c
 --- orig/mount_cd9660.c	Sun Aug 17 06:30:23 1997
 +++ ./mount_cd9660.c	Sat Oct 31 01:49:31 1998
 @@ -73,6 +73,7 @@
  	{ "extatt", 0, ISOFSMNT_EXTATT, 1 },
  	{ "gens", 0, ISOFSMNT_GENS, 1 },
  	{ "rrip", 1, ISOFSMNT_NORRIP, 1 },
 +	{ "joliet", 1, ISOFSMNT_NOJOLIET, 1 },
  	{ NULL }
  };
  
 @@ -91,13 +92,16 @@
  	mntflags = opts = verbose = 0;
  	memset(&args, 0, sizeof args);
  	args.ssector = -1;
 -	while ((ch = getopt(argc, argv, "ego:rs:v")) != -1)
 +	while ((ch = getopt(argc, argv, "egjo:rs:v")) != -1)
  		switch (ch) {
  		case 'e':
  			opts |= ISOFSMNT_EXTATT;
  			break;
  		case 'g':
  			opts |= ISOFSMNT_GENS;
 +			break;
 +		case 'j':
 +			opts |= ISOFSMNT_NOJOLIET;
  			break;
  		case 'o':
  			getmntopts(optarg, mopts, &mntflags, &opts);

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199810312300.PAA06804>