Initial import of libustctl and libustcomm
[lttng-tools.git] / libustcomm / libustcomm.c
CommitLineData
62d3069f
DG
1/*
2 * Copyright (C) 2009 Pierre-Marc Fournier
3 * 2010 Nils Carlson <nils.carlson@ericsson.com>
4 * 2011 David Goulet <david.goulet@polymtl.ca>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#define _GNU_SOURCE
22#include <dirent.h>
23#include <errno.h>
24#include <limits.h>
25#include <poll.h>
26#include <signal.h>
27#include <stdarg.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <sys/epoll.h>
32#include <sys/socket.h>
33#include <sys/stat.h>
34#include <sys/types.h>
35#include <sys/un.h>
36#include <unistd.h>
37
38#include "libustcomm.h"
39#include "lttngerr.h"
40
41#define MAX_SOCK_PATH_BASE_LEN 100
42
43/*
44 * get_sock_name
45 *
46 * Set sock_name to the libust socket path using the pid
47 * and the base directory dir_name.
48 */
49static int get_sock_name(char *dir_name, pid_t pid, char *sock_name)
50{
51 struct dirent *dirent;
52 char sock_path_base[MAX_SOCK_PATH_BASE_LEN];
53 int len;
54 DIR *dir;
55
56 dir = opendir(dir_name);
57 if (dir == NULL) {
58 ERR("ustcomm sock name opendir %s", dir_name);
59 goto out_err;
60 }
61
62 snprintf(sock_path_base, MAX_SOCK_PATH_BASE_LEN - 1, "%ld", (long) pid);
63 len = strlen(sock_path_base);
64
65 DBG("Socket directory %s", sock_path_base);
66
67 while ((dirent = readdir(dir))) {
68 if (!strcmp(dirent->d_name, ".") ||
69 !strcmp(dirent->d_name, "..") ||
70 !strcmp(dirent->d_name, "ust-consumer") ||
71 dirent->d_type == DT_DIR ||
72 strncmp(dirent->d_name, sock_path_base, len) != 0) {
73 continue;
74 }
75
76 if (snprintf(sock_name, PATH_MAX - 1, "%s/%s", dir_name, dirent->d_name) < 0) {
77 perror("path longer than PATH_MAX?");
78 goto out_err;
79 }
80
81 break;
82 }
83
84 return 0;
85
86out_err:
87 closedir(dir);
88 return -1;
89}
90
91/*
92 * create_sock_addr
93 *
94 * Create a sockaddr structure for unic socket.
95 */
96static struct sockaddr_un *create_sock_addr(const char *name, size_t *sock_addr_size)
97{
98 struct sockaddr_un * addr;
99 size_t alloc_size;
100
101 alloc_size = (size_t) (((struct sockaddr_un *) 0)->sun_path) +
102 strlen(name) + 1;
103
104 addr = malloc(alloc_size);
105 if (addr < 0) {
106 ERR("allocating addr failed");
107 return NULL;
108 }
109
110 addr->sun_family = AF_UNIX;
111 strcpy(addr->sun_path, name);
112
113 *sock_addr_size = alloc_size;
114
115 return addr;
116}
117
118/*
119 * connect_app_non_root
120 *
121 * Open a connection to a non root traceable app.
122 * On error, return -1 else 0
123 */
124static int connect_app_non_root(pid_t pid, int *app_fd)
125{
126 int result;
127 int retval = 0;
128 char *dir_name;
129 char sock_name[PATH_MAX];
130
131 dir_name = ustcomm_user_sock_dir();
132 if (!dir_name) {
133 return -ENOMEM;
134 }
135
136 if (get_sock_name(dir_name, pid, sock_name)) {
137 retval = -ENOENT;
138 goto free_dir_name;
139 }
140
141 result = ustcomm_connect_path(sock_name, app_fd);
142 if (result < 0) {
143 ERR("failed to connect to app");
144 retval = -1;
145 goto free_dir_name;
146 }
147
148free_dir_name:
149 free(dir_name);
150
151 return retval;
152}
153
154/*
155 * connect_app_root
156 *
157 * Open a connection to a root traceable app.
158 * On error, return -1 else 0
159 */
160static int connect_app_root(pid_t pid, int *app_fd)
161{
162 DIR *tmp_dir;
163 struct dirent *dirent;
164 char dir_name[PATH_MAX], sock_name[PATH_MAX];
165 int result = -1;
166
167 tmp_dir = opendir(USER_TMP_DIR);
168 if (!tmp_dir) {
169 return -1;
170 }
171
172 while ((dirent = readdir(tmp_dir))) {
173 if (!strncmp(dirent->d_name, USER_SOCK_DIR_BASE,
174 strlen(USER_SOCK_DIR_BASE))) {
175
176 if (snprintf(dir_name, PATH_MAX - 1, "%s/%s", USER_TMP_DIR,
177 dirent->d_name) < 0) {
178 continue;
179 }
180
181 if (get_sock_name(dir_name, pid, sock_name)) {
182 continue;
183 }
184
185 result = ustcomm_connect_path(sock_name, app_fd);
186
187 if (result == 0) {
188 goto close_tmp_dir;
189 }
190 }
191 }
192
193close_tmp_dir:
194 closedir(tmp_dir);
195
196 return result;
197}
198
199/*
200 * time_and_pid_from_socket_name
201 *
202 * Get time from socket name
203 */
204static int time_and_pid_from_socket_name(char *sock_name, unsigned long *time,
205 pid_t *pid)
206{
207 char *saveptr, *pid_m_time_str;
208 char *sock_basename = strdup(basename(sock_name));
209
210 if (!sock_basename) {
211 return -1;
212 }
213
214 /* This is the pid */
215 pid_m_time_str = strtok_r(sock_basename, ".", &saveptr);
216 if (!pid_m_time_str) {
217 goto out_err;
218 }
219
220 errno = 0;
221 *pid = (pid_t)strtoul(pid_m_time_str, NULL, 10);
222 if (errno) {
223 goto out_err;
224 }
225
226 /* This should be the time-stamp */
227 pid_m_time_str = strtok_r(NULL, ".", &saveptr);
228 if (!pid_m_time_str) {
229 goto out_err;
230 }
231
232 errno = 0;
233 *time = strtoul(pid_m_time_str, NULL, 10);
234 if (errno) {
235 goto out_err;
236 }
237
238 return 0;
239
240out_err:
241 free(sock_basename);
242 return -1;
243}
244
245/*
246 * ustcomm_is_socket_live
247 *
248 * Check if socket is available and "living".
249 */
250int ustcomm_is_socket_live(char *sock_name, pid_t *read_pid)
251{
252 time_t time_from_pid;
253 unsigned long time_from_sock;
254 pid_t pid;
255
256 if (time_and_pid_from_socket_name(sock_name, &time_from_sock, &pid)) {
257 return 0;
258 }
259
260 if (read_pid) {
261 *read_pid = pid;
262 }
263
264 time_from_pid = ustcomm_pid_st_mtime(pid);
265 if (!time_from_pid) {
266 return 0;
267 }
268
269 if ((unsigned long) time_from_pid == time_from_sock) {
270 return 1;
271 }
272
273 return 0;
274}
275
276/*
277 * ustcomm_init_sock
278 *
279 * Init socket for communication between libust and libustcomm.
280 */
281struct ustcomm_sock *ustcomm_init_sock(int fd, int epoll_fd,
282 struct cds_list_head *list)
283{
284 struct epoll_event ev;
285 struct ustcomm_sock *sock;
286
287 sock = malloc(sizeof(struct ustcomm_sock));
288 if (!sock) {
289 perror("malloc: couldn't allocate ustcomm_sock");
290 return NULL;
291 }
292
293 ev.events = EPOLLIN;
294 ev.data.ptr = sock;
295 sock->fd = fd;
296
297 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock->fd, &ev) == -1) {
298 perror("epoll_ctl: failed to add socket\n");
299 free(sock);
300 return NULL;
301 }
302
303 sock->epoll_fd = epoll_fd;
304 if (list) {
305 cds_list_add(&sock->list, list);
306 } else {
307 CDS_INIT_LIST_HEAD(&sock->list);
308 }
309
310 return sock;
311}
312
313/*
314 * ustcomm_del_sock
315 *
316 * Delete socket and remove it from the epoll set.
317 */
318void ustcomm_del_sock(struct ustcomm_sock *sock, int keep_in_epoll)
319{
320 cds_list_del(&sock->list);
321 if (!keep_in_epoll) {
322 if (epoll_ctl(sock->epoll_fd, EPOLL_CTL_DEL, sock->fd, NULL) == -1) {
323 perror("epoll_ctl: failed to delete socket");
324 }
325 }
326 close(sock->fd);
327 free(sock);
328}
329
330/*
331 * ustcomm_init_named_socket
332 *
333 * Init unix named socket
334 */
335struct ustcomm_sock *ustcomm_init_named_socket(const char *name, int epoll_fd)
336{
337 int result;
338 int fd;
339 size_t sock_addr_size;
340 struct sockaddr_un * addr;
341 struct ustcomm_sock *sock;
342
343 fd = socket(PF_UNIX, SOCK_STREAM, 0);
344 if(fd == -1) {
345 perror("socket");
346 return NULL;
347 }
348
349 addr = create_sock_addr(name, &sock_addr_size);
350 if (addr == NULL) {
351 ERR("allocating addr, UST thread bailing");
352 goto close_sock;
353 }
354
355 result = access(name, F_OK);
356 if(result == 0) {
357 /* file exists */
358 result = unlink(name);
359 if(result == -1) {
360 perror("unlink of socket file");
361 goto free_addr;
362 }
363 DBG("socket already exists; overwriting");
364 }
365
366 result = bind(fd, (struct sockaddr *)addr, sock_addr_size);
367 if(result == -1) {
368 perror("bind");
369 goto free_addr;
370 }
371
372 result = listen(fd, 1);
373 if(result == -1) {
374 perror("listen");
375 goto free_addr;
376 }
377
378 sock = ustcomm_init_sock(fd, epoll_fd, NULL);
379 if (!sock) {
380 ERR("failed to create ustcomm_sock");
381 goto free_addr;
382 }
383
384 free(addr);
385
386 return sock;
387
388free_addr:
389 free(addr);
390close_sock:
391 close(fd);
392
393 return NULL;
394}
395
396/*
397 * ustcomm_del_named_sock
398 *
399 * Delete named socket
400 */
401void ustcomm_del_named_sock(struct ustcomm_sock *sock, int keep_socket_file)
402{
403 int result, fd;
404 struct stat st;
405 struct sockaddr dummy;
406 struct sockaddr_un *sockaddr = NULL;
407 int alloc_size;
408
409 fd = sock->fd;
410
411 if(!keep_socket_file) {
412
413 /* Get the socket name */
414 alloc_size = sizeof(dummy);
415 if (getsockname(fd, &dummy, (socklen_t *)&alloc_size) < 0) {
416 perror("getsockname failed");
417 goto del_sock;
418 }
419
420 sockaddr = malloc(alloc_size);
421 if (!sockaddr) {
422 ERR("failed to allocate sockaddr");
423 goto del_sock;
424 }
425
426 if (getsockname(fd, sockaddr, (socklen_t *)&alloc_size) < 0) {
427 perror("getsockname failed");
428 goto free_sockaddr;
429 }
430
431 /* Destroy socket */
432 result = stat(sockaddr->sun_path, &st);
433 if(result < 0) {
434 ERR("stat (%s)", sockaddr->sun_path);
435 goto free_sockaddr;
436 }
437
438 /* Paranoid check before deleting. */
439 result = S_ISSOCK(st.st_mode);
440 if(!result) {
441 ERR("The socket we are about to delete is not a socket.");
442 goto free_sockaddr;
443 }
444
445 result = unlink(sockaddr->sun_path);
446 if(result < 0) {
447 perror("unlink");
448 }
449 }
450
451free_sockaddr:
452 free(sockaddr);
453
454del_sock:
455 ustcomm_del_sock(sock, keep_socket_file);
456}
457
458/*
459 * ustcomm_recv_alloc
460 *
461 * Receive data and allocate data reception buffers.
462 */
463int ustcomm_recv_alloc(int sock, struct ustcomm_header *header, char **data)
464{
465 int result;
466 struct ustcomm_header peek_header;
467 struct iovec iov[2];
468 struct msghdr msg;
469
470 /* Just to make the caller fail hard */
471 *data = NULL;
472
473 result = recv(sock, &peek_header, sizeof(peek_header), MSG_PEEK | MSG_WAITALL);
474 if (result <= 0) {
475 if(errno == ECONNRESET) {
476 return 0;
477 } else if (errno == EINTR) {
478 return -1;
479 } else if (result < 0) {
480 perror("recv");
481 return -1;
482 }
483 return 0;
484 }
485
486 memset(&msg, 0, sizeof(msg));
487
488 iov[0].iov_base = (char *)header;
489 iov[0].iov_len = sizeof(struct ustcomm_header);
490
491 msg.msg_iov = iov;
492 msg.msg_iovlen = 1;
493
494 if (peek_header.size) {
495 *data = malloc(peek_header.size);
496 if (!*data) {
497 return -ENOMEM;
498 }
499
500 iov[1].iov_base = *data;
501 iov[1].iov_len = peek_header.size;
502
503 msg.msg_iovlen++;
504 }
505
506 result = recvmsg(sock, &msg, MSG_WAITALL);
507 if (result < 0) {
508 free(*data);
509 perror("recvmsg failed");
510 }
511
512 return result;
513}
514
515/*
516 * ustcomm_recv_fd
517 *
518 * Receive data from fd.
519 * returns 1 to indicate a message was received
520 * returns 0 to indicate no message was received (end of stream)
521 * returns -1 to indicate an error
522 */
523int ustcomm_recv_fd(int sock, struct ustcomm_header *header, char *data, int *fd)
524{
525 int result;
526 struct ustcomm_header peek_header;
527 struct iovec iov[2];
528 struct msghdr msg;
529 struct cmsghdr *cmsg;
530 char buf[CMSG_SPACE(sizeof(int))];
531
532 result = recv(sock, &peek_header, sizeof(peek_header), MSG_PEEK | MSG_WAITALL);
533 if (result <= 0) {
534 if(errno == ECONNRESET) {
535 return 0;
536 } else if (errno == EINTR) {
537 return -1;
538 } else if (result < 0) {
539 perror("recv");
540 return -1;
541 }
542 return 0;
543 }
544
545 memset(&msg, 0, sizeof(msg));
546
547 iov[0].iov_base = (char *)header;
548 iov[0].iov_len = sizeof(struct ustcomm_header);
549
550 msg.msg_iov = iov;
551 msg.msg_iovlen = 1;
552
553 if (peek_header.size && data) {
554 if (peek_header.size < 0 ||
555 peek_header.size > USTCOMM_DATA_SIZE) {
556 ERR("big peek header! %ld", peek_header.size);
557 return 0;
558 }
559
560 iov[1].iov_base = data;
561 iov[1].iov_len = peek_header.size;
562
563 msg.msg_iovlen++;
564 }
565
566 if (fd && peek_header.fd_included) {
567 msg.msg_control = buf;
568 msg.msg_controllen = sizeof(buf);
569 }
570
571 result = recvmsg(sock, &msg, MSG_WAITALL);
572 if (result <= 0) {
573 if (result < 0) {
574 perror("recvmsg failed");
575 }
576 return result;
577 }
578
579 if (fd && peek_header.fd_included) {
580 cmsg = CMSG_FIRSTHDR(&msg);
581 result = 0;
582 while (cmsg != NULL) {
583 if (cmsg->cmsg_level == SOL_SOCKET
584 && cmsg->cmsg_type == SCM_RIGHTS) {
585 *fd = *(int *) CMSG_DATA(cmsg);
586 result = 1;
587 break;
588 }
589 cmsg = CMSG_NXTHDR(&msg, cmsg);
590 }
591 if (!result) {
592 ERR("Failed to receive file descriptor\n");
593 }
594 }
595
596 return 1;
597}
598
599/*
600 * ustcomm_recv
601 *
602 * Recv wrapper
603 */
604int ustcomm_recv(int sock, struct ustcomm_header *header, char *data)
605{
606 return ustcomm_recv_fd(sock, header, data, NULL);
607}
608
609/*
610 * ustcomm_send_fd
611 *
612 * Send data to fd.
613 */
614int ustcomm_send_fd(int sock, const struct ustcomm_header *header,
615 const char *data, int *fd)
616{
617 struct iovec iov[2];
618 struct msghdr msg;
619 int result;
620 struct cmsghdr *cmsg;
621 char buf[CMSG_SPACE(sizeof(int))];
622
623 memset(&msg, 0, sizeof(msg));
624
625 iov[0].iov_base = (char *)header;
626 iov[0].iov_len = sizeof(struct ustcomm_header);
627
628 msg.msg_iov = iov;
629 msg.msg_iovlen = 1;
630
631 if (header->size && data) {
632 iov[1].iov_base = (char *)data;
633 iov[1].iov_len = header->size;
634
635 msg.msg_iovlen++;
636
637 }
638
639 if (fd && header->fd_included) {
640 msg.msg_control = buf;
641 msg.msg_controllen = sizeof(buf);
642 cmsg = CMSG_FIRSTHDR(&msg);
643 cmsg->cmsg_level = SOL_SOCKET;
644 cmsg->cmsg_type = SCM_RIGHTS;
645 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
646 *(int *) CMSG_DATA(cmsg) = *fd;
647 msg.msg_controllen = cmsg->cmsg_len;
648 }
649
650 result = sendmsg(sock, &msg, MSG_NOSIGNAL);
651 if (result < 0 && errno != EPIPE) {
652 perror("sendmsg failed");
653 }
654 return result;
655}
656
657/*
658 * ustcomm_send
659 *
660 * Send wrapper
661 */
662int ustcomm_send(int sock, const struct ustcomm_header *header, const char *data)
663{
664 return ustcomm_send_fd(sock, header, data, NULL);
665}
666
667/*
668 * ustcomm_req
669 *
670 * Do a request to the libust socket which means sending data and
671 * receiving data.
672 */
673int ustcomm_req(int sock,
674 const struct ustcomm_header *req_header,
675 const char *req_data,
676 struct ustcomm_header *res_header,
677 char *res_data)
678{
679 int result;
680
681 result = ustcomm_send(sock, req_header, req_data);
682 if ( result <= 0) {
683 return result;
684 }
685
686 return ustcomm_recv(sock, res_header, res_data);
687}
688
689/*
690 * ustcomm_connect_path
691 *
692 * Connect to an fd.
693 * Return value:
694 * 0: success
695 * -1: error
696 */
697int ustcomm_connect_path(const char *name, int *connection_fd)
698{
699 int result, fd;
700 size_t sock_addr_size;
701 struct sockaddr_un *addr;
702
703 fd = socket(PF_UNIX, SOCK_STREAM, 0);
704 if(fd == -1) {
705 perror("socket");
706 return -1;
707 }
708
709 addr = create_sock_addr(name, &sock_addr_size);
710 if (addr == NULL) {
711 ERR("allocating addr failed");
712 goto close_sock;
713 }
714
715 result = connect(fd, (struct sockaddr *)addr, sock_addr_size);
716 if(result == -1) {
717 perror("ustcomm connect path");
718 goto free_sock_addr;
719 }
720
721 *connection_fd = fd;
722
723 free(addr);
724
725 return 0;
726
727free_sock_addr:
728 free(addr);
729close_sock:
730 close(fd);
731
732 return -1;
733}
734
735/*
736 * ustcomm_user_sock_dir
737 *
738 * Returns the current users socket directory, must be freed.
739 */
740char *ustcomm_user_sock_dir(void)
741{
742 int result;
743 char *sock_dir = NULL;
744
745 result = asprintf(&sock_dir, "/tmp/ust-app-socks/");
746 if (result < 0) {
747 ERR("string overflow allocating directory name");
748 return NULL;
749 }
750
751 return sock_dir;
752}
753
754/*
755 * ustcomm_pid_st_mtime
756 *
757 * Return time of the process pid creation.
758 */
759time_t ustcomm_pid_st_mtime(pid_t pid)
760{
761 struct stat proc_stat;
762 char proc_name[PATH_MAX];
763
764 if (snprintf(proc_name, PATH_MAX - 1, "/proc/%ld", (long) pid) < 0) {
765 return 0;
766 }
767
768 if (stat(proc_name, &proc_stat)) {
769 return 0;
770 }
771
772 return proc_stat.st_mtime;
773}
774
775/*
776 * ustcomm_connect_app
777 *
778 * Connect to libust application using the pid.
779 */
780int ustcomm_connect_app(pid_t pid, int *app_fd)
781{
782 *app_fd = 0;
783
784 if (geteuid()) {
785 return connect_app_non_root(pid, app_fd);
786 } else {
787 return connect_app_root(pid, app_fd);
788 }
789
790}
791
792/*
793 * ustcomm_print_data
794 *
795 * Print data in a data_field.
796 */
797char *ustcomm_print_data(char *data_field, int field_size,
798 int *offset, const char *format, ...)
799{
800 va_list args;
801 int count, limit;
802 char *ptr = USTCOMM_POISON_PTR;
803
804 limit = field_size - *offset;
805 va_start(args, format);
806 count = vsnprintf(&data_field[*offset], limit, format, args);
807 va_end(args);
808
809 if (count < limit && count > -1) {
810 ptr = NULL + *offset;
811 *offset = *offset + count + 1;
812 }
813
814 return ptr;
815}
816
817/*
818 * ustcomm_restore_ptr
819 */
820char *ustcomm_restore_ptr(char *ptr, char *data_field, int data_field_size)
821{
822 if ((unsigned long)ptr > data_field_size || ptr == USTCOMM_POISON_PTR) {
823 return NULL;
824 }
825
826 return data_field + (long)ptr;
827}
828
829/*
830 * ustcomm_pack_single_field
831 */
832int ustcomm_pack_single_field(struct ustcomm_header *header,
833 struct ustcomm_single_field *single_field,
834 const char *string)
835{
836 int offset = 0;
837
838 single_field->field = ustcomm_print_data(single_field->data,
839 sizeof(single_field->data),
840 &offset,
841 string);
842
843 if (single_field->field == USTCOMM_POISON_PTR) {
844 return -ENOMEM;
845 }
846
847 header->size = COMPUTE_MSG_SIZE(single_field, offset);
848
849 return 0;
850}
851
852/*
853 * ustcomm_unpack_single_field
854 */
855int ustcomm_unpack_single_field(struct ustcomm_single_field *single_field)
856{
857 single_field->field = ustcomm_restore_ptr(single_field->field,
858 single_field->data,
859 sizeof(single_field->data));
860 if (!single_field->field) {
861 return -EINVAL;
862 }
863
864 return 0;
865}
866
867/*
868 * ustcomm_pack_channel_info
869 */
870int ustcomm_pack_channel_info(struct ustcomm_header *header,
871 struct ustcomm_channel_info *ch_inf, const char *trace, const char *channel)
872{
873 int offset = 0;
874
875 ch_inf->trace = ustcomm_print_data(ch_inf->data,
876 sizeof(ch_inf->data), &offset, trace);
877
878 if (ch_inf->trace == USTCOMM_POISON_PTR) {
879 return -ENOMEM;
880 }
881
882 ch_inf->channel = ustcomm_print_data(ch_inf->data,
883 sizeof(ch_inf->data), &offset, channel);
884
885 if (ch_inf->channel == USTCOMM_POISON_PTR) {
886 return -ENOMEM;
887 }
888
889 header->size = COMPUTE_MSG_SIZE(ch_inf, offset);
890
891 return 0;
892}
893
894/*
895 * ustcomm_unpack_channel_info
896 */
897int ustcomm_unpack_channel_info(struct ustcomm_channel_info *ch_inf)
898{
899 ch_inf->trace = ustcomm_restore_ptr(ch_inf->trace,
900 ch_inf->data, sizeof(ch_inf->data));
901 if (!ch_inf->trace) {
902 return -EINVAL;
903 }
904
905 ch_inf->channel = ustcomm_restore_ptr(ch_inf->channel,
906 ch_inf->data, sizeof(ch_inf->data));
907 if (!ch_inf->channel) {
908 return -EINVAL;
909 }
910
911 return 0;
912}
913
914/*
915 * ustcomm_pack_buffer_info
916 */
917int ustcomm_pack_buffer_info(struct ustcomm_header *header,
918 struct ustcomm_buffer_info *buf_inf,
919 const char *trace, const char *channel, int channel_cpu)
920{
921 int offset = 0;
922
923 buf_inf->trace = ustcomm_print_data(buf_inf->data,
924 sizeof(buf_inf->data), &offset, trace);
925
926 if (buf_inf->trace == USTCOMM_POISON_PTR) {
927 return -ENOMEM;
928 }
929
930 buf_inf->channel = ustcomm_print_data(buf_inf->data,
931 sizeof(buf_inf->data), &offset, channel);
932
933 if (buf_inf->channel == USTCOMM_POISON_PTR) {
934 return -ENOMEM;
935 }
936
937 buf_inf->ch_cpu = channel_cpu;
938
939 header->size = COMPUTE_MSG_SIZE(buf_inf, offset);
940
941 return 0;
942}
943
944/*
945 * ustcomm_unpack_buffer_info
946 */
947int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf)
948{
949 buf_inf->trace = ustcomm_restore_ptr(buf_inf->trace,
950 buf_inf->data, sizeof(buf_inf->data));
951 if (!buf_inf->trace) {
952 return -EINVAL;
953 }
954
955 buf_inf->channel = ustcomm_restore_ptr(buf_inf->channel,
956 buf_inf->data, sizeof(buf_inf->data));
957 if (!buf_inf->channel) {
958 return -EINVAL;
959 }
960
961 return 0;
962}
963
964/*
965 * ustcomm_pack_ust_marker_info
966 */
967int ustcomm_pack_ust_marker_info(struct ustcomm_header *header,
968 struct ustcomm_ust_marker_info *ust_marker_inf,
969 const char *trace, const char *channel, const char *ust_marker)
970{
971 int offset = 0;
972
973 ust_marker_inf->trace = ustcomm_print_data(ust_marker_inf->data,
974 sizeof(ust_marker_inf->data), &offset, trace);
975
976 if (ust_marker_inf->trace == USTCOMM_POISON_PTR) {
977 return -ENOMEM;
978 }
979
980
981 ust_marker_inf->channel = ustcomm_print_data(ust_marker_inf->data,
982 sizeof(ust_marker_inf->data), &offset, channel);
983
984 if (ust_marker_inf->channel == USTCOMM_POISON_PTR) {
985 return -ENOMEM;
986 }
987
988
989 ust_marker_inf->ust_marker = ustcomm_print_data(ust_marker_inf->data,
990 sizeof(ust_marker_inf->data), &offset, ust_marker);
991
992 if (ust_marker_inf->ust_marker == USTCOMM_POISON_PTR) {
993 return -ENOMEM;
994 }
995
996 header->size = COMPUTE_MSG_SIZE(ust_marker_inf, offset);
997
998 return 0;
999}
1000
1001/*
1002 * ustcomm_unpack_ust_marker_info
1003 */
1004int ustcomm_unpack_ust_marker_info(struct ustcomm_ust_marker_info *ust_marker_inf)
1005{
1006 ust_marker_inf->trace = ustcomm_restore_ptr(ust_marker_inf->trace,
1007 ust_marker_inf->data,
1008 sizeof(ust_marker_inf->data));
1009 if (!ust_marker_inf->trace) {
1010 return -EINVAL;
1011 }
1012
1013 ust_marker_inf->channel = ustcomm_restore_ptr(ust_marker_inf->channel,
1014 ust_marker_inf->data, sizeof(ust_marker_inf->data));
1015 if (!ust_marker_inf->channel) {
1016 return -EINVAL;
1017 }
1018
1019 ust_marker_inf->ust_marker = ustcomm_restore_ptr(ust_marker_inf->ust_marker,
1020 ust_marker_inf->data, sizeof(ust_marker_inf->data));
1021 if (!ust_marker_inf->ust_marker) {
1022 return -EINVAL;
1023 }
1024
1025 return 0;
1026}
1027
This page took 0.058448 seconds and 4 git commands to generate.