]> git.proxmox.com Git - mirror_lxc.git/blob - src/liblxc/monitor.c
Added C++ compatibility, change to libtool, improve monitoring
[mirror_lxc.git] / src / liblxc / monitor.c
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>
34 #include <sys/un.h>
35 #include <netinet/in.h>
36 #include <net/if.h>
37 #include <lxc.h>
38
39 #ifndef UNIX_PATH_MAX
40 #define UNIX_PATH_MAX 108
41 #endif
42
43 int lxc_monitor(const char *name, int output_fd)
44 {
45 char path[MAXPATHLEN];
46 int err = -1, nfd, wfd, state;
47
48 nfd = inotify_init();
49 if (nfd < 0) {
50 lxc_log_syserror("failed to initialize inotify");
51 return -1;
52 }
53
54 snprintf(path, MAXPATHLEN, LXCPATH "/%s/state", name);
55
56 wfd = inotify_add_watch(nfd, path, IN_DELETE_SELF|IN_CLOSE_WRITE);
57 if (wfd < 0) {
58 lxc_log_syserror("failed to add a watch on %s", path);
59 goto out;
60 }
61
62 for(;;) {
63 struct inotify_event evt;
64
65 if (read(nfd, &evt, sizeof(evt)) < 0) {
66 lxc_log_syserror("failed to read inotify event");
67 goto out;
68 }
69
70 if (evt.mask & IN_CLOSE_WRITE) {
71
72 state = lxc_getstate(name);
73 if (state < 0) {
74 lxc_log_error("failed to get the state for %s",
75 name);
76 goto out;
77 }
78
79 if (write(output_fd, &state, sizeof(state)) < 0) {
80 lxc_log_syserror("failed to send state to %d",
81 output_fd);
82 goto out;
83 }
84 continue;
85 }
86
87 if (evt.mask & IN_DELETE_SELF) {
88 close(output_fd);
89 err = 0;
90 goto out;
91 }
92
93 lxc_log_error("unknown evt for inotity (%d)", evt.mask);
94 goto out;
95 }
96
97 out:
98 inotify_rm_watch(nfd, wfd);
99 close(nfd);
100 return err;
101 }
102
103 void lxc_monitor_send_state(const char *name, lxc_state_t state)
104 {
105 int fd;
106 struct sockaddr_un addr;
107
108 fd = socket(PF_UNIX, SOCK_DGRAM, 0);
109 if (fd < 0)
110 lxc_log_syserror("failed to create notification socket");
111
112 memset(&addr, 0, sizeof(addr));
113 addr.sun_family = AF_UNIX;
114 snprintf(addr.sun_path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name);
115
116 sendto(fd, &state, sizeof(state), 0,
117 (const struct sockaddr *)&addr, sizeof(addr));
118
119 close(fd);
120 }
121
122 void lxc_monitor_cleanup(const char *name)
123 {
124 char path[UNIX_PATH_MAX];
125 snprintf(path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name);
126 unlink(path);
127 }
128
129 int lxc_monitor_open(const char *name)
130 {
131 int fd;
132 struct sockaddr_un addr;
133
134 fd = socket(PF_UNIX, SOCK_DGRAM, 0);
135 if (fd < 0) {
136 lxc_log_syserror("failed to create notification socket");
137 return -1;
138 }
139
140 memset(&addr, 0, sizeof(addr));
141
142 addr.sun_family = AF_UNIX;
143 snprintf(addr.sun_path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name);
144 unlink(addr.sun_path);
145
146 if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr))) {
147 lxc_log_syserror("failed to bind to '%s'", addr.sun_path);
148 return -1;
149 }
150
151 return fd;
152 }
153
154 int lxc_monitor_read(int fd, lxc_state_t *state)
155 {
156 int ret;
157
158 ret = recv(fd, state, sizeof(*state), 0);
159 if (ret < 0) {
160 lxc_log_syserror("failed to received state");
161 return -1;
162 }
163
164 return ret;
165 }
166
167 int lxc_monitor_close(int fd)
168 {
169 return close(fd);
170 }