Fix: liblttng-ctl: unreported truncations when copying strings
[lttng-tools.git] / src / lib / lttng-ctl / snapshot.c
CommitLineData
da3c9ec1 1/*
ab5be9fa 2 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
da3c9ec1 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
da3c9ec1 5 *
da3c9ec1
DG
6 */
7
6c1c0768 8#define _LGPL_SOURCE
da3c9ec1
DG
9#include <assert.h>
10#include <string.h>
11
12#include <common/sessiond-comm/sessiond-comm.h>
13#include <lttng/lttng-error.h>
14#include <lttng/snapshot.h>
15#include <lttng/snapshot-internal.h>
16
17#include "lttng-ctl-helper.h"
18
19/*
20 * Add an output object to a session identified by name.
21 *
22 * Return 0 on success or else a negative LTTNG_ERR code.
23 */
24int lttng_snapshot_add_output(const char *session_name,
25 struct lttng_snapshot_output *output)
26{
27 int ret;
28 struct lttcomm_session_msg lsm;
29 struct lttcomm_lttng_output_id *reply;
30
31 if (!session_name || !output) {
e1b624d0
JG
32 ret = -LTTNG_ERR_INVALID;
33 goto end;
da3c9ec1
DG
34 }
35
36 memset(&lsm, 0, sizeof(lsm));
37 lsm.cmd_type = LTTNG_SNAPSHOT_ADD_OUTPUT;
38
e1b624d0 39 ret = lttng_strncpy(lsm.session.name, session_name,
da3c9ec1 40 sizeof(lsm.session.name));
e1b624d0
JG
41 if (ret) {
42 ret = -LTTNG_ERR_INVALID;
43 goto end;
44 }
45
da3c9ec1
DG
46 memcpy(&lsm.u.snapshot_output.output, output,
47 sizeof(lsm.u.snapshot_output.output));
48
49 ret = lttng_ctl_ask_sessiond(&lsm, (void **) &reply);
50 if (ret < 0) {
e1b624d0 51 goto end;
da3c9ec1
DG
52 }
53
54 output->id = reply->id;
55 free(reply);
e1b624d0
JG
56 ret = 0;
57end:
58 return ret;
da3c9ec1
DG
59}
60
61/*
62 * Delete an output object to a session identified by name.
63 *
64 * Return 0 on success or else a negative LTTNG_ERR code.
65 */
66int lttng_snapshot_del_output(const char *session_name,
67 struct lttng_snapshot_output *output)
68{
e1b624d0 69 int ret;
da3c9ec1
DG
70 struct lttcomm_session_msg lsm;
71
72 if (!session_name || !output) {
e1b624d0
JG
73 ret = -LTTNG_ERR_INVALID;
74 goto end;
da3c9ec1
DG
75 }
76
77 memset(&lsm, 0, sizeof(lsm));
78 lsm.cmd_type = LTTNG_SNAPSHOT_DEL_OUTPUT;
79
e1b624d0
JG
80 ret = lttng_strncpy(lsm.session.name, session_name,
81 sizeof(lsm.session.name));
82 if (ret) {
83 ret = -LTTNG_ERR_INVALID;
84 goto end;
85 }
86
da3c9ec1
DG
87 memcpy(&lsm.u.snapshot_output.output, output,
88 sizeof(lsm.u.snapshot_output.output));
89
e1b624d0
JG
90 ret = lttng_ctl_ask_sessiond(&lsm, NULL);
91end:
92 return ret;
da3c9ec1
DG
93}
94
95/*
96 * List all snapshot output(s) of a session identified by name. The output list
97 * object is populated and can be iterated over with the get_next call below.
98 *
99 * Return 0 on success or else a negative LTTNG_ERR code and the list pointer
100 * is untouched.
101 */
102int lttng_snapshot_list_output(const char *session_name,
103 struct lttng_snapshot_output_list **list)
104{
105 int ret;
106 struct lttcomm_session_msg lsm;
107 struct lttng_snapshot_output_list *new_list = NULL;
108
109 if (!session_name || !list) {
110 ret = -LTTNG_ERR_INVALID;
111 goto error;
112 }
113
114 memset(&lsm, 0, sizeof(lsm));
115 lsm.cmd_type = LTTNG_SNAPSHOT_LIST_OUTPUT;
116
e1b624d0
JG
117 ret = lttng_strncpy(lsm.session.name, session_name,
118 sizeof(lsm.session.name));
119 if (ret) {
120 ret = -LTTNG_ERR_INVALID;
121 goto error;
122 }
da3c9ec1
DG
123
124 new_list = zmalloc(sizeof(*new_list));
125 if (!new_list) {
126 ret = -LTTNG_ERR_NOMEM;
127 goto error;
128 }
129
130 ret = lttng_ctl_ask_sessiond(&lsm, (void **) &new_list->array);
131 if (ret < 0) {
132 goto free_error;
133 }
134
135 new_list->count = ret / sizeof(struct lttng_snapshot_output);
136 *list = new_list;
137 return 0;
138
139free_error:
140 free(new_list);
141error:
142 return ret;
143}
144
145/*
146 * Return the next available snapshot output object in the given list. A list
147 * output command MUST have been done before.
148 *
149 * Return the next object on success or else NULL indicating the end of the
150 * list.
151 */
152struct lttng_snapshot_output *lttng_snapshot_output_list_get_next(
153 struct lttng_snapshot_output_list *list)
154{
155 struct lttng_snapshot_output *output = NULL;
156
157 if (!list) {
158 goto error;
159 }
160
161 /* We've reached the end. */
162 if (list->index == list->count) {
163 goto end;
164 }
165
166 output = &list->array[list->index];
167 list->index++;
168
169end:
170error:
171 return output;
172}
173
174/*
175 * Free an output list object.
176 */
177void lttng_snapshot_output_list_destroy(struct lttng_snapshot_output_list *list)
178{
179 if (!list) {
180 return;
181 }
182
183 free(list->array);
184 free(list);
185}
186
187/*
188 * Snapshot a trace for the given session.
189 *
190 * The output object can be NULL but an add output MUST be done prior to this
191 * call. If it's not NULL, it will be used to snapshot a trace.
192 *
193 * The wait parameter is ignored for now. The snapshot record command will
194 * ALWAYS wait for the snapshot to complete before returning meaning the
195 * snapshot has been written on disk or streamed over the network to a relayd.
196 *
197 * Return 0 on success or else a negative LTTNG_ERR value.
198 */
199int lttng_snapshot_record(const char *session_name,
200 struct lttng_snapshot_output *output, int wait)
201{
e1b624d0 202 int ret;
da3c9ec1
DG
203 struct lttcomm_session_msg lsm;
204
205 if (!session_name) {
e1b624d0
JG
206 ret = -LTTNG_ERR_INVALID;
207 goto end;
da3c9ec1
DG
208 }
209
210 memset(&lsm, 0, sizeof(lsm));
211 lsm.cmd_type = LTTNG_SNAPSHOT_RECORD;
212
e1b624d0 213 ret = lttng_strncpy(lsm.session.name, session_name,
da3c9ec1 214 sizeof(lsm.session.name));
e1b624d0
JG
215 if (ret) {
216 ret = -LTTNG_ERR_INVALID;
217 goto end;
218 }
da3c9ec1
DG
219
220 /*
221 * Not having an output object will use the default one of the session that
222 * would need to be set by a call to add output prior to calling snapshot
223 * record.
224 */
225 if (output) {
226 memcpy(&lsm.u.snapshot_record.output, output,
227 sizeof(lsm.u.snapshot_record.output));
228 }
229
230 /* The wait param is ignored. */
e1b624d0
JG
231 ret = lttng_ctl_ask_sessiond(&lsm, NULL);
232end:
233 return ret;
da3c9ec1
DG
234}
235
236/*
237 * Return an newly allocated snapshot output object or NULL on error.
238 */
239struct lttng_snapshot_output *lttng_snapshot_output_create(void)
240{
e1986656
DG
241 struct lttng_snapshot_output *output;
242
243 output = zmalloc(sizeof(struct lttng_snapshot_output));
244 if (!output) {
245 goto error;
246 }
247
248 output->max_size = (uint64_t) -1ULL;
249
250error:
251 return output;
da3c9ec1
DG
252}
253
254/*
255 * Free a given snapshot output object.
256 */
257void lttng_snapshot_output_destroy(struct lttng_snapshot_output *obj)
258{
259 if (obj) {
260 free(obj);
261 }
262}
263
264/*
265 * Getter family functions of snapshot output.
266 */
267
268uint32_t lttng_snapshot_output_get_id(struct lttng_snapshot_output *output)
269{
270 return output->id;
271}
272
273const char *lttng_snapshot_output_get_name(
274 struct lttng_snapshot_output *output)
275{
276 return output->name;
277}
278
279const char *lttng_snapshot_output_get_data_url(struct lttng_snapshot_output *output)
280{
281 return output->data_url;
282}
283
284const char *lttng_snapshot_output_get_ctrl_url(struct lttng_snapshot_output *output)
285{
286 return output->ctrl_url;
287}
288
289uint64_t lttng_snapshot_output_get_maxsize(
290 struct lttng_snapshot_output *output)
291{
292 return output->max_size;
293}
294
295/*
296 * Setter family functions for snapshot output.
297 */
298
299int lttng_snapshot_output_set_id(uint32_t id,
300 struct lttng_snapshot_output *output)
301{
302 if (!output || id == 0) {
303 return -LTTNG_ERR_INVALID;
304 }
305
306 output->id = id;
307 return 0;
308}
309
310int lttng_snapshot_output_set_size(uint64_t size,
311 struct lttng_snapshot_output *output)
312{
313 if (!output) {
314 return -LTTNG_ERR_INVALID;
315 }
316
317 output->max_size = size;
318 return 0;
319}
320
321int lttng_snapshot_output_set_name(const char *name,
322 struct lttng_snapshot_output *output)
323{
e1b624d0
JG
324 int ret;
325
da3c9ec1 326 if (!output || !name) {
e1b624d0
JG
327 ret = -LTTNG_ERR_INVALID;
328 goto end;
da3c9ec1
DG
329 }
330
e1b624d0
JG
331 ret = lttng_strncpy(output->name, name, sizeof(output->name));
332 if (ret) {
333 ret = -LTTNG_ERR_INVALID;
334 goto end;
335 }
336
337end:
338 return ret;
da3c9ec1
DG
339}
340
341int lttng_snapshot_output_set_ctrl_url(const char *url,
342 struct lttng_snapshot_output *output)
343{
e1b624d0
JG
344 int ret;
345
da3c9ec1 346 if (!output || !url) {
e1b624d0
JG
347 ret = -LTTNG_ERR_INVALID;
348 goto end;
da3c9ec1
DG
349 }
350
e1b624d0
JG
351 ret = lttng_strncpy(output->ctrl_url, url, sizeof(output->ctrl_url));
352 if (ret) {
353 ret = -LTTNG_ERR_INVALID;
354 goto end;
355 }
356
357end:
358 return ret;
da3c9ec1
DG
359}
360
361int lttng_snapshot_output_set_data_url(const char *url,
362 struct lttng_snapshot_output *output)
363{
e1b624d0
JG
364 int ret;
365
da3c9ec1 366 if (!output || !url) {
e1b624d0
JG
367 ret = -LTTNG_ERR_INVALID;
368 goto end;
da3c9ec1
DG
369 }
370
e1b624d0
JG
371 ret = lttng_strncpy(output->data_url, url, sizeof(output->data_url));
372 if (ret) {
373 ret = -LTTNG_ERR_INVALID;
374 goto end;
375 }
376
377end:
378 return ret;
da3c9ec1 379}
b30fa191
JR
380
381int lttng_snapshot_output_set_local_path(const char *path,
382 struct lttng_snapshot_output *output)
383{
384 int ret;
385 struct lttng_uri *uris = NULL;
386 ssize_t num_uris;
387
388 if (!path || !output) {
389 ret = -LTTNG_ERR_INVALID;
390 goto end;
391 }
392
393 num_uris = uri_parse_str_urls(path, NULL, &uris);
394 if (num_uris != 1) {
395 ret = -LTTNG_ERR_INVALID;
396 goto end;
397 }
398
399 if (uris[0].dtype != LTTNG_DST_PATH) {
400 ret = -LTTNG_ERR_INVALID;
401 goto end;
402 }
403
404 ret = lttng_strncpy(output->ctrl_url, path, sizeof(output->ctrl_url));
405 if (ret != 0) {
406 ret = -LTTNG_ERR_INVALID;
407 goto end;
408 }
409
410end:
411 free(uris);
412 return ret;
413}
414
415int lttng_snapshot_output_set_network_url(const char *url,
416 struct lttng_snapshot_output *output)
417{
418 int ret;
419 struct lttng_uri *uris = NULL;
420 ssize_t num_uris;
421
422 if (!url || !output) {
423 ret = -LTTNG_ERR_INVALID;
424 goto end;
425 }
426
427 num_uris = uri_parse_str_urls(url, NULL, &uris);
428 if (num_uris != 2) {
429 ret = -LTTNG_ERR_INVALID;
430 goto end;
431 }
432
433 if (uris[0].dtype != LTTNG_DST_IPV4 &&
434 uris[0].dtype != LTTNG_DST_IPV6) {
435 ret = -LTTNG_ERR_INVALID;
436 goto end;
437 }
438
439 if (uris[1].dtype != LTTNG_DST_IPV4 &&
440 uris[1].dtype != LTTNG_DST_IPV6) {
441 ret = -LTTNG_ERR_INVALID;
442 goto end;
443 }
444
445 ret = lttng_strncpy(output->ctrl_url, url, sizeof(output->ctrl_url));
446 if (ret != 0) {
447 ret = -LTTNG_ERR_INVALID;
448 goto end;
449 }
450
451end:
452 free(uris);
453 return ret;
454}
455
456int lttng_snapshot_output_set_network_urls(
457 const char *ctrl_url, const char *data_url,
458 struct lttng_snapshot_output *output)
459{
460 int ret;
461 struct lttng_uri *uris = NULL;
462 ssize_t num_uris;
463
464 if (!ctrl_url || !data_url || !output) {
465 ret = -LTTNG_ERR_INVALID;
466 goto end;
467 }
468
469 num_uris = uri_parse_str_urls(ctrl_url, data_url, &uris);
470 if (num_uris != 2) {
471 ret = -LTTNG_ERR_INVALID;
472 goto end;
473 }
474
475 if (uris[0].dtype != LTTNG_DST_IPV4 &&
476 uris[0].dtype != LTTNG_DST_IPV6) {
477 ret = -LTTNG_ERR_INVALID;
478 goto end;
479 }
480
481 if (uris[1].dtype != LTTNG_DST_IPV4 &&
482 uris[1].dtype != LTTNG_DST_IPV6) {
483 ret = -LTTNG_ERR_INVALID;
484 goto end;
485 }
486
487 ret = lttng_strncpy(output->ctrl_url, ctrl_url, sizeof(output->ctrl_url));
488 if (ret != 0) {
489 ret = -LTTNG_ERR_INVALID;
490 goto end;
491 }
492
493 ret = lttng_strncpy(output->data_url, data_url, sizeof(output->data_url));
494 if (ret != 0) {
495 ret = -LTTNG_ERR_INVALID;
496 goto end;
497 }
498
499end:
500 free(uris);
501 return ret;
502}
This page took 0.058634 seconds and 4 git commands to generate.