mirror of
https://gitlab.freedesktop.org/libbsd/libbsd.git
synced 2025-07-03 01:05:24 +02:00
Add pidfile functions
Taken from FreeBSD. Remove MAXPATHLEN from ‘struct pidfh’ and allocate pf_path dynamically, as some systems do not have such limits. Use dev_t instead of __dev_t. Replace EDOOFUS with EINVAL.
This commit is contained in:
parent
98a2479f0b
commit
2a81893cc0
2
Makefile
2
Makefile
@ -31,6 +31,7 @@ LIB_SRCS := \
|
|||||||
dehumanize_number.c \
|
dehumanize_number.c \
|
||||||
inet_net_pton.c \
|
inet_net_pton.c \
|
||||||
hash/md5.c \
|
hash/md5.c \
|
||||||
|
pidfile.c \
|
||||||
readpassphrase.c \
|
readpassphrase.c \
|
||||||
setmode.c \
|
setmode.c \
|
||||||
strmode.c \
|
strmode.c \
|
||||||
@ -82,6 +83,7 @@ LIB_MANS := \
|
|||||||
humanize_number.3 \
|
humanize_number.3 \
|
||||||
fmtcheck.3 \
|
fmtcheck.3 \
|
||||||
nlist.3 \
|
nlist.3 \
|
||||||
|
pidfile.3 \
|
||||||
setmode.3 \
|
setmode.3 \
|
||||||
getmode.3 \
|
getmode.3 \
|
||||||
strmode.3 \
|
strmode.3 \
|
||||||
|
5
Versions
5
Versions
@ -53,5 +53,10 @@ LIBBSD_0.2 {
|
|||||||
readpassphrase;
|
readpassphrase;
|
||||||
|
|
||||||
flopen;
|
flopen;
|
||||||
|
|
||||||
|
pidfile_open;
|
||||||
|
pidfile_write;
|
||||||
|
pidfile_close;
|
||||||
|
pidfile_remove;
|
||||||
} LIBBSD_0.1;
|
} LIBBSD_0.1;
|
||||||
|
|
||||||
|
@ -42,12 +42,24 @@
|
|||||||
#include <features.h>
|
#include <features.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/* for pidfile.c */
|
||||||
|
struct pidfh {
|
||||||
|
int pf_fd;
|
||||||
|
char *pf_path;
|
||||||
|
dev_t pf_dev;
|
||||||
|
ino_t pf_ino;
|
||||||
|
};
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
int humanize_number(char *buf, size_t len, int64_t bytes,
|
int humanize_number(char *buf, size_t len, int64_t bytes,
|
||||||
const char *suffix, int scale, int flags);
|
const char *suffix, int scale, int flags);
|
||||||
|
|
||||||
int flopen(const char *_path, int _flags, ...);
|
int flopen(const char *_path, int _flags, ...);
|
||||||
|
|
||||||
|
struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
|
||||||
|
int pidfile_write(struct pidfh *pfh);
|
||||||
|
int pidfile_close(struct pidfh *pfh);
|
||||||
|
int pidfile_remove(struct pidfh *pfh);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
/* humanize_number(3) */
|
/* humanize_number(3) */
|
||||||
|
254
src/pidfile.3
Normal file
254
src/pidfile.3
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||||
|
.\" 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$
|
||||||
|
.\"
|
||||||
|
.Dd October 20, 2008
|
||||||
|
.Dt PIDFILE 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pidfile_open ,
|
||||||
|
.Nm pidfile_write ,
|
||||||
|
.Nm pidfile_close ,
|
||||||
|
.Nm pidfile_remove
|
||||||
|
.Nd "library for PID files handling"
|
||||||
|
.Sh LIBRARY
|
||||||
|
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
|
||||||
|
.Lb libbsd
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In libutil.h
|
||||||
|
.Ft "struct pidfh *"
|
||||||
|
.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile_write "struct pidfh *pfh"
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile_close "struct pidfh *pfh"
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile_remove "struct pidfh *pfh"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm pidfile
|
||||||
|
family of functions allows daemons to handle PID files.
|
||||||
|
It uses
|
||||||
|
.Xr flopen 3
|
||||||
|
to lock a pidfile and detect already running daemons.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function opens (or creates) a file specified by the
|
||||||
|
.Fa path
|
||||||
|
argument and locks it.
|
||||||
|
If a file can not be locked, a PID of an already running daemon is returned in
|
||||||
|
the
|
||||||
|
.Fa pidptr
|
||||||
|
argument (if it is not
|
||||||
|
.Dv NULL ) .
|
||||||
|
The function does not write process' PID into the file here, so it can be
|
||||||
|
used before
|
||||||
|
.Fn fork Ns ing
|
||||||
|
and exit with a proper error message when needed.
|
||||||
|
If the
|
||||||
|
.Fa path
|
||||||
|
argument is
|
||||||
|
.Dv NULL ,
|
||||||
|
.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
|
||||||
|
file will be used.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_write
|
||||||
|
function writes process' PID into a previously opened file.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_close
|
||||||
|
function closes a pidfile.
|
||||||
|
It should be used after daemon
|
||||||
|
.Fn fork Ns s
|
||||||
|
to start a child process.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_remove
|
||||||
|
function closes and removes a pidfile.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function returns a valid pointer to a
|
||||||
|
.Vt pidfh
|
||||||
|
structure on success, or
|
||||||
|
.Dv NULL
|
||||||
|
if an error occurs.
|
||||||
|
If an error occurs,
|
||||||
|
.Va errno
|
||||||
|
will be set.
|
||||||
|
.Pp
|
||||||
|
.Rv -std pidfile_write pidfile_close pidfile_remove
|
||||||
|
.Sh EXAMPLES
|
||||||
|
The following example shows in which order these functions should be used.
|
||||||
|
Note that it is safe to pass
|
||||||
|
.Dv NULL
|
||||||
|
to
|
||||||
|
.Fn pidfile_write ,
|
||||||
|
.Fn pidfile_remove
|
||||||
|
and
|
||||||
|
.Fn pidfile_close
|
||||||
|
functions.
|
||||||
|
.Bd -literal
|
||||||
|
struct pidfh *pfh;
|
||||||
|
pid_t otherpid, childpid;
|
||||||
|
|
||||||
|
pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
|
||||||
|
if (pfh == NULL) {
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
|
||||||
|
(intmax_t)otherpid);
|
||||||
|
}
|
||||||
|
/* If we cannot create pidfile from other reasons, only warn. */
|
||||||
|
warn("Cannot open or create pidfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemon(0, 0) == -1) {
|
||||||
|
warn("Cannot daemonize");
|
||||||
|
pidfile_remove(pfh);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pidfile_write(pfh);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
/* Do work. */
|
||||||
|
childpid = fork();
|
||||||
|
switch (childpid) {
|
||||||
|
case -1:
|
||||||
|
syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
pidfile_close(pfh);
|
||||||
|
/* Do child work. */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pidfile_remove(pfh);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
.Ed
|
||||||
|
.Sh ERRORS
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EEXIST
|
||||||
|
Some process already holds the lock on the given pidfile, meaning that a
|
||||||
|
daemon is already running.
|
||||||
|
.It Bq Er ENAMETOOLONG
|
||||||
|
Specified pidfile's name is too long.
|
||||||
|
.It Bq Er EINVAL
|
||||||
|
Some process already holds the lock on the given pidfile, but PID read
|
||||||
|
from there is invalid.
|
||||||
|
.It Bq Er EAGAIN
|
||||||
|
Some process already holds the lock on the given pidfile, but the file
|
||||||
|
is truncated.
|
||||||
|
Most likely, the existing daemon is writing new PID into
|
||||||
|
the file.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function may also fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr fstat 2 ,
|
||||||
|
.Xr open 2 ,
|
||||||
|
and
|
||||||
|
.Xr read 2
|
||||||
|
calls.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_write
|
||||||
|
function will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EINVAL
|
||||||
|
Improper function use.
|
||||||
|
Probably called before
|
||||||
|
.Fn pidfile_open .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_write
|
||||||
|
function may also fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr fstat 2 ,
|
||||||
|
.Xr ftruncate 2 ,
|
||||||
|
and
|
||||||
|
.Xr write 2
|
||||||
|
calls.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_close
|
||||||
|
function may fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr close 2
|
||||||
|
and
|
||||||
|
.Xr fstat 2
|
||||||
|
calls.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_remove
|
||||||
|
function will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EINVAL
|
||||||
|
Improper function use.
|
||||||
|
Probably called not from the process which made
|
||||||
|
.Fn pidfile_write .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_remove
|
||||||
|
function may also fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr close 2 ,
|
||||||
|
.Xr fstat 2 ,
|
||||||
|
.Xr write 2 ,
|
||||||
|
and
|
||||||
|
.Xr unlink 2
|
||||||
|
system calls and the
|
||||||
|
.Xr flopen 3
|
||||||
|
library function.
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr open 2 ,
|
||||||
|
.Xr daemon 3 ,
|
||||||
|
.Xr flopen 3
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Nm pidfile
|
||||||
|
functionality is based on ideas from
|
||||||
|
.An John-Mark Gurney Aq jmg@FreeBSD.org .
|
||||||
|
.Pp
|
||||||
|
The code and manual page was written by
|
||||||
|
.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org .
|
255
src/pidfile.c
Normal file
255
src/pidfile.c
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libutil.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 (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
|
||||||
|
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 = asprintf(&pfh->pf_path, "/var/run/%s.pid", getprogname());
|
||||||
|
if (len < 0) {
|
||||||
|
free(pfh);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
pfh->pf_path = strdup(path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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->pf_path);
|
||||||
|
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);
|
||||||
|
free(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->pf_path);
|
||||||
|
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->pf_path);
|
||||||
|
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));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user