+ *connection_fd = fd;
+
+ free(addr);
+
+ return 0;
+
+free_sock_addr:
+ free(addr);
+close_sock:
+ close(fd);
+
+ 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;
+}
+
+/* Open a connection to a traceable app.
+ *
+ * Return value:
+ * 0: success
+ * -1: error
+ */
+
+int ustcomm_connect_app(pid_t pid, int *app_fd)
+{
+ int result;
+ int retval = 0;
+ char *dir_name, *sock_name;
+
+ dir_name = ustcomm_user_sock_dir();
+ if (!dir_name)
+ return -ENOMEM;
+
+ result = asprintf(&sock_name, "%s/%d", dir_name, pid);
+ if (result < 0) {
+ ERR("failed to allocate socket name");
+ retval = -1;
+ goto free_dir_name;
+ }
+
+ result = ustcomm_connect_path(sock_name, app_fd);
+ if (result < 0) {
+ ERR("failed to connect to app");
+ retval = -1;
+ goto free_sock_name;
+ }
+
+free_sock_name:
+ free(sock_name);
+free_dir_name:
+ free(dir_name);
+
+ return retval;
+}
+
+int ensure_dir_exists(const char *dir, mode_t mode)
+{
+ struct stat st;
+ int result;
+
+ if (!strcmp(dir, ""))
+ return -1;
+
+ result = stat(dir, &st);
+ if (result < 0 && errno != ENOENT) {
+ return -1;
+ } else if (result < 0) {
+ /* ENOENT */
+ int result;
+
+ 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;
+}
+
+char * ustcomm_print_data(char *data_field, int field_size,
+ int *offset, const char *format, ...)
+{
+ va_list args;
+ int count, limit;
+ char *ptr = USTCOMM_POISON_PTR;
+
+ limit = field_size - *offset;
+ va_start(args, format);
+ count = vsnprintf(&data_field[*offset], limit, format, args);
+ va_end(args);
+
+ if (count < limit && count > -1) {
+ ptr = NULL + *offset;
+ *offset = *offset + count + 1;
+ }
+
+ return ptr;
+}
+
+char * ustcomm_restore_ptr(char *ptr, char *data_field, int data_field_size)
+{
+ if ((unsigned long)ptr > data_field_size ||
+ ptr == USTCOMM_POISON_PTR) {
+ return NULL;
+ }
+
+ return data_field + (long)ptr;
+}
+
+int ustcomm_pack_single_field(struct ustcomm_header *header,
+ struct ustcomm_single_field *single_field,
+ const char *string)
+{
+ int offset = 0;
+
+ single_field->field = ustcomm_print_data(single_field->data,
+ sizeof(single_field->data),
+ &offset,
+ string);
+
+ if (single_field->field == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+ header->size = COMPUTE_MSG_SIZE(single_field, offset);
+
+ return 0;
+}
+
+int ustcomm_unpack_single_field(struct ustcomm_single_field *single_field)
+{
+ single_field->field = ustcomm_restore_ptr(single_field->field,
+ single_field->data,
+ sizeof(single_field->data));
+ if (!single_field->field) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int ustcomm_pack_channel_info(struct ustcomm_header *header,
+ struct ustcomm_channel_info *ch_inf,
+ const char *trace,
+ const char *channel)
+{
+ int offset = 0;
+
+ ch_inf->trace = ustcomm_print_data(ch_inf->data,
+ sizeof(ch_inf->data),
+ &offset,
+ trace);
+
+ if (ch_inf->trace == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+ ch_inf->channel = ustcomm_print_data(ch_inf->data,
+ sizeof(ch_inf->data),
+ &offset,
+ channel);
+
+ if (ch_inf->channel == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+ header->size = COMPUTE_MSG_SIZE(ch_inf, offset);
+
+ return 0;
+}
+
+
+int ustcomm_unpack_channel_info(struct ustcomm_channel_info *ch_inf)
+{
+ ch_inf->trace = ustcomm_restore_ptr(ch_inf->trace,
+ ch_inf->data,
+ sizeof(ch_inf->data));
+ if (!ch_inf->trace) {
+ return -EINVAL;
+ }
+
+ ch_inf->channel = ustcomm_restore_ptr(ch_inf->channel,
+ ch_inf->data,
+ sizeof(ch_inf->data));
+ if (!ch_inf->channel) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int ustcomm_pack_buffer_info(struct ustcomm_header *header,
+ struct ustcomm_buffer_info *buf_inf,
+ const char *trace,
+ const char *channel,
+ int channel_cpu)
+{
+ int offset = 0;
+
+ buf_inf->trace = ustcomm_print_data(buf_inf->data,
+ sizeof(buf_inf->data),
+ &offset,
+ trace);
+
+ if (buf_inf->trace == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+ buf_inf->channel = ustcomm_print_data(buf_inf->data,
+ sizeof(buf_inf->data),
+ &offset,
+ channel);
+
+ if (buf_inf->channel == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+ buf_inf->ch_cpu = channel_cpu;
+
+ header->size = COMPUTE_MSG_SIZE(buf_inf, offset);
+
+ return 0;
+}
+
+
+int ustcomm_unpack_buffer_info(struct ustcomm_buffer_info *buf_inf)
+{
+ buf_inf->trace = ustcomm_restore_ptr(buf_inf->trace,
+ buf_inf->data,
+ sizeof(buf_inf->data));
+ if (!buf_inf->trace) {
+ return -EINVAL;
+ }
+
+ buf_inf->channel = ustcomm_restore_ptr(buf_inf->channel,
+ buf_inf->data,
+ sizeof(buf_inf->data));
+ if (!buf_inf->channel) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int ustcomm_pack_marker_info(struct ustcomm_header *header,
+ struct ustcomm_marker_info *marker_inf,
+ const char *trace,
+ const char *channel,
+ const char *marker)
+{
+ int offset = 0;
+
+ marker_inf->trace = ustcomm_print_data(marker_inf->data,
+ sizeof(marker_inf->data),
+ &offset,
+ trace);
+
+ if (marker_inf->trace == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+
+ marker_inf->channel = ustcomm_print_data(marker_inf->data,
+ sizeof(marker_inf->data),
+ &offset,
+ channel);
+
+ if (marker_inf->channel == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+
+ marker_inf->marker = ustcomm_print_data(marker_inf->data,
+ sizeof(marker_inf->data),
+ &offset,
+ marker);
+
+ if (marker_inf->marker == USTCOMM_POISON_PTR) {
+ return -ENOMEM;
+ }
+
+ header->size = COMPUTE_MSG_SIZE(marker_inf, offset);