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>
