X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=libustcmd%2Fustcmd.c;h=62c117f8cfa87de2d162370acc35f9e91242e572;hb=eb78cc5f9e75f620e9037708874f88b0a17e4ed8;hp=ac90f6cae099c681218ffc73cd3ec0f0777e368d;hpb=4723ca096d740ff93da400df304c9902e9834e5f;p=ust.git diff --git a/libustcmd/ustcmd.c b/libustcmd/ustcmd.c index ac90f6c..62c117f 100644 --- a/libustcmd/ustcmd.c +++ b/libustcmd/ustcmd.c @@ -28,6 +28,61 @@ #include "ust/ustcmd.h" #include "usterr.h" +static int do_cmd(const pid_t pid, + const struct ustcomm_header *req_header, + const char *req_data, + struct ustcomm_header *res_header, + char **res_data) +{ + int app_fd, result, saved_errno = 0; + char *recv_buf; + + if (ustcomm_connect_app(pid, &app_fd)) { + ERR("could not connect to PID %u", (unsigned int) pid); + errno = ENOTCONN; + return -1; + } + + recv_buf = zmalloc(USTCOMM_BUFFER_SIZE); + if (!recv_buf) { + saved_errno = ENOMEM; + goto close_app_fd; + } + + result = ustcomm_req(app_fd, req_header, req_data, res_header, recv_buf); + if (result > 0) { + saved_errno = -res_header->result; + if (res_header->size == 0 || saved_errno > 0) { + free(recv_buf); + } else { + if (res_data) { + *res_data = recv_buf; + } else { + free(recv_buf); + } + } + } else { + ERR("ustcomm req failed"); + if (result == 0) { + saved_errno = ENOTCONN; + } else { + saved_errno = -result; + } + free(recv_buf); + } + +close_app_fd: + close(app_fd); + + errno = saved_errno; + + if (errno) { + return -1; + } + + return 0; +} + pid_t *ustcmd_get_online_pids(void) { struct dirent *dirent; @@ -43,13 +98,13 @@ pid_t *ustcmd_get_online_pids(void) while ((dirent = readdir(dir))) { if (!strcmp(dirent->d_name, ".") || - !strcmp(dirent->d_name, "..")) { + !strcmp(dirent->d_name, "..")) { continue; } if (dirent->d_type != DT_DIR && - !!strcmp(dirent->d_name, "ustd")) { + !!strcmp(dirent->d_name, "ust-consumer")) { sscanf(dirent->d_name, "%u", (unsigned int *) &ret[i]); /* FIXME: Here we previously called pid_is_online, which @@ -68,7 +123,7 @@ pid_t *ustcmd_get_online_pids(void) ret[i] = 0; /* Array end */ if (ret[0] == 0) { - /* No PID at all */ + /* No PID at all */ free(ret); return NULL; } @@ -85,30 +140,27 @@ pid_t *ustcmd_get_online_pids(void) * @param pid Traced process ID * @return 0 if successful, or errors {USTCMD_ERR_GEN, USTCMD_ERR_ARG} */ -int ustcmd_set_marker_state(const char *mn, int state, pid_t pid) +int ustcmd_set_marker_state(const char *trace, const char *channel, + const char *marker, int state, pid_t pid) { - char *cmd_str [] = {"disable_marker", "enable_marker"}; - char *cmd; + struct ustcomm_header req_header, res_header; + struct ustcomm_marker_info marker_inf; int result; - if (mn == NULL) { - return USTCMD_ERR_ARG; + result = ustcomm_pack_marker_info(&req_header, + &marker_inf, + trace, + channel, + marker); + if (result < 0) { + errno = -result; + return -1; } - if (asprintf(&cmd, "%s %s", cmd_str[state], mn) < 0) { - ERR("ustcmd_set_marker_state : asprintf failed (%s %s)", - cmd_str[state], mn); - return USTCMD_ERR_GEN; - } + req_header.command = state ? ENABLE_MARKER : DISABLE_MARKER; - result = ustcmd_send_cmd(cmd, pid, NULL); - if (result != 1) { - free(cmd); - return USTCMD_ERR_GEN; - } - - free(cmd); - return 0; + return do_cmd(pid, &req_header, (char *)&marker_inf, + &res_header, NULL); } /** @@ -118,25 +170,27 @@ int ustcmd_set_marker_state(const char *mn, int state, pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error */ -int ustcmd_set_subbuf_size(const char *channel_size, pid_t pid) +int ustcmd_set_subbuf_size(const char *trace, const char *channel, + unsigned int subbuf_size, pid_t pid) { - char *cmd; + struct ustcomm_header req_header, res_header; + struct ustcomm_channel_info ch_inf; int result; - if (asprintf(&cmd, "%s %s", "set_subbuf_size", channel_size) < 0) { - ERR("ustcmd_set_subbuf_size : asprintf failed (set_subbuf_size %s)", - channel_size); + result = ustcomm_pack_channel_info(&req_header, + &ch_inf, + trace, + channel); + if (result < 0) { + errno = -result; return -1; } - result = ustcmd_send_cmd(cmd, pid, NULL); - if (result != 1) { - free(cmd); - return 1; - } + req_header.command = SET_SUBBUF_SIZE; + ch_inf.subbuf_size = subbuf_size; - free(cmd); - return 0; + return do_cmd(pid, &req_header, (char *)&ch_inf, + &res_header, NULL); } /** @@ -146,87 +200,123 @@ int ustcmd_set_subbuf_size(const char *channel_size, pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error */ -int ustcmd_set_subbuf_num(const char *channel_size, pid_t pid) +int ustcmd_set_subbuf_num(const char *trace, const char *channel, + unsigned int num, pid_t pid) { - char *cmd; + struct ustcomm_header req_header, res_header; + struct ustcomm_channel_info ch_inf; int result; - if (asprintf(&cmd, "%s %s", "set_subbuf_num", channel_size) < 0) { - ERR("ustcmd_set_subbuf_num : asprintf failed (set_subbuf_num %s", - channel_size); + result = ustcomm_pack_channel_info(&req_header, + &ch_inf, + trace, + channel); + if (result < 0) { + errno = -result; return -1; } - result = ustcmd_send_cmd(cmd, pid, NULL); - if (result != 1) { - free(cmd); - return 1; + req_header.command = SET_SUBBUF_NUM; + ch_inf.subbuf_num = num; + + return do_cmd(pid, &req_header, (char *)&ch_inf, + &res_header, NULL); + +} + +static int ustcmd_get_subbuf_num_size(const char *trace, const char *channel, + pid_t pid, int *num, int *size) +{ + struct ustcomm_header req_header, res_header; + struct ustcomm_channel_info ch_inf, *ch_inf_res; + int result; + + + result = ustcomm_pack_channel_info(&req_header, + &ch_inf, + trace, + channel); + if (result < 0) { + errno = -result; + return -1; + } + + req_header.command = GET_SUBBUF_NUM_SIZE; + + result = do_cmd(pid, &req_header, (char *)&ch_inf, + &res_header, (char **)&ch_inf_res); + if (result < 0) { + return -1; } - free(cmd); + *num = ch_inf_res->subbuf_num; + *size = ch_inf_res->subbuf_size; + + free(ch_inf_res); + return 0; } /** - * Get subbuffer size. + * Get subbuffer num. * * @param channel Channel name * @param pid Traced process ID - * @return subbuf size if successful, or error + * @return subbuf cnf if successful, or error */ -int ustcmd_get_subbuf_size(const char *channel, pid_t pid) +int ustcmd_get_subbuf_num(const char *trace, const char *channel, pid_t pid) { - char *cmd, *reply; - int result; + int num, size, result; - /* format: channel_cpu */ - if (asprintf(&cmd, "%s %s_0", "get_subbuf_size", channel) < 0) { - ERR("ustcmd_get_subbuf_size : asprintf failed (get_subbuf_size, %s_0", - channel); - return -1; - } - - result = ustcmd_send_cmd(cmd, pid, &reply); - if (result != 1) { - free(cmd); + result = ustcmd_get_subbuf_num_size(trace, channel, pid, + &num, &size); + if (result < 0) { + errno = -result; return -1; } - result = atoi(reply); - free(cmd); - free(reply); - return result; + return num; } /** - * Get subbuffer num. + * Get subbuffer size. * * @param channel Channel name * @param pid Traced process ID - * @return subbuf cnf if successful, or error + * @return subbuf size if successful, or error */ -int ustcmd_get_subbuf_num(const char *channel, pid_t pid) +int ustcmd_get_subbuf_size(const char *trace, const char *channel, pid_t pid) { - char *cmd, *reply; - int result; + int num, size, result; - /* format: channel_cpu */ - if (asprintf(&cmd, "%s %s_0", "get_n_subbufs", channel) < 0) { - ERR("ustcmd_get_subbuf_num : asprintf failed (get_n_subbufs, %s_0", - channel); + result = ustcmd_get_subbuf_num_size(trace, channel, pid, + &num, &size); + if (result < 0) { + errno = -result; return -1; } - result = ustcmd_send_cmd(cmd, pid, &reply); - if (result != 1) { - free(cmd); + return size; +} + + +static int do_trace_cmd(const char *trace, pid_t pid, int command) +{ + struct ustcomm_header req_header, res_header; + struct ustcomm_single_field trace_inf; + int result; + + result = ustcomm_pack_single_field(&req_header, + &trace_inf, + trace); + if (result < 0) { + errno = -result; return -1; } - result = atoi(reply); - free(cmd); - free(reply); - return result; + req_header.command = command; + + return do_cmd(pid, &req_header, (char *)&trace_inf, &res_header, NULL); } /** @@ -235,16 +325,9 @@ int ustcmd_get_subbuf_num(const char *channel, pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error USTCMD_ERR_GEN */ -int ustcmd_destroy_trace(pid_t pid) +int ustcmd_destroy_trace(const char *trace, pid_t pid) { - int result; - - result = ustcmd_send_cmd("trace_destroy", pid, NULL); - if (result != 1) { - return USTCMD_ERR_GEN; - } - - return 0; + return do_trace_cmd(trace, pid, DESTROY_TRACE); } /** @@ -253,16 +336,9 @@ int ustcmd_destroy_trace(pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error USTCMD_ERR_GEN */ -int ustcmd_setup_and_start(pid_t pid) +int ustcmd_setup_and_start(const char *trace, pid_t pid) { - int result; - - result = ustcmd_send_cmd("start", pid, NULL); - if (result != 1) { - return USTCMD_ERR_GEN; - } - - return 0; + return do_trace_cmd(trace, pid, START); } /** @@ -271,16 +347,9 @@ int ustcmd_setup_and_start(pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error USTCMD_ERR_GEN */ -int ustcmd_create_trace(pid_t pid) +int ustcmd_create_trace(const char *trace, pid_t pid) { - int result; - - result = ustcmd_send_cmd("trace_create", pid, NULL); - if (result != 1) { - return USTCMD_ERR_GEN; - } - - return 0; + return do_trace_cmd(trace, pid, CREATE_TRACE); } /** @@ -289,16 +358,9 @@ int ustcmd_create_trace(pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error USTCMD_ERR_GEN */ -int ustcmd_start_trace(pid_t pid) +int ustcmd_start_trace(const char *trace, pid_t pid) { - int result; - - result = ustcmd_send_cmd("trace_start", pid, NULL); - if (result != 1) { - return USTCMD_ERR_GEN; - } - - return 0; + return do_trace_cmd(trace, pid, START_TRACE); } /** @@ -307,16 +369,9 @@ int ustcmd_start_trace(pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error USTCMD_ERR_GEN */ -int ustcmd_alloc_trace(pid_t pid) +int ustcmd_alloc_trace(const char *trace, pid_t pid) { - int result; - - result = ustcmd_send_cmd("trace_alloc", pid, NULL); - if (result != 1) { - return USTCMD_ERR_GEN; - } - - return 0; + return do_trace_cmd(trace, pid, ALLOC_TRACE); } /** @@ -325,16 +380,9 @@ int ustcmd_alloc_trace(pid_t pid) * @param pid Traced process ID * @return 0 if successful, or error USTCMD_ERR_GEN */ -int ustcmd_stop_trace(pid_t pid) +int ustcmd_stop_trace(const char *trace, pid_t pid) { - int result; - - result = ustcmd_send_cmd("trace_stop", pid, NULL); - if (result != 1) { - return USTCMD_ERR_GEN; - } - - return 0; + return do_trace_cmd(trace, pid, STOP_TRACE); } /** @@ -391,22 +439,40 @@ int ustcmd_free_cmsf(struct marker_status *cmsf) */ int ustcmd_get_cmsf(struct marker_status **cmsf, const pid_t pid) { + struct ustcomm_header req_header, res_header; char *big_str = NULL; - int result; + int result, app_fd; struct marker_status *tmp_cmsf = NULL; unsigned int i = 0, cmsf_ind = 0; if (cmsf == NULL) { return -1; } - result = ustcmd_send_cmd("list_markers", pid, &big_str); - if (result != 1) { - ERR("error while getting markers list"); + + if (ustcomm_connect_app(pid, &app_fd)) { + ERR("could not connect to PID %u", (unsigned int) pid); + return -1; + } + + req_header.command = LIST_MARKERS; + req_header.size = 0; + + result = ustcomm_send(app_fd, &req_header, NULL); + if (result <= 0) { + PERROR("error while requesting markers list for process %d", pid); + return -1; + } + + result = ustcomm_recv_alloc(app_fd, &res_header, &big_str); + if (result <= 0) { + ERR("error while receiving markers list"); return -1; } - tmp_cmsf = (struct marker_status *) malloc(sizeof(struct marker_status) * - (ustcmd_count_nl(big_str) + 1)); + close(app_fd); + + tmp_cmsf = (struct marker_status *) zmalloc(sizeof(struct marker_status) * + (ustcmd_count_nl(big_str) + 1)); if (tmp_cmsf == NULL) { ERR("Failed to allocate CMSF array"); return -1; @@ -417,12 +483,12 @@ int ustcmd_get_cmsf(struct marker_status **cmsf, const pid_t pid) char state; sscanf(big_str + i, "marker: %a[^/]/%a[^ ] %c %a[^\n]", - &tmp_cmsf[cmsf_ind].channel, - &tmp_cmsf[cmsf_ind].marker, - &state, - &tmp_cmsf[cmsf_ind].fs); + &tmp_cmsf[cmsf_ind].channel, + &tmp_cmsf[cmsf_ind].marker, + &state, + &tmp_cmsf[cmsf_ind].fs); tmp_cmsf[cmsf_ind].state = (state == USTCMD_MS_CHR_ON ? - USTCMD_MS_ON : USTCMD_MS_OFF); /* Marker state */ + USTCMD_MS_ON : USTCMD_MS_OFF); /* Marker state */ while (big_str[i] != '\n') { ++i; /* Go to next '\n' */ @@ -472,10 +538,11 @@ int ustcmd_free_tes(struct trace_event_status *tes) * @return 0 if successful, or -1 on error */ int ustcmd_get_tes(struct trace_event_status **tes, - const pid_t pid) + const pid_t pid) { + struct ustcomm_header req_header, res_header; char *big_str = NULL; - int result; + int result, app_fd; struct trace_event_status *tmp_tes = NULL; unsigned int i = 0, tes_ind = 0; @@ -483,12 +550,28 @@ int ustcmd_get_tes(struct trace_event_status **tes, return -1; } - result = ustcmd_send_cmd("list_trace_events", pid, &big_str); + if (ustcomm_connect_app(pid, &app_fd)) { + ERR("could not connect to PID %u", (unsigned int) pid); + return -1; + } + + req_header.command = LIST_TRACE_EVENTS; + req_header.size = 0; + + result = ustcomm_send(app_fd, &req_header, NULL); if (result != 1) { - ERR("error while getting trace_event list"); + ERR("error while requesting trace_event list"); return -1; } + result = ustcomm_recv_alloc(app_fd, &res_header, &big_str); + if (result != 1) { + ERR("error while receiving markers list"); + return -1; + } + + close(app_fd); + tmp_tes = (struct trace_event_status *) zmalloc(sizeof(struct trace_event_status) * (ustcmd_count_nl(big_str) + 1)); @@ -499,10 +582,8 @@ int ustcmd_get_tes(struct trace_event_status **tes, /* Parse received reply string (format: "[name]"): */ while (big_str[i] != '\0') { - char state; - sscanf(big_str + i, "trace_event: %a[^\n]", - &tmp_tes[tes_ind].name); + &tmp_tes[tes_ind].name); while (big_str[i] != '\n') { ++i; /* Go to next '\n' */ } @@ -526,23 +607,22 @@ int ustcmd_get_tes(struct trace_event_status **tes, */ int ustcmd_set_sock_path(const char *sock_path, pid_t pid) { - char *cmd; int result; - - if (asprintf(&cmd, "%s %s", "set_sock_path", sock_path) < 0) { - ERR("ustcmd_set_sock_path : asprintf failed (set_sock_path, %s", - sock_path); + struct ustcomm_header req_header, res_header; + struct ustcomm_single_field sock_path_msg; + + result = ustcomm_pack_single_field(&req_header, + &sock_path_msg, + sock_path); + if (result < 0) { + errno = -result; return -1; } - result = ustcmd_send_cmd(cmd, pid, NULL); - if (result != 1) { - free(cmd); - return USTCMD_ERR_GEN; - } + req_header.command = SET_SOCK_PATH; - free(cmd); - return 0; + return do_cmd(pid, &req_header, (char *)&sock_path_msg, + &res_header, NULL); } /** @@ -554,60 +634,38 @@ int ustcmd_set_sock_path(const char *sock_path, pid_t pid) */ int ustcmd_get_sock_path(char **sock_path, pid_t pid) { - char *cmd, *reply; int result; + struct ustcomm_header req_header, res_header; + struct ustcomm_single_field *sock_path_msg; - if (asprintf(&cmd, "%s", "get_sock_path") < 0) { - ERR("ustcmd_get_sock_path : asprintf failed"); - return USTCMD_ERR_GEN; - } + req_header.command = GET_SOCK_PATH; + req_header.size = 0; - result = ustcmd_send_cmd(cmd, pid, &reply); - if (result != 1) { - free(cmd); - return USTCMD_ERR_GEN; + result = do_cmd(pid, &req_header, NULL, &res_header, + (char **)&sock_path_msg); + if (result < 0) { + return -1; } - free(cmd); - *sock_path = reply; - return 0; -} + result = ustcomm_unpack_single_field(sock_path_msg); + if (result < 0) { + return result; + } -int ustcmd_force_switch(pid_t pid) -{ - int result; + *sock_path = strdup(sock_path_msg->field); - result = ustcmd_send_cmd("force_switch", pid, NULL); - if (result != 1) { - return USTCMD_ERR_GEN; - } + free(sock_path_msg); return 0; } -/** - * Sends a given command to a traceable process - * - * @param cmd Null-terminated command to send - * @param pid Targeted PID - * @param reply Pointer to string to be filled with a reply string (must - * be NULL if no reply is needed for the given command). - * @return -1 if not successful, 0 on EOT, 1 on success - */ - -int ustcmd_send_cmd(const char *cmd, const pid_t pid, char **reply) +int ustcmd_force_switch(pid_t pid) { - int app_fd; - int retval; - - if (ustcomm_connect_app(pid, &app_fd)) { - ERR("could not connect to PID %u", (unsigned int) pid); - return -1; - } + struct ustcomm_header req_header, res_header; - retval = ustcomm_send_request(app_fd, cmd, reply); + req_header.command = FORCE_SUBBUF_SWITCH; + req_header.size = 0; - close(app_fd); - - return retval; + return do_cmd(pid, &req_header, NULL, &res_header, NULL); } +