Module Name:    src
Committed By:   chuck
Date:           Thu Nov  5 19:34:06 UTC 2009

Modified Files:
        src/usr.sbin/ypbind: ypbind.c

Log Message:
in the case where ypbind is serving more than one domain (i.e.
not just the yp_get_default_domain() domain), we must remove
any old binding files from /var/yp/binding (BINDINGDIR) from
previous runs, or the non-yp_get_default_domain()'s will not
bind properly.   add a purge_bindingdir() function that basically
does "rm BINDINGDIR/*.[0-9]" at ypbind startup time.

example case of where this is an issue: bind a second (non-default)
domain.   ypbind will create and flock a /var/yp/binding/xxx.2
file for it.  stop and restart ypbind.  the old /var/yp/binding/xxx.2
file will remain from the previous run.   since it is not flock()'d
by the new instance of ypbind, libc functions like yp_master() will
fail without even bothering to talk to ypbind itself.   (and ypbind
is totally unaware of the old file...)


To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/usr.sbin/ypbind/ypbind.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/ypbind/ypbind.c
diff -u src/usr.sbin/ypbind/ypbind.c:1.58 src/usr.sbin/ypbind/ypbind.c:1.59
--- src/usr.sbin/ypbind/ypbind.c:1.58	Sun Jan 18 10:39:17 2009
+++ src/usr.sbin/ypbind/ypbind.c	Thu Nov  5 19:34:06 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ypbind.c,v 1.58 2009/01/18 10:39:17 lukem Exp $	*/
+/*	$NetBSD: ypbind.c,v 1.59 2009/11/05 19:34:06 chuck Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993 Theo de Raadt <[email protected]>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifndef LINT
-__RCSID("$NetBSD: ypbind.c,v 1.58 2009/01/18 10:39:17 lukem Exp $");
+__RCSID("$NetBSD: ypbind.c,v 1.59 2009/11/05 19:34:06 chuck Exp $");
 #endif
 
 #include <sys/param.h>
@@ -129,6 +129,7 @@
 static struct _dom_binding *makebinding(const char *);
 static int makelock(struct _dom_binding *);
 static void removelock(struct _dom_binding *);
+static int purge_bindingdir(char *);
 static void *ypbindproc_null_2(SVCXPRT *, void *);
 static void *ypbindproc_domain_2(SVCXPRT *, void *);
 static void *ypbindproc_setdom_2(SVCXPRT *, void *);
@@ -221,6 +222,49 @@
 	(void)unlink(path);
 }
 
+/*
+ * purge_bindingdir: remove old binding files (i.e. "rm BINDINGDIR/*.[0-9]")
+ *
+ * local YP functions [e.g. yp_master()] will fail without even talking
+ * to ypbind if there is a stale (non-flock'd) binding file present.
+ * we have to scan the entire BINDINGDIR for binding files, because
+ * ypbind may bind more than just the yp_get_default_domain() domain.
+ */
+static int
+purge_bindingdir(char *dirpath) {
+	DIR *dirp;
+	int unlinkedfiles, l;
+	struct dirent *dp;
+	char pathname[MAXPATHLEN];
+
+	if ((dirp = opendir(dirpath)) == NULL)
+		return(-1);   /* at this point, shouldn't ever happen */
+
+	do {
+		unlinkedfiles = 0;
+		while ((dp = readdir(dirp)) != NULL) {
+			l = dp->d_namlen;
+			/* 'rm *.[0-9]' */
+			if (l > 2 && dp->d_name[l-2] == '.' &&
+			    dp->d_name[l-1] >= '0' && dp->d_name[l-1] <= '9') {
+				(void)snprintf(pathname, sizeof(pathname), 
+					"%s/%s", dirpath, dp->d_name);
+				if (unlink(pathname) < 0 && errno != ENOENT)
+					return(-1);
+				unlinkedfiles++;
+			}
+		}
+
+		/* rescan dir if we removed it */
+		if (unlinkedfiles)
+			rewinddir(dirp);
+
+	} while (unlinkedfiles);
+
+	closedir(dirp);
+	return(0);
+}
+
 static void *
 /*ARGSUSED*/
 ypbindproc_null_2(SVCXPRT *transp, void *argp)
@@ -507,8 +551,6 @@
 	/* initialise syslog */
 	openlog("ypbind", LOG_PERROR | LOG_PID, LOG_DAEMON);
 
-	/* blow away everything in BINDINGDIR */
-
 	lockfd = open(_PATH_YPBIND_LOCK, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644);
 	if (lockfd == -1)
 		err(1, "Cannot create %s", _PATH_YPBIND_LOCK);
@@ -559,6 +601,10 @@
 	if (_yp_invalid_domain(domainname))
 		errx(1, "bad domainname: %s", domainname);
 
+	/* blow away old bindings in BINDINGDIR */
+	if (purge_bindingdir(BINDINGDIR) < 0)
+		errx(1, "unable to purge old bindings from %s", BINDINGDIR);
+
 	/* build initial domain binding, make it "unsuccessful" */
 	ypbindlist = makebinding(domainname);
 	ypbindlist->dom_vers = YPVERS;

Reply via email to