]>
Commit | Line | Data |
---|---|---|
0ad19a3f | 1 | /* |
2 | * lxc: linux Container library | |
3 | * | |
4 | * (C) Copyright IBM Corp. 2007, 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Daniel Lezcano <dlezcano at fr.ibm.com> | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | #include <stdio.h> | |
24 | #include <errno.h> | |
25 | #include <unistd.h> | |
26 | #include <string.h> | |
27 | #include <stdlib.h> | |
28 | #include <fcntl.h> | |
29 | #include <sys/types.h> | |
30 | #include <sys/stat.h> | |
31 | #include <sys/param.h> | |
32 | #include <sys/inotify.h> | |
33 | #include <sys/socket.h> | |
31c53c2e | 34 | #include <sys/un.h> |
0ad19a3f | 35 | #include <netinet/in.h> |
36 | #include <net/if.h> | |
b113348e | 37 | |
e2bcd7db | 38 | #include "error.h" |
31c53c2e | 39 | #include "af_unix.h" |
b113348e | 40 | #include <lxc/lxc.h> |
36eb9bde CLG |
41 | #include <lxc/log.h> |
42 | ||
43 | lxc_log_define(lxc_monitor, lxc); | |
0ad19a3f | 44 | |
45 | #ifndef UNIX_PATH_MAX | |
46 | #define UNIX_PATH_MAX 108 | |
47 | #endif | |
48 | ||
49 | int lxc_monitor(const char *name, int output_fd) | |
50 | { | |
51 | char path[MAXPATHLEN]; | |
52 | int err = -1, nfd, wfd, state; | |
53 | ||
54 | nfd = inotify_init(); | |
55 | if (nfd < 0) { | |
36eb9bde | 56 | SYSERROR("failed to initialize inotify"); |
0ad19a3f | 57 | return -1; |
58 | } | |
59 | ||
60 | snprintf(path, MAXPATHLEN, LXCPATH "/%s/state", name); | |
61 | ||
62 | wfd = inotify_add_watch(nfd, path, IN_DELETE_SELF|IN_CLOSE_WRITE); | |
63 | if (wfd < 0) { | |
36eb9bde | 64 | SYSERROR("failed to add a watch on %s", path); |
0ad19a3f | 65 | goto out; |
66 | } | |
67 | ||
68 | for(;;) { | |
69 | struct inotify_event evt; | |
70 | ||
71 | if (read(nfd, &evt, sizeof(evt)) < 0) { | |
36eb9bde | 72 | SYSERROR("failed to read inotify event"); |
0ad19a3f | 73 | goto out; |
74 | } | |
75 | ||
76 | if (evt.mask & IN_CLOSE_WRITE) { | |
77 | ||
78 | state = lxc_getstate(name); | |
79 | if (state < 0) { | |
36eb9bde | 80 | ERROR("failed to get the state for %s", |
0ad19a3f | 81 | name); |
82 | goto out; | |
83 | } | |
84 | ||
85 | if (write(output_fd, &state, sizeof(state)) < 0) { | |
36eb9bde | 86 | SYSERROR("failed to send state to %d", |
0ad19a3f | 87 | output_fd); |
88 | goto out; | |
89 | } | |
90 | continue; | |
91 | } | |
92 | ||
93 | if (evt.mask & IN_DELETE_SELF) { | |
94 | close(output_fd); | |
95 | err = 0; | |
96 | goto out; | |
97 | } | |
98 | ||
36eb9bde | 99 | ERROR("unknown evt for inotity (%d)", evt.mask); |
0ad19a3f | 100 | goto out; |
101 | } | |
102 | ||
103 | out: | |
104 | inotify_rm_watch(nfd, wfd); | |
105 | close(nfd); | |
106 | return err; | |
107 | } | |
108 | ||
80f41298 | 109 | static void lxc_monitor_send(struct lxc_msg *msg) |
0ad19a3f | 110 | { |
111 | int fd; | |
31c53c2e DL |
112 | struct sockaddr_un addr = { .sun_family = AF_UNIX }; |
113 | char *offset = &addr.sun_path[1]; | |
0ad19a3f | 114 | |
31c53c2e | 115 | strcpy(offset, "lxc-monitor"); |
80f41298 | 116 | |
31c53c2e DL |
117 | fd = socket(PF_UNIX, SOCK_DGRAM, 0); |
118 | if (fd < 0) | |
119 | return; | |
0ad19a3f | 120 | |
eae6543d | 121 | sendto(fd, msg, sizeof(*msg), 0, |
0ad19a3f | 122 | (const struct sockaddr *)&addr, sizeof(addr)); |
123 | ||
124 | close(fd); | |
125 | } | |
126 | ||
eae6543d | 127 | void lxc_monitor_send_state(const char *name, lxc_state_t state) |
128 | { | |
129 | struct lxc_msg msg = { .type = lxc_msg_state, | |
130 | .value = state }; | |
80f41298 | 131 | strncpy(msg.name, name, sizeof(msg.name)); |
eae6543d | 132 | |
80f41298 | 133 | lxc_monitor_send(&msg); |
0ad19a3f | 134 | } |
135 | ||
80f41298 | 136 | int lxc_monitor_open(void) |
0ad19a3f | 137 | { |
31c53c2e DL |
138 | struct sockaddr_un addr = { .sun_family = AF_UNIX }; |
139 | char *offset = &addr.sun_path[1]; | |
0ad19a3f | 140 | int fd; |
0ad19a3f | 141 | |
31c53c2e | 142 | strcpy(offset, "lxc-monitor"); |
0ad19a3f | 143 | |
31c53c2e DL |
144 | fd = socket(PF_UNIX, SOCK_DGRAM, 0); |
145 | if (fd < 0) | |
146 | return -1; | |
0ad19a3f | 147 | |
31c53c2e | 148 | if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { |
0ad19a3f | 149 | close(fd); |
150 | return -1; | |
151 | } | |
152 | ||
153 | return fd; | |
154 | } | |
155 | ||
eae6543d | 156 | int lxc_monitor_read(int fd, struct lxc_msg *msg) |
0ad19a3f | 157 | { |
31c53c2e | 158 | struct sockaddr_un from; |
80f41298 | 159 | socklen_t len = sizeof(from); |
0ad19a3f | 160 | int ret; |
161 | ||
80f41298 | 162 | ret = recvfrom(fd, msg, sizeof(*msg), 0, |
163 | (struct sockaddr *)&from, &len); | |
0ad19a3f | 164 | if (ret < 0) { |
3ab87b66 | 165 | SYSERROR("failed to receive state"); |
75b1e198 | 166 | return -1; |
0ad19a3f | 167 | } |
168 | ||
169 | return ret; | |
170 | } | |
171 | ||
172 | int lxc_monitor_close(int fd) | |
173 | { | |
174 | return close(fd); | |
175 | } |