X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=libustcomm%2Fustcomm.c;h=07f7f8748daec2d29a04798244b63f5293da0677;hb=5c3950f8809ce2c5272fdbfa27b606f648b485fb;hp=63eed5fa8b63d19fc2957e1105ed0338aad898ca;hpb=0222e1213f196b66cbc08cd29093aca4a28e9ffb;p=ust.git diff --git a/libustcomm/ustcomm.c b/libustcomm/ustcomm.c index 63eed5f..07f7f87 100644 --- a/libustcomm/ustcomm.c +++ b/libustcomm/ustcomm.c @@ -18,9 +18,11 @@ /* API used by UST components to communicate with each other via sockets. */ #define _GNU_SOURCE +#include #include #include #include +#include #include #include #include @@ -31,7 +33,6 @@ #include #include #include -#include #include "ustcomm.h" #include "usterr.h" @@ -371,7 +372,7 @@ int ustcomm_recv_fd(int sock, if (peek_header.size && data) { if (peek_header.size < 0 || peek_header.size > USTCOMM_DATA_SIZE) { - ERR("big peek header! %d", peek_header.size); + ERR("big peek header! %ld", peek_header.size); return 0; } @@ -533,6 +534,142 @@ close_sock: return -1; } +/* Returns the current users socket directory, must be freed */ +char *ustcomm_user_sock_dir(void) +{ + int result; + char *sock_dir = NULL; + + result = asprintf(&sock_dir, "%s%s", USER_SOCK_DIR, + cuserid(NULL)); + if (result < 0) { + ERR("string overflow allocating directory name"); + return NULL; + } + + return sock_dir; +} + +static int time_and_pid_from_socket_name(char *sock_name, unsigned long *time, + pid_t *pid) +{ + char *saveptr, *pid_m_time_str; + char *sock_basename = strdup(basename(sock_name)); + + if (!sock_basename) { + return -1; + } + + /* This is the pid */ + pid_m_time_str = strtok_r(sock_basename, ".", &saveptr); + if (!pid_m_time_str) { + goto out_err; + } + + errno = 0; + *pid = (pid_t)strtoul(pid_m_time_str, NULL, 10); + if (errno) { + goto out_err; + } + + /* This should be the time-stamp */ + pid_m_time_str = strtok_r(NULL, ".", &saveptr); + if (!pid_m_time_str) { + goto out_err; + } + + errno = 0; + *time = strtoul(pid_m_time_str, NULL, 10); + if (errno) { + goto out_err; + } + + return 0; + +out_err: + free(sock_basename); + return -1; +} + +time_t ustcomm_pid_st_mtime(pid_t pid) +{ + struct stat proc_stat; + char proc_name[PATH_MAX]; + + if (snprintf(proc_name, PATH_MAX - 1, "/proc/%ld", (long) pid) < 0) { + return 0; + } + + if (stat(proc_name, &proc_stat)) { + return 0; + } + + return proc_stat.st_mtime; +} + +int ustcomm_is_socket_live(char *sock_name, pid_t *read_pid) +{ + time_t time_from_pid; + unsigned long time_from_sock; + pid_t pid; + + if (time_and_pid_from_socket_name(sock_name, &time_from_sock, &pid)) { + return 0; + } + + if (read_pid) { + *read_pid = pid; + } + + time_from_pid = ustcomm_pid_st_mtime(pid); + if (!time_from_pid) { + return 0; + } + + if ((unsigned long) time_from_pid == time_from_sock) { + return 1; + } + + return 0; +} + +#define MAX_SOCK_PATH_BASE_LEN 100 + +static int ustcomm_get_sock_name(char *dir_name, pid_t pid, char *sock_name) +{ + struct dirent *dirent; + char sock_path_base[MAX_SOCK_PATH_BASE_LEN]; + int len; + DIR *dir = opendir(dir_name); + + snprintf(sock_path_base, MAX_SOCK_PATH_BASE_LEN - 1, + "%ld.", (long) pid); + len = strlen(sock_path_base); + + while ((dirent = readdir(dir))) { + if (!strcmp(dirent->d_name, ".") || + !strcmp(dirent->d_name, "..") || + !strcmp(dirent->d_name, "ust-consumer") || + dirent->d_type == DT_DIR || + strncmp(dirent->d_name, sock_path_base, len)) { + continue; + } + + if (ustcomm_is_socket_live(dirent->d_name, NULL)) { + if (snprintf(sock_name, PATH_MAX - 1, "%s/%s", + dir_name, dirent->d_name) < 0) { + PERROR("path longer than PATH_MAX?"); + goto out_err; + } + closedir(dir); + return 0; + } + } + +out_err: + closedir(dir); + return -1; +} /* Open a connection to a traceable app. * @@ -541,51 +678,116 @@ close_sock: * -1: error */ -int ustcomm_connect_app(pid_t pid, int *app_fd) +static int connect_app_non_root(pid_t pid, int *app_fd) { int result; int retval = 0; - char *name; + char *dir_name; + char sock_name[PATH_MAX]; - result = asprintf(&name, "%s/%d", SOCK_DIR, pid); - if (result < 0) { - ERR("failed to allocate socket name"); - return -1; + dir_name = ustcomm_user_sock_dir(); + if (!dir_name) + return -ENOMEM; + + if (ustcomm_get_sock_name(dir_name, pid, sock_name)) { + retval = -ENOENT; + goto free_dir_name; } - result = ustcomm_connect_path(name, app_fd); + result = ustcomm_connect_path(sock_name, app_fd); if (result < 0) { ERR("failed to connect to app"); retval = -1; + goto free_dir_name; } - free(name); +free_dir_name: + free(dir_name); return retval; } -int ensure_dir_exists(const char *dir) + + +static int connect_app_root(pid_t pid, int *app_fd) +{ + DIR *tmp_dir; + struct dirent *dirent; + char dir_name[PATH_MAX], sock_name[PATH_MAX]; + int result = -1; + + tmp_dir = opendir(USER_TMP_DIR); + if (!tmp_dir) { + return -1; + } + + while ((dirent = readdir(tmp_dir))) { + if (!strncmp(dirent->d_name, USER_SOCK_DIR_BASE, + strlen(USER_SOCK_DIR_BASE))) { + + if (snprintf(dir_name, PATH_MAX - 1, "%s/%s", USER_TMP_DIR, + dirent->d_name) < 0) { + continue; + } + + if (ustcomm_get_sock_name(dir_name, pid, sock_name)) { + continue; + } + + result = ustcomm_connect_path(sock_name, app_fd); + + if (result == 0) { + goto close_tmp_dir; + } + } + } + +close_tmp_dir: + closedir(tmp_dir); + + return result; +} + +int ustcomm_connect_app(pid_t pid, int *app_fd) +{ + *app_fd = 0; + + if (geteuid()) { + return connect_app_non_root(pid, app_fd); + } else { + return connect_app_root(pid, app_fd); + } + +} + +int ensure_dir_exists(const char *dir, mode_t mode) { struct stat st; int result; - if(!strcmp(dir, "")) + if (!strcmp(dir, "")) return -1; result = stat(dir, &st); - if(result == -1 && errno != ENOENT) { + if (result < 0 && errno != ENOENT) { return -1; - } - else if(result == -1) { + } else if (result < 0) { /* ENOENT */ int result; - /* mkdir mode to 0777 */ - result = mkdir_p(dir, S_IRWXU | S_IRWXG | S_IRWXO); + result = mkdir_p(dir, mode); if(result != 0) { ERR("executing in recursive creation of directory %s", dir); return -1; } + } else { + if (st.st_mode != mode) { + result = chmod(dir, mode); + if (result < 0) { + ERR("couldn't set directory mode on %s", dir); + return -1; + } + } } return 0; @@ -621,33 +823,32 @@ char * ustcomm_restore_ptr(char *ptr, char *data_field, int data_field_size) return data_field + (long)ptr; } -int ustcomm_pack_trace_info(struct ustcomm_header *header, - struct ustcomm_trace_info *trace_inf, - const char *trace) +int ustcomm_pack_single_field(struct ustcomm_header *header, + struct ustcomm_single_field *single_field, + const char *string) { int offset = 0; - trace_inf->trace = ustcomm_print_data(trace_inf->data, - sizeof(trace_inf->data), - &offset, - trace); + single_field->field = ustcomm_print_data(single_field->data, + sizeof(single_field->data), + &offset, + string); - if (trace_inf->trace == USTCOMM_POISON_PTR) { + if (single_field->field == USTCOMM_POISON_PTR) { return -ENOMEM; } - header->size = COMPUTE_MSG_SIZE(trace_inf, offset); + header->size = COMPUTE_MSG_SIZE(single_field, offset); return 0; } - -int ustcomm_unpack_trace_info(struct ustcomm_trace_info *trace_inf) +int ustcomm_unpack_single_field(struct ustcomm_single_field *single_field) { - trace_inf->trace = ustcomm_restore_ptr(trace_inf->trace, - trace_inf->data, - sizeof(trace_inf->data)); - if (!trace_inf->trace) { + single_field->field = ustcomm_restore_ptr(single_field->field, + single_field->data, + sizeof(single_field->data)); + if (!single_field->field) { return -EINVAL; } @@ -757,102 +958,68 @@ int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf) return 0; } -int ustcomm_pack_marker_info(struct ustcomm_header *header, - struct ustcomm_marker_info *marker_inf, +int ustcomm_pack_ust_marker_info(struct ustcomm_header *header, + struct ustcomm_ust_marker_info *ust_marker_inf, const char *trace, const char *channel, - const char *marker) + const char *ust_marker) { int offset = 0; - marker_inf->trace = ustcomm_print_data(marker_inf->data, - sizeof(marker_inf->data), + ust_marker_inf->trace = ustcomm_print_data(ust_marker_inf->data, + sizeof(ust_marker_inf->data), &offset, trace); - if (marker_inf->trace == USTCOMM_POISON_PTR) { + if (ust_marker_inf->trace == USTCOMM_POISON_PTR) { return -ENOMEM; } - marker_inf->channel = ustcomm_print_data(marker_inf->data, - sizeof(marker_inf->data), + ust_marker_inf->channel = ustcomm_print_data(ust_marker_inf->data, + sizeof(ust_marker_inf->data), &offset, channel); - if (marker_inf->channel == USTCOMM_POISON_PTR) { + if (ust_marker_inf->channel == USTCOMM_POISON_PTR) { return -ENOMEM; } - marker_inf->marker = ustcomm_print_data(marker_inf->data, - sizeof(marker_inf->data), + ust_marker_inf->ust_marker = ustcomm_print_data(ust_marker_inf->data, + sizeof(ust_marker_inf->data), &offset, - marker); + ust_marker); - if (marker_inf->marker == USTCOMM_POISON_PTR) { + if (ust_marker_inf->ust_marker == USTCOMM_POISON_PTR) { return -ENOMEM; } - header->size = COMPUTE_MSG_SIZE(marker_inf, offset); + header->size = COMPUTE_MSG_SIZE(ust_marker_inf, offset); return 0; } -int ustcomm_unpack_marker_info(struct ustcomm_marker_info *marker_inf) +int ustcomm_unpack_ust_marker_info(struct ustcomm_ust_marker_info *ust_marker_inf) { - marker_inf->trace = ustcomm_restore_ptr(marker_inf->trace, - marker_inf->data, - sizeof(marker_inf->data)); - if (!marker_inf->trace) { - return -EINVAL; - } - - marker_inf->channel = ustcomm_restore_ptr(marker_inf->channel, - marker_inf->data, - sizeof(marker_inf->data)); - if (!marker_inf->channel) { + ust_marker_inf->trace = ustcomm_restore_ptr(ust_marker_inf->trace, + ust_marker_inf->data, + sizeof(ust_marker_inf->data)); + if (!ust_marker_inf->trace) { return -EINVAL; } - marker_inf->marker = ustcomm_restore_ptr(marker_inf->marker, - marker_inf->data, - sizeof(marker_inf->data)); - if (!marker_inf->marker) { + ust_marker_inf->channel = ustcomm_restore_ptr(ust_marker_inf->channel, + ust_marker_inf->data, + sizeof(ust_marker_inf->data)); + if (!ust_marker_inf->channel) { return -EINVAL; } - return 0; -} - -int ustcomm_pack_sock_path(struct ustcomm_header *header, - struct ustcomm_sock_path *sock_path_inf, - const char *socket_path) -{ - int offset = 0; - - sock_path_inf->sock_path = - ustcomm_print_data(sock_path_inf->data, - sizeof(sock_path_inf->data), - &offset, - socket_path); - - if (sock_path_inf->sock_path == USTCOMM_POISON_PTR) { - return -ENOMEM; - } - - header->size = COMPUTE_MSG_SIZE(sock_path_inf, offset); - - return 0; -} - -int ustcomm_unpack_sock_path(struct ustcomm_sock_path *sock_path_inf) -{ - sock_path_inf->sock_path = - ustcomm_restore_ptr(sock_path_inf->sock_path, - sock_path_inf->data, - sizeof(sock_path_inf->data)); - if (!sock_path_inf->sock_path) { + ust_marker_inf->ust_marker = ustcomm_restore_ptr(ust_marker_inf->ust_marker, + ust_marker_inf->data, + sizeof(ust_marker_inf->data)); + if (!ust_marker_inf->ust_marker) { return -EINVAL; }