SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / bin / lttng / conf.c
CommitLineData
f3ed775e 1/*
ab5be9fa 2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
f3ed775e 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
f3ed775e 5 *
f3ed775e
DG
6 */
7
6c1c0768 8#define _LGPL_SOURCE
f3ed775e
DG
9#include <limits.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
1dac0189 16#include <errno.h>
f3ed775e 17
9908810a 18#include <common/common.h>
feb0f3e5 19#include <common/utils.h>
10a8a223 20
beb8c75a 21#include "conf.h"
f3ed775e
DG
22
23/*
28eee19b
FG
24 * Returns the path with '/CONFIG_FILENAME' added to it;
25 * path will be NULL if an error occurs.
f3ed775e 26 */
9b27c721 27char *config_get_file_path(const char *path)
f3ed775e
DG
28{
29 int ret;
30 char *file_path;
31
32 ret = asprintf(&file_path, "%s/%s", path, CONFIG_FILENAME);
33 if (ret < 0) {
34 ERR("Fail allocating config file path");
487b253b 35 file_path = NULL;
f3ed775e
DG
36 }
37
38 return file_path;
39}
40
41/*
28eee19b
FG
42 * Returns an open FILE pointer to the config file;
43 * on error, NULL is returned.
f3ed775e 44 */
9b27c721 45static FILE *open_config(const char *path, const char *mode)
f3ed775e
DG
46{
47 FILE *fp = NULL;
48 char *file_path;
49
58a97671 50 file_path = config_get_file_path(path);
f3ed775e
DG
51 if (file_path == NULL) {
52 goto error;
53 }
54
55 fp = fopen(file_path, mode);
56 if (fp == NULL) {
f3ed775e
DG
57 goto error;
58 }
59
60error:
0e428499 61 free(file_path);
f3ed775e
DG
62 return fp;
63}
64
65/*
28eee19b
FG
66 * Creates the empty config file at the path.
67 * On success, returns 0;
68 * on error, returns -1.
f3ed775e 69 */
4f00620d 70static int create_config_file(const char *path)
f3ed775e
DG
71{
72 int ret;
73 FILE *fp;
74
75 fp = open_config(path, "w+");
76 if (fp == NULL) {
77 ERR("Unable to create config file");
78 ret = -1;
79 goto error;
80 }
81
82 ret = fclose(fp);
83
84error:
85 return ret;
86}
87
f3ed775e 88/*
28eee19b
FG
89 * Append data to the config file in file_path
90 * On success, returns 0;
91 * on error, returns -1.
f3ed775e 92 */
9b27c721 93static int write_config(const char *file_path, size_t size, char *data)
f3ed775e
DG
94{
95 FILE *fp;
a079cd4d
MD
96 size_t len;
97 int ret = 0;
f3ed775e
DG
98
99 fp = open_config(file_path, "a");
100 if (fp == NULL) {
a079cd4d
MD
101 ret = -1;
102 goto end;
f3ed775e
DG
103 }
104
105 /* Write session name into config file */
a079cd4d 106 len = fwrite(data, size, 1, fp);
27089920 107 if (len != 1) {
a079cd4d
MD
108 ret = -1;
109 }
f66c074c
DG
110 if (fclose(fp)) {
111 PERROR("close write_config");
112 }
a079cd4d
MD
113end:
114 return ret;
f3ed775e
DG
115}
116
f3ed775e 117/*
28eee19b 118 * Destroys directory config and file config.
f3ed775e 119 */
9b27c721 120void config_destroy(const char *path)
f3ed775e
DG
121{
122 int ret;
123 char *config_path;
124
58a97671
DG
125 config_path = config_get_file_path(path);
126 if (config_path == NULL) {
127 return;
128 }
f3ed775e 129
d6a07e7d
FG
130 if (!config_exists(config_path)) {
131 goto end;
132 }
133
134 DBG("Removing %s\n", config_path);
f3ed775e
DG
135 ret = remove(config_path);
136 if (ret < 0) {
6f04ed72 137 PERROR("remove config file");
f3ed775e 138 }
d6a07e7d 139end:
f3ed775e
DG
140 free(config_path);
141}
142
d6a07e7d 143/*
28eee19b 144 * Destroys the default config
d6a07e7d 145 */
d6a07e7d
FG
146void config_destroy_default(void)
147{
4f00620d 148 const char *path = utils_get_home_dir();
d6a07e7d
FG
149 if (path == NULL) {
150 return;
151 }
152 config_destroy(path);
153}
154
155/*
28eee19b 156 * Returns 1 if config exists, 0 otherwise
d6a07e7d
FG
157 */
158int config_exists(const char *path)
159{
160 int ret;
161 struct stat info;
162
163 ret = stat(path, &info);
164 if (ret < 0) {
165 return 0;
166 }
167 return S_ISREG(info.st_mode) || S_ISDIR(info.st_mode);
168}
169
1dac0189 170static
9b27c721 171int _config_read_session_name(const char *path, char **name)
f3ed775e 172{
1dac0189 173 int ret = 0;
f3ed775e
DG
174 FILE *fp;
175 char var[NAME_MAX], *session_name;
09b72f7a 176
8ab7c0d9
MD
177#if (NAME_MAX == 255)
178#define NAME_MAX_SCANF_IS_A_BROKEN_API "254"
179#endif
f3ed775e 180
9908810a 181 session_name = zmalloc(NAME_MAX);
27089920 182 if (session_name == NULL) {
1dac0189 183 ret = -ENOMEM;
27089920
TD
184 ERR("Out of memory");
185 goto error;
186 }
187
f3ed775e
DG
188 fp = open_config(path, "r");
189 if (fp == NULL) {
1dac0189 190 ret = -ENOENT;
f3ed775e
DG
191 goto error;
192 }
193
f3ed775e 194 while (!feof(fp)) {
8ab7c0d9
MD
195 if ((ret = fscanf(fp, "%" NAME_MAX_SCANF_IS_A_BROKEN_API
196 "[^'=']=%" NAME_MAX_SCANF_IS_A_BROKEN_API "s\n",
197 var, session_name)) != 2) {
f3ed775e
DG
198 if (ret == -1) {
199 ERR("Missing session=NAME in config file.");
00f36863 200 goto error_close;
f3ed775e
DG
201 }
202 continue;
203 }
204
205 if (strcmp(var, "session") == 0) {
206 goto found;
207 }
208 }
209
00f36863 210error_close:
1dac0189 211 if (fclose(fp) < 0) {
f66c074c
DG
212 PERROR("close config read session name");
213 }
f3ed775e 214error:
1dac0189
PPM
215 free(session_name);
216 return ret;
f3ed775e 217found:
1dac0189
PPM
218 *name = session_name;
219 if (fclose(fp) < 0) {
f66c074c
DG
220 PERROR("close config read session name found");
221 }
1dac0189
PPM
222 return ret;
223}
224
225/*
226 * Returns the session name from the config file.
227 *
228 * The caller is responsible for freeing the returned string.
229 * On error, NULL is returned.
230 */
9b27c721 231char *config_read_session_name(const char *path)
1dac0189
PPM
232{
233 int ret;
234 char *name = NULL;
235
236 ret = _config_read_session_name(path, &name);
237 if (ret == -ENOENT) {
238 const char *home_dir = utils_get_home_dir();
239
240 ERR("Can't find valid lttng config %s/.lttngrc", home_dir);
241 MSG("Did you create a session? (lttng create <my_session>)");
242 }
243
244 return name;
245}
246
247/*
248 * Returns the session name from the config file. (no warnings/errors emitted)
249 *
250 * The caller is responsible for freeing the returned string.
251 * On error, NULL is returned.
252 */
9b27c721 253char *config_read_session_name_quiet(const char *path)
1dac0189
PPM
254{
255 char *name = NULL;
f3ed775e 256
1dac0189
PPM
257 (void) _config_read_session_name(path, &name);
258 return name;
f3ed775e
DG
259}
260
261/*
28eee19b
FG
262 * Write session name option to the config file.
263 * On success, returns 0;
264 * on error, returns -1.
f3ed775e 265 */
9b27c721 266int config_add_session_name(const char *path, const char *name)
f3ed775e
DG
267{
268 int ret;
1831ae68 269 const char *attr = "session=";
487b253b
DG
270 /* Max name len accepted plus attribute's len and the NULL byte. */
271 char session_name[NAME_MAX + strlen(attr) + 1];
f3ed775e 272
27089920
TD
273 /*
274 * With GNU C < 2.1, snprintf returns -1 if the target buffer is too small;
275 * With GNU C >= 2.1, snprintf returns the required size (excluding closing null)
276 */
487b253b
DG
277 ret = snprintf(session_name, sizeof(session_name), "%s%s\n", attr, name);
278 if (ret < 0) {
27089920 279 ret = -1;
f3ed775e
DG
280 goto error;
281 }
a079cd4d 282 ret = write_config(path, ret, session_name);
f3ed775e
DG
283error:
284 return ret;
285}
286
f3ed775e 287/*
28eee19b
FG
288 * Init configuration directory and file.
289 * On success, returns 0;
290 * on error, returns -1.
f3ed775e 291 */
9b27c721 292int config_init(const char *session_name)
f3ed775e
DG
293{
294 int ret;
4f00620d 295 const char *path;
f3ed775e 296
feb0f3e5 297 path = utils_get_home_dir();
58a97671
DG
298 if (path == NULL) {
299 ret = -1;
f3ed775e
DG
300 goto error;
301 }
302
303 /* Create default config file */
304 ret = create_config_file(path);
305 if (ret < 0) {
306 goto error;
307 }
308
58a97671
DG
309 ret = config_add_session_name(path, session_name);
310 if (ret < 0) {
311 goto error;
312 }
313
f3ed775e
DG
314 DBG("Init config session in %s", path);
315
316error:
317 return ret;
318}
This page took 0.088072 seconds and 5 git commands to generate.