Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Aug 1997 10:32:36 +0200 (MET DST)
From:      Udo Wolter <uwp@ukrv.de>
To:        sebesty@cs.elte.hu (Zoltan Sebestyen)
Cc:        freebsd-questions@FreeBSD.ORG
Subject:   Re: Multi-session CD-ROM
Message-ID:  <9708250832.AA16459@merlin.ukrv.de>
In-Reply-To: <Pine.ULT.3.93.970822112921.17481A-100000@konig> from Zoltan Sebestyen at "Aug 22, 97 11:30:42 am"

next in thread | previous in thread | raw e-mail | index | archive | help
Hi !

>  I wonder if FreeBSD can mount a multi-session CDROM properly? (Or more,
> can it mount only one of those sessions?)

It is possible, but only with -current...:-(
But Jörg Wunsch (j@uriah.heep.sax.de) gave me the patches, maybe they should
be incorporated into 2.2.5 ? They really work well and it's also possible
to get the old data loaded because you can mount a specific session.
With this feature it's possible to load an "empty but full disk" i.e. when you
had a session which contained data and the next session got a last directory.
You can now make CDs which are only readable with FreeBSD. :-)

Anyway, here the patches come. If something doesn't work ask Jörg. Any comments
should go to him. BTW, you not just have to generate a new kernel. You even
have to generate a new mount_cd9660 command !

--- snip ---
Index: /usr/src/sbin/mount_cd9660/mount_cd9660.c
===================================================================
RCS file: /home/cvs/src/sbin/mount_cd9660/mount_cd9660.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -u -r1.11 -r1.12
--- mount_cd9660.c	1997/03/29 03:32:35	1.11
+++ mount_cd9660.c	1997/04/29 15:56:40	1.12
@@ -49,9 +49,11 @@
 static char sccsid[] = "@(#)mount_cd9660.c	8.7 (Berkeley) 5/1/95";
 */
 static const char rcsid[] =
-	"$Id: mount_cd9660.c,v 1.11 1997/03/29 03:32:35 imp Exp $";
+	"$Id: mount_cd9660.c,v 1.12 1997/04/29 15:56:40 joerg Exp $";
 #endif /* not lint */
 
+#include <sys/cdio.h>
+#include <sys/file.h>
 #include <sys/param.h>
 #include <sys/mount.h>
 #include <sys/../isofs/cd9660/cd9660_mount.h>
@@ -74,21 +76,22 @@
 	{ NULL }
 };
 
-void	usage __P((void));
+int	get_ssector(const char *dev);
+void	usage(void);
 
 int
