From dwmalone@maths.tcd.ie  Thu Apr 23 15:01:23 1998
Received: from salmon.maths.tcd.ie (mmdf@salmon.maths.tcd.ie [134.226.81.11])
          by hub.freebsd.org (8.8.8/8.8.8) with SMTP id PAA04899
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 23 Apr 1998 15:01:20 -0700 (PDT)
          (envelope-from dwmalone@maths.tcd.ie)
Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP
          id <aa25208@salmon.maths.tcd.ie>; 23 Apr 98 23:01:16 +0100 (BST)
Message-Id: <9804232301.aa28604@walton.maths.tcd.ie>
Date: Thu, 23 Apr 98 23:01:13 +0100 (BST)
From: dwmalone@maths.tcd.ie
Sender: dwmalone@maths.tcd.ie
Reply-To: dwmalone@maths.tcd.ie
To: FreeBSD-gnats-submit@freebsd.org
Subject: Mount doesn't behave as described in the man page.
X-Send-Pr-Version: 3.2

>Number:         6399
>Category:       bin
>Synopsis:       [PATCH] When using "-u" mount doesn't start from the fstab options.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Apr 23 15:10:01 PDT 1998
>Closed-Date:    Thu May 6 22:31:46 PDT 1999
>Last-Modified:  Thu May  6 22:33:41 PDT 1999
>Originator:     David Malone
>Release:        FreeBSD 2.2.6-STABLE i386
>Organization:
School of Maths, Trinity College, Dublin.
>Environment:

	2.2-STABLE or 3.0-CURRENT

>Description:

	Because there is no syntax for adding or removing mount options
	mount -u begins from no options rather than those listed in fstab.
	This isn't what the man page says.

	Also the man page claims that saying "-o update" is the same as
	-u, which doesn't seem to be the case. Saying "-o update" does
	actually start with the options in fstab.

>How-To-Repeat:

	Experimenting with mount -d with demo the problem.

>Fix:
	
	I've included a patch which changes "mount -u".  It only changes
	the effect when conflicting options are given. In this case the
	rightmost option wins out. For example:

		mount -u -o sync,noatime,nosync

	is equivelent to:

		mount -u -o noatime,nosync

	Previously I think the default option won out. It also adds two
	new options "-o fstab" and "-o cur". The first is equivelent to
	giving all the options in fstab and the second is equivelent to
	the options currently in effect (as listed by mount -p).

	These options allow you to do things like:

		mount -u -o fstab,noatime /usr
		checksum stuff
		mount -u -o fstab /usr

	The mount source code is in a bit of a mess as it takes its
	option names from about 3 different places, however I didn't
	think it was my place to fix this ;-)

	My man page patch doesn't mention that mount -u is actually
	different from mount -o update, 'cos I'm not sure which is
	"correct". The patch is for 2.2, if people want similar code
	for current I can cook some up.


diff -cwr /usr/src/sbin/mount/mount.8 ./mount.8
*** /usr/src/sbin/mount/mount.8	Thu Dec  4 23:04:38 1997
--- ./mount.8	Sat Apr 18 22:03:55 1998
***************
*** 108,119 ****
--- 108,132 ----
  flag to set,
  and should not be used unless you are prepared to recreate the file
  system should your system crash.
+ .It cur
+ When using the
+ .Fl u
+ flag this is the same as giving the options currently in effect. To
+ see what these options are you can use the
+ .Fl p
+ flag.
  .It force
  The same as
  .Fl f ;
  forces the revocation of write access when trying to downgrade
  a filesystem mount status from read-write to read-only. Also
  forces the R/W mount of an unclean filesystem (dangerous; use with caution).
+ .It fstab
+ When using the
+ .Fl u
+ this is the same as giving all the options listed in the
+ .Xr fstab 5
+ file for the filesystem.
  .It noatime
  Do not update the file access time when reading from a file. This option
  is useful on filesystems where there are large numbers of files and
***************
*** 253,263 ****
  files on the filesystem are currently open for writing unless the
  .Fl f
  flag is also specified.
! The set of options is determined by first extracting the options
! for the file system from the
! .Xr fstab
! table,
! then applying any options specified by the
  .Fl o
  argument,
  and finally applying the
