From b2b00a3b8c3f5a2bb06c7df516573148ac512eda Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sat, 27 Dec 2008 12:32:38 -0500 Subject: [PATCH] Nsswitch now supports caching. See ncsd(8) for details. --- lib/libc/Makefile.inc | 7 +- lib/libc/net/Makefile.inc | 7 +- usr.sbin/Makefile | 7 +- usr.sbin/nscd/Makefile | 8 +- usr.sbin/nscd/nscd.c | 1 + usr.sbin/nscd/pidfile.c | 255 ++++++++++++++++++++++++++++++++++++++ usr.sbin/nscd/pidfile.h | 50 ++++++++ usr.sbin/nscd/query.c | 1 + 8 files changed, 320 insertions(+), 16 deletions(-) create mode 100644 usr.sbin/nscd/pidfile.c create mode 100644 usr.sbin/nscd/pidfile.h diff --git a/lib/libc/Makefile.inc b/lib/libc/Makefile.inc index bfc7ade651..ae9e9b5e73 100644 --- a/lib/libc/Makefile.inc +++ b/lib/libc/Makefile.inc @@ -49,10 +49,9 @@ CFLAGS+= -DYP .if defined(WANT_HESIOD) CFLAGS+= -DHESIOD .endif -# Caching isn't ready yet -#.if !defined(NO_NS_CACHING) -#CFLAGS+= -DNS_CACHING -#.endif +.if !defined(NO_NS_CACHING) +CFLAGS+= -DNS_CACHING +.endif # If there are no machine dependent sources, append all the # machine-independent sources: diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index fa1f3a8ba2..8112dcc007 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -22,10 +22,9 @@ SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c eui64.c \ rthdr.c send.c vars.c # not supported: iso_addr.c -# This isn't ready yet. -#.if !defined(NO_NS_CACHING) -#SRCS+= nscache.c nscachedcli.c -#.endif +.if !defined(NO_NS_CACHING) +SRCS+= nscache.c nscachedcli.c +.endif CFLAGS+=-DINET6 -I${.OBJDIR} diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index ba80da7c0d..95c47d6b37 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -161,10 +161,9 @@ SUBDIR+=named \ SUBDIR+=lpr .endif -# This isn't ready yet. -#.if !defined(NO_NS_CACHING) -#SUBDIR+=nscd -#.endif +.if !defined(NO_NS_CACHING) +SUBDIR+=nscd +.endif .if !defined(NO_SENDMAIL) SUBDIR+=editmap \ diff --git a/usr.sbin/nscd/Makefile b/usr.sbin/nscd/Makefile index d1e1da0d5a..b135b4844a 100644 --- a/usr.sbin/nscd/Makefile +++ b/usr.sbin/nscd/Makefile @@ -3,11 +3,11 @@ PROG= nscd MAN= nscd.conf.5 nscd.8 -WARNS?= 2 +WARNS?= 0 CFLAGS+=-fno-strict-aliasing -SRCS= agent.c nscd.c nscdcli.c cachelib.c cacheplcs.c debug.c log.c \ - config.c query.c mp_ws_query.c mp_rs_query.c singletons.c protocol.c \ - parser.c +SRCS= agent.c cachelib.c cacheplcs.c config.c debug.c log.c \ + mp_rs_query.c mp_ws_query.c nscd.c nscdcli.c parser.c pidfile.c \ + protocol.c query.c singletons.c CFLAGS+= -DCONFIG_PATH="\"${PREFIX}/etc/nscd.conf\"" DPADD= ${LIBM} ${LIBPTHREAD} ${LIBUTIL} LDADD= -lm -lpthread -lutil diff --git a/usr.sbin/nscd/nscd.c b/usr.sbin/nscd/nscd.c index ec18f23bbb..d8d01eedfa 100644 --- a/usr.sbin/nscd/nscd.c +++ b/usr.sbin/nscd/nscd.c @@ -53,6 +53,7 @@ #include "log.h" #include "nscdcli.h" #include "parser.h" +#include "pidfile.h" #include "query.h" #include "singletons.h" diff --git a/usr.sbin/nscd/pidfile.c b/usr.sbin/nscd/pidfile.c new file mode 100644 index 0000000000..eff5620767 --- /dev/null +++ b/usr.sbin/nscd/pidfile.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2005 Pawel Jakub Dawidek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libutil/pidfile.c,v 1.9 2008/10/20 17:41:08 des Exp $ + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pidfile.h" + +static int _pidfile_remove(struct pidfh *pfh, int freeit); + +static int +pidfile_verify(struct pidfh *pfh) +{ + struct stat sb; + + if (pfh == NULL || pfh->pf_fd == -1) + return (EDOOFUS); + /* + * Check remembered descriptor. + */ + if (fstat(pfh->pf_fd, &sb) == -1) + return (errno); + if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino) + return (EDOOFUS); + return (0); +} + +static int +pidfile_read(const char *path, pid_t *pidptr) +{ + char buf[16], *endptr; + int error, fd, i; + + fd = open(path, O_RDONLY); + if (fd == -1) + return (errno); + + i = read(fd, buf, sizeof(buf) - 1); + error = errno; /* Remember errno in case close() wants to change it. */ + close(fd); + if (i == -1) + return (error); + else if (i == 0) + return (EAGAIN); + buf[i] = '\0'; + + *pidptr = strtol(buf, &endptr, 10); + if (endptr != &buf[i]) + return (EINVAL); + + return (0); +} + +struct pidfh * +pidfile_open(const char *path, mode_t mode, pid_t *pidptr) +{ + struct pidfh *pfh; + struct stat sb; + int error, fd, len, count; + struct timespec rqtp; + + pfh = malloc(sizeof(*pfh)); + if (pfh == NULL) + return (NULL); + + if (path == NULL) + len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), + "/var/run/%s.pid", getprogname()); + else + len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), + "%s", path); + if (len >= (int)sizeof(pfh->pf_path)) { + free(pfh); + errno = ENAMETOOLONG; + return (NULL); + } + + /* + * Open the PID file and obtain exclusive lock. + * We truncate PID file here only to remove old PID immediatelly, + * PID file will be truncated again in pidfile_write(), so + * pidfile_write() can be called multiple times. + */ + fd = flopen(pfh->pf_path, + O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode); + if (fd == -1) { + count = 0; + rqtp.tv_sec = 0; + rqtp.tv_nsec = 5000000; + if (errno == EWOULDBLOCK && pidptr != NULL) { + again: + errno = pidfile_read(pfh->pf_path, pidptr); + if (errno == 0) + errno = EEXIST; + else if (errno == EAGAIN) { + if (++count <= 3) { + nanosleep(&rqtp, 0); + goto again; + } + } + } + free(pfh); + return (NULL); + } + /* + * Remember file information, so in pidfile_write() we are sure we write + * to the proper descriptor. + */ + if (fstat(fd, &sb) == -1) { + error = errno; + unlink(pfh->pf_path); + close(fd); + free(pfh); + errno = error; + return (NULL); + } + + pfh->pf_fd = fd; + pfh->pf_dev = sb.st_dev; + pfh->pf_ino = sb.st_ino; + + return (pfh); +} + +int +pidfile_write(struct pidfh *pfh) +{ + char pidstr[16]; + int error, fd; + + /* + * Check remembered descriptor, so we don't overwrite some other + * file if pidfile was closed and descriptor reused. + */ + errno = pidfile_verify(pfh); + if (errno != 0) { + /* + * Don't close descriptor, because we are not sure if it's ours. + */ + return (-1); + } + fd = pfh->pf_fd; + + /* + * Truncate PID file, so multiple calls of pidfile_write() are allowed. + */ + if (ftruncate(fd, 0) == -1) { + error = errno; + _pidfile_remove(pfh, 0); + errno = error; + return (-1); + } + + snprintf(pidstr, sizeof(pidstr), "%u", getpid()); + if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { + error = errno; + _pidfile_remove(pfh, 0); + errno = error; + return (-1); + } + + return (0); +} + +int +pidfile_close(struct pidfh *pfh) +{ + int error; + + error = pidfile_verify(pfh); + if (error != 0) { + errno = error; + return (-1); + } + + if (close(pfh->pf_fd) == -1) + error = errno; + free(pfh); + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} + +static int +_pidfile_remove(struct pidfh *pfh, int freeit) +{ + int error; + + error = pidfile_verify(pfh); + if (error != 0) { + errno = error; + return (-1); + } + + if (unlink(pfh->pf_path) == -1) + error = errno; + if (close(pfh->pf_fd) == -1) { + if (error == 0) + error = errno; + } + if (freeit) + free(pfh); + else + pfh->pf_fd = -1; + if (error != 0) { + errno = error; + return (-1); + } + return (0); +} + +int +pidfile_remove(struct pidfh *pfh) +{ + + return (_pidfile_remove(pfh, 1)); +} diff --git a/usr.sbin/nscd/pidfile.h b/usr.sbin/nscd/pidfile.h new file mode 100644 index 0000000000..974b76c922 --- /dev/null +++ b/usr.sbin/nscd/pidfile.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 + * The DragonFly Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _PIDFILE_H_ +#define _PIDFILE_H_ + +#include + +struct pidfh { + int pf_fd; + char pf_path[MAXPATHLEN + 1]; + dev_t pf_dev; + ino_t pf_ino; +}; + +int pidfile_close(struct pidfh *pfh); +struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr); +int pidfile_remove(struct pidfh *pfh); +int pidfile_write(struct pidfh *pfh); + +#endif /* _PIDFILE_H_ */ diff --git a/usr.sbin/nscd/query.c b/usr.sbin/nscd/query.c index ed9a2cb901..f317136ed8 100644 --- a/usr.sbin/nscd/query.c +++ b/usr.sbin/nscd/query.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include -- 2.41.0