*BSD News Article 20630


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!elroy.jpl.nasa.gov!swrinde!cs.utexas.edu!utnut!torn!nermal.cs.uoguelph.ca!herman!rmacklem
From: rmacklem@uoguelph.ca (Richard A Macklem)
Newsgroups: comp.os.386bsd.bugs
Subject: NFS Exports bug/fix
Date: 8 Sep 1993 14:40:54 GMT
Organization: University of Guelph
Lines: 317
Message-ID: <26kqtm$k69@nermal.cs.uoguelph.ca>
NNTP-Posting-Host: herman.cs.uoguelph.ca
Summary: pcnfsdv2 requires export of all directories
Keywords: NFS export pcnfsd mountd
X-Newsreader: TIN [version 1.2 PL1]

The export file format for Net/2 did not export all directories within the
server file system, exporting the specified directory path(s) only. At the
time, this was considered a desirable feature, since it allowed the system
manager to have tighter control over the exported file systems. It turns
out that there are a couple of situations where exporting all directories
within the server file system is needed.

- pcnfsdv2 sometimes creates directories to be used as mount points on the
  fly
- some sites need to export many mount points (user's home dirs) and doing
  so explicitly can be tedious

As such, the following changes to mountd.c add an "alldirs" flag to the
export file format for the above purpose. Note that the diff -c is against
the vanilla Net/2 mountd.c and line numbers are probably different for
most systems, due to other patches. (Rumour has it that "patch -F 20" will
do the trick.)

Just in case you need it, rick

*** mountd.c.bak	Tue Sep  7 10:59:27 1993
--- mountd.c	Tue Sep  7 13:48:22 1993
***************
*** 76,95 ****
--- 76,96 ----
  	char	ml_host[RPCMNT_NAMELEN+1];
  	char	ml_dirp[RPCMNT_PATHLEN+1];
  };
  
  struct exportlist {
  	struct exportlist *ex_next;
  	struct exportlist *ex_prev;
  	struct grouplist *ex_groups;
  	int	ex_rootuid;
  	int	ex_exflags;
+ 	int	ex_alldirflg;
  	dev_t	ex_dev;
  	char	ex_dirp[RPCMNT_PATHLEN+1];
  };
  
  struct grouplist {
  	struct grouplist *gr_next;
  	struct hostent *gr_hp;
  };
  
  /* Global defs */
