NetBSD Problem Report #48808

From www@NetBSD.org  Wed May 14 08:32:06 2014
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	(using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 4B424A5813
	for <gnats-bugs@gnats.NetBSD.org>; Wed, 14 May 2014 08:32:06 +0000 (UTC)
Message-Id: <20140514083202.54F2BA5856@mollari.NetBSD.org>
Date: Wed, 14 May 2014 08:32:01 +0000 (UTC)
From: scdbackup@gmx.net
Reply-To: scdbackup@gmx.net
To: gnats-bugs@NetBSD.org
Subject: Enhance mount_cd9660 by option -s like in other BSDs
X-Send-Pr-Version: www-1.0

>Number:         48808
>Category:       kern
>Synopsis:       Enhance mount_cd9660 by option -s like in other BSDs
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed May 14 08:35:00 +0000 2014
>Last-Modified:  Sun Jun 01 15:05:01 +0000 2014
>Originator:     Thomas Schmitt
>Release:        6.99.40 as of early may 2014, with kern/48787
>Organization:
>Environment:
NetBSD netbsd 6.99.40 NetBSD 6.99.40 (GENERIC) #65: Tue May 13 20:39:35 UTC 2014  thomas@netbsd:/usr/obj/sys/arch/i386/compile/GENERIC i386
>Description:
I have running on my modified 6.99.40 kernel a /sbin/mount_cd9660
which knows option -s to address an ISO 9660 superblock other than
the ones pointed to by /dev/cd0a or /dev/cd0d.

struct iso_args as of /usr/include/isofs/cd9660/mount_cd9660.h
has been enhanced with special care to maintain API and ABI
compatibility for older userland and kernels.

My addition to man 8 mount_cd9660 says: 

[ The options are as follows:]
[...]
[ -o  Options are specified with a -o flag followed by a comma]
     [...]
     ssector
             Is ignored as input option but reported by getargs if
             option -s is in effect.

 -s block_offset
     Read the superblock from a block address, which is computed by
     adding block_offset to the partition offset implied by the choice
     of the device file.  With /dev/cdXd this partition offset is 0,
     which leads to the first and oldest ISO-9660 session on the
     medium.  /dev/cdXa has the offset of the last and youngest
     recognized medium partition.  Other sessions may be reached from
     /dev/cdXd by -s with a block_offset which can be obtained from
     burn software for optical media.  The block size is 2048 bytes.

     /dev/cdX partitions are recognized from logical tracks of
     unformatted optical media.  Formatted media appear as a single
     partition. Nevertheless they may bear several ISO-9660 sessions.
     Refer to their ISO-9660 producer for offset info.

Compatibility between old/new kernel and new/old userland:

/sbin/mount_cd9660 will not offer option -s if not ISOFSMNT_SSECTOR
was defined in /usr/include/isofs/cd9660/cd9660_mount.h at compile
time.
Such a binary will react on -s like the current /sbin/mount_cd9660:

  netbsd# mount_cd9660 -s 8768 /dev/cd0d /mnt/iso
  mount_cd9660: unknown option -- s
  usage: mount_cd9660 [-o options] special node

If -s is enabled and gets used with a non-zero value, then
mount_cd9660 will check after successful mounting, whether the kernel
seems to have expected the old struct iso_args and thus must have
ignored ISOFSMNT_SSECTOR and iso_args.ssector.
It will then unmount(2) the freshly but wrongly mounted ISO.

On a kernel with old struct iso_args this yields

  netbsd# mount_cd9660 -s 8768 /dev/cd0d /mnt/iso
  mount_cd9660 : Kernel ignored option -s.
  mount_cd9660 : Had to revoke mount attempt with option -s
  netbsd# mount | grep cd0d
  netbsd#

  netbsd# mount_cd9660 /dev/cd0d /mnt/iso
  netbsd# mount | grep cd0d
  /dev/cd0d on /mnt/iso type cd9660 (read-only, local)

On a kernel with new struct iso_args, both are supposed to work

  netbsd# mount_cd9660 -s 8768 /dev/cd0d /mnt/iso
  netbsd# mount | grep cd0d
  /dev/cd0d on /mnt/iso type cd9660 (read-only, local)

The inquiry by MNT_GETARGS will report non-zero -s values

  netbsd# mount_cd9660 -o getargs /dev/cd0d /mnt/iso
  0x40<ssector>
  -s 8768

Old mount_9660 on a new kernel works (without -s, of course).

Some background about the number used:

Session start block numbers for the ISO filesystem are learned from

  netbsd$ xorriso -indev /dev/rcd0d -toc
  ...
  TOC layout   : Idx ,  sbsector ,       Size , Volume Id
  ISO session  :   1 ,        32 ,        24s , ISOIMAGE
  ISO session  :   2 ,        64 ,      8695s , ISOIMAGE
  ISO session  :   3 ,      8768 ,      7936s , ISOIMAGE
  ISO session  :   4 ,     16704 ,   2097240s , ISOIMAGE
  ISO session  :   5 ,   2113952 ,      7883s , ISOIMAGE

The numbers underneath "sbsector" are valid parameters for -s.

cd0d and cd0a both are session 5, pointed to by the default
superblock at offset 0. (The other superblocks form a chain
by starting at the next 32-blocks-aligned address after the
previous image end.)

Above -toc is from a virtual CD-ROM drive, behaving like a DVD+RW
(i.e. formatted medium) in a read-only drive. Real multi-session media,
e.g. BD-R have their first session at block 0, and there would be a
difference between cd0a and cd0d:
  ISO session  :   1 ,         0 ,   1452463s , HOME_2014_04_20_120026
  ISO session  :   2 ,   1452640 ,     37251s , HOME_2014_04_21_123352
  ...
  ISO session  :  23 ,   2508608 ,     54916s , HOME_2014_05_12_115406
  ISO session  :  24 ,   2563680 ,     54686s , HOME_2014_05_13_111159
cd0d is then session 1. cd0a is (supposed to be) session 24.

The sessions inbetween are now reachable by -s.
They then provide daily snapshots of $HOME from my real computer.
I hope to use this BD-R for another half year of backups.
Somehwere between session 200 and 300 it will go on strike 
if it is not full before. All snapshots will still be readable
then, only writing will not work any more.

Important notice for all reviewers:

The kernel patch proposal contains the termination of publishing
all cd9660 header files, except
  /usr/include/isofs/cd9660/mount_cd9660.h
which is public for usage with mount(2).

A discussion on tech-kern did not yield objections up to now. See
  http://mail-index.netbsd.org/tech-kern/2014/05/13/msg017048.html
and follow-ups.
The public exposure of the then private headers makes it nearly
impossible to augment the implementation without disturbing
potential undue includers.
I hope there are none, or that they show up and start discussing.

>How-To-Repeat:
Test ISO image is once again

    http://scdbackup.webframe.org/large.iso.bz2

4470 bytes, MD5 7d78dc3efaec8ea3f1801335329f410d.
It inflates to 4,329,897,984 bytes.

Do this only if the fix of kern/48787 is applied.
If not, you will not get rid of the /mnt/iso mount point until reboot !

It bears two sessions. Number 2 is mounted by default:
  TOC layout   : Idx ,  sbsector ,       Size , Volume Id
  ISO session  :   1 ,        32 ,   2113977s , ISOIMAGE
  ISO session  :   2 ,   2114016 ,        25s , ISOIMAGE

If the ISO is submitted as /dev/cd0, do:

  mount_cd9660 -s 32 /dev/cd0d /mnt/iso
  ls -l /mnt/iso

which should show only one file in the ISO root (containing a
large file which triggers an interesting bug):

  drwxr-xr-x  1 thomas  dbus  2048 May  6 15:30 my

Now for session 2 which is default:

  umount /mnt/iso
  mount_cd9660 /dev/cd0d /mnt/iso
  ls -l /mnt/iso

should show two files in the ISO root:

  drwxr-xr-x  1 thomas  dbus  2048 May  6 15:30 my
  -rw-r--r--  1 thomas  dbus     6 May  6 15:34 small_file

(Actually user id 1000, group id 1000)

>Fix:
I will propose three patches.
One for sys/fs/cd9660, one for sbin/mount_cd9660, and one for
/usr/src/distrib/sets/lists/comp/mi, where the now private header
files are currently listed as "comp-c-include".

The kernel patch proposal still contains open questions, marked by "XXX":

- There is a very peculiar "partition" semantic with /dev/cd*.
  The position of the superblock is taken from a partition offset.
  cd9660_vfsops.c:
        sess = label.d_partitions[DISKPART(dev)].p_cdsession;
  Nevertheless the block addressing is done relative to the base device
  /dev/cdXd. This is indeed appropriate for ISO 9660 multi-session, but
  hardly for partitions.

  I still have to explore the effect of above code line with partitioned
  hard disk media. Does .p_cdsession show non-zero values there ?
  Do the bread() operations work relative to the partition start ?

- I allocate a struct iso_args as local variable on the stack.
  Size is 120 bytes on i386. Is there a rigid stack dscipline which
  would demand malloc() and free() for larger objects ?

- The old kernels silently ignore my new flags bit ISOFSMNT_SSECTOR.
  This makes necessary in sbin/mount_cd9660 a cumbersome check after
  mount(2) and eventually revocation of the misdirected mount by
  unmount(2).
  I would like to avoid this with future changes.
  Therefore i want to throw EINVAL on unknown flags bits.
  Martin Husemann stated to me, that struct iso_arg is supposed
  to be submitted properly zeroized in all unused bits and bytes.

- I see flags bit ISOFSMNT_NOCASETRANS missing in the statement which
  memorizes the options for inquiry by mount(2) MNT_GETARGS.
  Can this be intentional ? Why ?

None of these is essential for the desired mount feature.
But they need to be decided for getting a neat patch.

>Audit-Trail:
From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@NetBSD.org
Cc: kern-bug-people@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org
Subject: Re: kern/48808: Enhance mount_cd9660 by option -s like in other BSDs
Date: Wed, 14 May 2014 10:45:52 +0200

 On Wed, May 14, 2014 at 08:35:00AM +0000, scdbackup@gmx.net wrote:
 > If -s is enabled and gets used with a non-zero value, then
 > mount_cd9660 will check after successful mounting, whether the kernel
 > seems to have expected the old struct iso_args and thus must have
 > ignored ISOFSMNT_SSECTOR and iso_args.ssector.
 > It will then unmount(2) the freshly but wrongly mounted ISO.

 Forward binary compat like this is not needed - a new mount_cd9660 binary
 can expect a new kernel always.

 Martin

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Wed, 14 May 2014 10:58:22 +0200

 --- sys/fs/cd9660/Makefile.orig	2002-12-23 17:52:08.000000000 +0000
 +++ sys/fs/cd9660/Makefile	2014-05-13 21:41:50.000000000 +0000
 @@ -2,7 +2,6 @@

  INCSDIR= /usr/include/isofs/cd9660

 -INCS=	cd9660_extern.h cd9660_mount.h cd9660_node.h cd9660_rrip.h iso.h \
 -	iso_rrip.h
 +INCS=	cd9660_mount.h

  .include <bsd.kinc.mk>
 --- sys/fs/cd9660/cd9660_extern.h.orig	2013-06-23 07:28:36.000000000 +0000
 +++ sys/fs/cd9660/cd9660_extern.h	2014-05-13 21:18:11.000000000 +0000
 @@ -72,15 +72,17 @@ struct iso_mnt {
  	int im_bshift;
  	int im_bmask;

 -	int volume_space_size;
 +	uint32_t volume_space_size;

  	char root[ISODCL (157, 190)];
 -	int root_extent;
 -	int root_size;
 +	uint32_t root_extent;
 +	uint32_t root_size;
  	enum ISO_FTYPE  iso_ftype;

  	int rr_skip;
  	int rr_skip0;
 +
 +	uint32_t im_ssector;
  };

  #define VFSTOISOFS(mp)	((struct iso_mnt *)((mp)->mnt_data))
 --- sys/fs/cd9660/cd9660_mount.h.orig	2005-12-03 17:34:43.000000000 +0000
 +++ sys/fs/cd9660/cd9660_mount.h	2014-05-13 20:38:41.000000000 +0000
 @@ -38,6 +38,8 @@
  #ifndef _ISOFS_CD9660_CD9660_MOUNT_H_
  #define _ISOFS_CD9660_CD9660_MOUNT_H_

 +#include <sys/types.h>
 +
  /*
   * Arguments to mount ISO 9660 filesystems.
   */
 @@ -45,6 +47,18 @@ struct iso_args {
  	const char	*fspec;		/* block special device to mount */
  	struct	export_args30 _pad1; /* compat with old userland tools */
  	int	flags;			/* mounting flags, see below */
 +	uint32_t ssector;		/* start sector of session (relative to
 +					 * the partition offset of fspec),
 +					 * if flags & ISOFSMNT_SSECTOR 
 +					 */
 +	/* XXX
 +	 * Up to now the effect of ssector could be tested only with devices
 +	 * which have partition offset 0. Like /dev/cd0d (or cd0a on CD-ROM).
 +	 * It is supposed to get added to the partition offset of fspec. 
 +	 * XXX ???
 +	 * Would completely overriding the partition offset work at all ?
 +	 * Are there cases with no device file with offset 0 ?
 +	 */
  };
  #define	ISOFSMNT_NORRIP		0x00000001 /* disable Rock Ridge Ext.*/
  #define	ISOFSMNT_GENS		0x00000002 /* enable generation numbers */
 @@ -52,8 +66,32 @@ struct iso_args {
  #define	ISOFSMNT_NOJOLIET	0x00000008 /* disable Joliet extensions */
  #define	ISOFSMNT_NOCASETRANS	0x00000010 /* do not make names lower case */
  #define	ISOFSMNT_RRCASEINS	0x00000020 /* case insensitive Rock Ridge */
 +#define	ISOFSMNT_SSECTOR  	0x00000040 /* add ssector to the partition
 +					    * offset of fspec
 +					    */

  #define ISOFSMNT_BITS "\177\20" \
      "b\00norrip\0b\01gens\0b\02extatt\0b\03nojoliet\0" \
 -    "b\04nocasetrans\0b\05rrcaseins\0"
 +    "b\04nocasetrans\0b\05rrcaseins\0b\06ssector\0"
 +
 +
 +/* Compatibility precaution:
 + *
 + * struct old_iso_args_v_1_6 is the definition of struct iso_args before
 + * may 2014. Such structs are still accepted by mount(2) and will be defaulted
 + * to (flags & ~ISOFSMNT_SSECTOR).
 + *
 + * The old struct is exposed here to serve as size benchmark for the reply
 + * of mount(2) with ISOFSMNT_SSECTOR. If after successful mount(2), the inquiry
 + * by MNT_GETARGS yields sizeof(struct old_iso_args_v_1_6) then the
 + * kernel was built with the old struct iso_args. In this case it silently
 + * ignored ISOFSMNT_SSECTOR and iso_args.ssector.
 + * This test can be done only after mounting, because else -1 gets returned.
 + */
 +struct old_iso_args_v_1_6 {
 +	const char		*fspec;
 +	struct export_args30	_pad1;
 +	int			flags;
 +};
 +
  #endif /* _ISOFS_CD9660_CD9660_MOUNT_H_ */
 --- sys/fs/cd9660/cd9660_vfsops.c.patch_006	2014-05-11 10:02:49.000000000 +0000
 +++ sys/fs/cd9660/cd9660_vfsops.c	2014-05-13 20:39:31.000000000 +0000
 @@ -216,20 +216,47 @@ cd9660_mount(struct mount *mp, const cha
  	int error;
  	struct iso_mnt *imp = VFSTOISOFS(mp);

 +	/* XXX do i have to malloc this memory and free it on exit ? */
 +	struct iso_args defaulted_iso_args;
 +
  	if (args == NULL)
  		return EINVAL;
 -	if (*data_len < sizeof *args)
 -		return EINVAL;
 +	if (*data_len < sizeof *args) {
 +		if (*data_len < sizeof (struct old_iso_args_v_1_6))
 +			return EINVAL; /* Too small even for old iso_args */
 +		if (!(mp->mnt_flag & MNT_GETARGS)) {
 +			/* Upgrade old struct by defaults */
 +			args = &defaulted_iso_args;
 +			memset(args, 0, sizeof *args);
 +			memcpy(args, data, sizeof (struct old_iso_args_v_1_6));
 +			args->flags &= ~ISOFSMNT_SSECTOR;
 +			printf("cd9660_mount: Upgraded old struct iso_args\n");
 +		}
 +	}

  	if (mp->mnt_flag & MNT_GETARGS) {
  		if (imp == NULL)
  			return EIO;
  		args->fspec = NULL;
  		args->flags = imp->im_flags;
 -		*data_len = sizeof (*args);
 +		if (*data_len >= sizeof *args) {
 +			args->ssector = imp->im_ssector;
 +			*data_len = sizeof (*args);
 +		} else {
 +			*data_len = sizeof (struct old_iso_args_v_1_6);
 +		}
  		return 0;
  	}

 +	/* XXX Check for any unknown flags and eventually throw EINVAL ?
 +	 *     This would allow future extensions to fail on old kernels
 +	 *     rather than to be silently ignored, which causes the need
 +	 *     to verify their effectiveness.
 +	 *     See cd9660_mount.h: struct old_iso_args_v_1_6
 +	 *     (One cannot use *data_len as indicator for undue demands.
 +	 *      A newer iso_args may well express old fulfillable wishes.)
 +	 */
 +
  	if ((mp->mnt_flag & MNT_RDONLY) == 0)
  		return (EROFS);

 @@ -277,6 +304,11 @@ cd9660_mount(struct mount *mp, const cha
  		VOP_UNLOCK(devvp);
  		/* reference to devvp is donated through iso_mountfs */
  	} else {
 +		if ((imp->im_flags & ISOFSMNT_SSECTOR ? imp->im_ssector : 0) !=
 +		    (args->flags & ISOFSMNT_SSECTOR ? args->ssector : 0)) {
 +			error = EINVAL;		/* wish to change superblock */
 +			goto fail;
 +		}
  		if (devvp != imp->im_devvp &&
  		    devvp->v_rdev != imp->im_devvp->v_rdev) {
  			error = EINVAL;		/* needs translation */
 @@ -345,11 +377,11 @@ iso_mountfs(struct vnode *devvp, struct 
  	int error = EINVAL;
  	int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  	int iso_bsize;
 -	int iso_blknum;
 +	uint32_t iso_blknum;
  	int joliet_level;
  	struct iso_volume_descriptor *vdp;
  	struct iso_supplementary_descriptor *sup;
 -	int sess = 0;
 +	uint32_t sess = 0;
  	int ext_attr_length;
  	struct disklabel label;

 @@ -376,12 +408,15 @@ iso_mountfs(struct vnode *devvp, struct 
  		if (error)
  			sess = 0;	/* never mind */
  	}
 +	if (argp->flags & ISOFSMNT_SSECTOR)
 +		sess += argp->ssector;
  #ifdef ISO_DEBUG
  	printf("isofs: session offset (part %"PRId32") %d\n", DISKPART(dev), sess);
  #endif

  	for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
 -		if ((error = bread(devvp, (iso_blknum+sess) * btodb(iso_bsize),
 +		if ((error = bread(devvp, ((daddr_t) iso_blknum + sess)
 +							 * btodb(iso_bsize),
  				   iso_bsize, NOCRED, 0, &bp)) != 0)
  			goto out;

 @@ -434,6 +469,8 @@ iso_mountfs(struct vnode *devvp, struct 
  		goto out;
  	}

 +	if (argp->flags & ISOFSMNT_SSECTOR)
 +		isomp->im_ssector = argp->ssector;
  	isomp->volume_space_size += sess;

  	brelse(pribp, BC_AGE);
 @@ -478,8 +515,14 @@ iso_mountfs(struct vnode *devvp, struct 
  		brelse(bp, BC_AGE);
  		bp = NULL;
  	}
 +
 +	/* XXX Why is ISOFSMNT_NOCASETRANS missing here ?
 +	 *     Is it because man mount_cd9660 prefers "nomaplcase" whereas
 +	 *     the macro ISOFSMNT_BITS in cd9660_mount.h says "nocasetrans" ?
 +	 */
  	isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
 -		 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_RRCASEINS);
 +		 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_RRCASEINS |
 +		 ISOFSMNT_SSECTOR);

  	if (isomp->im_flags & ISOFSMNT_GENS)
  		isomp->iso_ftype = ISO_FTYPE_9660;

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Wed, 14 May 2014 11:04:44 +0200

 --- sbin/mount_cd9660/mount_cd9660.c.orig	2011-08-29 14:35:00.000000000 +0000
 +++ sbin/mount_cd9660/mount_cd9660.c	2014-05-13 19:09:42.000000000 +0000
 @@ -59,6 +59,7 @@ __RCSID("$NetBSD: mount_cd9660.c,v 1.32 
  #include <string.h>
  #include <unistd.h>
  #include <util.h>
 +#include <errno.h>

  #include <isofs/cd9660/cd9660_mount.h>

 @@ -79,6 +80,7 @@ static const struct mntopt mopts[] = {
  	{ "rrip", 1, ISOFSMNT_NORRIP, 1 },
  	{ "joliet", 1, ISOFSMNT_NOJOLIET, 1 },
  	{ "rrcaseins", 0, ISOFSMNT_RRCASEINS, 1 },
 +	{ "ssector", 0, 0, 1 }, /* not setable, only for info via getargs */
  	MOPT_NULL,
  };

 @@ -102,11 +104,15 @@ mount_cd9660_parseargs(int argc, char **
  	int ch, opts;
  	mntoptparse_t mp;
  	char *dev, *dir;
 +#ifdef ISOFSMNT_SSECTOR
 +	char *ep;
 +	long long int llnum;
 +#endif

  	memset(args, 0, sizeof(*args));
  	*mntflags = opts = 0;
  	optind = optreset = 1;
 -	while ((ch = getopt(argc, argv, "egijo:r")) != -1)
 +	while ((ch = getopt(argc, argv, "egijo:rs:")) != -1)
  		switch (ch) {
  		case 'e':
  			/* obsolete, retained for compatibility only, use
 @@ -134,6 +140,23 @@ mount_cd9660_parseargs(int argc, char **
  			 * -o norrip */
  			opts |= ISOFSMNT_NORRIP;
  			break;
 +		case 's':
 +#ifdef ISOFSMNT_SSECTOR
 +			/* learned from mount/fattr.c : a_num() */
 +			llnum = strtoll(optarg, &ep, 0);
 +			if (*ep || optarg == ep || llnum < 0 ||
 +			    llnum > (long long int) 0xffffff00) {
 +				(void)fprintf(stderr,
 +				    "%s : unusable parameter with option -s\n",
 +				    getprogname());
 +				usage();
 +			}
 +			args->ssector = llnum;
 +			opts |= ISOFSMNT_SSECTOR;
 +			break;
 +#else
 +			usage();
 +#endif
  		case '?':
  		default:
  			usage();
 @@ -161,6 +184,38 @@ mount_cd9660_parseargs(int argc, char **
  	args->flags = opts;
  }

 +#ifdef ISOFSMNT_SSECTOR
 +
 +/* Inquire after mount whether the running kernel knows iso_args.ssector.
 + * This cannot be done before mount(2), because then MNT_GETARGS will yield
 + * no result. Afterwards, the size of the MNT_GETARGS reply can tell.
 + */
 +static int
 +kernel_has_args_ssector(char *canon_dir)
 +{
 +	struct iso_args args;
 +	int mntflags = MNT_GETARGS, kernel_args_size;
 +
 +	kernel_args_size = mount(MOUNT_CD9660, canon_dir, mntflags,
 +				 &args, sizeof args);
 +	if (kernel_args_size == -1) {
 +		(void)fprintf(stderr,
 +			"%s : Error when inquiring success of option -s : %s\n",
 +			getprogname(),
 +			errno != 0 ? strerror(errno) : "unrecognizable error");
 +		return 0;
 +	}
 +	if (kernel_args_size < (int) (sizeof (struct old_iso_args_v_1_6) +
 +				      sizeof (unsigned long int))) {
 +		(void)fprintf(stderr, "%s : Kernel ignored option -s\n",
 +			      getprogname());
 +		return 0;
 +	}
 +	return (1);
 +}
 +
 +#endif /* ISOFSMNT_SSECTOR */
 +
  int
  mount_cd9660(int argc, char **argv)
  {
 @@ -177,6 +232,20 @@ mount_cd9660(int argc, char **argv)
  		char buf[2048];
  		(void)snprintb(buf, sizeof(buf), ISOFSMNT_BITS, args.flags);
  		printf("%s\n", buf);
 +
 +#ifdef ISOFSMNT_SSECTOR
 +
 +		if (args.flags & ISOFSMNT_SSECTOR)
 +			printf("-s %lu\n", args.ssector);
 +	} else if ((args.flags & ISOFSMNT_SSECTOR) && args.ssector > 0) {
 +		if (!kernel_has_args_ssector(canon_dir)) {
 +			if (unmount(canon_dir, 0) == 0)
 +				(void)fprintf(stderr,
 +			   "%s : Had to revoke mount attempt with option -s\n",
 +					getprogname());
 +			exit(1);
 +		}
 +#endif
  	}

  	exit(0);
 @@ -185,7 +254,13 @@ mount_cd9660(int argc, char **argv)
  static void
  usage(void)
  {
 +#ifdef ISOFSMNT_SSECTOR
 +	(void)fprintf(stderr,
 +		"usage: %s [-o options | -s block_offset] special node\n",
 +		getprogname());
 +#else
  	(void)fprintf(stderr,
  		"usage: %s [-o options] special node\n", getprogname());
 +#endif
  	exit(1);
  }
 --- sbin/mount_cd9660/mount_cd9660.8.orig	2009-01-03 22:56:23.000000000 +0000
 +++ sbin/mount_cd9660/mount_cd9660.8	2014-05-13 18:34:13.000000000 +0000
 @@ -57,7 +57,7 @@
  .\"
  .\"     @(#)mount_cd9660.8	8.3 (Berkeley) 3/27/94
  .\"
 -.Dd January 3, 2009
 +.Dd May, 12, 2014
  .Dt MOUNT_CD9660 8
  .Os
  .Sh NAME
 @@ -66,6 +66,7 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl o Ar options
 +.Op Fl s Ar block_offset
  .Ar special node
  .Sh DESCRIPTION
  The
 @@ -130,8 +131,35 @@ For compatibility with Solaris only.
  .It Cm rrcaseins
  Makes all lookups case-insensitive even for CD-ROMs with Rock-Ridge
  extensions (for Rock-Ridge, default is case-sensitive lookup).
 +.It Cm ssector
 +Is ignored as input option but reported by
 +.Cm getargs
 +if option
 +.Cm Fl s
 +is in effect.
  .El
  .El
 +.Bl -tag -width indent
 +.It Fl s Ar block_offset
 +Read the superblock from a block address, which is computed by adding
 +.Ar block_offset
 +to the partition offset implied by the choice of the device file.
 +With /dev/cdXd this partition offset is 0,
 +which leads to the first and oldest ISO-9660 session on the medium.
 +/dev/cdXa has the offset of the last and youngest recognized medium
 +partition.
 +Other sessions may be reached from /dev/cdXd by
 +.Fl s
 +with a
 +.Ar block_offset
 +which can be obtained from burn software for optical media.
 +The block size is 2048 bytes.
 +.Pp
 +/dev/cdX partitions are recognized from logical tracks of unformatted
 +optical media.
 +Formatted media appear as a single partition. Nevertheless they may bear
 +several ISO-9660 sessions. Refer to their ISO-9660 producer for offset info.
 +.El
  .Pp
  For compatibility with previous releases, following obsolete flags are
  still recognized:

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Wed, 14 May 2014 11:15:36 +0200

 --- distrib/sets/lists/comp/mi.orig	2014-04-25 00:24:39.000000000 +0000
 +++ distrib/sets/lists/comp/mi	2014-05-14 07:12:18.000000000 +0000
 @@ -2356,12 +2356,12 @@
  ./usr/include/isns.h				comp-c-include	
  ./usr/include/isns_defs.h			comp-c-include	
  ./usr/include/iso646.h				comp-c-include
 -./usr/include/isofs/cd9660/cd9660_extern.h	comp-c-include
 +./usr/include/isofs/cd9660/cd9660_extern.h	comp-obsolete		obsolete
  ./usr/include/isofs/cd9660/cd9660_mount.h	comp-c-include
 -./usr/include/isofs/cd9660/cd9660_node.h	comp-c-include
 -./usr/include/isofs/cd9660/cd9660_rrip.h	comp-c-include
 -./usr/include/isofs/cd9660/iso.h		comp-c-include
 -./usr/include/isofs/cd9660/iso_rrip.h		comp-c-include
 +./usr/include/isofs/cd9660/cd9660_node.h	comp-obsolete		obsolete
 +./usr/include/isofs/cd9660/cd9660_rrip.h	comp-obsolete		obsolete
 +./usr/include/isofs/cd9660/iso.h		comp-obsolete		obsolete
 +./usr/include/isofs/cd9660/iso_rrip.h		comp-obsolete		obsolete
  ./usr/include/kadm5/admin.h			comp-krb5-include	kerberos
  ./usr/include/kadm5/kadm5-private.h		comp-krb5-include	kerberos
  ./usr/include/kadm5/kadm5-protos.h		comp-krb5-include	kerberos

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Wed, 14 May 2014 11:26:40 +0200

 Martin Husemann:
 > Forward binary compat like this is not needed - a new mount_cd9660 binary
 > can expect a new kernel always.

 mount_cd9660(8) is not the exclusive caller of mount(2) with
 struct iso_args. So i felt obliged to provide a detection method
 in mount_cd9660.h (struct old_iso_args_v_1_6).

 I'm a userlander and not far from calling mount(2) in own software.
 It would be decisive for me to know whether my args.ssector was
 taken into respect.

 Next i (in my new role as kernel hacker) had to test whether this
 distinction works. This was most easy to do in mount_cd9660(8).

 We can tear down all ifdef ISOFSMNT_SSECTOR in mount_cd9660(8)
 if they are deemed too ugly.
 But they are of educational use for anybody who wants to learn
 about this revolution after 20 years of stability.

 Errata:
    * The old struct is exposed here to serve as size benchmark for the reply
  - * of mount(2) with ISOFSMNT_SSECTOR. If after successful mount(2), the inquiry
  + * of mount(2) with MNT_GETARGS. If after successful mount(2), the inquiry
    * by MNT_GETARGS yields sizeof(struct old_iso_args_v_1_6) then the

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Wed, 14 May 2014 18:17:03 +0200

 I can now answer the question about partitioned devices, which
 are not cd but rather wd (XXX in cd9660_mount.h):

 Mounting of /dev/wdX? is indeed handled by cd9660_vfsops.c
 differently than with /dev/cdX?.

 A hard disk partition is used with its own block addressing
 which starts by 0.
 A cd "partition" is used with the block addressing of the
 base device /dev/cdXd and a superblock offset given by the
 cd "partition" start.

 I will have to clarify the man page.
 Not easy to explain ... would this text be understandable ?
 ------------------------------------------------------------------
   -s block_offset
      Read the superblock from a block address, which is computed by
      adding block_offset to the default superblock offset implied by
      the choice of the device file.  The block size is 2048 bytes.

      Optical drives /dev/cd* with unformatted media are handled
      differently than other storage partitions.  /dev/cd?d points to
      the start of the first and oldest logical track on the loaded
      medium. /dev/cd?a points to the last and youngest logical track.
      Nevertheless all block addressing is done relative to /dev/cd?d.
      Only the default offset is taken from /dev/cd?a, if that one is
      used. This matches the needs of ISO-9660 multisession on
      unformatted optical media.

      Formatted optical media and other kinds of storage partitions
      show no such default superblock offsets. Nevertheless they may
      bear several ISO-9660 sessions. Usually the superblock at offset
      0 leads to the youngest session.

      Other ISO-9660 sessions can be mounted by help of option -s with
      a block_offset which can be obtained from burn software for
      optical media. Among the /dev/cd* devices, use /dev/cd?d for this
      purpose.
 ------------------------------------------------------------------

 I have to stress that this situation is not created by my new option.
 It just adds a user-defined offset to the mess described above.

 ------------------------------------------------------------------
 My experiment:
 ------------------------------------------------------------------
 (Thanks to https://www.netbsd.org/docs/guide/en/chap-rmmedia.html)

 disklabel wd1 reports about my virtual MBR-formatted USB stick:

   #        size    offset     fstype [fsize bsize cpg/sgs]
    d:  10485760         0     unused      0     0        # ...
    e:   1606437        63 Linux Ext2      0     0        # ...
    f:   8867880   1606500 Linux Ext2      0     0        # ...

 Permissions are set quite liberally
   brw-r--r--  1 root  operator  0, 11 Feb  7 18:01 /dev/wd1d
   brw-rw-rw-  1 root  operator  0, 12 Feb  4 17:37 /dev/wd1e
   brw-rw-rw-  1 root  operator  0, 13 Feb  4 17:37 /dev/wd1f

 I write an ISO image into partition 1

   xorriso -outdev stdio:/dev/wd1e \
           -blank as_needed \
           -map libisofs-1.3.6 /libisofs-1.3.6

 xorriso can load the result and report about its files.
 Inspection with a hex dumper shows that the ISO 9660 Primary
 Volume Descriptor indeed is stored 63 * 512 + 16 * 2048 bytes
 after start of /dev/wd1d. All as expected for a partition
 with start at 512-block 63.

 So if partition /dev/wd1e can be mounted, then not with block
 addresses relative to /dev/wd1d (as would be done with with
 /dev/cd0a and /dev/cd0d). The offset of 63 * 512 would disalign
 all block addresses of the ISO which counts 2048-blocks.

 Well, mounting works fine:
   mount_cd9660 /dev/wd1e /mnt/iso
   ls -l /mnt/iso
   find /mnt/iso | less

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Wed, 14 May 2014 19:51:21 +0200

 It seems clearer to document and more similar to the behavior
 of other operating systems, if -s overrides the offset of /dev/cd0a
 rather than adding to it.

 cd9660_vfsops.c:
           if (argp->flags & ISOFSMNT_SSECTOR)
 -                 sess += argp->ssector;
 +                 sess = argp->ssector;
   #ifdef ISO_DEBUG

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Thu, 15 May 2014 09:37:24 +0200

 I overhauled the man page description of the new option.

 The main problem is that several device models meet at this
 topic.

 There is NetBSD CD partitioning, which might surprise even
 experienced users, when they encounter it for the first time.
   http://www.netbsd.org/docs/guide/en/chap-rmmedia.html#multisession

 It reflects the device model of SCSI/MMC which distinguishes
 two large families of media capabilities:
 Sequential, which get shown partitioned by NetBSD.
 Overwritable, which get shown like a hard disk with a single partition.
 Both under the device name cd.
 These are not really media families, because DVD-RW and BD-R media
 can play on both fields.
 I may not even distinguish the families by "formatted" and
 "unformatted", because one of the three BD-R personalities is
 formatted and sequential at the same time.

 This has to be explained to a person who might assume the normal
 VFS device model of partitions and filesystems.

 Well, did i succeed with the following text ?
 --------------------------------------------------------------------
   -s block_offset
      Read the superblock from block address block_offset rather than
      from the default position implied by the choice of the device
      file.  The block size is 2048 bytes.

      Optical drives /dev/cd* with multi-session media are handled
      differently than other storage partitions.  /dev/cd?d points to
      the start of the first and oldest logical track on the loaded
      medium. /dev/cd?a points to the last and youngest logical track.
      Nevertheless all block addressing is done relative to /dev/cd?d.
      Only the default offset is taken from /dev/cd?a, if that one is
      used. This matches the needs of ISO-9660 multisession on such
      optical media.

      Optical media, which are formatted to support random read-write
      access, as well as other kinds of storage partitions show no such
      default superblock offsets.  Nevertheless they may bear several
      ISO-9660 sessions. The default superblock is at offset 0 and
      usually leads to the youngest session.

      Other ISO-9660 sessions can be mounted by help of option -s with
      a block_offset which can be obtained from burn software for
      optical media.
 ----------------------------------------------------------------------

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Thu, 15 May 2014 12:19:20 +0200

 Or maybe i should just point to mscdlabel(8), and give a modest
 hint why it is not able to do what mount_cd9660 -s can do:

 --------------------------------------------------------------------
   -s block_offset
      Read the superblock from block address block_offset rather than
      from the default position implied by the choice of the device
      file.  The block size is 2048 bytes.

      Command mscdlabel(8) may have connected some /dev/cd* files to
      logical tracks of an optical multi-session medium, giving the
      device files the matching superblock positions for the recognized
      ISO-9660 filesystems.  Such a default offset will be overridden
      by option -s so that all /dev/cd* will behave like /dev/cd*d.

      mscdlabel(8) has limitations with finding all ISO-9660 sessions
      which are accessible via a storage device. The burn software
      suite which produced the ISO-9660 filesystem should be able to
      tell all suitable block_offset values.
 --------------------------------------------------------------------

 Actually the limitations of mscdlabel(8) applies even to CD media:
 How to represent the about 40 sessions which i could squeeze on a
 CD-R ? (Despite the wasted MBs between CD sessions.)
 How to represent a DVD+R with up to 150 sessions or a multi-session
 BD-R with up to 300 sessions ?

 Nevertheless, mscdlabel(8) could become a tool which tells block_offset
 values for mount_cd9660 -s. I will have a look at it ... later.

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Fri, 16 May 2014 08:31:24 +0200

 I finished my tests of the new mount_c9660 without finding
 problems, which were not present before.

 The test with mount(2) option MNT_UPDATE works insofar that the
 kernel refuses on the request to change the superblock offset
 (as i told it to do).

 But the usefulness of MNT_UPDATE resp -o update with the current
 implementation is questionable, because it seems to do nothing.
 A change from default rrip,joliet,maplcase by
   mount_cd9660 -o norrip,nojoliet,nomaplcase /dev/cd0a /mnt/iso
 would make sense.
 Among other things it would change
   -rw-r--r--  1 thomas  dbus  4294965248 Jun 23  2012 powerpc.img
   -rw-r--r--  1 thomas  dbus  4294965248 Jun 23  2012 powerpc.img
 to
   -r-xr-xr-x  1 root  wheel  2048 Jun 23  2012 POWERPC.IMG
 which is at least educational. (.. and would allow to concatenate
 the true 4 GiB file from both faulty representations. :))

 The implementation seems tricky, because parts of iso_mountfs()
 would have to be performed to verify the validity of the new
 options. Also i am uncertain about the impact on existing iso_node
 objects if mount flags get changed.

 UDF simply throws EOPNOTSUPP on MNT_UPDATE. But it also does it
 on udf_mountroot() which serves as struct vfsops.vfs_mountroot().

From: Julian Coleman <jdc@coris.org.uk>
To: gnats-bugs@NetBSD.org, scdbackup@gmx.net
Cc: 
Subject: Re: kern/48808: Enhance mount_cd9660 by option -s like in other BSDs
Date: Fri, 16 May 2014 10:36:17 +0100

 Hi,

 >  -s block_offset
 >      of the device file.  With /dev/cdXd this partition offset is 0,

 A couple of notes:

   cdXd is only the raw partition on some ports, it will be cdXc on others
   (e.g. see the BUGS section of disklabel(8)), so that should be noted
   somewhere - I don't think that we have a good way of doing that though.

   how likely are we to crash if the block_offset isn't a superblock?

 Thanks,

 J

 -- 
    NetBSD: simple; works; documented    /        Sailing at Newbiggin
         http://www.netbsd.org/        /   http://www.newbigginsailingclub.org/

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Fri, 16 May 2014 12:52:56 +0200

 Hi,

 > cdXd is only the raw partition on some ports, it will be cdXc on others
 > (e.g. see the BUGS section of disklabel(8)), so that should be noted
 > somewhere - I don't think that we have a good way of doing that though.

 It's indeed mentionen in man 8 mscdlabel:
     "The raw partition (typically partition c, but d on i386 and some other
      platforms) is left alone during this process."

 I change the man page proposal of mount_cd9660:

   Such a default offset will be overridden by option
   .Fl s
 - so that all /dev/cd* will behave like /dev/cd*d.
 + so that all /dev/cd* will behave like the raw partition device /dev/cd*d
 + resp. /dev/cd*c.
   .Pp
   .Xr mscdlabel 8


 > how likely are we to crash if the block_offset isn't a superblock?

 To my estimation not more than with a user applying
   mount -t 9660
 to a not suitable device rep. medium.

 I tried unsuitable offsets already (sorry for not reporting):

   netbsd# mount_cd9660 -s 12345 /dev/cd0a /mnt/iso
   mount_cd9660: /dev/cd0a on /mnt/iso: Invalid argument

 With unsuitable medium content i get the same

   netbsd# mount_cd9660  /dev/wd1f /mnt/iso
   mount_cd9660: /dev/wd1f on /mnt/iso: Invalid argument

 Existing precautions in cd9660:

 In sys/fs/cd9660/cd9660_vfsops.c the loop
         for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
 is searching for ISO 9660 Volume Descriptors.
 If it does not find one, then it throws the error
         if (pribp == NULL) {
                 error = EINVAL;
                 goto out;
         }

 The loop ends on the first block that does not look like
 a ISO 9660 volume descriptor.
                 if (memcmp(vdp->id, ISO_STANDARD_ID, sizeof(vdp->id)) != 0) {

 It could be made a notch sharper by demanding a Primary Volume
 Descriptor (case ISO_VD_PRIMARY:) in the first block that is
 examined by the loop.
 (The macros are defined in iso.h and match my knowledge about
  ISO 9660.)

From: Julian Coleman <jdc@coris.org.uk>
To: gnats-bugs@NetBSD.org, Thomas Schmitt <scdbackup@gmx.net>
Cc: 
Subject: Re: kern/48808
Date: Fri, 16 May 2014 12:38:46 +0100

 Hi,

 >  I change the man page proposal of mount_cd9660:

 That looks good to me.

 >  To my estimation not more than with a user applying
 >    mount -t 9660
 >  to a not suitable device rep. medium.

 Thanks for the details.  This sounds fine (and we also have rump_cd9660
 available for really untrusted media).

 Thanks,

 J

 -- 
    NetBSD: simple; works; documented    /        Sailing at Newbiggin
         http://www.netbsd.org/        /   http://www.newbigginsailingclub.org/

From: matthew green <mrg@eterna.com.au>
To: gnats-bugs@NetBSD.org
Cc: kern-bug-people@netbsd.org, gnats-admin@netbsd.org,
    netbsd-bugs@netbsd.org, scdbackup@gmx.net
Subject: re: kern/48808
Date: Sat, 17 May 2014 04:22:16 +1000

 some minor mdoc issues below.  thanks.

 >  It's indeed mentionen in man 8 mscdlabel:
 >      "The raw partition (typically partition c, but d on i386 and some other
 >       platforms) is left alone during this process."
 >  
 >  I change the man page proposal of mount_cd9660:
 >  
 >    Such a default offset will be overridden by option
 >    .Fl s
 >  - so that all /dev/cd* will behave like /dev/cd*d.
 >  + so that all /dev/cd* will behave like the raw partition device /dev/cd*d
 >  + resp. /dev/cd*c.
 >    .Pp
 >    .Xr mscdlabel 8

 all pathnames should be written with ".Pa" macro.  also, i'd
 reference sysctl kern.rawpartition -- 'a' + that is the name
 you'll see in /dev.  ie, value '2' and '3' are common.  eg:

 	so that all
 	.Pa /dev/cd*
 	will behave like the raw partition device.
 	See
 	.Xr sysctl 7
 	kern.rawpartition value to determine the raw partition, usually 
 	.Pa /dev/cd0c
 	or
 	.Pa /dev/cd0d .


 .mrg.

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Fri, 16 May 2014 21:01:25 +0200

 Actually it does not matter which device is the raw partition.
 All cd partition devices will behave the same as soon as -s is
 present.

 A hint about sysctl kern.rawpartition would rather be appropriate
 for the man page of mscdlabel(8).

 So how about just not talking about "c", "d", "cd0", or "cd1" ?
 -----------------------------------------------------------------
   Such a default offset will be overridden by option
   .Fl s
 - so that all /dev/cd* will behave like the raw partition device /dev/cd*d
 - resp. /dev/cd*c.
 + so that all
 + .Pa /dev/cd*
 + will behave like raw partition devices.
   .Pp
   .Xr mscdlabel 8
 -----------------------------------------------------------------

 The explanation of "raw partition device" can be found by following
 the now many references to mscdlabel(8).

 In context this would state
 ----------------------------------------------------------------
      Command mscdlabel(8) may have connected some /dev/cd* files to
      logical tracks of an optical multi-session medium, giving the
      device files the matching superblock positions for the recognized
      ISO-9660 filesystems.  Such a default offset will be overridden
      by option -s so that all /dev/cd* will behave like raw partition
      devices.
 ----------------------------------------------------------------

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Sun, 18 May 2014 16:25:43 +0200

 I answered to myself the rest of the XXX questions.

 - Nobody objected adding 120 bytes on the stack. So it stays
   this way. No clean-up code against memory leaks is needed.

 - I will submit the proposal to reject unknown ISOFSMNT_* flags
   as a separate PR. The comment is still in my proposed change.

 - I leave the remarks about the non-operation of MNT_UPDATE
   for somebody who has more clue about how this is supposed to
   work. Currently and after my change, it silently does nothing.

 - I added ISOFSMNT_NOCASETRANS to the memorized mount flags in
   struct iso_mnt.im_flags.

 Further i adapted ISOFSMNT_BITS to the "new formatting style" example
 in man 9 snprintb. (It does not solve the ugly output "0x0>"
 of -o getargs on a default mount.)

 ------------------------------------------------------------------------

 To Martin Husemann:
 > Forward binary compat like this is not needed - a new mount_cd9660 binary
 > can expect a new kernel always.

 Shall i understand "is not needed" as "is not desirable" and remove
 the after-mount test in mount_cd9660(8) ?

 To other commenters:
 If you are not satisfied with my reactions, then please tell.

 ------------------------------------------------------------------------

 I will now send two refurbished change proposals for sys/fs/cd9660
 and sbin/mount_9660. I deem them ready for committer review.

 The patch proposal
   Date: Wed, 14 May 2014 11:15:36 +0200
 for
   distrib/sets/lists/comp/mi
 stays valid.

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Sun, 18 May 2014 16:31:30 +0200

 --- sys/fs/cd9660/Makefile.orig	2002-12-23 17:52:08.000000000 +0000
 +++ sys/fs/cd9660/Makefile	2014-05-13 21:41:50.000000000 +0000
 @@ -2,7 +2,6 @@

  INCSDIR= /usr/include/isofs/cd9660

 -INCS=	cd9660_extern.h cd9660_mount.h cd9660_node.h cd9660_rrip.h iso.h \
 -	iso_rrip.h
 +INCS=	cd9660_mount.h

  .include <bsd.kinc.mk>
 --- sys/fs/cd9660/cd9660_extern.h.orig	2013-06-23 07:28:36.000000000 +0000
 +++ sys/fs/cd9660/cd9660_extern.h	2014-05-13 21:18:11.000000000 +0000
 @@ -72,15 +72,17 @@ struct iso_mnt {
  	int im_bshift;
  	int im_bmask;

 -	int volume_space_size;
 +	uint32_t volume_space_size;

  	char root[ISODCL (157, 190)];
 -	int root_extent;
 -	int root_size;
 +	uint32_t root_extent;
 +	uint32_t root_size;
  	enum ISO_FTYPE  iso_ftype;

  	int rr_skip;
  	int rr_skip0;
 +
 +	uint32_t im_ssector;
  };

  #define VFSTOISOFS(mp)	((struct iso_mnt *)((mp)->mnt_data))
 --- sys/fs/cd9660/cd9660_mount.h.orig	2005-12-03 17:34:43.000000000 +0000
 +++ sys/fs/cd9660/cd9660_mount.h	2014-05-18 12:41:55.000000000 +0000
 @@ -38,6 +38,8 @@
  #ifndef _ISOFS_CD9660_CD9660_MOUNT_H_
  #define _ISOFS_CD9660_CD9660_MOUNT_H_

 +#include <sys/types.h>
 +
  /*
   * Arguments to mount ISO 9660 filesystems.
   */
 @@ -45,6 +47,9 @@ struct iso_args {
  	const char	*fspec;		/* block special device to mount */
  	struct	export_args30 _pad1; /* compat with old userland tools */
  	int	flags;			/* mounting flags, see below */
 +	uint32_t ssector;		/* start sector of session,
 +					 * if flags & ISOFSMNT_SSECTOR 
 +					 */
  };
  #define	ISOFSMNT_NORRIP		0x00000001 /* disable Rock Ridge Ext.*/
  #define	ISOFSMNT_GENS		0x00000002 /* enable generation numbers */
 @@ -52,8 +57,30 @@ struct iso_args {
  #define	ISOFSMNT_NOJOLIET	0x00000008 /* disable Joliet extensions */
  #define	ISOFSMNT_NOCASETRANS	0x00000010 /* do not make names lower case */
  #define	ISOFSMNT_RRCASEINS	0x00000020 /* case insensitive Rock Ridge */
 +#define	ISOFSMNT_SSECTOR  	0x00000040 /* use ssector as session start */

 -#define ISOFSMNT_BITS "\177\20" \
 +#define ISOFSMNT_BITS "\177\020" \
      "b\00norrip\0b\01gens\0b\02extatt\0b\03nojoliet\0" \
 -    "b\04nocasetrans\0b\05rrcaseins\0"
 +    "b\04nocasetrans\0b\05rrcaseins\0b\06ssector\0\0"
 +
 +
 +/* Compatibility precaution:
 + *
 + * struct old_iso_args_v_1_6 is the definition of struct iso_args before
 + * may 2014. Such structs are still accepted by mount(2) and will be defaulted
 + * to (flags & ~ISOFSMNT_SSECTOR).
 + *
 + * The old struct is exposed here to serve as size benchmark for the reply
 + * of mount(2) with MNT_GETARGS. If after successful mount(2), the inquiry
 + * by MNT_GETARGS yields sizeof(struct old_iso_args_v_1_6) then the
 + * kernel was built with the old struct iso_args. In this case it silently
 + * ignored ISOFSMNT_SSECTOR and iso_args.ssector.
 + * This test can be done only after mounting, because else -1 gets returned.
 + */
 +struct old_iso_args_v_1_6 {
 +	const char		*fspec;
 +	struct export_args30	_pad1;
 +	int			flags;
 +};
 +
  #endif /* _ISOFS_CD9660_CD9660_MOUNT_H_ */
 --- sys/fs/cd9660/cd9660_vfsops.c.patch_006	2014-05-11 10:02:49.000000000 +0000
 +++ sys/fs/cd9660/cd9660_vfsops.c	2014-05-18 12:42:37.000000000 +0000
 @@ -215,21 +215,45 @@ cd9660_mount(struct mount *mp, const cha
  	struct iso_args *args = data;
  	int error;
  	struct iso_mnt *imp = VFSTOISOFS(mp);
 +	struct iso_args defaulted_iso_args;

  	if (args == NULL)
  		return EINVAL;
 -	if (*data_len < sizeof *args)
 -		return EINVAL;
 -
 +	if (*data_len < sizeof *args) {
 +		if (*data_len < sizeof (struct old_iso_args_v_1_6))
 +			return EINVAL; /* Too small even for old iso_args */
 +		if (!(mp->mnt_flag & MNT_GETARGS)) {
 +			/* Upgrade old struct by defaults */
 +			args = &defaulted_iso_args;
 +			memset(args, 0, sizeof *args);
 +			memcpy(args, data, sizeof (struct old_iso_args_v_1_6));
 +			args->flags &= ~ISOFSMNT_SSECTOR;
 +			printf("cd9660_mount: Upgraded old struct iso_args\n");
 +		}
 +	}
  	if (mp->mnt_flag & MNT_GETARGS) {
  		if (imp == NULL)
  			return EIO;
  		args->fspec = NULL;
  		args->flags = imp->im_flags;
 -		*data_len = sizeof (*args);
 +		if (*data_len >= sizeof *args) {
 +			args->ssector = imp->im_ssector;
 +			*data_len = sizeof (*args);
 +		} else {
 +			*data_len = sizeof (struct old_iso_args_v_1_6);
 +		}
  		return 0;
  	}

 +	/* XXX Check for any unknown flags and eventually throw EINVAL ?
 +	 *     This would allow future extensions to fail on old kernels
 +	 *     rather than to be silently ignored, which causes the need
 +	 *     to verify their effectiveness.
 +	 *     See cd9660_mount.h: struct old_iso_args_v_1_6
 +	 *     (One cannot use *data_len as indicator for undue demands.
 +	 *      A newer iso_args may well express old fulfillable wishes.)
 +	 */
 +
  	if ((mp->mnt_flag & MNT_RDONLY) == 0)
  		return (EROFS);

 @@ -244,7 +268,6 @@ cd9660_mount(struct mount *mp, const cha
  				NSM_FOLLOW_NOEMULROOT, &devvp);
  	if (error != 0)
  		return (error);
 -
  	if (devvp->v_type != VBLK) {
  		vrele(devvp);
  		return ENOTBLK;
 @@ -277,11 +300,22 @@ cd9660_mount(struct mount *mp, const cha
  		VOP_UNLOCK(devvp);
  		/* reference to devvp is donated through iso_mountfs */
  	} else {
 +		if ((imp->im_flags & ISOFSMNT_SSECTOR ? imp->im_ssector : 0) !=
 +		    (args->flags & ISOFSMNT_SSECTOR ? args->ssector : 0)) {
 +			error = EINVAL;		/* wish to change superblock */
 +			goto fail;
 +		}
  		if (devvp != imp->im_devvp &&
  		    devvp->v_rdev != imp->im_devvp->v_rdev) {
  			error = EINVAL;		/* needs translation */
  			goto fail;
  		}
 +
 +		/* XXX Should not something be done here ?
 +		       norrip, nojoliet, nomaplcase, ... ?
 +		*/
 +		/* XXX UDF throws EOPNOTSUPP instead of silently ignoring */
 +
  		VOP_UNLOCK(devvp);
  		vrele(devvp);
  	}
 @@ -345,11 +379,11 @@ iso_mountfs(struct vnode *devvp, struct 
  	int error = EINVAL;
  	int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  	int iso_bsize;
 -	int iso_blknum;
 +	uint32_t iso_blknum;
  	int joliet_level;
  	struct iso_volume_descriptor *vdp;
  	struct iso_supplementary_descriptor *sup;
 -	int sess = 0;
 +	uint32_t sess = 0;
  	int ext_attr_length;
  	struct disklabel label;

 @@ -376,12 +410,15 @@ iso_mountfs(struct vnode *devvp, struct 
  		if (error)
  			sess = 0;	/* never mind */
  	}
 +	if (argp->flags & ISOFSMNT_SSECTOR)
 +		sess = argp->ssector;
  #ifdef ISO_DEBUG
  	printf("isofs: session offset (part %"PRId32") %d\n", DISKPART(dev), sess);
  #endif

  	for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
 -		if ((error = bread(devvp, (iso_blknum+sess) * btodb(iso_bsize),
 +		if ((error = bread(devvp, ((daddr_t) iso_blknum + sess)
 +							 * btodb(iso_bsize),
  				   iso_bsize, NOCRED, 0, &bp)) != 0)
  			goto out;

 @@ -434,6 +471,8 @@ iso_mountfs(struct vnode *devvp, struct 
  		goto out;
  	}

 +	if (argp->flags & ISOFSMNT_SSECTOR)
 +		isomp->im_ssector = argp->ssector;
  	isomp->volume_space_size += sess;

  	brelse(pribp, BC_AGE);
 @@ -479,7 +518,8 @@ iso_mountfs(struct vnode *devvp, struct 
  		bp = NULL;
  	}
  	isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
 -		 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_RRCASEINS);
 +		 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_NOCASETRANS |
 +		 ISOFSMNT_RRCASEINS | ISOFSMNT_SSECTOR);

  	if (isomp->im_flags & ISOFSMNT_GENS)
  		isomp->iso_ftype = ISO_FTYPE_9660;

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Sun, 18 May 2014 16:39:13 +0200

 --- sbin/mount_cd9660/mount_cd9660.c.orig	2011-08-29 14:35:00.000000000 +0000
 +++ sbin/mount_cd9660/mount_cd9660.c	2014-05-18 13:59:46.000000000 +0000
 @@ -59,6 +59,7 @@ __RCSID("$NetBSD: mount_cd9660.c,v 1.32 
  #include <string.h>
  #include <unistd.h>
  #include <util.h>
 +#include <errno.h>

  #include <isofs/cd9660/cd9660_mount.h>

 @@ -79,6 +80,7 @@ static const struct mntopt mopts[] = {
  	{ "rrip", 1, ISOFSMNT_NORRIP, 1 },
  	{ "joliet", 1, ISOFSMNT_NOJOLIET, 1 },
  	{ "rrcaseins", 0, ISOFSMNT_RRCASEINS, 1 },
 +	{ "ssector", 0, 0, 1 }, /* not setable, only for info via getargs */
  	MOPT_NULL,
  };

 @@ -102,11 +104,15 @@ mount_cd9660_parseargs(int argc, char **
  	int ch, opts;
  	mntoptparse_t mp;
  	char *dev, *dir;
 +#ifdef ISOFSMNT_SSECTOR
 +	char *ep;
 +	long long int llnum;
 +#endif

  	memset(args, 0, sizeof(*args));
  	*mntflags = opts = 0;
  	optind = optreset = 1;
 -	while ((ch = getopt(argc, argv, "egijo:r")) != -1)
 +	while ((ch = getopt(argc, argv, "egijo:rs:")) != -1)
  		switch (ch) {
  		case 'e':
  			/* obsolete, retained for compatibility only, use
 @@ -134,6 +140,23 @@ mount_cd9660_parseargs(int argc, char **
  			 * -o norrip */
  			opts |= ISOFSMNT_NORRIP;
  			break;
 +		case 's':
 +#ifdef ISOFSMNT_SSECTOR
 +			/* learned from mount/fattr.c : a_num() */
 +			llnum = strtoll(optarg, &ep, 0);
 +			if (*ep || optarg == ep || llnum < 0 ||
 +			    llnum > (long long int) 0xffffff00) {
 +				(void)fprintf(stderr,
 +				    "%s : unusable parameter with option -s\n",
 +				    getprogname());
 +				usage();
 +			}
 +			args->ssector = llnum;
 +			opts |= ISOFSMNT_SSECTOR;
 +			break;
 +#else
 +			usage();
 +#endif
  		case '?':
  		default:
  			usage();
 @@ -161,6 +184,38 @@ mount_cd9660_parseargs(int argc, char **
  	args->flags = opts;
  }

 +#ifdef ISOFSMNT_SSECTOR
 +
 +/* Inquire after mount whether the running kernel knows iso_args.ssector.
 + * This cannot be done before mount(2), because then MNT_GETARGS will yield
 + * no result. Afterwards, the size of the MNT_GETARGS reply can tell.
 + */
 +static int
 +kernel_has_args_ssector(char *canon_dir)
 +{
 +	struct iso_args args;
 +	int mntflags = MNT_GETARGS, kernel_args_size;
 +
 +	kernel_args_size = mount(MOUNT_CD9660, canon_dir, mntflags,
 +				 &args, sizeof args);
 +	if (kernel_args_size == -1) {
 +		(void)fprintf(stderr,
 +			"%s : Error when inquiring success of option -s : %s\n",
 +			getprogname(),
 +			errno != 0 ? strerror(errno) : "unrecognizable error");
 +		return 0;
 +	}
 +	if (kernel_args_size < (int) (sizeof (struct old_iso_args_v_1_6) +
 +				      sizeof (unsigned long int))) {
 +		(void)fprintf(stderr, "%s : Kernel ignored option -s\n",
 +			      getprogname());
 +		return 0;
 +	}
 +	return (1);
 +}
 +
 +#endif /* ISOFSMNT_SSECTOR */
 +
  int
  mount_cd9660(int argc, char **argv)
  {
 @@ -177,6 +232,20 @@ mount_cd9660(int argc, char **argv)
  		char buf[2048];
  		(void)snprintb(buf, sizeof(buf), ISOFSMNT_BITS, args.flags);
  		printf("%s\n", buf);
 +
 +#ifdef ISOFSMNT_SSECTOR
 +
 +		if (args.flags & ISOFSMNT_SSECTOR)
 +			printf("-s %"PRIu32"\n", args.ssector);
 +	} else if ((args.flags & ISOFSMNT_SSECTOR) && args.ssector > 0) {
 +		if (!kernel_has_args_ssector(canon_dir)) {
 +			if (unmount(canon_dir, 0) == 0)
 +				(void)fprintf(stderr,
 +			   "%s : Had to revoke mount attempt with option -s\n",
 +					getprogname());
 +			exit(1);
 +		}
 +#endif
  	}

  	exit(0);
 @@ -185,7 +254,13 @@ mount_cd9660(int argc, char **argv)
  static void
  usage(void)
  {
 +#ifdef ISOFSMNT_SSECTOR
 +	(void)fprintf(stderr,
 +		"usage: %s [-o options | -s block_offset] special node\n",
 +		getprogname());
 +#else
  	(void)fprintf(stderr,
  		"usage: %s [-o options] special node\n", getprogname());
 +#endif
  	exit(1);
  }
 --- sbin/mount_cd9660/mount_cd9660.8.orig	2009-01-03 22:56:23.000000000 +0000
 +++ sbin/mount_cd9660/mount_cd9660.8	2014-05-16 19:49:05.000000000 +0000
 @@ -57,7 +57,7 @@
  .\"
  .\"     @(#)mount_cd9660.8	8.3 (Berkeley) 3/27/94
  .\"
 -.Dd January 3, 2009
 +.Dd May, 16, 2014
  .Dt MOUNT_CD9660 8
  .Os
  .Sh NAME
 @@ -66,6 +66,7 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl o Ar options
 +.Op Fl s Ar block_offset
  .Ar special node
  .Sh DESCRIPTION
  The
 @@ -130,8 +131,41 @@ For compatibility with Solaris only.
  .It Cm rrcaseins
  Makes all lookups case-insensitive even for CD-ROMs with Rock-Ridge
  extensions (for Rock-Ridge, default is case-sensitive lookup).
 +.It Cm ssector
 +Is ignored as input option but reported by
 +.Cm getargs
 +if option
 +.Cm Fl s
 +is in effect.
  .El
  .El
 +.Bl -tag -width indent
 +.It Fl s Ar block_offset
 +Read the superblock from block address
 +.Ar block_offset
 +rather than from the default position implied by the choice of the device file.
 +The block size is 2048 bytes.
 +.Pp
 +Command
 +.Xr mscdlabel 8
 +may have connected some
 +.Pa /dev/cd*
 +files to logical tracks of an optical
 +multi-session medium, giving the device files the matching superblock
 +positions for the recognized ISO-9660 filesystems.
 +Such a default offset will be overridden by option
 +.Fl s
 +so that all
 +.Pa /dev/cd*
 +will behave like raw partition devices.
 +.Pp
 +.Xr mscdlabel 8
 +has limitations with finding all ISO-9660 sessions which are accessible via
 +a storage device. The burn software suite which produced the ISO-9660
 +filesystem should be able to tell all suitable
 +.Ar block_offset
 +values.
 +.El
  .Pp
  For compatibility with previous releases, following obsolete flags are
  still recognized:

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Mon, 19 May 2014 23:24:54 +0200

 I see in the patch text that i forgot to adapt the debugging code
 to the new data type of variable "sess".
 For review, please virtually apply this change to the patch for
 sys/fs/cd9660/cd9660_vfsops.c:

   #ifdef ISO_DEBUG
 -  	printf("isofs: session offset (part %"PRId32") %d\n", DISKPART(dev), sess);
 +  	printf("isofs: session offset (part %"PRIu32") %d\n", DISKPART(dev), sess);
   #endif

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Tue, 20 May 2014 07:34:28 +0200

 Another attempt to get that debugging line right

   #ifdef ISO_DEBUG
 -       printf("isofs: session offset (part %"PRId32") %d\n", DISKPART(dev), sess);
 +       printf("isofs: session offset (part %"PRId32") %"PRIu32"\n", DISKPART(dev), sess);
   #endif

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Sun, 25 May 2014 09:26:43 +0200

 I have to retract the proposal to remove most of the .h files
 from /usr/include/isofs/cd9660.

 As reported in 
   http://mail-index.netbsd.org/tech-kern/2014/05/24/msg017141.html
   http://mail-index.netbsd.org/tech-kern/2014/05/25/msg017143.html
 there are indeed includers of these files:
   fstat(1), pmap(1), makefs(8)

 None of them is affected by the header changes proposed in this
 PR kern/48808.

 (There will be API/ABI problems with fstat(1) if struct iso_node
  gets changed to support files of 4 GiB or larger.)

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Sun, 01 Jun 2014 16:50:16 +0200

 Hi,

 after counselling by Martin Husemann: new patch proposals.

 The patch for distrib/sets/lists/comp/mi.orig is now retracted.

 The patch for sys/fs/cd9660 is slightley modified to reflect
 my grown deference towards the semi-public API/ABI of cd9660.
 cd9660_extern.h will not have (uint32_t) as replacement of
 inappropriate (int), but rather (unsigned int).
 I expect 16 bit int to fail miserably anyway, so it is only
 about not breaking the ABI for machines with 64 bit (int).
 The change of signedness can hardly affect existing ISO 9660
 filesystems, because it shows up only above 4 TiB size.

 The patch for sbin/mount_cd9660 was shrunk by the assumption
 that new /sbin/mount_cd9660 will always be compiled in a *.h
 environment and run on a kernel which implement the new session
 offset feature from the sys/fs/cd9660 patch.
 I considered to remove only the after-mount test for success of
 the new option. But actually it makes few sense to allow an
 old kernel header environment at compile time, but to assume a
 new kernel at run time.
 So there are two alternative patches for choice:
 - The older one, ready for old and new kernels.
     Date: Sun, 18 May 2014 16:39:13 +0200
 - The new one, ready only for new kernels.

 The new patches are tested by the ISO filesystem which also
 serves for the upcomming large file patch. All seems well,
 except of course 2 failed large file tests.


 Have a nice day :)

 Thomas

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Sun, 01 Jun 2014 16:56:46 +0200

 --- sys/fs/cd9660/cd9660_extern.h.orig	2013-06-23 07:28:36.000000000 +0000
 +++ sys/fs/cd9660/cd9660_extern.h	2014-06-01 13:21:20.000000000 +0000
 @@ -72,15 +72,17 @@ struct iso_mnt {
  	int im_bshift;
  	int im_bmask;

 -	int volume_space_size;
 +	unsigned int volume_space_size;

  	char root[ISODCL (157, 190)];
 -	int root_extent;
 -	int root_size;
 +	unsigned int root_extent;
 +	unsigned int root_size;
  	enum ISO_FTYPE  iso_ftype;

  	int rr_skip;
  	int rr_skip0;
 +
 +	unsigned int im_ssector;
  };

  #define VFSTOISOFS(mp)	((struct iso_mnt *)((mp)->mnt_data))
 --- sys/fs/cd9660/cd9660_mount.h.orig	2005-12-03 17:34:43.000000000 +0000
 +++ sys/fs/cd9660/cd9660_mount.h	2014-06-01 13:04:55.000000000 +0000
 @@ -38,6 +38,8 @@
  #ifndef _ISOFS_CD9660_CD9660_MOUNT_H_
  #define _ISOFS_CD9660_CD9660_MOUNT_H_

 +#include <sys/types.h>
 +
  /*
   * Arguments to mount ISO 9660 filesystems.
   */
 @@ -45,6 +47,9 @@ struct iso_args {
  	const char	*fspec;		/* block special device to mount */
  	struct	export_args30 _pad1; /* compat with old userland tools */
  	int	flags;			/* mounting flags, see below */
 +	uint32_t ssector;		/* start sector of session,
 +					 * if flags & ISOFSMNT_SSECTOR 
 +					 */
  };
  #define	ISOFSMNT_NORRIP		0x00000001 /* disable Rock Ridge Ext.*/
  #define	ISOFSMNT_GENS		0x00000002 /* enable generation numbers */
 @@ -52,8 +57,30 @@ struct iso_args {
  #define	ISOFSMNT_NOJOLIET	0x00000008 /* disable Joliet extensions */
  #define	ISOFSMNT_NOCASETRANS	0x00000010 /* do not make names lower case */
  #define	ISOFSMNT_RRCASEINS	0x00000020 /* case insensitive Rock Ridge */
 +#define	ISOFSMNT_SSECTOR  	0x00000040 /* use ssector as session start */

 -#define ISOFSMNT_BITS "\177\20" \
 +#define ISOFSMNT_BITS "\177\020" \
      "b\00norrip\0b\01gens\0b\02extatt\0b\03nojoliet\0" \
 -    "b\04nocasetrans\0b\05rrcaseins\0"
 +    "b\04nocasetrans\0b\05rrcaseins\0b\06ssector\0\0"
 +
 +
 +/* Compatibility precaution:
 + *
 + * struct old_iso_args_v_1_6 is the definition of struct iso_args before
 + * may 2014. Such structs are still accepted by mount(2) and will be defaulted
 + * to (flags & ~ISOFSMNT_SSECTOR).
 + *
 + * The old struct is exposed here to serve as size benchmark for the reply
 + * of mount(2) with MNT_GETARGS. If after successful mount(2), the inquiry
 + * by MNT_GETARGS yields sizeof(struct old_iso_args_v_1_6) then the
 + * kernel was built with the old struct iso_args. In this case it silently
 + * ignored ISOFSMNT_SSECTOR and iso_args.ssector.
 + * This test can be done only after mounting, because else -1 gets returned.
 + */
 +struct old_iso_args_v_1_6 {
 +	const char		*fspec;
 +	struct export_args30	_pad1;
 +	int			flags;
 +};
 +
  #endif /* _ISOFS_CD9660_CD9660_MOUNT_H_ */
 --- sys/fs/cd9660/cd9660_vfsops.c.patch_006	2014-06-01 13:16:27.000000000 +0000
 +++ sys/fs/cd9660/cd9660_vfsops.c	2014-06-01 13:04:55.000000000 +0000
 @@ -215,21 +215,45 @@ cd9660_mount(struct mount *mp, const cha
  	struct iso_args *args = data;
  	int error;
  	struct iso_mnt *imp = VFSTOISOFS(mp);
 +	struct iso_args defaulted_iso_args;

  	if (args == NULL)
  		return EINVAL;
 -	if (*data_len < sizeof *args)
 -		return EINVAL;
 -
 +	if (*data_len < sizeof *args) {
 +		if (*data_len < sizeof (struct old_iso_args_v_1_6))
 +			return EINVAL; /* Too small even for old iso_args */
 +		if (!(mp->mnt_flag & MNT_GETARGS)) {
 +			/* Upgrade old struct by defaults */
 +			args = &defaulted_iso_args;
 +			memset(args, 0, sizeof *args);
 +			memcpy(args, data, sizeof (struct old_iso_args_v_1_6));
 +			args->flags &= ~ISOFSMNT_SSECTOR;
 +			printf("cd9660_mount: Upgraded old struct iso_args\n");
 +		}
 +	}
  	if (mp->mnt_flag & MNT_GETARGS) {
  		if (imp == NULL)
  			return EIO;
  		args->fspec = NULL;
  		args->flags = imp->im_flags;
 -		*data_len = sizeof (*args);
 +		if (*data_len >= sizeof *args) {
 +			args->ssector = imp->im_ssector;
 +			*data_len = sizeof (*args);
 +		} else {
 +			*data_len = sizeof (struct old_iso_args_v_1_6);
 +		}
  		return 0;
  	}

 +	/* XXX Check for any unknown flags and eventually throw EINVAL ?
 +	 *     This would allow future extensions to fail on old kernels
 +	 *     rather than to be silently ignored, which causes the need
 +	 *     to verify their effectiveness.
 +	 *     See cd9660_mount.h: struct old_iso_args_v_1_6
 +	 *     (One cannot use *data_len as indicator for undue demands.
 +	 *      A newer iso_args may well express old fulfillable wishes.)
 +	 */
 +
  	if ((mp->mnt_flag & MNT_RDONLY) == 0)
  		return (EROFS);

 @@ -244,7 +268,6 @@ cd9660_mount(struct mount *mp, const cha
  				NSM_FOLLOW_NOEMULROOT, &devvp);
  	if (error != 0)
  		return (error);
 -
  	if (devvp->v_type != VBLK) {
  		vrele(devvp);
  		return ENOTBLK;
 @@ -277,11 +300,22 @@ cd9660_mount(struct mount *mp, const cha
  		VOP_UNLOCK(devvp);
  		/* reference to devvp is donated through iso_mountfs */
  	} else {
 +		if ((imp->im_flags & ISOFSMNT_SSECTOR ? imp->im_ssector : 0) !=
 +		    (args->flags & ISOFSMNT_SSECTOR ? args->ssector : 0)) {
 +			error = EINVAL;		/* wish to change superblock */
 +			goto fail;
 +		}
  		if (devvp != imp->im_devvp &&
  		    devvp->v_rdev != imp->im_devvp->v_rdev) {
  			error = EINVAL;		/* needs translation */
  			goto fail;
  		}
 +
 +		/* XXX Should not something be done here ?
 +		       norrip, nojoliet, nomaplcase, ... ?
 +		*/
 +		/* XXX UDF throws EOPNOTSUPP instead of silently ignoring */
 +
  		VOP_UNLOCK(devvp);
  		vrele(devvp);
  	}
 @@ -345,11 +379,11 @@ iso_mountfs(struct vnode *devvp, struct 
  	int error = EINVAL;
  	int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  	int iso_bsize;
 -	int iso_blknum;
 +	uint32_t iso_blknum;
  	int joliet_level;
  	struct iso_volume_descriptor *vdp;
  	struct iso_supplementary_descriptor *sup;
 -	int sess = 0;
 +	uint32_t sess = 0;
  	int ext_attr_length;
  	struct disklabel label;

 @@ -376,12 +410,15 @@ iso_mountfs(struct vnode *devvp, struct 
  		if (error)
  			sess = 0;	/* never mind */
  	}
 +	if (argp->flags & ISOFSMNT_SSECTOR)
 +		sess = argp->ssector;
  #ifdef ISO_DEBUG
 -	printf("isofs: session offset (part %"PRId32") %d\n", DISKPART(dev), sess);
 +	printf("isofs: session offset (part %"PRId32") %"PRIu32"\n", DISKPART(dev), sess);
  #endif

  	for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
 -		if ((error = bread(devvp, (iso_blknum+sess) * btodb(iso_bsize),
 +		if ((error = bread(devvp, ((daddr_t) iso_blknum + sess)
 +							 * btodb(iso_bsize),
  				   iso_bsize, NOCRED, 0, &bp)) != 0)
  			goto out;

 @@ -434,6 +471,8 @@ iso_mountfs(struct vnode *devvp, struct 
  		goto out;
  	}

 +	if (argp->flags & ISOFSMNT_SSECTOR)
 +		isomp->im_ssector = argp->ssector;
  	isomp->volume_space_size += sess;

  	brelse(pribp, BC_AGE);
 @@ -479,7 +518,8 @@ iso_mountfs(struct vnode *devvp, struct 
  		bp = NULL;
  	}
  	isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
 -		 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_RRCASEINS);
 +		 ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_NOCASETRANS |
 +		 ISOFSMNT_RRCASEINS | ISOFSMNT_SSECTOR);

  	if (isomp->im_flags & ISOFSMNT_GENS)
  		isomp->iso_ftype = ISO_FTYPE_9660;

From: "Thomas Schmitt" <scdbackup@gmx.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/48808
Date: Sun, 01 Jun 2014 17:03:09 +0200

 --- sbin/mount_cd9660/mount_cd9660.c.orig	2011-08-29 14:35:00.000000000 +0000
 +++ sbin/mount_cd9660/mount_cd9660.c	2014-06-01 13:56:09.000000000 +0000
 @@ -79,6 +79,7 @@ static const struct mntopt mopts[] = {
  	{ "rrip", 1, ISOFSMNT_NORRIP, 1 },
  	{ "joliet", 1, ISOFSMNT_NOJOLIET, 1 },
  	{ "rrcaseins", 0, ISOFSMNT_RRCASEINS, 1 },
 +	{ "ssector", 0, 0, 1 }, /* not setable, only for info via getargs */
  	MOPT_NULL,
  };

 @@ -102,11 +103,13 @@ mount_cd9660_parseargs(int argc, char **
  	int ch, opts;
  	mntoptparse_t mp;
  	char *dev, *dir;
 +	char *ep;
 +	long long int llnum;

  	memset(args, 0, sizeof(*args));
  	*mntflags = opts = 0;
  	optind = optreset = 1;
 -	while ((ch = getopt(argc, argv, "egijo:r")) != -1)
 +	while ((ch = getopt(argc, argv, "egijo:rs:")) != -1)
  		switch (ch) {
  		case 'e':
  			/* obsolete, retained for compatibility only, use
 @@ -134,6 +137,19 @@ mount_cd9660_parseargs(int argc, char **
  			 * -o norrip */
  			opts |= ISOFSMNT_NORRIP;
  			break;
 +		case 's':
 +			/* learned from mount/fattr.c : a_num() */
 +			llnum = strtoll(optarg, &ep, 0);
 +			if (*ep || optarg == ep || llnum < 0 ||
 +			    llnum > (long long int) 0xffffff00) {
 +				(void)fprintf(stderr,
 +				    "%s : unusable parameter with option -s\n",
 +				    getprogname());
 +				usage();
 +			}
 +			args->ssector = llnum;
 +			opts |= ISOFSMNT_SSECTOR;
 +			break;
  		case '?':
  		default:
  			usage();
 @@ -177,6 +193,8 @@ mount_cd9660(int argc, char **argv)
  		char buf[2048];
  		(void)snprintb(buf, sizeof(buf), ISOFSMNT_BITS, args.flags);
  		printf("%s\n", buf);
 +		if (args.flags & ISOFSMNT_SSECTOR)
 +			printf("-s %"PRIu32"\n", args.ssector);
  	}

  	exit(0);
 @@ -186,6 +204,7 @@ static void
  usage(void)
  {
  	(void)fprintf(stderr,
 -		"usage: %s [-o options] special node\n", getprogname());
 +		"usage: %s [-o options | -s block_offset] special node\n",
 +		getprogname());
  	exit(1);
  }
 --- sbin/mount_cd9660/mount_cd9660.8.orig	2009-01-03 22:56:23.000000000 +0000
 +++ sbin/mount_cd9660/mount_cd9660.8	2014-05-16 19:49:05.000000000 +0000
 @@ -57,7 +57,7 @@
  .\"
  .\"     @(#)mount_cd9660.8	8.3 (Berkeley) 3/27/94
  .\"
 -.Dd January 3, 2009
 +.Dd May, 16, 2014
  .Dt MOUNT_CD9660 8
  .Os
  .Sh NAME
 @@ -66,6 +66,7 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl o Ar options
 +.Op Fl s Ar block_offset
  .Ar special node
  .Sh DESCRIPTION
  The
 @@ -130,8 +131,41 @@ For compatibility with Solaris only.
  .It Cm rrcaseins
  Makes all lookups case-insensitive even for CD-ROMs with Rock-Ridge
  extensions (for Rock-Ridge, default is case-sensitive lookup).
 +.It Cm ssector
 +Is ignored as input option but reported by
 +.Cm getargs
 +if option
 +.Cm Fl s
 +is in effect.
  .El
  .El
 +.Bl -tag -width indent
 +.It Fl s Ar block_offset
 +Read the superblock from block address
 +.Ar block_offset
 +rather than from the default position implied by the choice of the device file.
 +The block size is 2048 bytes.
 +.Pp
 +Command
 +.Xr mscdlabel 8
 +may have connected some
 +.Pa /dev/cd*
 +files to logical tracks of an optical
 +multi-session medium, giving the device files the matching superblock
 +positions for the recognized ISO-9660 filesystems.
 +Such a default offset will be overridden by option
 +.Fl s
 +so that all
 +.Pa /dev/cd*
 +will behave like raw partition devices.
 +.Pp
 +.Xr mscdlabel 8
 +has limitations with finding all ISO-9660 sessions which are accessible via
 +a storage device. The burn software suite which produced the ISO-9660
 +filesystem should be able to tell all suitable
 +.Ar block_offset
 +values.
 +.El
  .Pp
  For compatibility with previous releases, following obsolete flags are
  still recognized:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.