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) { | |
fbae86d6 | 374 | ERR("big peek header! %ld", peek_header.size); |
72098143 | 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 | ||
dbd75de7 NC |
536 | /* Returns the current users socket directory, must be freed */ |
537 | char *ustcomm_user_sock_dir(void) | |
538 | { | |
539 | int result; | |
540 | char *sock_dir = NULL; | |
541 | ||
542 | result = asprintf(&sock_dir, "%s%s", USER_SOCK_DIR, | |
543 | cuserid(NULL)); | |
544 | if (result < 0) { | |
545 | ERR("string overflow allocating directory name"); | |
546 | return NULL; | |
547 | } | |
548 | ||
549 | return sock_dir; | |
550 | } | |
4723ca09 | 551 | |
2a79ceeb PMF |
552 | /* Open a connection to a traceable app. |
553 | * | |
554 | * Return value: | |
555 | * 0: success | |
556 | * -1: error | |
557 | */ | |
558 | ||
4723ca09 | 559 | int ustcomm_connect_app(pid_t pid, int *app_fd) |
4e2a8808 PMF |
560 | { |
561 | int result; | |
4723ca09 | 562 | int retval = 0; |
dbd75de7 NC |
563 | char *dir_name, *sock_name; |
564 | ||
565 | dir_name = ustcomm_user_sock_dir(); | |
566 | if (!dir_name) | |
567 | return -ENOMEM; | |
4e2a8808 | 568 | |
dbd75de7 | 569 | result = asprintf(&sock_name, "%s/%d", dir_name, pid); |
4723ca09 NC |
570 | if (result < 0) { |
571 | ERR("failed to allocate socket name"); | |
dbd75de7 NC |
572 | retval = -1; |
573 | goto free_dir_name; | |
4e2a8808 PMF |
574 | } |
575 | ||
dbd75de7 | 576 | result = ustcomm_connect_path(sock_name, app_fd); |
4723ca09 NC |
577 | if (result < 0) { |
578 | ERR("failed to connect to app"); | |
579 | retval = -1; | |
dbd75de7 | 580 | goto free_sock_name; |
4723ca09 | 581 | } |
2a79ceeb | 582 | |
dbd75de7 NC |
583 | free_sock_name: |
584 | free(sock_name); | |
585 | free_dir_name: | |
586 | free(dir_name); | |
2a79ceeb | 587 | |
4723ca09 | 588 | return retval; |
2a79ceeb PMF |
589 | } |
590 | ||
4723ca09 | 591 | int ensure_dir_exists(const char *dir) |
dce0b474 PMF |
592 | { |
593 | struct stat st; | |
594 | int result; | |
595 | ||
596 | if(!strcmp(dir, "")) | |
597 | return -1; | |
598 | ||
599 | result = stat(dir, &st); | |
600 | if(result == -1 && errno != ENOENT) { | |
601 | return -1; | |
602 | } | |
603 | else if(result == -1) { | |
604 | /* ENOENT */ | |
dce0b474 PMF |
605 | int result; |
606 | ||
18baca84 DG |
607 | /* mkdir mode to 0777 */ |
608 | result = mkdir_p(dir, S_IRWXU | S_IRWXG | S_IRWXO); | |
dce0b474 | 609 | if(result != 0) { |
d6d27063 | 610 | ERR("executing in recursive creation of directory %s", dir); |
dce0b474 PMF |
611 | return -1; |
612 | } | |
613 | } | |
614 | ||
615 | return 0; | |
616 | } | |
617 | ||
72098143 NC |
618 | char * ustcomm_print_data(char *data_field, int field_size, |
619 | int *offset, const char *format, ...) | |
620 | { | |
621 | va_list args; | |
622 | int count, limit; | |
623 | char *ptr = USTCOMM_POISON_PTR; | |
624 | ||
625 | limit = field_size - *offset; | |
626 | va_start(args, format); | |
627 | count = vsnprintf(&data_field[*offset], limit, format, args); | |
628 | va_end(args); | |
629 | ||
630 | if (count < limit && count > -1) { | |
631 | ptr = NULL + *offset; | |
632 | *offset = *offset + count + 1; | |
633 | } | |
634 | ||
635 | return ptr; | |
636 | } | |
637 | ||
638 | char * ustcomm_restore_ptr(char *ptr, char *data_field, int data_field_size) | |
639 | { | |
640 | if ((unsigned long)ptr > data_field_size || | |
641 | ptr == USTCOMM_POISON_PTR) { | |
642 | return NULL; | |
643 | } | |
08230db7 | 644 | |
72098143 NC |
645 | return data_field + (long)ptr; |
646 | } | |
2a79ceeb | 647 | |
28c1bb40 NC |
648 | int ustcomm_pack_single_field(struct ustcomm_header *header, |
649 | struct ustcomm_single_field *single_field, | |
650 | const char *string) | |
10f2b724 NC |
651 | { |
652 | int offset = 0; | |
653 | ||
28c1bb40 NC |
654 | single_field->field = ustcomm_print_data(single_field->data, |
655 | sizeof(single_field->data), | |
656 | &offset, | |
657 | string); | |
10f2b724 | 658 | |
28c1bb40 | 659 | if (single_field->field == USTCOMM_POISON_PTR) { |
10f2b724 NC |
660 | return -ENOMEM; |
661 | } | |
662 | ||
28c1bb40 | 663 | header->size = COMPUTE_MSG_SIZE(single_field, offset); |
10f2b724 NC |
664 | |
665 | return 0; | |
666 | } | |
667 | ||
28c1bb40 | 668 | int ustcomm_unpack_single_field(struct ustcomm_single_field *single_field) |
10f2b724 | 669 | { |
28c1bb40 NC |
670 | single_field->field = ustcomm_restore_ptr(single_field->field, |
671 | single_field->data, | |
672 | sizeof(single_field->data)); | |
673 | if (!single_field->field) { | |
10f2b724 NC |
674 | return -EINVAL; |
675 | } | |
676 | ||
677 | return 0; | |
678 | } | |
72098143 NC |
679 | |
680 | int ustcomm_pack_channel_info(struct ustcomm_header *header, | |
681 | struct ustcomm_channel_info *ch_inf, | |
d89b8191 | 682 | const char *trace, |
72098143 | 683 | const char *channel) |
b02e31e5 | 684 | { |
72098143 NC |
685 | int offset = 0; |
686 | ||
d89b8191 NC |
687 | ch_inf->trace = ustcomm_print_data(ch_inf->data, |
688 | sizeof(ch_inf->data), | |
689 | &offset, | |
690 | trace); | |
691 | ||
692 | if (ch_inf->trace == USTCOMM_POISON_PTR) { | |
693 | return -ENOMEM; | |
694 | } | |
695 | ||
72098143 NC |
696 | ch_inf->channel = ustcomm_print_data(ch_inf->data, |
697 | sizeof(ch_inf->data), | |
698 | &offset, | |
699 | channel); | |
b02e31e5 | 700 | |
72098143 NC |
701 | if (ch_inf->channel == USTCOMM_POISON_PTR) { |
702 | return -ENOMEM; | |
b02e31e5 PMF |
703 | } |
704 | ||
72098143 NC |
705 | header->size = COMPUTE_MSG_SIZE(ch_inf, offset); |
706 | ||
707 | return 0; | |
b02e31e5 PMF |
708 | } |
709 | ||
72098143 NC |
710 | |
711 | int ustcomm_unpack_channel_info(struct ustcomm_channel_info *ch_inf) | |
b02e31e5 | 712 | { |
d89b8191 NC |
713 | ch_inf->trace = ustcomm_restore_ptr(ch_inf->trace, |
714 | ch_inf->data, | |
715 | sizeof(ch_inf->data)); | |
716 | if (!ch_inf->trace) { | |
717 | return -EINVAL; | |
718 | } | |
719 | ||
72098143 NC |
720 | ch_inf->channel = ustcomm_restore_ptr(ch_inf->channel, |
721 | ch_inf->data, | |
722 | sizeof(ch_inf->data)); | |
723 | if (!ch_inf->channel) { | |
724 | return -EINVAL; | |
725 | } | |
b02e31e5 | 726 | |
72098143 NC |
727 | return 0; |
728 | } | |
729 | ||
730 | int ustcomm_pack_buffer_info(struct ustcomm_header *header, | |
731 | struct ustcomm_buffer_info *buf_inf, | |
d89b8191 | 732 | const char *trace, |
72098143 NC |
733 | const char *channel, |
734 | int channel_cpu) | |
735 | { | |
736 | int offset = 0; | |
737 | ||
d89b8191 NC |
738 | buf_inf->trace = ustcomm_print_data(buf_inf->data, |
739 | sizeof(buf_inf->data), | |
740 | &offset, | |
741 | trace); | |
742 | ||
743 | if (buf_inf->trace == USTCOMM_POISON_PTR) { | |
744 | return -ENOMEM; | |
745 | } | |
746 | ||
72098143 NC |
747 | buf_inf->channel = ustcomm_print_data(buf_inf->data, |
748 | sizeof(buf_inf->data), | |
749 | &offset, | |
750 | channel); | |
751 | ||
752 | if (buf_inf->channel == USTCOMM_POISON_PTR) { | |
753 | return -ENOMEM; | |
b02e31e5 PMF |
754 | } |
755 | ||
72098143 NC |
756 | buf_inf->ch_cpu = channel_cpu; |
757 | ||
758 | header->size = COMPUTE_MSG_SIZE(buf_inf, offset); | |
759 | ||
760 | return 0; | |
b02e31e5 PMF |
761 | } |
762 | ||
72098143 NC |
763 | |
764 | int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf) | |
b02e31e5 | 765 | { |
d89b8191 NC |
766 | buf_inf->trace = ustcomm_restore_ptr(buf_inf->trace, |
767 | buf_inf->data, | |
768 | sizeof(buf_inf->data)); | |
769 | if (!buf_inf->trace) { | |
770 | return -EINVAL; | |
771 | } | |
772 | ||
72098143 NC |
773 | buf_inf->channel = ustcomm_restore_ptr(buf_inf->channel, |
774 | buf_inf->data, | |
775 | sizeof(buf_inf->data)); | |
776 | if (!buf_inf->channel) { | |
777 | return -EINVAL; | |
778 | } | |
b02e31e5 | 779 | |
72098143 NC |
780 | return 0; |
781 | } | |
782 | ||
783 | int ustcomm_pack_marker_info(struct ustcomm_header *header, | |
784 | struct ustcomm_marker_info *marker_inf, | |
d89b8191 | 785 | const char *trace, |
72098143 NC |
786 | const char *channel, |
787 | const char *marker) | |
788 | { | |
789 | int offset = 0; | |
b02e31e5 | 790 | |
d89b8191 NC |
791 | marker_inf->trace = ustcomm_print_data(marker_inf->data, |
792 | sizeof(marker_inf->data), | |
793 | &offset, | |
794 | trace); | |
795 | ||
796 | if (marker_inf->trace == USTCOMM_POISON_PTR) { | |
797 | return -ENOMEM; | |
798 | } | |
799 | ||
800 | ||
72098143 NC |
801 | marker_inf->channel = ustcomm_print_data(marker_inf->data, |
802 | sizeof(marker_inf->data), | |
803 | &offset, | |
804 | channel); | |
b02e31e5 | 805 | |
72098143 NC |
806 | if (marker_inf->channel == USTCOMM_POISON_PTR) { |
807 | return -ENOMEM; | |
808 | } | |
809 | ||
810 | ||
811 | marker_inf->marker = ustcomm_print_data(marker_inf->data, | |
812 | sizeof(marker_inf->data), | |
813 | &offset, | |
814 | marker); | |
b02e31e5 | 815 | |
72098143 NC |
816 | if (marker_inf->marker == USTCOMM_POISON_PTR) { |
817 | return -ENOMEM; | |
b02e31e5 PMF |
818 | } |
819 | ||
72098143 | 820 | header->size = COMPUTE_MSG_SIZE(marker_inf, offset); |
b02e31e5 | 821 | |
72098143 NC |
822 | return 0; |
823 | } | |
b02e31e5 | 824 | |
72098143 NC |
825 | int ustcomm_unpack_marker_info(struct ustcomm_marker_info *marker_inf) |
826 | { | |
d89b8191 NC |
827 | marker_inf->trace = ustcomm_restore_ptr(marker_inf->trace, |
828 | marker_inf->data, | |
829 | sizeof(marker_inf->data)); | |
830 | if (!marker_inf->trace) { | |
831 | return -EINVAL; | |
832 | } | |
833 | ||
72098143 NC |
834 | marker_inf->channel = ustcomm_restore_ptr(marker_inf->channel, |
835 | marker_inf->data, | |
836 | sizeof(marker_inf->data)); | |
837 | if (!marker_inf->channel) { | |
838 | return -EINVAL; | |
839 | } | |
840 | ||
841 | marker_inf->marker = ustcomm_restore_ptr(marker_inf->marker, | |
842 | marker_inf->data, | |
843 | sizeof(marker_inf->data)); | |
844 | if (!marker_inf->marker) { | |
845 | return -EINVAL; | |
846 | } | |
847 | ||
848 | return 0; | |
b02e31e5 PMF |
849 | } |
850 |