#include <common/compat/string.h>
#include <common/defaults.h>
#include <common/dynamic-buffer.h>
+#include <common/dynamic-array.h>
#include <common/payload.h>
#include <common/payload-view.h>
#include <common/sessiond-comm/sessiond-comm.h>
#include <common/tracker.h>
+#include <common/unix.h>
#include <common/uri.h>
#include <common/utils.h>
#include <lttng/channel-internal.h>
#include <lttng/session-internal.h>
#include <lttng/trigger/trigger-internal.h>
#include <lttng/userspace-probe-internal.h>
+#include <lttng/lttng-error.h>
-#include "filter/filter-ast.h"
-#include "filter/filter-parser.h"
-#include "filter/filter-bytecode.h"
-#include "filter/memstream.h"
+#include <common/filter/filter-ast.h>
+#include <common/filter/filter-parser.h>
+#include <common/filter/filter-bytecode.h>
+#include <common/filter/memstream.h>
#include "lttng-ctl-helper.h"
-#ifdef DEBUG
-static const int print_xml = 1;
-#define dbg_printf(fmt, args...) \
- printf("[debug liblttng-ctl] " fmt, ## args)
-#else
-static const int print_xml = 0;
-#define dbg_printf(fmt, args...) \
-do { \
- /* do nothing but check printf format */ \
- if (0) \
- printf("[debug liblttnctl] " fmt, ## args); \
-} while (0)
-#endif
-
#define COPY_DOMAIN_PACKED(dst, src) \
do { \
struct lttng_domain _tmp_domain; \
{
int ret;
struct lttcomm_lttng_msg llm;
+ const int fd_count = lttng_payload_view_get_fd_handle_count(message);
assert(reply->buffer.size == 0);
- assert(reply->_fds.size == 0);
+ assert(lttng_dynamic_pointer_array_get_count(&reply->_fd_handles) == 0);
ret = connect_sessiond();
if (ret < 0) {
goto end;
}
- if (lttng_payload_view_get_fd_count(message) > 0) {
- ret = lttcomm_send_fds_unix_sock(sessiond_socket,
- (const int *) message->_fds.buffer.data,
- lttng_dynamic_array_get_count(&message->_fds));
+ if (fd_count > 0) {
+ ret = lttcomm_send_payload_view_fds_unix_sock(sessiond_socket,
+ message);
+ if (ret < 0) {
+ ret = -LTTNG_ERR_FATAL;
+ goto end;
+ }
}
/* Get header from data transmission */
}
if (llm.fd_count > 0) {
- ret = lttng_dynamic_array_set_count(&reply->_fds, llm.fd_count);
- if (ret) {
- ret = -LTTNG_ERR_NOMEM;
- goto end;
- }
-
- ret = lttcomm_recv_fds_unix_sock(sessiond_socket,
- (int *) reply->_fds.buffer.data, llm.fd_count);
- if (ret > 0 && ret != llm.fd_count * sizeof(int)) {
- ret = -LTTNG_ERR_INVALID_PROTOCOL;
- goto end;
- } else if (ret <= 0) {
- ret = -LTTNG_ERR_FATAL;
+ ret = lttcomm_recv_payload_fds_unix_sock(
+ sessiond_socket, llm.fd_count, reply);
+ if (ret < 0) {
goto end;
}
}
return NULL;
}
-/*
- * Generate the filter bytecode from a given filter expression string. Put the
- * newly allocated parser context in ctxp and populate the lsm object with the
- * expression len.
- *
- * Return 0 on success else a LTTNG_ERR_* code and ctxp is untouched.
- */
-static int generate_filter(char *filter_expression,
- struct lttcomm_session_msg *lsm, struct filter_parser_ctx **ctxp)
-{
- int ret;
- struct filter_parser_ctx *ctx = NULL;
- FILE *fmem = NULL;
-
- assert(filter_expression);
- assert(lsm);
- assert(ctxp);
-
- /*
- * Casting const to non-const, as the underlying function will use it in
- * read-only mode.
- */
- fmem = lttng_fmemopen((void *) filter_expression,
- strlen(filter_expression), "r");
- if (!fmem) {
- fprintf(stderr, "Error opening memory as stream\n");
- ret = -LTTNG_ERR_FILTER_NOMEM;
- goto error;
- }
- ctx = filter_parser_ctx_alloc(fmem);
- if (!ctx) {
- fprintf(stderr, "Error allocating parser\n");
- ret = -LTTNG_ERR_FILTER_NOMEM;
- goto filter_alloc_error;
- }
- ret = filter_parser_ctx_append_ast(ctx);
- if (ret) {
- fprintf(stderr, "Parse error\n");
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
- if (print_xml) {
- ret = filter_visitor_print_xml(ctx, stdout, 0);
- if (ret) {
- fflush(stdout);
- fprintf(stderr, "XML print error\n");
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
- }
-
- dbg_printf("Generating IR... ");
- fflush(stdout);
- ret = filter_visitor_ir_generate(ctx);
- if (ret) {
- fprintf(stderr, "Generate IR error\n");
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
- dbg_printf("done\n");
-
- dbg_printf("Validating IR... ");
- fflush(stdout);
- ret = filter_visitor_ir_check_binary_op_nesting(ctx);
- if (ret) {
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
-
- /* Normalize globbing patterns in the expression. */
- ret = filter_visitor_ir_normalize_glob_patterns(ctx);
- if (ret) {
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
-
- /* Validate strings used as literals in the expression. */
- ret = filter_visitor_ir_validate_string(ctx);
- if (ret) {
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
-
- /* Validate globbing patterns in the expression. */
- ret = filter_visitor_ir_validate_globbing(ctx);
- if (ret) {
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
-
- dbg_printf("done\n");
-
- dbg_printf("Generating bytecode... ");
- fflush(stdout);
- ret = filter_visitor_bytecode_generate(ctx);
- if (ret) {
- fprintf(stderr, "Generate bytecode error\n");
- ret = -LTTNG_ERR_FILTER_INVAL;
- goto parse_error;
- }
- dbg_printf("done\n");
- dbg_printf("Size of bytecode generated: %u bytes.\n",
- bytecode_get_len(&ctx->bytecode->b));
-
- lsm->u.enable.bytecode_len = sizeof(ctx->bytecode->b)
- + bytecode_get_len(&ctx->bytecode->b);
- lsm->u.enable.expression_len = strlen(filter_expression) + 1;
-
- /* No need to keep the memory stream. */
- if (fclose(fmem) != 0) {
- PERROR("fclose");
- }
-
- *ctxp = ctx;
- return 0;
-
-parse_error:
- filter_ir_free(ctx);
- filter_parser_ctx_free(ctx);
-filter_alloc_error:
- if (fclose(fmem) != 0) {
- PERROR("fclose");
- }
-error:
- return ret;
-}
-
/*
* Enable event(s) for a channel, possibly with exclusions and a filter.
* If no event name is specified, all events are enabled.
}
}
- ret = generate_filter(filter_expression, &lsm, &ctx);
+ ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
if (ret) {
goto filter_error;
}
+
+ lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b)
+ + bytecode_get_len(&ctx->bytecode->b);
+ lsm.u.enable.expression_len = strlen(filter_expression) + 1;
}
ret = lttng_dynamic_buffer_set_capacity(&payload.buffer,
{
struct lttng_payload_view view = lttng_payload_view_from_payload(
&payload, 0, -1);
- int fd_count = lttng_payload_view_get_fd_count(&view);
+ int fd_count = lttng_payload_view_get_fd_handle_count(&view);
int fd_to_send;
if (fd_count < 0) {
assert(fd_count == 0 || fd_count == 1);
if (fd_count == 1) {
- ret = lttng_payload_view_pop_fd(&view);
- if (ret < 0) {
+ struct fd_handle *handle =
+ lttng_payload_view_pop_fd_handle(&view);
+
+ if (!handle) {
goto mem_error;
}
- fd_to_send = ret;
+ fd_to_send = fd_handle_get_fd(handle);
+ fd_handle_put(handle);
}
ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm,
}
}
- ret = generate_filter(filter_expression, &lsm, &ctx);
+ ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx);
if (ret) {
goto filter_error;
}
+
+ lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b)
+ + bytecode_get_len(&ctx->bytecode->b);
+ lsm.u.enable.expression_len = strlen(filter_expression) + 1;
}
varlen_data = zmalloc(lsm.u.disable.bytecode_len
int lttng_register_trigger(struct lttng_trigger *trigger)
{
int ret;
- struct lttcomm_session_msg lsm;
- struct lttng_payload payload;
+ struct lttcomm_session_msg lsm = {
+ .cmd_type = LTTNG_REGISTER_TRIGGER,
+ };
+ struct lttcomm_session_msg *message_lsm;
+ struct lttng_payload message;
+ struct lttng_payload reply;
+
+ lttng_payload_init(&message);
+ lttng_payload_init(&reply);
- lttng_payload_init(&payload);
if (!trigger) {
ret = -LTTNG_ERR_INVALID;
goto end;
goto end;
}
- ret = lttng_trigger_serialize(trigger, &payload);
+ ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /*
+ * This is needed to populate the trigger object size for the command
+ * header.
+ */
+ message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+
+ ret = lttng_trigger_serialize(trigger, &message);
if (ret < 0) {
ret = -LTTNG_ERR_UNK;
goto end;
}
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_REGISTER_TRIGGER;
- lsm.u.trigger.length = (uint32_t) payload.buffer.size;
- ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
- &lsm, payload.buffer.data, payload.buffer.size, NULL);
+ message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
+
+ {
+ struct lttng_payload_view message_view =
+ lttng_payload_view_from_payload(
+ &message, 0, -1);
+
+ message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
+ &message_view);
+ ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+ if (ret < 0) {
+ goto end;
+ }
+ }
+
+ ret = 0;
end:
- lttng_payload_reset(&payload);
+ lttng_payload_reset(&message);
+ lttng_payload_reset(&reply);
return ret;
}
{
int ret;
struct lttcomm_session_msg lsm;
- struct lttng_payload payload;
+ struct lttcomm_session_msg *message_lsm;
+ struct lttng_payload message;
+ struct lttng_payload reply;
+
+ lttng_payload_init(&message);
+ lttng_payload_init(&reply);
- lttng_payload_init(&payload);
if (!trigger) {
ret = -LTTNG_ERR_INVALID;
goto end;
goto end;
}
- ret = lttng_trigger_serialize(trigger, &payload);
+ memset(&lsm, 0, sizeof(lsm));
+ lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER;
+
+ ret = lttng_dynamic_buffer_append(&message.buffer, &lsm, sizeof(lsm));
+ if (ret) {
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ /*
+ * This is needed to populate the trigger object size for the command
+ * header and number of fds sent.
+ */
+ message_lsm = (struct lttcomm_session_msg *) message.buffer.data;
+
+ ret = lttng_trigger_serialize(trigger, &message);
if (ret < 0) {
ret = -LTTNG_ERR_UNK;
goto end;
}
- memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_UNREGISTER_TRIGGER;
- lsm.u.trigger.length = (uint32_t) payload.buffer.size;
- ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
- &lsm, payload.buffer.data, payload.buffer.size, NULL);
+ message_lsm->u.trigger.length = (uint32_t) message.buffer.size - sizeof(lsm);
+
+ {
+ struct lttng_payload_view message_view =
+ lttng_payload_view_from_payload(
+ &message, 0, -1);
+
+ /*
+ * Update the message header with the number of fd that will be
+ * sent.
+ */
+ message_lsm->fd_count = lttng_payload_view_get_fd_handle_count(
+ &message_view);
+
+ ret = lttng_ctl_ask_sessiond_payload(&message_view, &reply);
+ if (ret < 0) {
+ goto end;
+ }
+ }
+
+ ret = 0;
end:
- lttng_payload_reset(&payload);
+ lttng_payload_reset(&message);
+ lttng_payload_reset(&reply);
return ret;
}