From owner-freebsd-questions Mon Aug 25 01:33:02 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id BAA28672 for questions-outgoing; Mon, 25 Aug 1997 01:33:02 -0700 (PDT) Received: from gatekeeper.ukrv.de (gatekeeper.ukrv.de [193.175.72.2]) by hub.freebsd.org (8.8.7/8.8.7) with SMTP id BAA28662 for ; Mon, 25 Aug 1997 01:32:49 -0700 (PDT) Received: by gatekeeper.ukrv.de; (5.65/1.1.8.2/17Oct95-0336PM) id AA21880; Mon, 25 Aug 1997 10:32:46 +0200 Received: from mailhost(193.175.66.33) by gatekeeper.ukrv.de via smap (V1.3-JSC) id sma012684; Mon Aug 25 10:32:37 1997 Received: from merlin.ukrv.de by mailhost.ukrv.de; (5.65/1.1.8.2/08Mar95-0213PM) id AA23728; Mon, 25 Aug 1997 10:32:37 +0200 Received: by merlin.ukrv.de (4.1/UKRV-Gen PCG 0.1) id AA16459; Mon, 25 Aug 97 10:32:37 +0200 From: Udo Wolter Message-Id: <9708250832.AA16459@merlin.ukrv.de> Subject: Re: Multi-session CD-ROM In-Reply-To: from Zoltan Sebestyen at "Aug 22, 97 11:30:42 am" To: sebesty@cs.elte.hu (Zoltan Sebestyen) Date: Mon, 25 Aug 1997 10:32:36 +0200 (MET DST) Cc: freebsd-questions@FreeBSD.ORG X-Mailer: ELM [version 2.4ME+ PL31 (25)] Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by hub.freebsd.org id BAA28666 Sender: owner-freebsd-questions@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk 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 +#include #include #include #include @@ -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 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 #include #include 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 #include #include 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 #include #include 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 #include #include 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 #include #include 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 #include #include @@ -48,6 +50,8 @@ #include #include #include +#include +#include #include #include #include @@ -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 #include #include 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 !!!