From f4d93dcaff3858b8490578efb581eebc97878d9f Mon Sep 17 00:00:00 2001 From: wpaul Date: Wed, 10 Jan 1996 17:44:10 +0000 Subject: - Fix error reporting when checking order number via NIS: we return zero on a failure, but if we're checking a corrupt map we could also get back a zero from ypserv without really encountering any actual error. Flag this condition and generate an meaningful error message. - Fix transmission of ypxfr_clear to ypserv: error checking was wrong and we sending YPXFR_YPERR as an error status instead of YPXFR_CLEAR. - To help avoid a race condition (or at least reduce the likelyhood of it occuring), use rename() to move a newly transfered map into place instead of unlink()ing the old one first and then renaming. Da man page sez that rename should do the unlink() for us. This prevents ypserv from returning 'no such map in domain' when asked to query a map which ypxfr has just unlink()ed but not yet replaced. --- libexec/ypxfr/ypxfr_main.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'libexec/ypxfr') diff --git a/libexec/ypxfr/ypxfr_main.c b/libexec/ypxfr/ypxfr_main.c index e603409..cc4e1b4 100644 --- a/libexec/ypxfr/ypxfr_main.c +++ b/libexec/ypxfr/ypxfr_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ypxfr_main.c,v 1.13 1996/01/06 19:59:41 wpaul Exp $ + * $Id: ypxfr_main.c,v 1.15 1996/01/10 17:41:55 wpaul Exp $ */ #include #include @@ -43,13 +43,14 @@ #include #include #include +#include #include struct dom_binding {}; #include #include "ypxfr_extern.h" #ifndef lint -static const char rcsid[] = "$Id: ypxfr_main.c,v 1.13 1996/01/06 19:59:41 wpaul Exp $"; +static const char rcsid[] = "$Id: ypxfr_main.c,v 1.15 1996/01/10 17:41:55 wpaul Exp $"; #endif char *progname = "ypxfr"; @@ -333,7 +334,8 @@ the local domain name isn't set"); ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", - ypxfr_mapname, ypxfrerr_string(yp_errno)); + ypxfr_mapname, yp_errno == YPXFR_SUCC ? + "map has order 0" : ypxfrerr_string(yp_errno)); ypxfr_exit(YPXFR_YPERR,NULL); } @@ -454,7 +456,8 @@ the local domain name isn't set"); ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", - ypxfr_mapname, ypxfrerr_string(yp_errno)); + ypxfr_mapname, yp_errno == YPXFR_SUCC ? + "map has order 0" : ypxfrerr_string(yp_errno)); ypxfr_exit(YPXFR_YPERR,&ypxfr_temp_map); } @@ -466,21 +469,26 @@ the local domain name isn't set"); * The FreeBSD ypserv doesn't really need this, but we send it * here anyway for the sake of consistency. */ - if (!ypxfr_clear) { + if (ypxfr_clear) { char in = 0; char *out = NULL; - if (callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, xdr_void, - (void *)&in, xdr_void, (void *)out) == NULL) { - yp_error("failed to send 'clear' to local ypserv"); - ypxfr_exit(YPXFR_YPERR, &ypxfr_temp_map); + int stat; + if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, + xdr_void, (void *)&in, + xdr_void, (void *)out)) != RPC_SUCCESS) { + yp_error("failed to send 'clear' to local ypserv: %s", + clnt_sperrno((enum clnt_stat) stat)); + ypxfr_exit(YPXFR_CLEAR, &ypxfr_temp_map); } } - if (unlink(buf) == -1 && errno != ENOENT) { - yp_error("unlink(%s) failed: %s", buf, strerror(errno)); - ypxfr_exit(YPXFR_FILE,NULL); - } - + /* + * Put the new map in place immediately. I'm not sure if the + * kernel does an unlink() and rename() atomically in the event + * that we move a new copy of a map over the top of an existing + * one, but there's less chance of a race condition happening + * than if we were to do the unlink() ourselves. + */ if (rename(ypxfr_temp_map, buf) == -1) { yp_error("rename(%s,%s) failed: %s", ypxfr_temp_map, buf, strerror(errno)); -- cgit v1.1