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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
/* ISC license. */
#include <limits.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <skalibs/strerr2.h>
#include <skalibs/djbunix.h>
#include <s6/s6-supervise.h>
#ifdef PATH_MAX
# define S6_PATH_MAX PATH_MAX
#else
# define S6_PATH_MAX 4096
#endif
int s6_supervise_lock_mode (char const *subdir, unsigned int subdirmode, unsigned int controlmode)
{
size_t subdirlen = strlen(subdir) ;
int fdctl, fdctlw, fdlock ;
char control[subdirlen + 9] ;
char lock[subdirlen + 6] ;
memcpy(control, subdir, subdirlen) ;
memcpy(control + subdirlen, "/control", 9) ;
memcpy(lock, subdir, subdirlen) ;
memcpy(lock + subdirlen, "/lock", 6) ;
if (mkdir(subdir, (mode_t)subdirmode) == -1)
{
if (errno != EEXIST) strerr_diefu2sys(111, "mkdir ", subdir) ;
else
{
char buf[S6_PATH_MAX] ;
ssize_t r = readlink(subdir, buf, S6_PATH_MAX) ;
if (r < 0)
{
errno = EEXIST ;
strerr_diefu2sys(111, "mkdir ", subdir) ;
}
if (r == S6_PATH_MAX)
{
errno = ENAMETOOLONG ;
strerr_diefu2sys(111, "readlink ", subdir) ;
}
buf[r] = 0 ;
if (mkdir(buf, (mode_t)subdirmode) == -1)
strerr_diefu2sys(111, "mkdir ", buf) ;
}
}
if (mkfifo(control, controlmode) < 0)
{
struct stat st ;
if (errno != EEXIST)
strerr_diefu2sys(111, "mkfifo ", control) ;
if (stat(control, &st) < 0)
strerr_diefu2sys(111, "stat ", control) ;
if (!S_ISFIFO(st.st_mode))
strerr_diefu2x(100, control, " is not a FIFO") ;
}
fdlock = openc_create(lock) ;
if (fdlock < 0)
strerr_diefu2sys(111, "open_create ", lock) ;
if (lock_ex(fdlock) < 0)
strerr_diefu2sys(111, "lock ", lock) ;
fdctlw = openc_write(control) ;
if (fdctlw >= 0) strerr_dief1x(100, "directory already locked") ;
if (errno != ENXIO)
strerr_diefu2sys(111, "open_write ", control) ;
fdctl = openc_read(control) ;
if (fdctl < 0)
strerr_diefu2sys(111, "open_read ", control) ;
fdctlw = openc_write(control) ;
if (fdctlw < 0)
strerr_diefu2sys(111, "open_write ", control) ;
fd_close(fdlock) ;
return fdctl ;
/* we leak fdctlw but it's coe. */
}
|