+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustcomm_send_reg_msg(int sock,
+ enum ustctl_socket_type type,
+ uint32_t bits_per_long,
+ uint32_t uint8_t_alignment,
+ uint32_t uint16_t_alignment,
+ uint32_t uint32_t_alignment,
+ uint32_t uint64_t_alignment,
+ uint32_t long_alignment)
+{
+ ssize_t len;
+ struct ustctl_reg_msg reg_msg;
+
+ reg_msg.magic = LTTNG_UST_COMM_MAGIC;
+ reg_msg.major = LTTNG_UST_ABI_MAJOR_VERSION;
+ reg_msg.minor = LTTNG_UST_ABI_MINOR_VERSION;
+ reg_msg.pid = getpid();
+ reg_msg.ppid = getppid();
+ reg_msg.uid = getuid();
+ reg_msg.gid = getgid();
+ reg_msg.bits_per_long = bits_per_long;
+ reg_msg.uint8_t_alignment = uint8_t_alignment;
+ reg_msg.uint16_t_alignment = uint16_t_alignment;
+ reg_msg.uint32_t_alignment = uint32_t_alignment;
+ reg_msg.uint64_t_alignment = uint64_t_alignment;
+ reg_msg.long_alignment = long_alignment;
+ reg_msg.socket_type = type;
+ lttng_ust_getprocname(reg_msg.name);
+ memset(reg_msg.padding, 0, sizeof(reg_msg.padding));
+
+ len = ustcomm_send_unix_sock(sock, ®_msg, sizeof(reg_msg));
+ if (len > 0 && len != sizeof(reg_msg))
+ return -EIO;
+ if (len < 0)
+ return len;
+ return 0;
+}
+
+static
+int serialize_string_encoding(enum ustctl_string_encodings *ue,
+ enum lttng_string_encodings le)
+{
+ switch (le) {
+ case lttng_encode_none:
+ *ue = ustctl_encode_none;
+ break;
+ case lttng_encode_UTF8:
+ *ue = ustctl_encode_UTF8;
+ break;
+ case lttng_encode_ASCII:
+ *ue = ustctl_encode_ASCII;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static
+int serialize_basic_type(enum ustctl_abstract_types *uatype,
+ enum lttng_abstract_types atype,
+ union _ustctl_basic_type *ubt,
+ const union _lttng_basic_type *lbt)
+{
+ switch (atype) {
+ case atype_integer:
+ {
+ struct ustctl_integer_type *uit;
+ const struct lttng_integer_type *lit;
+
+ uit = &ubt->integer;
+ lit = &lbt->integer;
+ uit->size = lit->size;
+ uit->signedness = lit->signedness;
+ uit->reverse_byte_order = lit->reverse_byte_order;
+ uit->base = lit->base;
+ if (serialize_string_encoding(&uit->encoding, lit->encoding))
+ return -EINVAL;
+ uit->alignment = lit->alignment;
+ *uatype = ustctl_atype_integer;
+ break;
+ }
+ case atype_string:
+ {
+ if (serialize_string_encoding(&ubt->string.encoding,
+ lbt->string.encoding))
+ return -EINVAL;
+ *uatype = ustctl_atype_string;
+ break;
+ }
+ case atype_float:
+ {
+ struct ustctl_float_type *uft;
+ const struct lttng_float_type *lft;
+
+ uft = &ubt->_float;
+ lft = &lbt->_float;
+ uft->exp_dig = lft->exp_dig;
+ uft->mant_dig = lft->mant_dig;
+ uft->alignment = lft->alignment;
+ uft->reverse_byte_order = lft->reverse_byte_order;
+ *uatype = ustctl_atype_float;
+ break;
+ }
+ case atype_enum:
+ case atype_array:
+ case atype_sequence:
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static
+int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
+{
+ int ret;
+
+ switch (lt->atype) {
+ case atype_integer:
+ case atype_float:
+ case atype_string:
+ ret = serialize_basic_type(&ut->atype, lt->atype,
+ &ut->u.basic, <->u.basic);
+ if (ret)
+ return ret;
+ break;
+ case atype_array:
+ {
+ struct ustctl_basic_type *ubt;
+ const struct lttng_basic_type *lbt;
+ int ret;
+
+ ubt = &ut->u.array.elem_type;
+ lbt = <->u.array.elem_type;
+ ut->u.array.length = lt->u.array.length;
+ ret = serialize_basic_type(&ubt->atype, lbt->atype,
+ &ubt->u.basic, &lbt->u.basic);
+ if (ret)
+ return -EINVAL;
+ ut->atype = ustctl_atype_array;
+ break;
+ }
+ case atype_sequence:
+ {
+ struct ustctl_basic_type *ubt;
+ const struct lttng_basic_type *lbt;
+ int ret;
+
+ ubt = &ut->u.sequence.length_type;
+ lbt = <->u.sequence.length_type;
+ ret = serialize_basic_type(&ubt->atype, lbt->atype,
+ &ubt->u.basic, &lbt->u.basic);
+ if (ret)
+ return -EINVAL;
+ ubt = &ut->u.sequence.elem_type;
+ lbt = <->u.sequence.elem_type;
+ ret = serialize_basic_type(&ubt->atype, lbt->atype,
+ &ubt->u.basic, &lbt->u.basic);
+ if (ret)
+ return -EINVAL;
+ ut->atype = ustctl_atype_sequence;
+ break;
+ }
+ case atype_enum:
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static
+int serialize_fields(size_t *_nr_write_fields,
+ struct ustctl_field **ustctl_fields,
+ size_t nr_fields,
+ const struct lttng_event_field *lttng_fields)
+{
+ struct ustctl_field *fields;
+ int i, ret;
+ size_t nr_write_fields = 0;
+
+ fields = zmalloc(nr_fields * sizeof(*fields));
+ if (!fields)
+ return -ENOMEM;
+
+ for (i = 0; i < nr_fields; i++) {
+ struct ustctl_field *f;
+ const struct lttng_event_field *lf;
+
+ f = &fields[nr_write_fields];
+ lf = <tng_fields[i];
+
+ /* skip 'nowrite' fields */
+ if (lf->nowrite)
+ continue;
+ strncpy(f->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
+ f->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+ ret = serialize_one_type(&f->type, &lf->type);
+ if (ret)
+ goto error_type;
+ nr_write_fields++;
+ }
+
+ *_nr_write_fields = nr_write_fields;
+ *ustctl_fields = fields;
+ return 0;
+
+error_type:
+ free(fields);
+ return ret;
+}
+
+static
+int serialize_ctx_fields(size_t *_nr_write_fields,
+ struct ustctl_field **ustctl_fields,
+ size_t nr_fields,
+ const struct lttng_ctx_field *lttng_fields)
+{
+ struct ustctl_field *fields;
+ int i, ret;
+ size_t nr_write_fields = 0;
+
+ fields = zmalloc(nr_fields * sizeof(*fields));
+ if (!fields)
+ return -ENOMEM;
+
+ for (i = 0; i < nr_fields; i++) {
+ struct ustctl_field *f;
+ const struct lttng_event_field *lf;
+
+ f = &fields[nr_write_fields];
+ lf = <tng_fields[i].event_field;
+
+ /* skip 'nowrite' fields */
+ if (lf->nowrite)
+ continue;
+ strncpy(f->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
+ f->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+ ret = serialize_one_type(&f->type, &lf->type);
+ if (ret)
+ goto error_type;
+ nr_write_fields++;
+ }
+
+ *_nr_write_fields = nr_write_fields;
+ *ustctl_fields = fields;
+ return 0;
+
+error_type:
+ free(fields);
+ return ret;
+}