summaryrefslogtreecommitdiffstats
path: root/sbin/mount_cd9660/mount_cd9660.c
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1997-04-29 15:56:40 +0000
committerjoerg <joerg@FreeBSD.org>1997-04-29 15:56:40 +0000
commitaae566870b75a1750d60935043266ae63691a1b4 (patch)
tree3cecdd2daa4a6dc3d33bd1dcb2edb0cbbe5dba7a /sbin/mount_cd9660/mount_cd9660.c
parent57e93106aa9f89b04e44d5b1042cfae84541c5d2 (diff)
downloadFreeBSD-src-aae566870b75a1750d60935043266ae63691a1b4.zip
FreeBSD-src-aae566870b75a1750d60935043266ae63691a1b4.tar.gz
Userland part of ISO9660 multi-session support. mount_cd9660(8) will
now by default mount the last data track (thus last session), as opposed to the very first session it has been mounting previously. This is consistent with the ISO9660 multi-session idea, and the way other operating systems are working. There's support to mount arbitrary sessions using the -s option. This way, you can simulate multi-session CDs on something like vn devices that don't support CDIO* ioctl commands. You can also force the historic behaviour with mount -t cd9660 -o -s=0 /dev/cd0a /cdrom
Diffstat (limited to 'sbin/mount_cd9660/mount_cd9660.c')
-rw-r--r--sbin/mount_cd9660/mount_cd9660.c91
1 files changed, 81 insertions, 10 deletions
diff --git a/sbin/mount_cd9660/mount_cd9660.c b/sbin/mount_cd9660/mount_cd9660.c
index 23ccd0e..a5b0cc0 100644
--- a/sbin/mount_cd9660/mount_cd9660.c
+++ b/sbin/mount_cd9660/mount_cd9660.c
@@ -49,9 +49,11 @@ static char copyright[] =
static char sccsid[] = "@(#)mount_cd9660.c 8.7 (Berkeley) 5/1/95";
*/
static const char rcsid[] =
- "$Id: mount_cd9660.c,v 1.10 1997/03/11 12:29:02 peter Exp $";
+ "$Id: mount_cd9660.c,v 1.11 1997/03/29 03:32:35 imp 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 @@ struct mntopt mopts[] = {
{ 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 @@ main(argc, argv)
case 'r':
opts |= ISOFSMNT_NORRIP;
break;
+ case 's':
+ args.ssector = atoi(optarg);
+ break;
+ case 'v':
+ verbose++;
+ break;
case '?':
default:
usage();
@@ -125,6 +134,26 @@ main(argc, argv)
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 @@ main(argc, argv)
}
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);
+}
OpenPOWER on IntegriCloud