***************
*** 225,245 ****
  			S_IFDIR) {
  			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
  				syslog(LOG_ERR, "Can't send reply");
  			return;
  		}
  
  		/* Check in the exports list */
  		omask = sigblock(sigmask(SIGHUP));
  		ep = exphead.ex_next;
  		while (ep != NULL) {
! 			if (!strcmp(ep->ex_dirp, dirpath)) {
  				grp = ep->ex_groups;
  				if (grp == NULL)
  					break;
  
  				/* Check for a host match */
  				addrp = (u_long **)grp->gr_hp->h_addr_list;
  				for (;;) {
  					if (**addrp == saddr)
  						break;
  					if (*++addrp == NULL)
--- 226,247 ----
  			S_IFDIR) {
  			if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
  				syslog(LOG_ERR, "Can't send reply");
  			return;
  		}
  
  		/* Check in the exports list */
  		omask = sigblock(sigmask(SIGHUP));
  		ep = exphead.ex_next;
  		while (ep != NULL) {
! 			if (!strcmp(ep->ex_dirp, dirpath) ||
! 			    (stb.st_dev == ep->ex_dev && ep->ex_alldirflg)) {
  				grp = ep->ex_groups;
  				if (grp == NULL)
  					break;
  
  				/* Check for a host match */
  				addrp = (u_long **)grp->gr_hp->h_addr_list;
  				for (;;) {
  					if (**addrp == saddr)
  						break;
  					if (*++addrp == NULL)
***************
*** 430,450 ****
  	register int i;
  	register struct grouplist *grp;
  	register struct exportlist *ep, *ep2;
  	struct statfs stfsbuf;
  	struct ufs_args args;
  	struct stat sb;
  	FILE *inf;
  	char *cp, *endcp;
  	char savedc;
  	int len, dirplen;
! 	int rootuid, exflags;
  	u_long saddr;
  	struct exportlist *fep;
  
  	/*
  	 * First, get rid of the old list
  	 */
  	ep = exphead.ex_next;
  	while (ep != NULL) {
  		ep2 = ep;
  		ep = ep->ex_next;
--- 432,452 ----
  	register int i;
  	register struct grouplist *grp;
  	register struct exportlist *ep, *ep2;
  	struct statfs stfsbuf;
  	struct ufs_args args;
  	struct stat sb;
  	FILE *inf;
  	char *cp, *endcp;
  	char savedc;
  	int len, dirplen;
! 	int rootuid, exflags, alldirflg;
  	u_long saddr;
  	struct exportlist *fep;
  
  	/*
  	 * First, get rid of the old list
  	 */
  	ep = exphead.ex_next;
  	while (ep != NULL) {
  		ep2 = ep;
  		ep = ep->ex_next;
***************
*** 456,475 ****
--- 458,478 ----
  	 * exportfs() as we go along
  	 */
  	exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
  	if ((inf = fopen(exname, "r")) == NULL) {
  		syslog(LOG_ERR, "Can't open %s", exname);
  		exit(2);
  	}
  	while (fgets(line, LINESIZ, inf)) {
  		exflags = MNT_EXPORTED;
  		rootuid = def_rootuid;
+ 		alldirflg = 0;
  		cp = line;
  		nextfield(&cp, &endcp);
  
  		/*
  		 * Get file system devno and see if an entry for this
  		 * file system already exists.
  		 */
  		savedc = *endcp;
  		*endcp = '\0';
  		if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) {
***************
*** 508,528 ****
  		}
  		cp = endcp;
  		nextfield(&cp, &endcp);
  		len = endcp-cp;
  		while (len > 0) {
  			savedc = *endcp;
  			*endcp = '\0';
  			if (len > RPCMNT_NAMELEN)
  				goto more;
  			if (*cp == '-') {
! 				do_opt(cp + 1, fep, ep, &exflags, &rootuid);
  				goto more;
  			}
  			if (isdigit(*cp)) {
  				saddr = inet_addr(cp);
  				if (saddr == -1 ||
  				    (hp = gethostbyaddr((caddr_t)&saddr,
  				     sizeof(saddr), AF_INET)) == NULL) {
  					syslog(LOG_ERR,
  					    "Bad Exports File, %s: %s", cp,
  					    "Gethostbyaddr failed, ignored");
--- 511,532 ----
  		}
  		cp = endcp;
  		nextfield(&cp, &endcp);
  		len = endcp-cp;
  		while (len > 0) {
  			savedc = *endcp;
  			*endcp = '\0';
  			if (len > RPCMNT_NAMELEN)
  				goto more;
  			if (*cp == '-') {
! 				do_opt(cp + 1, fep, ep, &exflags, &rootuid,
! 					&alldirflg);
  				goto more;
  			}
  			if (isdigit(*cp)) {
  				saddr = inet_addr(cp);
  				if (saddr == -1 ||
  				    (hp = gethostbyaddr((caddr_t)&saddr,
  				     sizeof(saddr), AF_INET)) == NULL) {
  					syslog(LOG_ERR,
  					    "Bad Exports File, %s: %s", cp,
  					    "Gethostbyaddr failed, ignored");
***************
*** 599,621 ****
--- 603,633 ----
  					free_exp(ep);
  					goto nextline;
  				}
  				savedc = *cp;
  				*cp = '\0';
  			}
  			if (cp)
  				*cp = savedc;
  			ep->ex_rootuid = rootuid;
  			ep->ex_exflags = exflags;
+ 			ep->ex_alldirflg = alldirflg;
  		} else {
+ 			if (alldirflg || fep->ex_alldirflg) {
+ 				syslog(LOG_WARNING,
+ 				    "Can't export alldirs plus other exports");
+ 				free_exp(ep);
+ 				goto nextline;
+ 			}
  			ep->ex_rootuid = fep->ex_rootuid;
  			ep->ex_exflags = fep->ex_exflags;
+ 			ep->ex_alldirflg = 0;
  		}
  		ep->ex_dev = sb.st_dev;
  		ep->ex_next = exphead.ex_next;
  		ep->ex_prev = &exphead;
  		if (ep->ex_next != NULL)
  			ep->ex_next->ex_prev = ep;
  		exphead.ex_next = ep;
  nextline:
  		;
  	}
***************
*** 644,667 ****
  	}
  	*cp = p++;
  	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
  		p++;
  	*endcp = p;
  }
  
  /*
   * Parse the option string
   */
! do_opt(cpopt, fep, ep, exflagsp, rootuidp)
  	register char *cpopt;
  	struct exportlist *fep, *ep;
! 	int *exflagsp, *rootuidp;
  {
  	register char *cpoptarg, *cpoptend;
  
  	while (cpopt && *cpopt) {
  		if (cpoptend = index(cpopt, ','))
  			*cpoptend++ = '\0';
  		if (cpoptarg = index(cpopt, '='))
  			*cpoptarg++ = '\0';
  		if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
  			if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0)
--- 656,679 ----
  	}
  	*cp = p++;
  	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
  		p++;
  	*endcp = p;
  }
  
  /*
   * Parse the option string
   */
! do_opt(cpopt, fep, ep, exflagsp, rootuidp, alldirflgp)
  	register char *cpopt;
  	struct exportlist *fep, *ep;
! 	int *exflagsp, *rootuidp, *alldirflgp;
  {
  	register char *cpoptarg, *cpoptend;
  
  	while (cpopt && *cpopt) {
  		if (cpoptend = index(cpopt, ','))
  			*cpoptend++ = '\0';
  		if (cpoptarg = index(cpopt, '='))
  			*cpoptarg++ = '\0';
  		if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
  			if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0)
***************
*** 673,692 ****
--- 685,706 ----
  			if (cpoptarg && isdigit(*cpoptarg)) {
  				*rootuidp = atoi(cpoptarg);
  				if (fep && fep->ex_rootuid != *rootuidp)
  					syslog(LOG_WARNING,
  					       "uid failed for %s",
  					       ep->ex_dirp);
  			} else
  				syslog(LOG_WARNING,
  				       "uid failed for %s",
  				       ep->ex_dirp);
+ 		} else if (!strcmp(cpopt, "alldirs") || !strcmp(cpopt, "a")) {
+ 			*alldirflgp = 1;
  		} else
  			syslog(LOG_WARNING, "opt %s ignored for %s", cpopt,
  			       ep->ex_dirp);
  		cpopt = cpoptend;
  	}
  }
  
  #define	STRSIZ	(RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)
  /*
   * Routines that maintain the remote mounttab