-main(argc, argv)
-	int argc;
-	char **argv;
+main(int argc, char **argv)
 {
 	struct iso_args args;
 	int ch, mntflags, opts;
 	char *dev, *dir;
 	struct vfsconf vfc;
-	int error;
+	int error, verbose;
 
-	mntflags = opts = 0;
-	while ((ch = getopt(argc, argv, "ego:r")) != -1)
+	mntflags = opts = verbose = 0;
+	memset(&args, 0, sizeof args);
+	args.ssector = -1;
+	while ((ch = getopt(argc, argv, "ego:rs:v")) != -1)
 		switch (ch) {
 		case 'e':
 			opts |= ISOFSMNT_EXTATT;
@@ -102,6 +105,12 @@
 		case 'r':
 			opts |= ISOFSMNT_NORRIP;
 			break;
+		case 's':
+			args.ssector = atoi(optarg);
+			break;
+		case 'v':
+			verbose++;
+			break;
 		case '?':
 		default:
 			usage();
@@ -125,6 +134,26 @@
 	args.export.ex_root = DEFAULT_ROOTUID;
 	args.flags = opts;
 
+	if (args.ssector == -1) {
+		/*
+		 * The start of the session has not been specified on
+		 * the command line.  If we can successfully read the
+		 * TOC of a CD-ROM, use the last data track we find.
+		 * Otherwise, just use 0, in order to mount the very
+		 * first session.  This is compatible with the
+		 * historic behaviour of mount_cd9660(8).  If the user
+		 * has specified -s <ssector> above, we don't get here
+		 * and leave the user's will.
+		 */
+		if ((args.ssector = get_ssector(dev)) == -1) {
+			if (verbose)
+				printf("could not determine starting sector, "
+				       "using very first session\n");
+			args.ssector = 0;
+		} else if (verbose)
+			printf("using starting sector %d\n", args.ssector);
+	}
+
 	error = getvfsbyname("cd9660", &vfc);
 	if (error && vfsisloadable("cd9660")) {
 		if (vfsload("cd9660"))
@@ -141,9 +170,51 @@
 }
 
 void
-usage()
+usage(void)
 {
 	(void)fprintf(stderr,
-		"usage: mount_cd9660 [-egrt] [-o options] special node\n");
+		"usage: mount_cd9660 [-egrv] [-o options] [-s startsector] special node\n");
 	exit(EX_USAGE);
+}
+
+int
+get_ssector(const char *dev)
+{
+	struct ioc_toc_header h;
+	struct ioc_read_toc_entry t;
+	struct cd_toc_entry toc_buffer[100];
+	int fd, ntocentries, i;
+
+	if ((fd = open(dev, O_RDONLY)) == -1)
+		return -1;
+	if (ioctl(fd, CDIOREADTOCHEADER, &h) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	ntocentries = h.ending_track - h.starting_track + 1;
+	if (ntocentries > 100) {
+		/* unreasonable, only 100 allowed */
+		close(fd);
+		return -1;
+	}
+	t.address_format = CD_LBA_FORMAT;
+	t.starting_track = 0;
+	t.data_len = ntocentries * sizeof(struct cd_toc_entry);
+	t.data = toc_buffer;
+
+	if (ioctl(fd, CDIOREADTOCENTRYS, (char *) &t) == -1) {
+		close(fd);
+		return -1;
+	}
+	close(fd);
+	
+	for (i = ntocentries - 1; i >= 0; i--)
+		if ((toc_buffer[i].control & 4) != 0)
+			/* found a data track */
+			break;
+	if (i < 0)
+		return -1;
+
+	return ntohl(toc_buffer[i].addr.lba);
 }
Index: /usr/src/sbin/mount_cd9660/mount_cd9660.8
===================================================================
RCS file: /home/cvs/src/sbin/mount_cd9660/mount_cd9660.8,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -u -r1.3 -r1.4
--- mount_cd9660.8	1996/08/23 20:34:17	1.3
+++ mount_cd9660.8	1997/04/29 15:56:40	1.4
@@ -42,8 +42,9 @@
 .Nd mount an ISO-9660 filesystem
 .Sh SYNOPSIS
 .Nm mount_cd9660
-.Op Fl egr
+.Op Fl egrv
 .Op Fl o Ar options
+.Op Fl s startsector
 .Ar special | node
 .Sh DESCRIPTION
 The
@@ -75,11 +76,31 @@
 man page for possible options and their meanings.
 .It Fl r
 Do not use any Rockridge extensions included in the filesystem.
+.It Fl s Ar startsector
+Start the filesystem at
+.Ar startsector .
+Normally, if the underlying device is a CD-ROM drive,
+.Nm
+will try to figure out the last track from the CD-ROM containing
+data, and start the filesystem there.  If the device is not a CD-ROM,
+or the table of contents cannot be examined, the filesystem will be
+started at sector 0.  This option can be used to override the behaviour.
+Note that
+.Ar startsector
+is measured in CD-ROM blocks, with 2048 bytes each.  This is the same
+as for example the
+.Cm info
+command of
+.Xr cdcontrol 8
+is printing.
+.It Fl v
+Be verbose about the starting sector decisions made.
 .El
 .Sh SEE ALSO
 .Xr mount 2 ,
 .Xr unmount 2 ,
 .Xr fstab 5 ,
+.Xr cdcontrol 8 ,
 .Xr mount 8
 .Sh BUGS
 POSIX device node mapping is currently not supported.
Index: /sys/sys/cdio.h
===================================================================
RCS file: /home/cvs/src/sys/sys/cdio.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -u -r1.16 -r1.17
--- cdio.h	1997/02/22 09:44:53	1.16
+++ cdio.h	1997/05/04 15:24:23	1.17
@@ -158,6 +158,14 @@
 #define CDIOREADTOCENTRYS _IOWR('c',5,struct ioc_read_toc_entry)
 
 
+struct ioc_read_toc_single_entry {
+	u_char	address_format;
+	u_char	track;
+	struct  cd_toc_entry entry;
+};
+#define CDIOREADTOCENTRY _IOWR('c',6,struct ioc_read_toc_single_entry)
+
+
 struct	ioc_patch
 {
 	u_char	patch[4];	/* one for each channel */
Index: sys/mount.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/mount.h,v
retrieving revision 1.34
diff -u -r1.34 mount.h
--- mount.h	1996/10/17 17:12:03	1.34
+++ mount.h	1997/04/29 11:18:28
@@ -405,6 +405,7 @@
 	char *fspec;			/* block special device to mount */
 	struct	export_args export;	/* network export info */
 	int flags;			/* mounting flags, see below */
+	int ssector;			/* starting sector */
 
 };
 #define ISOFSMNT_NORRIP		0x00000001 /* disable Rock Ridge Ext.*/
Index: isofs/cd9660/cd9660_bmap.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_bmap.c,v
retrieving revision 1.3
diff -u -r1.3 cd9660_bmap.c
--- cd9660_bmap.c	1995/09/04 00:20:04	1.3
+++ cd9660_bmap.c	1997/05/26 14:06:35
@@ -39,6 +39,8 @@
  * $Id: cd9660_bmap.c,v 1.3 1995/09/04 00:20:04 dyson Exp $
  */
 
+#define CD9660 1  /* bogus dependency in sys/mount.h */
+
 #include <sys/param.h>
 #include <sys/namei.h>
 #include <sys/buf.h>
Index: isofs/cd9660/cd9660_lookup.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_lookup.c,v
retrieving revision 1.10
diff -u -r1.10 cd9660_lookup.c
--- cd9660_lookup.c	1996/10/20 21:01:42	1.10
+++ cd9660_lookup.c	1997/05/26 14:06:35
@@ -41,6 +41,8 @@
  * $Id: cd9660_lookup.c,v 1.10 1996/10/20 21:01:42 alex Exp $
  */
 
+#define CD9660 1  /* bogus dependency in sys/mount.h */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
Index: isofs/cd9660/cd9660_mount.h
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_mount.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 cd9660_mount.h
--- cd9660_mount.h	1996/03/11 19:20:01	1.1.1.1
+++ cd9660_mount.h	1997/04/29 11:09:49
@@ -45,6 +45,7 @@
 	char	*fspec;			/* block special device to mount */
 	struct	export_args export;	/* network export info */
 	int	flags;			/* mounting flags, see below */
+	int	ssector;		/* starting sector, 0 for 1st session */
 };
 #define	ISOFSMNT_NORRIP	0x00000001	/* disable Rock Ridge Ext.*/
 #define	ISOFSMNT_GENS	0x00000002	/* enable generation numbers */
Index: isofs/cd9660/cd9660_node.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_node.c,v
retrieving revision 1.14
diff -u -r1.14 cd9660_node.c
--- cd9660_node.c	1996/09/20 05:51:09	1.14
+++ cd9660_node.c	1997/05/26 14:06:35
@@ -39,6 +39,8 @@
  * $Id: cd9660_node.c,v 1.14 1996/09/20 05:51:09 nate Exp $
  */
 
+#define CD9660 1  /* bogus dependency in sys/mount.h */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/mount.h>
Index: isofs/cd9660/cd9660_rrip.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_rrip.c,v
retrieving revision 1.9
diff -u -r1.9 cd9660_rrip.c
--- cd9660_rrip.c	1995/12/03 17:14:36	1.9
+++ cd9660_rrip.c	1997/05/26 14:06:35
@@ -39,6 +39,8 @@
  * $Id: cd9660_rrip.c,v 1.9 1995/12/03 17:14:36 bde Exp $
  */
 
+#define CD9660 1  /* bogus dependency in sys/mount.h */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
Index: isofs/cd9660/cd9660_util.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_util.c,v
retrieving revision 1.5
diff -u -r1.5 cd9660_util.c
--- cd9660_util.c	1995/07/16 10:20:56	1.5
+++ cd9660_util.c	1997/05/26 14:06:35
@@ -39,6 +39,8 @@
  * $Id: cd9660_util.c,v 1.5 1995/07/16 10:20:56 joerg Exp $
  */
 
+#define CD9660 1  /* bogus dependency in sys/mount.h */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
Index: isofs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.15
diff -u -r1.15 cd9660_vfsops.c
--- cd9660_vfsops.c	1995/10/31 12:13:46	1.15
+++ cd9660_vfsops.c	1997/05/26 14:06:36
@@ -39,6 +39,8 @@
  * $Id: cd9660_vfsops.c,v 1.15 1995/10/31 12:13:46 phk Exp $
  */
 
+#define CD9660 1  /* bogus dependency in sys/mount.h */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
@@ -48,6 +50,8 @@
 #include <miscfs/specfs/specdev.h>
 #include <sys/mount.h>
 #include <sys/buf.h>
+#include <sys/cdio.h>
+#include <sys/conf.h>
 #include <sys/file.h>
 #include <sys/ioctl.h>
 #include <sys/errno.h>
@@ -96,11 +100,53 @@
  */
 #define ROOTNAME	"root_device"
 
+static int iso_get_ssector __P((dev_t dev, struct proc *p));
 static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
 			    struct proc *p, struct iso_args *argp));
 
+/*
+ * Try to find the start of the last data track on this CD-ROM.  This
+ * is used to mount the last session of a multi-session CD.  Bail out
+ * and return 0 if we fail, this is always a safe bet.
+ */
+static int
+iso_get_ssector(dev, p)
+	dev_t dev;
+	struct proc *p;
+{
+	struct ioc_toc_header h;
+	struct ioc_read_toc_single_entry t;
+	int i;
+	struct bdevsw *bd;
+	d_ioctl_t *ioctlp;
+
+	bd = bdevsw[major(dev)];
+	ioctlp = bd->d_ioctl;
+	if (ioctlp == NULL)
+		return 0;
+
+	if (ioctlp(dev, CDIOREADTOCHEADER, (caddr_t)&h, FREAD, p) == -1)
+		return 0;
+
+	for (i = h.ending_track; i >= 0; i--) {
+		t.address_format = CD_LBA_FORMAT;
+		t.track = i;
+		if (ioctlp(dev, CDIOREADTOCENTRY, (caddr_t)&t, FREAD, p) == -1)
+			return 0;
+		if ((t.entry.control & 4) != 0)
+			/* found a data track */
+			break;
+	}
+
+	if (i < 0)
+		return 0;
+
+	return ntohl(t.entry.addr.lba);
+}
+
 int
