]> git.ipfire.org Git - thirdparty/rng-tools.git/blame - util.c
Polish README a bit.
[thirdparty/rng-tools.git] / util.c
CommitLineData
c192b4cf
JG
1
2/*
3 * Copyright 2009 Red Hat, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20#define _GNU_SOURCE
21
22#ifndef HAVE_CONFIG_H
23#error Invalid or missing autoconf build environment
24#endif
25
26#include "rng-tools-config.h"
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <string.h>
32#include <errno.h>
33
34#include "rngd.h"
35
36int write_pid_file(const char *pid_fn)
37{
38 char str[32], *s;
39 size_t bytes;
40 int fd;
41 struct flock lock;
42 int err;
43
44 /* build file data */
45 sprintf(str, "%u\n", (unsigned int) getpid());
46
47 /* open non-exclusively (works on NFS v2) */
48 fd = open(pid_fn, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
49 if (fd < 0) {
50 err = errno;
51
52 message(LOG_DAEMON|LOG_ERR, "Cannot open PID file %s: %s",
53 pid_fn, strerror(err));
54 return -err;
55 }
56
57 /* lock */
58 memset(&lock, 0, sizeof(lock));
59 lock.l_type = F_WRLCK;
60 lock.l_whence = SEEK_SET;
61 if (fcntl(fd, F_SETLK, &lock) != 0) {
62 err = errno;
63 if (err == EAGAIN) {
64 message(LOG_DAEMON|LOG_ERR, "PID file %s is already locked",
65 pid_fn);
66 } else {
67 message(LOG_DAEMON|LOG_ERR, "Cannot lock PID file %s: %s",
68 pid_fn, strerror(err));
69 }
70 close(fd);
71 return -err;
72 }
73
74 /* write file data */
75 bytes = strlen(str);
76 s = str;
77 while (bytes > 0) {
78 ssize_t rc = write(fd, s, bytes);
79 if (rc < 0) {
80 err = errno;
81 message(LOG_DAEMON|LOG_ERR, "PID number write failed: %s",
82 strerror(err));
83 goto err_out;
84 }
85
86 bytes -= rc;
87 s += rc;
88 }
89
90 /* make sure file data is written to disk */
91 if (fsync(fd) < 0) {
92 err = errno;
93 message(LOG_DAEMON|LOG_ERR, "PID file fsync failed: %s", strerror(err));
94 goto err_out;
95 }
96
97 return fd;
98
99err_out:
100 unlink(pid_fn);
101 close(fd);
102 return -err;
103}
104