Coverage Report

Created: 2024-02-25 07:17

/src/fluent-bit/plugins/in_process_exporter_metrics/pe_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) 2023 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 "pe.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 pe_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 pe_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 pe_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
    flb_sds_cat_safe(&p, path, len);
95
96
0
    if (join_a) {
97
0
        flb_sds_cat_safe(&p, "/", 1);
98
0
        len = strlen(join_a);
99
0
        flb_sds_cat_safe(&p, join_a, len);
100
0
    }
101
102
0
    if (join_b) {
103
0
        flb_sds_cat_safe(&p, "/", 1);
104
0
        len = strlen(join_b);
105
0
        flb_sds_cat_safe(&p, join_b, len);
106
0
    }
107
108
0
    fd = open(p, O_RDONLY);
109
0
    if (fd == -1) {
110
0
        flb_sds_destroy(p);
111
0
        return -1;
112
0
    }
113
0
    flb_sds_destroy(p);
114
115
0
    bytes = read(fd, &tmp, sizeof(tmp));
116
0
    if (bytes == -1) {
117
0
        flb_errno();
118
0
        close(fd);
119
0
        return -1;
120
0
    }
121
0
    close(fd);
122
123
0
    ret = pe_utils_str_to_uint64(tmp, &val);
124
0
    if (ret == -1) {
125
0
        return -1;
126
0
    }
127
128
0
    *out_val = val;
129
0
    return 0;
130
0
}
131
132
/*
133
 * Read a file and every non-empty line is stored as a flb_slist_entry in the
134
 * given list.
135
 */
136
int pe_utils_file_read_lines(const char *mount, const char *path, struct mk_list *list)
137
0
{
138
0
    int len;
139
0
    int ret;
140
0
    FILE *f;
141
0
    char line[512];
142
0
    char real_path[2048];
143
144
0
    mk_list_init(list);
145
146
    /* Check the path starts with the mount point to prevent duplication. */
147
0
    if (strncasecmp(path, mount, strlen(mount)) == 0 &&
148
0
        path[strlen(mount)] == '/') {
149
0
        mount = "";
150
0
    }
151
152
0
    snprintf(real_path, sizeof(real_path) - 1, "%s%s", mount, path);
153
0
    f = fopen(real_path, "r");
154
0
    if (f == NULL) {
155
0
        if (errno == EACCES) {
156
0
            flb_debug("error reading procfs for path %s. errno = %d", real_path, errno);
157
0
        }
158
0
        else {
159
0
            flb_errno();
160
0
        }
161
0
        return -1;
162
0
    }
163
164
    /* Read the content */
165
0
    while (fgets(line, sizeof(line) - 1, f)) {
166
0
        len = strlen(line);
167
0
        if (line[len - 1] == '\n') {
168
0
            line[--len] = 0;
169
0
            if (len && line[len - 1] == '\r') {
170
0
                line[--len] = 0;
171
0
            }
172
0
        }
173
174
0
        ret = flb_slist_add(list, line);
175
0
        if (ret == -1) {
176
0
            fclose(f);
177
0
            flb_slist_destroy(list);
178
0
            return -1;
179
0
        }
180
0
    }
181
182
0
    fclose(f);
183
0
    return 0;
184
0
}
185
186
int pe_utils_path_scan(struct flb_pe *ctx, const char *mount, const char *path,
187
                       int expected, struct mk_list *list)
188
0
{
189
0
    int i;
190
0
    int ret;
191
0
    glob_t globbuf;
192
0
    struct stat st;
193
0
    char real_path[2048];
194
195
0
    if (!path) {
196
0
        return -1;
197
0
    }
198
199
    /* Safe reset for globfree() */
200
0
    globbuf.gl_pathv = NULL;
201
202
    /* Scan the real path */
203
0
    snprintf(real_path, sizeof(real_path) - 1, "%s%s", mount, path);
204
0
    ret = glob(real_path, GLOB_TILDE | GLOB_ERR, NULL, &globbuf);
205
0
    if (ret != 0) {
206
0
        switch (ret) {
207
0
        case GLOB_NOSPACE:
208
0
            flb_plg_error(ctx->ins, "no memory space available");
209
0
            return -1;
210
0
        case GLOB_ABORTED:
211
0
            flb_plg_error(ctx->ins, "read error, check permissions: %s", path);
212
0
            return -1;;
213
0
        case GLOB_NOMATCH:
214
0
            ret = stat(path, &st);
215
0
            if (ret == -1) {
216
0
                flb_plg_debug(ctx->ins, "cannot read info from: %s", path);
217
0
            }
218
0
            else {
219
0
                ret = access(path, R_OK);
220
0
                if (ret == -1 && errno == EACCES) {
221
0
                    flb_plg_error(ctx->ins, "NO read access for path: %s", path);
222
0
                }
223
0
                else {
224
0
                    flb_plg_debug(ctx->ins, "NO matches for path: %s", path);
225
0
                }
226
0
            }
227
0
            return -1;
228
0
        }
229
0
    }
230
231
0
    if (globbuf.gl_pathc <= 0) {
232
0
        globfree(&globbuf);
233
0
        return -1;
234
0
    }
235
236
    /* Initialize list */
237
0
    flb_slist_create(list);
238
239
    /* For every entry found, generate an output list */
240
0
    for (i = 0; i < globbuf.gl_pathc; i++) {
241
0
        ret = stat(globbuf.gl_pathv[i], &st);
242
0
        if (ret != 0) {
243
0
            continue;
244
0
        }
245
246
0
        if ((expected == NE_SCAN_FILE && S_ISREG(st.st_mode)) ||
247
0
            (expected == NE_SCAN_DIR && S_ISDIR(st.st_mode))) {
248
249
            /* Compose the path */
250
0
            ret = flb_slist_add(list, globbuf.gl_pathv[i]);
251
0
            if (ret != 0) {
252
0
                globfree(&globbuf);
253
0
                flb_slist_destroy(list);
254
0
                return -1;
255
0
            }
256
0
        }
257
0
    }
258
259
0
    globfree(&globbuf);
260
0
    return 0;
261
0
}