--- 266,273 ----
  files on the filesystem are currently open for writing unless the
  .Fl f
  flag is also specified.
! The set of options is determined by
! applying any options specified by the
  .Fl o
  argument,
  and finally applying the
diff -cwr /usr/src/sbin/mount/mount.c ./mount.c
*** /usr/src/sbin/mount/mount.c	Thu Mar  5 00:59:24 1998
--- ./mount.c	Thu Apr 23 22:30:47 1998
***************
*** 71,81 ****
--- 71,84 ----
  const char
        **makevfslist __P((char *));
  void	mangle __P((char *, int *, const char **));
+ char   *update_options __P((char *,char *,int));
  int	mountfs __P((const char *, const char *, const char *,
  			int, const char *, const char *));
+ void	remopt __P((char *,const char *));
  void	prmount __P((const char *, const char *, int));
  void	usage __P((void));
  void	putfsent __P((const struct statfs *));
+ char   *flags2opts __P((int));
  
  /* From mount_ufs.c. */
  int	mount_ufs __P((int, char * const *));
***************
*** 215,220 ****
--- 218,224 ----
  				errx(1, "can't find fstab entry for %s.",
  				    *argv);
  			/* If it's an update, ignore the fstab file options. */
+ 			options = update_options(options,fs->fs_mntops,mntbuf->f_flags);
  			fs->fs_mntops = NULL;
  			mntonname = mntbuf->f_mntonname;
  		} else {
***************
*** 547,552 ****
--- 551,625 ----
  	*argcp = argc;
  }
  
