Coverage Report

Created: 2024-02-25 07:17

/src/fluent-bit/plugins/in_node_exporter_metrics/ne_utils.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2024 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#include <fluent-bit/flb_info.h>
21
#include <fluent-bit/flb_input_plugin.h>
22
#include <fluent-bit/flb_sds.h>
23
#include "ne.h"
24
25
/* required by stat(2), open(2) */
26
#include <sys/types.h>
27
#include <sys/stat.h>
28
#include <unistd.h>
29
#include <fcntl.h>
30
31
#include <glob.h>
32
33
int ne_utils_str_to_double(char *str, double *out_val)
34
0
{
35
0
    double val;
36
0
    char *end;
37
38
0
    errno = 0;
39
0
    val = strtod(str, &end);
40
0
    if (errno != 0 || *end != '\0') {
41
0
        return -1;
42
0
    }
43
0
    *out_val = val;
44
0
    return 0;
45
0
}
46
47
int ne_utils_str_to_uint64(char *str, uint64_t *out_val)
48
0
{
49
0
    uint64_t val;
50
0
    char *end;
51
52
0
    errno = 0;
53
0
    val = strtoll(str, &end, 10);
54
0
    if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
55
0
        || (errno != 0 && val == 0)) {
56
0
        flb_errno();
57
0
        return -1;
58
0
    }
59
60
0
    if (end == str) {
61
0
        return -1;
62
0
    }
63
64
0
    *out_val = val;
65
0
    return 0;
66
0
}
67
68
int ne_utils_file_read_uint64(const char *mount,
69
                              const char *path,
70
                              const char *join_a, const char *join_b,
71
                              uint64_t *out_val)
72
0
{
73
0
    int fd;
74
0
    int len;
75
0
    int ret;
76
0
    flb_sds_t p;
77
0
    uint64_t val;
78
0
    ssize_t bytes;
79
0
    char tmp[32];
80
81
    /* Check the path starts with the mount point to prevent duplication. */
82
0
    if (strncasecmp(path, mount, strlen(mount)) == 0 &&
83
0
        path[strlen(mount)] == '/') {
84
0
        mount = "";
85
0
    }
86
87
    /* Compose the final path */
88
0
    p = flb_sds_create(mount);
89
0
    if (!p) {
90
0
        return -1;
91
0
    }
92
93
0
    len = strlen(path);
94
0
    if (flb_sds_cat_safe(&p, path, len) < 0) {
95
0
        flb_sds_destroy(p);
96
0
        return -1;
97
0
    }
98
99
0
    if (join_a) {
100
0
        if (flb_sds_cat_safe(&p, "/", 1) < 0) {
101
0
            flb_sds_destroy(p);
102
0
            return -1;
103
0
        }
104
0
        len = strlen(join_a);
105
0
        if (flb_sds_cat_safe(&p, join_a, len) < 0) {
106
0
            flb_sds_destroy(p);
107
0
            return -1;
108
0
        }
109
0
    }
110
111
0
    if (join_b) {
112
0
        if (flb_sds_cat_safe(&p, "/", 1) < 0) {
113
0
            flb_sds_destroy(p);
114
0
            return -1;
115
0
        }
116
0
        len = strlen(join_b);
117
0
        if (flb_sds_cat_safe(&p, join_b, len) < 0) {
118
0
            flb_sds_destroy(p);
119
0
            return -1;
120
0
        }
121
0
    }
122
123
0
    fd = open(p, O_RDONLY);
124
0
    if (fd == -1) {
125
0
        flb_sds_destroy(p);
126
0
        return -1;
127
0
    }
128
0
    flb_sds_destroy(p);
129
130
0
    bytes = read(fd, &tmp, sizeof(tmp));
131
0
    if (bytes == -1) {
132
0
        flb_errno();
133
0
        close(fd);
134
0
        return -1;
135
0
    }
136
0
    close(fd);
137
138
0
    ret = ne_utils_str_to_uint64(tmp, &val);
139
0
    if (ret == -1) {
140
0
        return -1;
141
0
    }
142
143
0
    *out_val = val;
144
0
    return 0;
145
0
}
146
147
/*
148
 * Read a file and every non-empty line is stored as a flb_slist_entry in the
149
 * given list.
150
 */
151
int ne_utils_file_read_lines(const char *mount, const char *path, struct mk_list *list)
152
0
{
153
0
    int len;
154
0
    int ret;
155
0
    FILE *f;
156
0
    char line[512];
157
0
    char real_path[2048];
158
159
0
    mk_list_init(list);
160
161
    /* Check the path starts with the mount point to prevent duplication. */
162
0
    if (strncasecmp(path, mount, strlen(mount)) == 0 &&
163
0
        path[strlen(mount)] == '/') {
164
0
        mount = "";
165
0
    }
166
167
0
    snprintf(real_path, sizeof(real_path) - 1, "%s%s", mount, path);
168
0
    f = fopen(real_path, "r");
169
0
    if (f == NULL) {
170
0
        flb_errno();
171
0
        return -1;
172
0
    }
173
174
    /* Read the content */
175
0
    while (fgets(line, sizeof(line) - 1, f)) {
176
0
        len = strlen(line);
177
0
        if (line[len - 1] == '\n') {
178
0
            line[--len] = 0;
179
0
            if (len && line[len - 1] == '\r') {
180
0
                line[--len] = 0;
181
0
            }
182
0
        }
183
184
0
        ret = flb_slist_add(list, line);
185
0
        if (ret == -1) {
186
0
            fclose(f);
187
0
            flb_slist_destroy(list);
188
0
            return -1;
189
0
        }
190
0
    }
191
192
0
    fclose(f);
193
0
    return 0;
194
0
}
195
196
/*
197
 * Read a file and store the first line as a string.
198
 */
199
int ne_utils_file_read_sds(const char *mount, 
200
                           const char *path, 
201
                           const char *join_a, 
202
                           const char *join_b,
203
                           flb_sds_t *str)
204
0
{
205
0
    int fd;
206
0
    int len;
207
0
    int i;
208
0
    flb_sds_t p;
209
0
    ssize_t bytes;
210
0
    char tmp[32];
211
212
    /* Check the path starts with the mount point to prevent duplication. */
213
0
    if (strncasecmp(path, mount, strlen(mount)) == 0 &&
214
0
        path[strlen(mount)] == '/') {
215
0
        mount = "";
216
0
    }
217
218
    /* Compose the final path */
219
0
    p = flb_sds_create(mount);
220
0
    if (!p) {
221
0
        return -1;
222
0
    }
223
224
0
    len = strlen(path);
225
0
    flb_sds_cat_safe(&p, path, len);
226
227
0
    if (join_a) {
228
0
        if (flb_sds_cat_safe(&p, "/", 1) < 0) {
229
0
            flb_sds_destroy(p);
230
0
            return -1;
231
0
        }
232
0
        len = strlen(join_a);
233
0
        if (flb_sds_cat_safe(&p, join_a, len) < 0) {
234
0
            flb_sds_destroy(p);
235
0
            return -1;
236
0
        }
237
0
    }
238
239
0
    if (join_b) {
240
0
        if (flb_sds_cat_safe(&p, "/", 1) < 0) {
241
0
            flb_sds_destroy(p);
242
0
            return -1;
243
0
        }
244
0
        len = strlen(join_b);
245
0
        if (flb_sds_cat_safe(&p, join_b, len) < 0) {
246
0
            flb_sds_destroy(p);
247
0
            return -1;
248
0
        }
249
0
    }
250
251
0
    fd = open(p, O_RDONLY);
252
0
    if (fd == -1) {
253
0
        flb_sds_destroy(p);
254
0
        return -1;
255
0
    }
256
0
    flb_sds_destroy(p);
257
258
0
    bytes = read(fd, &tmp, sizeof(tmp));
259
0
    if (bytes == -1) {
260
0
        flb_errno();
261
0
        close(fd);
262
0
        return -1;
263
0
    }
264
0
    close(fd);
265
266
0
    for (i = bytes-1; i > 0; i--) {
267
0
        if (tmp[i] != '\n' && tmp[i] != '\r') {
268
0
            break;
269
0
        }
270
0
    }
271
272
0
    *str = flb_sds_create_len(tmp, i+1);
273
0
    if (*str == NULL) {
274
0
        return -1;
275
0
    }
276
277
0
    return 0;
278
0
}
279
280
int ne_utils_path_scan(struct flb_ne *ctx, const char *mount, const char *path,
281
                       int expected, struct mk_list *list)
282
0
{
283
0
    int i;
284
0
    int ret;
285
0
    glob_t globbuf;
286
0
    struct stat st;
287
0
    char real_path[2048];
288
289
0
    if (!path) {
290
0
        return -1;
291
0
    }
292
293
    /* Safe reset for globfree() */
294
0
    globbuf.gl_pathv = NULL;
295
296
    /* Scan the real path */
297
0
    snprintf(real_path, sizeof(real_path) - 1, "%s%s", mount, path);
298
0
    ret = glob(real_path, GLOB_TILDE | GLOB_ERR, NULL, &globbuf);
299
0
    if (ret != 0) {
300
0
        switch (ret) {
301
0
        case GLOB_NOSPACE:
302
0
            flb_plg_error(ctx->ins, "no memory space available");
303
0
            return -1;
304
0
        case GLOB_ABORTED:
305
0
            flb_plg_error(ctx->ins, "read error, check permissions: %s", path);
306
0
            return -1;;
307
0
        case GLOB_NOMATCH:
308
0
            ret = stat(path, &st);
309
0
            if (ret == -1) {
310
0
                flb_plg_debug(ctx->ins, "cannot read info from: %s", path);
311
0
            }
312
0
            else {
313
0
                ret = access(path, R_OK);
314
0
                if (ret == -1 && errno == EACCES) {
315
0
                    flb_plg_error(ctx->ins, "NO read access for path: %s", path);
316
0
                }
317
0
                else {
318
0
                    flb_plg_debug(ctx->ins, "NO matches for path: %s", path);
319
0
                }
320
0
            }
321
0
            return -1;
322
0
        }
323
0
    }
324
325
0
    if (globbuf.gl_pathc <= 0) {
326
0
        globfree(&globbuf);
327
0
        return -1;
328
0
    }
329
330
    /* Initialize list */
331
0
    flb_slist_create(list);
332
333
    /* For every entry found, generate an output list */
334
0
    for (i = 0; i < globbuf.gl_pathc; i++) {
335
0
        ret = stat(globbuf.gl_pathv[i], &st);
336
0
        if (ret != 0) {
337
0
            continue;
338
0
        }
339
340
0
        if ((expected == NE_SCAN_FILE && S_ISREG(st.st_mode)) ||
341
0
            (expected == NE_SCAN_DIR && S_ISDIR(st.st_mode))) {
342
343
            /* Compose the path */
344
0
            ret = flb_slist_add(list, globbuf.gl_pathv[i]);
345
0
            if (ret != 0) {
346
0
                globfree(&globbuf);
347
0
                flb_slist_destroy(list);
348
0
                return -1;
349
0
            }
350
0
        }
351
0
    }
352
353
0
    globfree(&globbuf);
354
0
    return 0;
355
0
}