Commit | Line | Data |
---|---|---|
c39c72ee PMF |
1 | /* Copyright (C) 2009 Pierre-Marc Fournier |
2 | * | |
3 | * This library is free software; you can redistribute it and/or | |
4 | * modify it under the terms of the GNU Lesser General Public | |
5 | * License as published by the Free Software Foundation; either | |
6 | * version 2.1 of the License, or (at your option) any later version. | |
7 | * | |
8 | * This library is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * Lesser General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU Lesser General Public | |
14 | * License along with this library; if not, write to the Free Software | |
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
16 | */ | |
17 | ||
93e5ce29 PMF |
18 | /* API used by UST components to communicate with each other via sockets. */ |
19 | ||
d0b5f2b9 | 20 | #define _GNU_SOURCE |
f9e5ce61 PMF |
21 | #include <sys/types.h> |
22 | #include <signal.h> | |
23 | #include <errno.h> | |
24 | #include <sys/socket.h> | |
25 | #include <sys/un.h> | |
d0b5f2b9 | 26 | #include <unistd.h> |
aca1ad90 | 27 | #include <poll.h> |
4723ca09 | 28 | #include <sys/epoll.h> |
803a4f58 | 29 | #include <sys/stat.h> |
f9e5ce61 PMF |
30 | |
31 | #include <stdio.h> | |
32 | #include <stdlib.h> | |
d0b5f2b9 | 33 | #include <string.h> |
b0540e11 | 34 | #include <execinfo.h> |
d0b5f2b9 PMF |
35 | |
36 | #include "ustcomm.h" | |
6af64c43 | 37 | #include "usterr.h" |
2dae156b | 38 | #include "share.h" |
f9e5ce61 | 39 | |
d6d27063 PMF |
40 | static int mkdir_p(const char *path, mode_t mode) |
41 | { | |
c555b133 | 42 | const char *path_p; |
d6d27063 PMF |
43 | char *tmp; |
44 | ||
45 | int retval = 0; | |
46 | int result; | |
18baca84 | 47 | mode_t old_umask; |
d6d27063 | 48 | |
7032c7d3 | 49 | tmp = zmalloc(strlen(path) + 1); |
d6d27063 PMF |
50 | if (tmp == NULL) |
51 | return -1; | |
52 | ||
53 | /* skip first / */ | |
54 | path_p = path+1; | |
55 | ||
18baca84 | 56 | old_umask = umask(0); |
d6d27063 PMF |
57 | for(;;) { |
58 | while (*path_p != '/') { | |
59 | if(*path_p == 0) | |
60 | break; | |
61 | ++path_p; | |
62 | } | |
63 | if (*path_p == '/') { | |
64 | strncpy(tmp, path, path_p - path); | |
65 | tmp[path_p-path] = '\0'; | |
66 | if (tmp[path_p - path - 1] != '/') { | |
67 | result = mkdir(tmp, mode); | |
68 | if(result == -1) { | |
69 | if (!(errno == EEXIST || errno == EACCES || errno == EROFS)) { | |
70 | /* Then this is a real error */ | |
71 | retval = -1; | |
72 | break; | |
73 | } | |
74 | } | |
75 | } | |
76 | /* pass / */ | |
77 | path_p++; | |
78 | } else { | |
79 | /* last component */ | |
80 | result = mkdir(path, mode); | |
81 | if (result == -1) | |
82 | retval = -1; | |
83 | break; | |
84 | } | |
85 | } | |
86 | ||
87 | free(tmp); | |
18baca84 | 88 | umask(old_umask); |
d6d27063 PMF |
89 | return retval; |
90 | } | |
91 | ||
4723ca09 NC |
92 | static struct sockaddr_un * create_sock_addr(const char *name, |
93 | size_t *sock_addr_size) | |
f9e5ce61 | 94 | { |
4723ca09 NC |
95 | struct sockaddr_un * addr; |
96 | size_t alloc_size; | |
f9e5ce61 | 97 | |
4723ca09 NC |
98 | alloc_size = (size_t) (((struct sockaddr_un *) 0)->sun_path) + |
99 | strlen(name) + 1; | |
5932431b | 100 | |
4723ca09 NC |
101 | addr = malloc(alloc_size); |
102 | if (addr < 0) { | |
103 | ERR("allocating addr failed"); | |
104 | return NULL; | |
105 | } | |
ab33e65c | 106 | |
4723ca09 NC |
107 | addr->sun_family = AF_UNIX; |
108 | strcpy(addr->sun_path, name); | |
109 | ||
110 | *sock_addr_size = alloc_size; | |
111 | ||
112 | return addr; | |
113 | } | |
2dae156b | 114 | |
4723ca09 | 115 | struct ustcomm_sock * ustcomm_init_sock(int fd, int epoll_fd, |
0222e121 | 116 | struct cds_list_head *list) |
811e4b93 | 117 | { |
4723ca09 NC |
118 | struct epoll_event ev; |
119 | struct ustcomm_sock *sock; | |
811e4b93 | 120 | |
4723ca09 NC |
121 | sock = malloc(sizeof(struct ustcomm_sock)); |
122 | if (!sock) { | |
123 | perror("malloc: couldn't allocate ustcomm_sock"); | |
124 | return NULL; | |
811e4b93 | 125 | } |
4723ca09 NC |
126 | |
127 | ev.events = EPOLLIN; | |
128 | ev.data.ptr = sock; | |
129 | sock->fd = fd; | |
130 | ||
131 | if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock->fd, &ev) == -1) { | |
132 | perror("epoll_ctl: failed to add socket\n"); | |
133 | free(sock); | |
134 | return NULL; | |
688760ef | 135 | } |
811e4b93 | 136 | |
4723ca09 NC |
137 | sock->epoll_fd = epoll_fd; |
138 | if (list) { | |
0222e121 | 139 | cds_list_add(&sock->list, list); |
4723ca09 | 140 | } else { |
0222e121 | 141 | CDS_INIT_LIST_HEAD(&sock->list); |
4723ca09 NC |
142 | } |
143 | ||
144 | return sock; | |
811e4b93 PMF |
145 | } |
146 | ||
4723ca09 NC |
147 | void ustcomm_del_sock(struct ustcomm_sock *sock, int keep_in_epoll) |
148 | { | |
0222e121 | 149 | cds_list_del(&sock->list); |
4723ca09 NC |
150 | if (!keep_in_epoll) { |
151 | if (epoll_ctl(sock->epoll_fd, EPOLL_CTL_DEL, sock->fd, NULL) == -1) { | |
152 | PERROR("epoll_ctl: failed to delete socket"); | |
153 | } | |
154 | } | |
155 | close(sock->fd); | |
156 | free(sock); | |
157 | } | |
b0540e11 | 158 | |
4723ca09 NC |
159 | struct ustcomm_sock * ustcomm_init_named_socket(const char *name, |
160 | int epoll_fd) | |
b0540e11 | 161 | { |
b0540e11 | 162 | int result; |
4723ca09 NC |
163 | int fd; |
164 | size_t sock_addr_size; | |
165 | struct sockaddr_un * addr; | |
166 | struct ustcomm_sock *sock; | |
c97d4437 | 167 | |
4723ca09 NC |
168 | fd = socket(PF_UNIX, SOCK_STREAM, 0); |
169 | if(fd == -1) { | |
170 | PERROR("socket"); | |
171 | return NULL; | |
c97d4437 | 172 | } |
b0540e11 | 173 | |
4723ca09 NC |
174 | addr = create_sock_addr(name, &sock_addr_size); |
175 | if (addr == NULL) { | |
176 | ERR("allocating addr, UST thread bailing"); | |
177 | goto close_sock; | |
b0540e11 PMF |
178 | } |
179 | ||
4723ca09 NC |
180 | result = access(name, F_OK); |
181 | if(result == 0) { | |
182 | /* file exists */ | |
183 | result = unlink(name); | |
184 | if(result == -1) { | |
185 | PERROR("unlink of socket file"); | |
186 | goto free_addr; | |
187 | } | |
188 | DBG("socket already exists; overwriting"); | |
08b8805e | 189 | } |
b0540e11 | 190 | |
4723ca09 | 191 | result = bind(fd, (struct sockaddr *)addr, sock_addr_size); |
08230db7 | 192 | if(result == -1) { |
4723ca09 NC |
193 | PERROR("bind"); |
194 | goto free_addr; | |
08230db7 PMF |
195 | } |
196 | ||
4723ca09 | 197 | result = listen(fd, 1); |
08230db7 | 198 | if(result == -1) { |
4723ca09 NC |
199 | PERROR("listen"); |
200 | goto free_addr; | |
08230db7 PMF |
201 | } |
202 | ||
4723ca09 NC |
203 | sock = ustcomm_init_sock(fd, epoll_fd, |
204 | NULL); | |
205 | if (!sock) { | |
206 | ERR("failed to create ustcomm_sock"); | |
207 | goto free_addr; | |
208 | } | |
b0540e11 | 209 | |
4723ca09 | 210 | free(addr); |
b0540e11 | 211 | |
4723ca09 | 212 | return sock; |
811e4b93 | 213 | |
4723ca09 NC |
214 | free_addr: |
215 | free(addr); | |
216 | close_sock: | |
217 | close(fd); | |
2dae156b | 218 | |
4723ca09 NC |
219 | return NULL; |
220 | } | |
221 | ||
222 | void ustcomm_del_named_sock(struct ustcomm_sock *sock, | |
223 | int keep_socket_file) | |
d0b5f2b9 | 224 | { |
4723ca09 NC |
225 | int result, fd; |
226 | struct stat st; | |
227 | struct sockaddr dummy; | |
228 | struct sockaddr_un *sockaddr = NULL; | |
229 | int alloc_size; | |
d0b5f2b9 | 230 | |
4723ca09 | 231 | fd = sock->fd; |
b02e31e5 | 232 | |
4723ca09 | 233 | if(!keep_socket_file) { |
5932431b | 234 | |
4723ca09 NC |
235 | /* Get the socket name */ |
236 | alloc_size = sizeof(dummy); | |
237 | if (getsockname(fd, &dummy, (socklen_t *)&alloc_size) < 0) { | |
238 | PERROR("getsockname failed"); | |
239 | goto del_sock; | |
2dae156b | 240 | } |
b0540e11 | 241 | |
4723ca09 NC |
242 | sockaddr = zmalloc(alloc_size); |
243 | if (!sockaddr) { | |
244 | ERR("failed to allocate sockaddr"); | |
245 | goto del_sock; | |
5932431b PMF |
246 | } |
247 | ||
4723ca09 NC |
248 | if (getsockname(fd, sockaddr, (socklen_t *)&alloc_size) < 0) { |
249 | PERROR("getsockname failed"); | |
250 | goto free_sockaddr; | |
5932431b PMF |
251 | } |
252 | ||
4723ca09 NC |
253 | /* Destroy socket */ |
254 | result = stat(sockaddr->sun_path, &st); | |
255 | if(result < 0) { | |
256 | PERROR("stat (%s)", sockaddr->sun_path); | |
257 | goto free_sockaddr; | |
2dae156b | 258 | } |
4723ca09 NC |
259 | |
260 | /* Paranoid check before deleting. */ | |
261 | result = S_ISSOCK(st.st_mode); | |
262 | if(!result) { | |
263 | ERR("The socket we are about to delete is not a socket."); | |
264 | goto free_sockaddr; | |
2dae156b PMF |
265 | } |
266 | ||
4723ca09 NC |
267 | result = unlink(sockaddr->sun_path); |
268 | if(result < 0) { | |
269 | PERROR("unlink"); | |
270 | } | |
2dae156b | 271 | } |
b0540e11 | 272 | |
4723ca09 NC |
273 | free_sockaddr: |
274 | free(sockaddr); | |
2dae156b | 275 | |
4723ca09 NC |
276 | del_sock: |
277 | ustcomm_del_sock(sock, keep_socket_file); | |
d0b5f2b9 PMF |
278 | } |
279 | ||
72098143 NC |
280 | int ustcomm_recv_alloc(int sock, |
281 | struct ustcomm_header *header, | |
282 | char **data) { | |
283 | int result; | |
284 | struct ustcomm_header peek_header; | |
285 | struct iovec iov[2]; | |
286 | struct msghdr msg; | |
5932431b | 287 | |
72098143 NC |
288 | /* Just to make the caller fail hard */ |
289 | *data = NULL; | |
811e4b93 | 290 | |
72098143 NC |
291 | result = recv(sock, &peek_header, sizeof(peek_header), |
292 | MSG_PEEK | MSG_WAITALL); | |
293 | if (result <= 0) { | |
294 | if(errno == ECONNRESET) { | |
295 | return 0; | |
296 | } else if (errno == EINTR) { | |
297 | return -1; | |
298 | } else if (result < 0) { | |
299 | PERROR("recv"); | |
300 | return -1; | |
301 | } | |
302 | return 0; | |
811e4b93 PMF |
303 | } |
304 | ||
72098143 | 305 | memset(&msg, 0, sizeof(msg)); |
99b72dc0 | 306 | |
72098143 NC |
307 | iov[0].iov_base = (char *)header; |
308 | iov[0].iov_len = sizeof(struct ustcomm_header); | |
309 | ||
310 | msg.msg_iov = iov; | |
311 | msg.msg_iovlen = 1; | |
312 | ||
313 | if (peek_header.size) { | |
314 | *data = zmalloc(peek_header.size); | |
315 | if (!*data) { | |
316 | return -ENOMEM; | |
317 | } | |
318 | ||
319 | iov[1].iov_base = *data; | |
320 | iov[1].iov_len = peek_header.size; | |
321 | ||
322 | msg.msg_iovlen++; | |
4723ca09 | 323 | } |
99b72dc0 | 324 | |
72098143 | 325 | result = recvmsg(sock, &msg, MSG_WAITALL); |
4723ca09 | 326 | if (result < 0) { |
72098143 NC |
327 | free(*data); |
328 | PERROR("recvmsg failed"); | |
99b72dc0 PMF |
329 | } |
330 | ||
72098143 | 331 | return result; |
99b72dc0 PMF |
332 | } |
333 | ||
4723ca09 NC |
334 | /* returns 1 to indicate a message was received |
335 | * returns 0 to indicate no message was received (end of stream) | |
688760ef PMF |
336 | * returns -1 to indicate an error |
337 | */ | |
4723ca09 NC |
338 | int ustcomm_recv_fd(int sock, |
339 | struct ustcomm_header *header, | |
72098143 | 340 | char *data, int *fd) |
b0540e11 | 341 | { |
aca1ad90 | 342 | int result; |
4723ca09 NC |
343 | struct ustcomm_header peek_header; |
344 | struct iovec iov[2]; | |
345 | struct msghdr msg; | |
346 | struct cmsghdr *cmsg; | |
347 | char buf[CMSG_SPACE(sizeof(int))]; | |
348 | ||
349 | result = recv(sock, &peek_header, sizeof(peek_header), | |
350 | MSG_PEEK | MSG_WAITALL); | |
351 | if (result <= 0) { | |
352 | if(errno == ECONNRESET) { | |
353 | return 0; | |
354 | } else if (errno == EINTR) { | |
355 | return -1; | |
356 | } else if (result < 0) { | |
357 | PERROR("recv"); | |
aca1ad90 PMF |
358 | return -1; |
359 | } | |
4723ca09 NC |
360 | return 0; |
361 | } | |
aca1ad90 | 362 | |
4723ca09 | 363 | memset(&msg, 0, sizeof(msg)); |
5932431b | 364 | |
4723ca09 NC |
365 | iov[0].iov_base = (char *)header; |
366 | iov[0].iov_len = sizeof(struct ustcomm_header); | |
aca1ad90 | 367 | |
4723ca09 NC |
368 | msg.msg_iov = iov; |
369 | msg.msg_iovlen = 1; | |
aca1ad90 | 370 | |
72098143 NC |
371 | if (peek_header.size && data) { |
372 | if (peek_header.size < 0 || | |
373 | peek_header.size > USTCOMM_DATA_SIZE) { | |
374 | ERR("big peek header! %d", peek_header.size); | |
375 | return 0; | |
2a79ceeb | 376 | } |
688760ef | 377 | |
72098143 | 378 | iov[1].iov_base = data; |
4723ca09 | 379 | iov[1].iov_len = peek_header.size; |
aca1ad90 | 380 | |
4723ca09 NC |
381 | msg.msg_iovlen++; |
382 | } | |
aca1ad90 | 383 | |
4723ca09 NC |
384 | if (fd && peek_header.fd_included) { |
385 | msg.msg_control = buf; | |
386 | msg.msg_controllen = sizeof(buf); | |
387 | } | |
aca1ad90 | 388 | |
72098143 | 389 | result = recvmsg(sock, &msg, MSG_WAITALL); |
4723ca09 | 390 | if (result <= 0) { |
72098143 NC |
391 | if (result < 0) { |
392 | PERROR("recvmsg failed"); | |
aca1ad90 | 393 | } |
72098143 | 394 | return result; |
4723ca09 NC |
395 | } |
396 | ||
397 | if (fd && peek_header.fd_included) { | |
398 | cmsg = CMSG_FIRSTHDR(&msg); | |
399 | result = 0; | |
400 | while (cmsg != NULL) { | |
401 | if (cmsg->cmsg_level == SOL_SOCKET | |
402 | && cmsg->cmsg_type == SCM_RIGHTS) { | |
403 | *fd = *(int *) CMSG_DATA(cmsg); | |
404 | result = 1; | |
405 | break; | |
aca1ad90 | 406 | } |
4723ca09 NC |
407 | cmsg = CMSG_NXTHDR(&msg, cmsg); |
408 | } | |
409 | if (!result) { | |
410 | ERR("Failed to receive file descriptor\n"); | |
aca1ad90 | 411 | } |
aca1ad90 PMF |
412 | } |
413 | ||
4723ca09 | 414 | return 1; |
b0540e11 PMF |
415 | } |
416 | ||
4723ca09 NC |
417 | int ustcomm_recv(int sock, |
418 | struct ustcomm_header *header, | |
72098143 | 419 | char *data) |
811e4b93 | 420 | { |
4723ca09 | 421 | return ustcomm_recv_fd(sock, header, data, NULL); |
811e4b93 PMF |
422 | } |
423 | ||
4723ca09 | 424 | |
4723ca09 NC |
425 | int ustcomm_send_fd(int sock, |
426 | const struct ustcomm_header *header, | |
427 | const char *data, | |
428 | int *fd) | |
46ef48cd | 429 | { |
4723ca09 NC |
430 | struct iovec iov[2]; |
431 | struct msghdr msg; | |
432 | int result; | |
433 | struct cmsghdr *cmsg; | |
434 | char buf[CMSG_SPACE(sizeof(int))]; | |
435 | ||
436 | memset(&msg, 0, sizeof(msg)); | |
437 | ||
438 | iov[0].iov_base = (char *)header; | |
439 | iov[0].iov_len = sizeof(struct ustcomm_header); | |
440 | ||
441 | msg.msg_iov = iov; | |
442 | msg.msg_iovlen = 1; | |
443 | ||
72098143 | 444 | if (header->size && data) { |
4723ca09 NC |
445 | iov[1].iov_base = (char *)data; |
446 | iov[1].iov_len = header->size; | |
447 | ||
448 | msg.msg_iovlen++; | |
46ef48cd | 449 | |
46ef48cd PMF |
450 | } |
451 | ||
4723ca09 NC |
452 | if (fd && header->fd_included) { |
453 | msg.msg_control = buf; | |
454 | msg.msg_controllen = sizeof(buf); | |
455 | cmsg = CMSG_FIRSTHDR(&msg); | |
456 | cmsg->cmsg_level = SOL_SOCKET; | |
457 | cmsg->cmsg_type = SCM_RIGHTS; | |
458 | cmsg->cmsg_len = CMSG_LEN(sizeof(int)); | |
459 | *(int *) CMSG_DATA(cmsg) = *fd; | |
460 | msg.msg_controllen = cmsg->cmsg_len; | |
461 | } | |
462 | ||
463 | result = sendmsg(sock, &msg, MSG_NOSIGNAL); | |
464 | if (result < 0 && errno != EPIPE) { | |
465 | PERROR("sendmsg failed"); | |
466 | } | |
467 | return result; | |
46ef48cd PMF |
468 | } |
469 | ||
4723ca09 NC |
470 | int ustcomm_send(int sock, |
471 | const struct ustcomm_header *header, | |
472 | const char *data) | |
d0b5f2b9 | 473 | { |
4723ca09 NC |
474 | return ustcomm_send_fd(sock, header, data, NULL); |
475 | } | |
d0b5f2b9 | 476 | |
72098143 NC |
477 | int ustcomm_req(int sock, |
478 | const struct ustcomm_header *req_header, | |
479 | const char *req_data, | |
480 | struct ustcomm_header *res_header, | |
481 | char *res_data) | |
4723ca09 NC |
482 | { |
483 | int result; | |
aca1ad90 | 484 | |
72098143 | 485 | result = ustcomm_send(sock, req_header, req_data); |
4723ca09 NC |
486 | if ( result <= 0) { |
487 | return result; | |
b0540e11 | 488 | } |
d0b5f2b9 | 489 | |
72098143 | 490 | return ustcomm_recv(sock, res_header, res_data); |
4e2a8808 PMF |
491 | } |
492 | ||
2a79ceeb PMF |
493 | /* Return value: |
494 | * 0: success | |
495 | * -1: error | |
496 | */ | |
497 | ||
4723ca09 | 498 | int ustcomm_connect_path(const char *name, int *connection_fd) |
4e2a8808 | 499 | { |
4723ca09 NC |
500 | int result, fd; |
501 | size_t sock_addr_size; | |
502 | struct sockaddr_un *addr; | |
4e2a8808 | 503 | |
4723ca09 NC |
504 | fd = socket(PF_UNIX, SOCK_STREAM, 0); |
505 | if(fd == -1) { | |
4e2a8808 PMF |
506 | PERROR("socket"); |
507 | return -1; | |
508 | } | |
509 | ||
4723ca09 NC |
510 | addr = create_sock_addr(name, &sock_addr_size); |
511 | if (addr == NULL) { | |
512 | ERR("allocating addr failed"); | |
513 | goto close_sock; | |
52c51a47 | 514 | } |
4e2a8808 | 515 | |
4723ca09 | 516 | result = connect(fd, (struct sockaddr *)addr, sock_addr_size); |
4e2a8808 | 517 | if(result == -1) { |
4723ca09 NC |
518 | PERROR("connect (path=%s)", name); |
519 | goto free_sock_addr; | |
4e2a8808 PMF |
520 | } |
521 | ||
4723ca09 NC |
522 | *connection_fd = fd; |
523 | ||
524 | free(addr); | |
4e2a8808 PMF |
525 | |
526 | return 0; | |
4e2a8808 | 527 | |
4723ca09 NC |
528 | free_sock_addr: |
529 | free(addr); | |
530 | close_sock: | |
531 | close(fd); | |
532 | ||
533 | return -1; | |
4e2a8808 PMF |
534 | } |
535 | ||
4723ca09 | 536 | |
2a79ceeb PMF |
537 | /* Open a connection to a traceable app. |
538 | * | |
539 | * Return value: | |
540 | * 0: success | |
541 | * -1: error | |
542 | */ | |
543 | ||
4723ca09 | 544 | int ustcomm_connect_app(pid_t pid, int *app_fd) |
4e2a8808 PMF |
545 | { |
546 | int result; | |
4723ca09 NC |
547 | int retval = 0; |
548 | char *name; | |
4e2a8808 | 549 | |
4723ca09 NC |
550 | result = asprintf(&name, "%s/%d", SOCK_DIR, pid); |
551 | if (result < 0) { | |
552 | ERR("failed to allocate socket name"); | |
4e2a8808 PMF |
553 | return -1; |
554 | } | |
555 | ||
4723ca09 NC |
556 | result = ustcomm_connect_path(name, app_fd); |
557 | if (result < 0) { | |
558 | ERR("failed to connect to app"); | |
559 | retval = -1; | |
560 | } | |
2a79ceeb | 561 | |
4723ca09 | 562 | free(name); |
2a79ceeb | 563 | |
4723ca09 | 564 | return retval; |
2a79ceeb PMF |
565 | } |
566 | ||
4723ca09 | 567 | int ensure_dir_exists(const char *dir) |
dce0b474 PMF |
568 | { |
569 | struct stat st; | |
570 | int result; | |
571 | ||
572 | if(!strcmp(dir, "")) | |
573 | return -1; | |
574 | ||
575 | result = stat(dir, &st); | |
576 | if(result == -1 && errno != ENOENT) { | |
577 | return -1; | |
578 | } | |
579 | else if(result == -1) { | |
580 | /* ENOENT */ | |
dce0b474 PMF |
581 | int result; |
582 | ||
18baca84 DG |
583 | /* mkdir mode to 0777 */ |
584 | result = mkdir_p(dir, S_IRWXU | S_IRWXG | S_IRWXO); | |
dce0b474 | 585 | if(result != 0) { |
d6d27063 | 586 | ERR("executing in recursive creation of directory %s", dir); |
dce0b474 PMF |
587 | return -1; |
588 | } | |
589 | } | |
590 | ||
591 | return 0; | |
592 | } | |
593 | ||
72098143 NC |
594 | char * ustcomm_print_data(char *data_field, int field_size, |
595 | int *offset, const char *format, ...) | |
596 | { | |
597 | va_list args; | |
598 | int count, limit; | |
599 | char *ptr = USTCOMM_POISON_PTR; | |
600 | ||
601 | limit = field_size - *offset; | |
602 | va_start(args, format); | |
603 | count = vsnprintf(&data_field[*offset], limit, format, args); | |
604 | va_end(args); | |
605 | ||
606 | if (count < limit && count > -1) { | |
607 | ptr = NULL + *offset; | |
608 | *offset = *offset + count + 1; | |
609 | } | |
610 | ||
611 | return ptr; | |
612 | } | |
613 | ||
614 | char * ustcomm_restore_ptr(char *ptr, char *data_field, int data_field_size) | |
615 | { | |
616 | if ((unsigned long)ptr > data_field_size || | |
617 | ptr == USTCOMM_POISON_PTR) { | |
618 | return NULL; | |
619 | } | |
08230db7 | 620 | |
72098143 NC |
621 | return data_field + (long)ptr; |
622 | } | |
2a79ceeb | 623 | |
10f2b724 NC |
624 | int ustcomm_pack_trace_info(struct ustcomm_header *header, |
625 | struct ustcomm_trace_info *trace_inf, | |
626 | const char *trace) | |
627 | { | |
628 | int offset = 0; | |
629 | ||
630 | trace_inf->trace = ustcomm_print_data(trace_inf->data, | |
631 | sizeof(trace_inf->data), | |
632 | &offset, | |
633 | trace); | |
634 | ||
635 | if (trace_inf->trace == USTCOMM_POISON_PTR) { | |
636 | return -ENOMEM; | |
637 | } | |
638 | ||
639 | header->size = COMPUTE_MSG_SIZE(trace_inf, offset); | |
640 | ||
641 | return 0; | |
642 | } | |
643 | ||
644 | ||
645 | int ustcomm_unpack_trace_info(struct ustcomm_trace_info *trace_inf) | |
646 | { | |
647 | trace_inf->trace = ustcomm_restore_ptr(trace_inf->trace, | |
648 | trace_inf->data, | |
649 | sizeof(trace_inf->data)); | |
650 | if (!trace_inf->trace) { | |
651 | return -EINVAL; | |
652 | } | |
653 | ||
654 | return 0; | |
655 | } | |
72098143 NC |
656 | |
657 | int ustcomm_pack_channel_info(struct ustcomm_header *header, | |
658 | struct ustcomm_channel_info *ch_inf, | |
d89b8191 | 659 | const char *trace, |
72098143 | 660 | const char *channel) |
b02e31e5 | 661 | { |
72098143 NC |
662 | int offset = 0; |
663 | ||
d89b8191 NC |
664 | ch_inf->trace = ustcomm_print_data(ch_inf->data, |
665 | sizeof(ch_inf->data), | |
666 | &offset, | |
667 | trace); | |
668 | ||
669 | if (ch_inf->trace == USTCOMM_POISON_PTR) { | |
670 | return -ENOMEM; | |
671 | } | |
672 | ||
72098143 NC |
673 | ch_inf->channel = ustcomm_print_data(ch_inf->data, |
674 | sizeof(ch_inf->data), | |
675 | &offset, | |
676 | channel); | |
b02e31e5 | 677 | |
72098143 NC |
678 | if (ch_inf->channel == USTCOMM_POISON_PTR) { |
679 | return -ENOMEM; | |
b02e31e5 PMF |
680 | } |
681 | ||
72098143 NC |
682 | header->size = COMPUTE_MSG_SIZE(ch_inf, offset); |
683 | ||
684 | return 0; | |
b02e31e5 PMF |
685 | } |
686 | ||
72098143 NC |
687 | |
688 | int ustcomm_unpack_channel_info(struct ustcomm_channel_info *ch_inf) | |
b02e31e5 | 689 | { |
d89b8191 NC |
690 | ch_inf->trace = ustcomm_restore_ptr(ch_inf->trace, |
691 | ch_inf->data, | |
692 | sizeof(ch_inf->data)); | |
693 | if (!ch_inf->trace) { | |
694 | return -EINVAL; | |
695 | } | |
696 | ||
72098143 NC |
697 | ch_inf->channel = ustcomm_restore_ptr(ch_inf->channel, |
698 | ch_inf->data, | |
699 | sizeof(ch_inf->data)); | |
700 | if (!ch_inf->channel) { | |
701 | return -EINVAL; | |
702 | } | |
b02e31e5 | 703 | |
72098143 NC |
704 | return 0; |
705 | } | |
706 | ||
707 | int ustcomm_pack_buffer_info(struct ustcomm_header *header, | |
708 | struct ustcomm_buffer_info *buf_inf, | |
d89b8191 | 709 | const char *trace, |
72098143 NC |
710 | const char *channel, |
711 | int channel_cpu) | |
712 | { | |
713 | int offset = 0; | |
714 | ||
d89b8191 NC |
715 | buf_inf->trace = ustcomm_print_data(buf_inf->data, |
716 | sizeof(buf_inf->data), | |
717 | &offset, | |
718 | trace); | |
719 | ||
720 | if (buf_inf->trace == USTCOMM_POISON_PTR) { | |
721 | return -ENOMEM; | |
722 | } | |
723 | ||
72098143 NC |
724 | buf_inf->channel = ustcomm_print_data(buf_inf->data, |
725 | sizeof(buf_inf->data), | |
726 | &offset, | |
727 | channel); | |
728 | ||
729 | if (buf_inf->channel == USTCOMM_POISON_PTR) { | |
730 | return -ENOMEM; | |
b02e31e5 PMF |
731 | } |
732 | ||
72098143 NC |
733 | buf_inf->ch_cpu = channel_cpu; |
734 | ||
735 | header->size = COMPUTE_MSG_SIZE(buf_inf, offset); | |
736 | ||
737 | return 0; | |
b02e31e5 PMF |
738 | } |
739 | ||
72098143 NC |
740 | |
741 | int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf) | |
b02e31e5 | 742 | { |
d89b8191 NC |
743 | buf_inf->trace = ustcomm_restore_ptr(buf_inf->trace, |
744 | buf_inf->data, | |
745 | sizeof(buf_inf->data)); | |
746 | if (!buf_inf->trace) { | |
747 | return -EINVAL; | |
748 | } | |
749 | ||
72098143 NC |
750 | buf_inf->channel = ustcomm_restore_ptr(buf_inf->channel, |
751 | buf_inf->data, | |
752 | sizeof(buf_inf->data)); | |
753 | if (!buf_inf->channel) { | |
754 | return -EINVAL; | |
755 | } | |
b02e31e5 | 756 | |
72098143 NC |
757 | return 0; |
758 | } | |
759 | ||
760 | int ustcomm_pack_marker_info(struct ustcomm_header *header, | |
761 | struct ustcomm_marker_info *marker_inf, | |
d89b8191 | 762 | const char *trace, |
72098143 NC |
763 | const char *channel, |
764 | const char *marker) | |
765 | { | |
766 | int offset = 0; | |
b02e31e5 | 767 | |
d89b8191 NC |
768 | marker_inf->trace = ustcomm_print_data(marker_inf->data, |
769 | sizeof(marker_inf->data), | |
770 | &offset, | |
771 | trace); | |
772 | ||
773 | if (marker_inf->trace == USTCOMM_POISON_PTR) { | |
774 | return -ENOMEM; | |
775 | } | |
776 | ||
777 | ||
72098143 NC |
778 | marker_inf->channel = ustcomm_print_data(marker_inf->data, |
779 | sizeof(marker_inf->data), | |
780 | &offset, | |
781 | channel); | |
b02e31e5 | 782 | |
72098143 NC |
783 | if (marker_inf->channel == USTCOMM_POISON_PTR) { |
784 | return -ENOMEM; | |
785 | } | |
786 | ||
787 | ||
788 | marker_inf->marker = ustcomm_print_data(marker_inf->data, | |
789 | sizeof(marker_inf->data), | |
790 | &offset, | |
791 | marker); | |
b02e31e5 | 792 | |
72098143 NC |
793 | if (marker_inf->marker == USTCOMM_POISON_PTR) { |
794 | return -ENOMEM; | |
b02e31e5 PMF |
795 | } |
796 | ||
72098143 | 797 | header->size = COMPUTE_MSG_SIZE(marker_inf, offset); |
b02e31e5 | 798 | |
72098143 NC |
799 | return 0; |
800 | } | |
b02e31e5 | 801 | |
72098143 NC |
802 | int ustcomm_unpack_marker_info(struct ustcomm_marker_info *marker_inf) |
803 | { | |
d89b8191 NC |
804 | marker_inf->trace = ustcomm_restore_ptr(marker_inf->trace, |
805 | marker_inf->data, | |
806 | sizeof(marker_inf->data)); | |
807 | if (!marker_inf->trace) { | |
808 | return -EINVAL; | |
809 | } | |
810 | ||
72098143 NC |
811 | marker_inf->channel = ustcomm_restore_ptr(marker_inf->channel, |
812 | marker_inf->data, | |
813 | sizeof(marker_inf->data)); | |
814 | if (!marker_inf->channel) { | |
815 | return -EINVAL; | |
816 | } | |
817 | ||
818 | marker_inf->marker = ustcomm_restore_ptr(marker_inf->marker, | |
819 | marker_inf->data, | |
820 | sizeof(marker_inf->data)); | |
821 | if (!marker_inf->marker) { | |
822 | return -EINVAL; | |
823 | } | |
824 | ||
825 | return 0; | |
b02e31e5 PMF |
826 | } |
827 | ||
72098143 NC |
828 | int ustcomm_pack_sock_path(struct ustcomm_header *header, |
829 | struct ustcomm_sock_path *sock_path_inf, | |
830 | const char *socket_path) | |
b02e31e5 | 831 | { |
72098143 NC |
832 | int offset = 0; |
833 | ||
834 | sock_path_inf->sock_path = | |
835 | ustcomm_print_data(sock_path_inf->data, | |
836 | sizeof(sock_path_inf->data), | |
837 | &offset, | |
838 | socket_path); | |
b02e31e5 | 839 | |
72098143 NC |
840 | if (sock_path_inf->sock_path == USTCOMM_POISON_PTR) { |
841 | return -ENOMEM; | |
842 | } | |
b02e31e5 | 843 | |
72098143 | 844 | header->size = COMPUTE_MSG_SIZE(sock_path_inf, offset); |
b02e31e5 | 845 | |
72098143 NC |
846 | return 0; |
847 | } | |
b02e31e5 | 848 | |
72098143 NC |
849 | int ustcomm_unpack_sock_path(struct ustcomm_sock_path *sock_path_inf) |
850 | { | |
851 | sock_path_inf->sock_path = | |
852 | ustcomm_restore_ptr(sock_path_inf->sock_path, | |
853 | sock_path_inf->data, | |
854 | sizeof(sock_path_inf->data)); | |
855 | if (!sock_path_inf->sock_path) { | |
856 | return -EINVAL; | |
b02e31e5 PMF |
857 | } |
858 | ||
72098143 NC |
859 | return 0; |
860 | } | |
861 |