+ char *
+ update_options(opts, fstab, curflags)
+ 	char *opts;
+ 	char *fstab;
+ 	int curflags;
+ {
+ 	char *o,*p;
+ 	char *cur;
+ 	char *expopt, *newopt, *tmpopt;
+ 
+ 	if(opts == NULL)
+ 		return strdup("");
+ 
+ 	remopt(fstab,"fstab");
+ 	remopt(fstab,"cur");
+ 	cur = flags2opts(curflags);
+ 
+ 	expopt = NULL;
+ 	for ( p = opts; (o = strsep(&p, ",")) != NULL; ) {
+ 		if (strcmp("fstab",o) == 0)
+ 			expopt = catopt(expopt,fstab);
+ 		else if (strcmp("cur",o) == 0)
+ 			expopt = catopt(expopt,cur);
+ 		else
+ 			expopt = catopt(expopt,o);
+ 	}
+ 	free(cur);
+ 	free(opts);
+ 
+ 	newopt = NULL;
+ 	for ( p = expopt; (o = strsep(&p, ",")) != NULL; ) {
+ 		if ( (tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL)
+ 			err(1,NULL);
+ 	
+ 		strcpy(tmpopt,"no");
+ 		strcat(tmpopt,o);
+ 		remopt(newopt,tmpopt);
+ 		free(tmpopt);
+ 
+ 		if (strncmp("no",o,2) == 0) remopt(newopt,o+2);
+ 		newopt = catopt(newopt,o);
+ 	}
+ 	free(expopt);
+ 
+ 	return newopt;
+ }
+ 
+ void
+ remopt(string,opt)
+ 	char *string;
+ 	const char *opt;
+ {
+ 	char *o,*p,*r;
+ 
+ 	if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0')
+ 		return;
+ 
+ 	r = string;
+ 
+ 	for ( p = string; (o = strsep(&p, ",")) != NULL; ) {
+ 		if ( strcmp(opt,o) != 0 ) {
+ 			if (*r == ',' && *o != '\0') r++;
+ 			while( (*r++ = *o++) != '\0' );
+ 			*--r = ',';
+ 		}
+ 	}
+ 	*r = '\0';
+ }
+ 
  void
  usage()
  {
***************
*** 565,596 ****
      const struct statfs	    *ent;
  {
      struct fstab    *fst;
  
      printf ("%s\t%s\t%s %s",
  	    ent->f_mntfromname, ent->f_mntonname,
  	    mnttype[ent->f_type],
! 	    (ent->f_flags & MNT_RDONLY) ? "ro" : "rw");
! 
!     if (ent->f_flags & MNT_SYNCHRONOUS)
! 	printf (",sync");
! 
!     if (ent->f_flags & MNT_NOEXEC)
! 	printf (",noexec");
! 
!     if (ent->f_flags & MNT_NOSUID)
! 	printf (",nosuid");
! 
!     if (ent->f_flags & MNT_NODEV)
! 	printf (",nodev");
! 
!     if (ent->f_flags & MNT_UNION)
! 	printf (",union");
! 
!     if (ent->f_flags & MNT_ASYNC)
! 	printf (",async");
! 
!     if (ent->f_flags & MNT_NOATIME)
! 	printf (",noatime");
  
      if (fst = getfsspec (ent->f_mntfromname))
  	printf ("\t%u %u\n", fst->fs_freq, fst->fs_passno);
--- 638,651 ----
      const struct statfs	    *ent;
  {
      struct fstab    *fst;
+     char *opts;
  
+     opts = flags2opts(ent->f_flags);
      printf ("%s\t%s\t%s %s",
  	    ent->f_mntfromname, ent->f_mntonname,
  	    mnttype[ent->f_type],
!             opts);
!     free(opts);
  
      if (fst = getfsspec (ent->f_mntfromname))
  	printf ("\t%u %u\n", fst->fs_freq, fst->fs_passno);
***************
*** 600,603 ****
--- 655,677 ----
  	printf ("\t1 1\n");
      else
  	printf ("\t0 0\n");
+ }
+ 
+ char *
+ flags2opts(flags)
+ 	int flags;
+ {
+     char *res;
+ 
+     res = NULL;
+ 
+     res = catopt(res,(flags & MNT_RDONLY) ? "ro" : "rw");
+ 
+     if (flags & MNT_SYNCHRONOUS)	res = catopt(res, "sync");
+     if (flags & MNT_NOEXEC)		res = catopt(res, "noexec");
+     if (flags & MNT_NOSUID)		res = catopt(res, "nosuid");
+     if (flags & MNT_NODEV)		res = catopt(res, "nodev");
+     if (flags & MNT_UNION)		res = catopt(res, "union");
+     if (flags & MNT_ASYNC)		res = catopt(res, "async");
+     if (flags & MNT_NOATIME)		res = catopt(res, "noatime");
  }

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: phk 
State-Changed-When: Sat Apr 25 23:13:01 PDT 1998 
State-Changed-Why:  
There seems to have been a lot of action in mount between 2.2 and 
-current, so the supplied patch goes down in flames in -current. 
Can I persuade you to make a -current version ? 

From: David Malone <dwmalone@maths.tcd.ie>
To: freebsd-gnats-submit@freebsd.org, dwmalone@maths.tcd.ie
Cc:  Subject: Re: bin/6399: When using "-u" mount doesn't start from the fstab options.
Date: Mon, 25 May 1998 10:52:06 +0100

 I've done some diffs for current which provide exactly the same
 features as the one for stable. They are really just a by hand application
 of the patch for stable.
 
 	David.
 
 ==============================================================================
 
 *** mount.c	1998/03/08 09:56:02	1.23
 --- mount.c	1998/05/25 09:38:50
 ***************
 *** 73,83 ****
 --- 73,86 ----
   int	ismounted __P((struct fstab *, struct statfs *, int));
   int	isremountable __P((const char *));
   void	mangle __P((char *, int *, const char **));
 + char   *update_options __P((char *,char *,int));
   int	mountfs __P((const char *, const char *, const char *,
   			int, const char *, const char *));
 + void	remopt __P((char *,const char *));
   void	prmount __P((struct statfs *));
   void	putfsent __P((const struct statfs *));
   void	usage __P((void));
 + char   *flags2opts __P((int));
   
   /* Map from mount otions to printable formats. */
   static struct opt {
 ***************
 *** 227,232 ****
 --- 230,236 ----
   				mntfromname = fs->fs_spec;
   			else
   				mntfromname = mntbuf->f_mntfromname;
 + 			options = update_options(options,fs->fs_mntops,mntbuf->f_flags);
   			rval = mountfs(mntbuf->f_fstypename, mntfromname,
   			    mntbuf->f_mntonname, init_flags, options, 0);
   			break;
 ***************
 *** 563,568 ****
 --- 567,642 ----
   	*argcp = argc;
   }
   
 + 
 + char *
 + update_options(opts, fstab, curflags)
 + 	char *opts;
 + 	char *fstab;
 + 	int curflags;
 + {
 + 	char *o,*p;
 + 	char *cur;
 + 	char *expopt, *newopt, *tmpopt;
 + 
 + 	if(opts == NULL)
 + 		return strdup("");
 + 
 + 	remopt(fstab,"fstab");
 + 	remopt(fstab,"cur");
 + 	cur = flags2opts(curflags);
 + 
 + 	expopt = NULL;
 + 	for ( p = opts; (o = strsep(&p, ",")) != NULL; ) {
 + 		if (strcmp("fstab",o) == 0)
 + 			expopt = catopt(expopt,fstab);
 + 		else if (strcmp("cur",o) == 0)
 + 			expopt = catopt(expopt,cur);
 + 		else
 + 			expopt = catopt(expopt,o);
 + 	}
 + 	free(cur);
 + 	free(opts);
 + 
 + 	newopt = NULL;
 + 	for ( p = expopt; (o = strsep(&p, ",")) != NULL; ) {
 + 		if ( (tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL)
 + 			err(1,NULL);
 + 	
 + 		strcpy(tmpopt,"no");
 + 		strcat(tmpopt,o);
 + 		remopt(newopt,tmpopt);
 + 		free(tmpopt);
 + 
 + 		if (strncmp("no",o,2) == 0) remopt(newopt,o+2);
 + 		newopt = catopt(newopt,o);
 + 	}
 + 	free(expopt);
 + 
 + 	return newopt;
 + }
 + 
 + void
 + remopt(string,opt)
 + 	char *string;
 +  	const char *opt;
 + {
 + 	char *o,*p,*r;
 + 
 + 	if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0')
 + 		return;
 + 
 + 	r = string;
 + 
 + 	for ( p = string; (o = strsep(&p, ",")) != NULL; ) {
 + 		if ( strcmp(opt,o) != 0 ) {
 + 			if (*r == ',' && *o != '\0') r++;
 + 			while( (*r++ = *o++) != '\0' );
 + 			*--r = ',';
 + 		}
 + 	}
 + 	*r = '\0';
 + }
 + 
   void
   usage()
   {
 ***************
 *** 581,611 ****
   	const struct statfs *ent;
   {
   	struct fstab *fst;
   
   	printf("%s\t%s\t%s %s", ent->f_mntfromname, ent->f_mntonname,
 ! 	    ent->f_fstypename, (ent->f_flags & MNT_RDONLY) ? "ro" : "rw");
   
   	/* XXX should use optnames[] - put shorter names in it. */
 - 	if (ent->f_flags & MNT_SYNCHRONOUS)
 - 		printf(",sync");
 - 	if (ent->f_flags & MNT_NOEXEC)
 - 		printf(",noexec");
 - 	if (ent->f_flags & MNT_NOSUID)
 - 		printf(",nosuid");
 - 	if (ent->f_flags & MNT_NODEV)
 - 		printf(",nodev");
 - 	if (ent->f_flags & MNT_UNION)
 - 		printf(",union");
 - 	if (ent->f_flags & MNT_ASYNC)
 - 		printf(",async");
 - 	if (ent->f_flags & MNT_NOATIME)
 - 		printf(",noatime");
 - 	if (ent->f_flags & MNT_NOCLUSTERR)
 - 		printf(",noclusterr");
 - 	if (ent->f_flags & MNT_NOCLUSTERW)
 - 		printf(",noclusterw");
 - 	if (ent->f_flags & MNT_SUIDDIR)
 - 		printf(",suiddir");
   
   	if ((fst = getfsspec(ent->f_mntfromname)))
   		printf("\t%u %u\n", fst->fs_freq, fst->fs_passno);
 --- 655,668 ----
   	const struct statfs *ent;
   {
   	struct fstab *fst;
 + 	char *opts;
   
 + 	opts = flags2opts(ent->f_flags);
   	printf("%s\t%s\t%s %s", ent->f_mntfromname, ent->f_mntonname,
 ! 	    ent->f_fstypename, opts);
 ! 	free(opts);
   
   	/* XXX should use optnames[] - put shorter names in it. */
   
   	if ((fst = getfsspec(ent->f_mntfromname)))
   		printf("\t%u %u\n", fst->fs_freq, fst->fs_passno);
 ***************
 *** 615,618 ****
 --- 672,698 ----
   		printf("\t1 1\n");
   	else
   		printf("\t0 0\n");
 + }
 + 
 + 
 + char *
 + flags2opts(flags)
 + 	int flags;
 + {
 +     char *res;
 + 
 +     res = NULL;
 + 
 +     res = catopt(res,(flags & MNT_RDONLY) ? "ro" : "rw");
 + 
 +     if (flags & MNT_SYNCHRONOUS)	res = catopt(res, "sync");
 +     if (flags & MNT_NOEXEC)		res = catopt(res, "noexec");
 +     if (flags & MNT_NOSUID)		res = catopt(res, "nosuid");
 +     if (flags & MNT_NODEV)		res = catopt(res, "nodev");
 +     if (flags & MNT_UNION)		res = catopt(res, "union");
 +     if (flags & MNT_ASYNC)		res = catopt(res, "async");
 +     if (flags & MNT_NOATIME)		res = catopt(res, "noatime");
 +     if (flags & MNT_NOCLUSTERR)		res = catopt(res, "noclusterr");
 +     if (flags & MNT_NOCLUSTERW)		res = catopt(res, "noclusterw");
 +     if (flags & MNT_SUIDDIR)		res = catopt(res, "suiddir");
   }
 *** mount.8	1997/12/01 00:44:16	1.21
 --- mount.8	1998/05/25 09:45:31
 ***************
 *** 112,123 ****
 --- 112,136 ----
   flag to set,
   and should not be used unless you are prepared to recreate the file
   system should your system crash.
 + .It cur
 + When using the
 + .Fl u
 + flag this is the same as giving the options currently in effect. To
 + see what these options are you can use the
 + .Fl p
 + flag.
   .It force
   The same as
   .Fl f ;
   forces the revocation of write access when trying to downgrade
   a filesystem mount status from read-write to read-only. Also
   forces the R/W mount of an unclean filesystem (dangerous; use with caution).
 + .It fstab
 + When using the
 + .Fl u
 + this is the same as giving all the options listed in the
 + .Xr fstab 5
 + file for the filesystem.
   .It noatime
   Do not update the file access time when reading from a file. This option
   is useful on filesystems where there are large numbers of files and
 ***************
 *** 284,296 ****
   files on the filesystem are currently open for writing unless the
   .Fl f
   flag is also specified.
 ! The set of options is determined by first extracting the options
 ! for the file system from the
 ! .Xr fstab 5
 ! table,
 ! then applying any options specified by the
 ! .Fl o
   argument,
   and finally applying the
   .Fl r
   or
 --- 297,306 ----
   files on the filesystem are currently open for writing unless the
   .Fl f
   flag is also specified.
 ! The set of options is determined by
 ! applying any options specified by the
   argument,
 + .Fl o
   and finally applying the
   .Fl r
   or

From: <jkoshy@FreeBSD.org>
To: dwmalone@maths.tcd.ie
Cc: Freebsd-gnats-submit@freebsd.org
Subject: Re: bin/6399: [PATCH] When using "-u" mount doesn't start from the fstab options
Date: Wed, 5 May 1999 01:45:09 -0700 (PDT)

 A late followup (better late than never!) with some review comments:
 
 1 :::
 
 230         if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL)
 231                 mntfromname = fs->fs_spec;
 232         else
 233                 mntfromname = mntbuf->f_mntfromname;
 234         options = update_options(options,fs->fs_mntops,mntbuf->f_flags);
 
 We have a null pointer deference here if `getfsfile()' on line 230 returns
 NULL.
 
 2 :::
 
 602         for ( p = expopt; (o = strsep(&p, ",")) != NULL; ) {
 603                 if ( (tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL)
 604                         err(1,NULL);
 605
 606                 strcpy(tmpopt,"no");
 607                 strcat(tmpopt,o);
 608                 remopt(newopt,tmpopt);
 609                 free(tmpopt);
 610
 611                 if (strncmp("no",o,2) == 0) remopt(newopt,o+2); 
 
 Lines 606--608 are redundant if the option has a 'no' prefix; e.g:-
 "nofoo".  In this case the `remopt()' call gets called with `nonofoo'
 and is effectively a noop.  Shouldn't we be removing option 'foo' from
 the `newopt' list instead?
 
 Thanks for (patiently) redoing the patch for -current.
 
 Regards,
 Koshy
 <jkoshy@freebsd.org>
 
 
 

From: David Malone <dwmalone@maths.tcd.ie>
To: jkoshy@freebsd.org
Cc: Freebsd-gnats-submit@freebsd.org
Subject: Re: bin/6399: [PATCH] When using "-u" mount doesn't start from the fstab options 
Date: Wed, 05 May 1999 11:23:05 +0100

 > A late followup (better late than never!) with some review comments:
 
 ;-)
 I was working up to re-doing it for current again and then complaining
 bitterly!
 
 > 230         if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL)
 > 231                 mntfromname = fs->fs_spec;
 > 232         else
 > 233                 mntfromname = mntbuf->f_mntfromname;
 > 234         options = update_options(options,fs->fs_mntops,mntbuf->f_flags);
 > 
 > We have a null pointer deference here if `getfsfile()' on line 230 returns
 > NULL.
 
 Grand - I'll have a look at this one - should be easy enough to fix.
 
 > 606                 strcpy(tmpopt,"no");
 > 607                 strcat(tmpopt,o);
 > 608                 remopt(newopt,tmpopt);
 > 609                 free(tmpopt);
 > 610
 > 611                 if (strncmp("no",o,2) == 0) remopt(newopt,o+2); 
 > 
 > Lines 606--608 are redundant if the option has a 'no' prefix; e.g:-
 > "nofoo".  In this case the `remopt()' call gets called with `nonofoo'
 > and is effectively a noop.  Shouldn't we be removing option 'foo' from
 > the `newopt' list instead?
 
 We remove "foo" on line 611. I think I was worried about options like "notice"
 and its obvious inverse "nonotice", it has the less obvious inverse "tice"
 which hopefully wouldn't be a distinct option.
 
 I'll produce a version for -current of today with the NULL pointer
 dereference fixed and send it later today.
 
 	David.
 

From: David Malone <dwmalone@maths.tcd.ie>
To: jkoshy@freebsd.org
Cc: Freebsd-gnats-submit@freebsd.org
Subject: Re: bin/6399: [PATCH] When using "-u" mount doesn't start from the fstab options 
Date: Wed, 05 May 1999 21:51:53 +0100

 I've fixed the dereferencing a NULL pointer if the filesystem isn't in fstab,
 fixed a missing return, made the style more like the surounding style and added
 two comments. Is it suitable for committing yet?
 
 	David.
 
 --- mount.c.orig	Wed May  5 12:42:51 1999
 +++ mount.c	Wed May  5 14:02:40 1999
 @@ -72,11 +72,14 @@
  int	ismounted __P((struct fstab *, struct statfs *, int));
  int	isremountable __P((const char *));
  void	mangle __P((char *, int *, const char **));
 +char   *update_options __P((char *, char *, int));
  int	mountfs __P((const char *, const char *, const char *,
  			int, const char *, const char *));
 +void	remopt __P((char *, const char *));
  void	prmount __P((struct statfs *));
  void	putfsent __P((const struct statfs *));
  void	usage __P((void));
 +char   *flags2opts __P((int));
  
  /* Map from mount options to printable formats. */
  static struct opt {
 @@ -224,10 +227,15 @@
  				errx(1,
  				    "unknown special file or file system %s",
  				    *argv);
 -			if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL)
 +			if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) {
  				mntfromname = fs->fs_spec;
 -			else
 +				options = update_options(options, fs->fs_mntops,
 +				    mntbuf->f_flags);
 +			} else {
  				mntfromname = mntbuf->f_mntfromname;
 +				options = update_options(options, NULL,
 +				    mntbuf->f_flags);
 +			}
  			rval = mountfs(mntbuf->f_fstypename, mntfromname,
  			    mntbuf->f_mntonname, init_flags, options, 0);
  			break;
 @@ -524,6 +532,9 @@
  	size_t i;
  	char *cp;
  
 +	if (s1 == NULL || *s1 == '\0')
 +		return s0;
 +
  	if (s0 && *s0) {
  		i = strlen(s0) + strlen(s1) + 1 + 1;
  		if ((cp = malloc(i)) == NULL)
 @@ -564,6 +575,90 @@
  	*argcp = argc;
  }
  
 +
 +char *
 +update_options(opts, fstab, curflags)
 +	char *opts;
 +	char *fstab;
 +	int curflags;
 +{
 +	char *o, *p;
 +	char *cur;
 +	char *expopt, *newopt, *tmpopt;
 +
 +	if (opts == NULL)
 +		return strdup("");
 +
 +	fstab = strdup(fstab);
 +	remopt(fstab, "fstab");
 +	remopt(fstab, "cur");
 +	cur = flags2opts(curflags);
 +
 +	/*
 +	 * Expand all "cur" and "fstab" options passed to us first.
 +	 */
 +	expopt = NULL;
 +	for (p = opts; (o = strsep(&p, ",")) != NULL;) {
 +		if (strcmp("fstab", o) == 0)
 +			expopt = catopt(expopt, fstab);
 +		else if (strcmp("cur", o) == 0)
 +			expopt = catopt(expopt, cur);
 +		else
 +			expopt = catopt(expopt, o);
 +	}
 +	free(fstab);
 +	free(cur);
 +	free(opts);
 +
 +	/*
 +	 * Remove previous contradictory arguments. Given option "foo" we
 +	 * remove all the "nofoo" options. Given "nofoo" we remove "nonofoo"
 +	 * and "foo" - so we can deal with possible options like "notice".
 +	 */
 +	newopt = NULL;
 +	for (p = expopt; (o = strsep(&p, ",")) != NULL;) {
 +		if ((tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL)
 +			errx(1, "malloc failed");
 +	
 +		strcpy(tmpopt, "no");
 +		strcat(tmpopt, o);
 +		remopt(newopt, tmpopt);
 +		free(tmpopt);
 +
 +		if (strncmp("no", o, 2) == 0)
 +			remopt(newopt, o+2);
 +
 +		newopt = catopt(newopt, o);
 +	}
 +	free(expopt);
 +
 +	return newopt;
 +}
 +
 +void
 +remopt(string, opt)
 +	char *string;
 + 	const char *opt;
 +{
 +	char *o, *p, *r;
 +
 +	if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0')
 +		return;
 +
 +	r = string;
 +
 +	for (p = string; (o = strsep(&p, ",")) != NULL;) {
 +		if (strcmp(opt, o) != 0) {
 +			if (*r == ',' && *o != '\0')
 +				r++;
 +			while ((*r++ = *o++) != '\0')
 +			    ;
 +			*--r = ',';
 +		}
 +	}
 +	*r = '\0';
 +}
 +
  void
  usage()
  {
 @@ -580,33 +675,12 @@
  	const struct statfs *ent;
  {
  	struct fstab *fst;
 -
 +	char *opts;
 +  
 +	opts = flags2opts(ent->f_flags);
  	printf("%s\t%s\t%s %s", ent->f_mntfromname, ent->f_mntonname,
 -	    ent->f_fstypename, (ent->f_flags & MNT_RDONLY) ? "ro" : "rw");
 -
 -	/* XXX should use optnames[] - put shorter names in it. */
 -	if (ent->f_flags & MNT_SYNCHRONOUS)
 -		printf(",sync");
 -	if (ent->f_flags & MNT_NOEXEC)
 -		printf(",noexec");
 -	if (ent->f_flags & MNT_NOSUID)
 -		printf(",nosuid");
 -	if (ent->f_flags & MNT_NODEV)
 -		printf(",nodev");
 -	if (ent->f_flags & MNT_UNION)
 -		printf(",union");
 -	if (ent->f_flags & MNT_ASYNC)
 -		printf(",async");
 -	if (ent->f_flags & MNT_NOATIME)
 -		printf(",noatime");
 -	if (ent->f_flags & MNT_NOCLUSTERR)
 -		printf(",noclusterr");
 -	if (ent->f_flags & MNT_NOCLUSTERW)
 -		printf(",noclusterw");
 -	if (ent->f_flags & MNT_NOSYMFOLLOW)
 -		printf (",nosymfollow");
 -	if (ent->f_flags & MNT_SUIDDIR)
 -		printf(",suiddir");
 +	    ent->f_fstypename, opts);
 +	free(opts);
  
  	if ((fst = getfsspec(ent->f_mntfromname)))
  		printf("\t%u %u\n", fst->fs_freq, fst->fs_passno);
 @@ -616,4 +690,30 @@
  		printf("\t1 1\n");
  	else
  		printf("\t0 0\n");
 +}
 +
 +
 +char *
 +flags2opts(flags)
 +	int flags;
 +{
 +	char *res;
 +
 +	res = NULL;
 +
 +	res = catopt(res, (flags & MNT_RDONLY) ? "ro" : "rw");
 +
 +	if (flags & MNT_SYNCHRONOUS)	res = catopt(res, "sync");
 +	if (flags & MNT_NOEXEC)		res = catopt(res, "noexec");
 +	if (flags & MNT_NOSUID)		res = catopt(res, "nosuid");
 +	if (flags & MNT_NODEV)		res = catopt(res, "nodev");
 +	if (flags & MNT_UNION)		res = catopt(res, "union");
 +	if (flags & MNT_ASYNC)		res = catopt(res, "async");
 +	if (flags & MNT_NOATIME)	res = catopt(res, "noatime");
 +	if (flags & MNT_NOCLUSTERR)	res = catopt(res, "noclusterr");
 +	if (flags & MNT_NOCLUSTERW)	res = catopt(res, "noclusterw");
 +	if (flags & MNT_NOSYMFOLLOW)	res = catopt(res, "nosymfollow");
 +	if (flags & MNT_SUIDDIR)	res = catopt(res, "suiddir");
 +
 +	return res;
  }
 --- mount.8.orig	Wed May  5 12:42:51 1999
 +++ mount.8	Wed May  5 12:43:01 1999
 @@ -112,12 +112,25 @@
  flag to set,
  and should not be used unless you are prepared to recreate the file
  system should your system crash.
 +.It cur
 +When using the
 +.Fl u
 +flag this is the same as giving the options currently in effect. To
 +see what these options are you can use the
 +.Fl p
 +flag.
  .It force
  The same as
  .Fl f ;
  forces the revocation of write access when trying to downgrade
  a filesystem mount status from read-write to read-only. Also
  forces the R/W mount of an unclean filesystem (dangerous; use with caution).
 +.It fstab
 +When using the
 +.Fl u
 +this is the same as giving all the options listed in the
 +.Xr fstab 5
 +file for the filesystem.
  .It noatime
  Do not update the file access time when reading from a file. This option
  is useful on filesystems where there are large numbers of files and
 @@ -287,13 +300,10 @@
  files on the filesystem are currently open for writing unless the
  .Fl f
  flag is also specified.
 -The set of options is determined by first extracting the options
 -for the file system from the
 -.Xr fstab 5
 -table,
 -then applying any options specified by the
 -.Fl o
 +The set of options is determined by
 +applying any options specified by the
  argument,
 +.Fl o
  and finally applying the
  .Fl r
  or
 
State-Changed-From-To: feedback->closed 
State-Changed-By: jkoshy 
State-Changed-When: Thu May 6 22:31:46 PDT 1999 
State-Changed-Why:  
Patch applied, thanks! 
rev 1.26 "src/sbin/mount/mount.8" 
rev 1.30 "src/sbin/mount/mount.c" 
>Unformatted:
