summaryrefslogtreecommitdiff
path: root/multipathd/pidfile.c
blob: 9bac1dd6856addbc5a956affc1b47e75475f9c94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <sys/types.h> /* for pid_t */
#include <sys/stat.h>  /* for open */
#include <signal.h>    /* for kill() */
#include <errno.h>     /* for ESHRC */
#include <stdio.h>     /* for f...() */
#include <string.h>    /* for memset() */
#include <stdlib.h>    /* for atoi() */
#include <unistd.h>    /* for unlink() */
#include <fcntl.h>     /* for fcntl() */

#include "debug.h"

#include "pidfile.h"

int pidfile_create(const char *pidFile, pid_t pid)
{
	char buf[20];
	struct flock lock;
	int fd, value;

	if((fd = open(pidFile, O_WRONLY | O_CREAT,
		       (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
		condlog(0, "Cannot open pidfile [%s], error was [%s]",
			pidFile, strerror(errno));
		return -errno;
	}
	lock.l_type = F_WRLCK;
	lock.l_start = 0;
	lock.l_whence = SEEK_SET;
	lock.l_len = 0;

	if (fcntl(fd, F_SETLK, &lock) < 0) {
		if (errno != EACCES && errno != EAGAIN)
			condlog(0, "Cannot lock pidfile [%s], error was [%s]",
				pidFile, strerror(errno));
		else
			condlog(0, "process is already running");
		goto fail;
	}
	if (ftruncate(fd, 0) < 0) {
		condlog(0, "Cannot truncate pidfile [%s], error was [%s]",
			pidFile, strerror(errno));
		goto fail;
	}
	memset(buf, 0, sizeof(buf));
	snprintf(buf, sizeof(buf)-1, "%u", pid);
	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
		condlog(0, "Cannot write pid to pidfile [%s], error was [%s]",
			pidFile, strerror(errno));
		goto fail;
	}
	if ((value = fcntl(fd, F_GETFD, 0)) < 0) {
		condlog(0, "Cannot get close-on-exec flag from pidfile [%s], "
			"error was [%s]", pidFile, strerror(errno));
		goto fail;
	}
	value |= FD_CLOEXEC;
	if (fcntl(fd, F_SETFD, value) < 0) {
		condlog(0, "Cannot set close-on-exec flag from pidfile [%s], "
			"error was [%s]", pidFile, strerror(errno));
		goto fail;
	}
	return fd;
fail:
	close(fd);
	return -errno;
}