-cd9660_mountroot()
+cd9660_mountroot(dummy)
+	void *dummy;
 {
 	register struct mount *mp;
 	struct proc *p = curproc;	/* XXX */
@@ -120,6 +166,10 @@
 	mp->mnt_op = &cd9660_vfsops;
 	mp->mnt_flag = MNT_RDONLY;
 	args.flags = ISOFSMNT_ROOT;
+	args.ssector = iso_get_ssector(rootdev, p);
+	if (bootverbose)
+		printf("cd9660_mountroot(): using session at block %d\n",
+		       args.ssector);
 	if ((error = iso_mountfs(rootvp, mp, p, &args))) {
 		free(mp, M_MOUNT);
 		return (error);
@@ -276,7 +326,9 @@
 	 */
 	iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
 
-	for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
+	for (iso_blknum = 16 + argp->ssector;
+	     iso_blknum < 100 + argp->ssector;
+	     iso_blknum++) {
 		if ((error = bread (devvp, btodb(iso_blknum * iso_bsize),
 				    iso_bsize, NOCRED, &bp)))
 			goto out;
@@ -332,6 +384,15 @@
 		isonum_733 (high_sierra?
 			    pri_sierra->volume_space_size:
 			    pri->volume_space_size);
+	/*
+	 * Since an ISO9660 multi-session CD can also access previous
+	 * sessions, we have to include them into the space consider-
+	 * ations.  This doesn't yield a very accurate number since
+	 * parts of the old sessions might be inaccessible now, but we
+	 * can't do much better.  This is also important for the NFS
+	 * filehandle validation.
+	 */
+	isomp->volume_space_size += argp->ssector;
 	bcopy (rootp, isomp->root, sizeof isomp->root);
 	isomp->root_extent = isonum_733 (rootp->extent);
 	isomp->root_size = isonum_733 (rootp->size);
Index: isofs/cd9660/cd9660_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_vnops.c,v
retrieving revision 1.27
diff -u -r1.27 cd9660_vnops.c
--- cd9660_vnops.c	1996/10/20 21:01:43	1.27
+++ cd9660_vnops.c	1997/05/26 14:06:36
@@ -39,6 +39,8 @@
  * $Id: cd9660_vnops.c,v 1.27 1996/10/20 21:01:43 alex Exp $
  */
 
+#define CD9660 1  /* bogus dependency in sys/mount.h */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/namei.h>
Index: isofs/cd9660/iso.h
===================================================================
RCS file: /home/ncvs/src/sys/isofs/cd9660/iso.h,v
retrieving revision 1.9.4.1
diff -u -r1.9.4.1 iso.h
--- iso.h	1997/05/07 13:23:42	1.9.4.1
+++ iso.h	1997/05/23 14:06:14
@@ -223,7 +223,7 @@
 int iso_iput __P((struct iso_node *ip));
 int iso_ilock __P((struct iso_node *ip));
 int iso_iunlock __P((struct iso_node *ip));
-int cd9660_mountroot __P((void));
+int cd9660_mountroot __P((void *dummy));
 
 extern vop_t **cd9660_vnodeop_p;
 
Bye,
	Udo

-- 
Udo Wolter, email: uwp@cs.tu-berlin.de
!!! LOW-TECH Page: http://LOW-TECH.home.ml.org !!!



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