From 78a7a558feffc241c981fb813b3f2828d1a81198 Mon Sep 17 00:00:00 2001 From: des Date: Fri, 11 May 2007 11:14:32 +0000 Subject: [PATCH] Pull flopen() and pidfile_*() (renamed to vpf_*()) from FreeBSD. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1408 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/include/Makefile.am | 2 + varnish-cache/include/flopen.h | 33 +++ varnish-cache/include/vpf.h | 40 ++++ varnish-cache/lib/libvarnish/Makefile.am | 2 + varnish-cache/lib/libvarnish/flopen.c | 96 +++++++++ varnish-cache/lib/libvarnish/vpf.c | 259 +++++++++++++++++++++++ 6 files changed, 432 insertions(+) create mode 100644 varnish-cache/include/flopen.h create mode 100644 varnish-cache/include/vpf.h create mode 100644 varnish-cache/lib/libvarnish/flopen.c create mode 100644 varnish-cache/lib/libvarnish/vpf.c diff --git a/varnish-cache/include/Makefile.am b/varnish-cache/include/Makefile.am index af9f1aa9..aaa8d2a8 100644 --- a/varnish-cache/include/Makefile.am +++ b/varnish-cache/include/Makefile.am @@ -14,11 +14,13 @@ noinst_HEADERS = \ compat/strndup.h \ compat/vasprintf.h \ compat/vis.h \ + flopen.h \ http_headers.h \ libvarnish.h \ libvcl.h \ miniobj.h \ queue.h \ + vpf.h \ vsb.h \ shmlog.h \ shmlog_tags.h \ diff --git a/varnish-cache/include/flopen.h b/varnish-cache/include/flopen.h new file mode 100644 index 00000000..3af1eb26 --- /dev/null +++ b/varnish-cache/include/flopen.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2007 Dag-Erling Coïdan Smørgrav + * 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 + * in this position and unchanged. + * 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 AUTHOR 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 AUTHOR 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 FLOPEN_H_INCLUDED +#define FLOPEN_H_INCLUDED + +int flopen(const char *, int, ...); + +#endif diff --git a/varnish-cache/include/vpf.h b/varnish-cache/include/vpf.h new file mode 100644 index 00000000..8845ee72 --- /dev/null +++ b/varnish-cache/include/vpf.h @@ -0,0 +1,40 @@ +/*- + * 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. + * + * Derived from: + * $FreeBSD: src/lib/libutil/libutil.h,v 1.41 2005/08/24 17:21:38 pjd Exp $ + */ + +#ifndef VPF_H_INCLUDED +#define VPF_H_INCLUDED + +struct pidfh; + +struct pidfh *vpf_open(const char *path, mode_t mode, pid_t *pidptr); +int vpf_write(struct pidfh *pfh); +int vpf_close(struct pidfh *pfh); +int vpf_remove(struct pidfh *pfh); + +#endif diff --git a/varnish-cache/lib/libvarnish/Makefile.am b/varnish-cache/lib/libvarnish/Makefile.am index a4a56603..d2d1e0cd 100644 --- a/varnish-cache/lib/libvarnish/Makefile.am +++ b/varnish-cache/lib/libvarnish/Makefile.am @@ -11,8 +11,10 @@ libvarnish_la_SOURCES = \ cli.c \ cli_common.c \ crc32.c \ + flopen.c \ time.c \ version.c \ + vpf.c \ vsb.c libvarnish_la_CFLAGS = -include config.h diff --git a/varnish-cache/lib/libvarnish/flopen.c b/varnish-cache/lib/libvarnish/flopen.c new file mode 100644 index 00000000..02eb40f8 --- /dev/null +++ b/varnish-cache/lib/libvarnish/flopen.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2007 Dag-Erling Coïdan Smørgrav + * 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 + * in this position and unchanged. + * 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 AUTHOR 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 AUTHOR 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. + * + * Derived from: + * $FreeBSD: src/lib/libutil/flopen.c,v 1.4 2007/05/10 15:01:42 des Exp $ + */ + +#include +#include + +#include +#include +#include +#include + +#include "flopen.h" + +int +flopen(const char *path, int flags, ...) +{ + int fd, operation, serrno; + struct stat sb, fsb; + mode_t mode; + +#ifdef O_EXLOCK + flags &= ~O_EXLOCK; +#endif + + mode = 0; + if (flags & O_CREAT) { + va_list ap; + + va_start(ap, flags); + mode = va_arg(ap, int); /* mode_t promoted to int */ + va_end(ap); + } + + operation = LOCK_EX; + if (flags & O_NONBLOCK) + operation |= LOCK_NB; + + for (;;) { + if ((fd = open(path, flags, mode)) == -1) + /* non-existent or no access */ + return (-1); + if (flock(fd, operation) == -1) { + /* unsupported or interrupted */ + serrno = errno; + close(fd); + errno = serrno; + return (-1); + } + if (stat(path, &sb) == -1) { + /* disappeared from under our feet */ + close(fd); + continue; + } + if (fstat(fd, &fsb) == -1) { + /* can't happen [tm] */ + serrno = errno; + close(fd); + errno = serrno; + return (-1); + } + if (sb.st_dev != fsb.st_dev || + sb.st_ino != fsb.st_ino) { + /* changed under our feet */ + close(fd); + continue; + } + return (fd); + } +} diff --git a/varnish-cache/lib/libvarnish/vpf.c b/varnish-cache/lib/libvarnish/vpf.c new file mode 100644 index 00000000..a5e8010f --- /dev/null +++ b/varnish-cache/lib/libvarnish/vpf.c @@ -0,0 +1,259 @@ +/*- + * 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. + * + * Derived from: + * $FreeBSD: src/lib/libutil/pidfile.c,v 1.5 2007/05/11 11:10:05 des Exp $ + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_STRLCPY +#include "compat/strlcpy.h" +#endif + +#include "flopen.h" +#include "vpf.h" + +struct pidfh { + int pf_fd; + char pf_path[MAXPATHLEN + 1]; + __dev_t pf_dev; + ino_t pf_ino; +}; + +static int _vpf_remove(struct pidfh *pfh, int freeit); + +static int +vpf_verify(struct pidfh *pfh) +{ + struct stat sb; + + if (pfh == NULL || pfh->pf_fd == -1) + return (EINVAL); + /* + * 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 (EINVAL); + return (0); +} + +static int +vpf_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); + buf[i] = '\0'; + + *pidptr = strtol(buf, &endptr, 10); + if (endptr != &buf[i]) + return (EINVAL); + + return (0); +} + +struct pidfh * +vpf_open(const char *path, mode_t mode, pid_t *pidptr) +{ + struct pidfh *pfh; + struct stat sb; + int error, fd, len; + + pfh = malloc(sizeof(*pfh)); + if (pfh == NULL) + return (NULL); + +#if 0 + if (path == NULL) + len = snprintf(pfh->pf_path, sizeof(pfh->pf_path), + "/var/run/%s.pid", getprogname()); + else +#endif + 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 vpf_write(), so + * vpf_write() can be called multiple times. + */ + fd = flopen(pfh->pf_path, + O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode); + if (fd == -1) { + if (errno == EWOULDBLOCK && pidptr != NULL) { + errno = vpf_read(pfh->pf_path, pidptr); + if (errno == 0) + errno = EEXIST; + } + free(pfh); + return (NULL); + } + /* + * Remember file information, so in vpf_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 +vpf_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 = vpf_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 vpf_write() are allowed. + */ + if (ftruncate(fd, 0) == -1) { + error = errno; + _vpf_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; + _vpf_remove(pfh, 0); + errno = error; + return (-1); + } + + return (0); +} + +int +vpf_close(struct pidfh *pfh) +{ + int error; + + error = vpf_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 +_vpf_remove(struct pidfh *pfh, int freeit) +{ + int error; + + error = vpf_verify(pfh); + if (error != 0) { + errno = error; + return (-1); + } + + if (unlink(pfh->pf_path) == -1) + error = errno; + if (flock(pfh->pf_fd, LOCK_UN) == -1) { + if (error == 0) + 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 +vpf_remove(struct pidfh *pfh) +{ + + return (_vpf_remove(pfh, 1)); +} -- 2.39.5