17
17
* limitations under the License.
18
18
*/
19
19
20
- #include <glob.h>
21
- #include <sys/stat.h>
22
-
23
20
#include <fluent-bit/flb_info.h>
24
21
#include <fluent-bit/flb_input.h>
25
22
#include <fluent-bit/flb_input_plugin.h>
29
26
#include <fluent-bit/flb_time.h>
30
27
31
28
#include <cmetrics/cmt_decode_prometheus.h>
32
-
33
29
#include "prometheus_textfile.h"
34
30
31
+ #include <sys/stat.h>
32
+ /* Glob support */
33
+ #ifndef _MSC_VER
34
+ #include <glob.h>
35
+ #endif
36
+
37
+ #ifdef _WIN32
38
+ #include <Windows.h>
39
+ #include <strsafe.h>
40
+ #define PATH_MAX MAX_PATH
41
+ #endif
42
+
43
+ #ifndef _WIN32
44
+ static struct cfl_array * read_glob (const char * path )
45
+ {
46
+ int ret = -1 ;
47
+ int ret_glb = -1 ;
48
+ glob_t glb ;
49
+ size_t idx ;
50
+ struct cfl_array * list ;
51
+
52
+ ret_glb = glob (path , GLOB_NOSORT , NULL , & glb );
53
+
54
+ if (ret_glb != 0 ) {
55
+ switch (ret_glb ){
56
+ case GLOB_NOSPACE :
57
+ flb_warn ("[%s] glob: [%s] no space" , __FUNCTION__ , path );
58
+ break ;
59
+ case GLOB_NOMATCH :
60
+ flb_warn ("[%s] glob: [%s] no match" , __FUNCTION__ , path );
61
+ break ;
62
+ case GLOB_ABORTED :
63
+ flb_warn ("[%s] glob: [%s] aborted" , __FUNCTION__ , path );
64
+ break ;
65
+ default :
66
+ flb_warn ("[%s] glob: [%s] other error" , __FUNCTION__ , path );
67
+ }
68
+ return NULL ;
69
+ }
70
+
71
+ list = cfl_array_create (glb .gl_pathc );
72
+ for (idx = 0 ; idx < glb .gl_pathc ; idx ++ ) {
73
+ ret = cfl_array_append_string (list , glb .gl_pathv [idx ]);
74
+ if (ret < 0 ) {
75
+ cfl_array_destroy (list );
76
+ globfree (& glb );
77
+ return NULL ;
78
+ }
79
+ }
80
+
81
+ globfree (& glb );
82
+ return list ;
83
+ }
84
+ #else
85
+ static char * dirname (char * path )
86
+ {
87
+ char * ptr ;
88
+
89
+ ptr = strrchr (path , '\\' );
90
+
91
+ if (ptr == NULL ) {
92
+ return path ;
93
+ }
94
+ * ptr ++ = '\0' ;
95
+ return path ;
96
+ }
97
+
98
+ static struct cfl_array * read_glob_win (const char * path , struct cfl_array * list )
99
+ {
100
+ char * star , * p0 , * p1 ;
101
+ char pattern [MAX_PATH ];
102
+ char buf [MAX_PATH ];
103
+ int ret ;
104
+ struct stat st ;
105
+ HANDLE hnd ;
106
+ WIN32_FIND_DATA data ;
107
+
108
+ if (strlen (path ) > MAX_PATH - 1 ) {
109
+ flb_error ("path too long: %s" , path );
110
+ return NULL ;
111
+ }
112
+
113
+ star = strchr (path , '*' );
114
+ if (star == NULL ) {
115
+ flb_error ("path has no wild card: %s" , path );
116
+ return NULL ;
117
+ }
118
+
119
+ /*
120
+ * C:\data\tmp\input_*.conf
121
+ * 0<-----|
122
+ */
123
+ p0 = star ;
124
+ while (path <= p0 && * p0 != '\\' ) {
125
+ p0 -- ;
126
+ }
127
+
128
+ /*
129
+ * C:\data\tmp\input_*.conf
130
+ * |---->1
131
+ */
132
+ p1 = star ;
133
+ while (* p1 && * p1 != '\\' ) {
134
+ p1 ++ ;
135
+ }
136
+
137
+ memcpy (pattern , path , (p1 - path ));
138
+ pattern [p1 - path ] = '\0' ;
139
+
140
+ hnd = FindFirstFileA (pattern , & data );
141
+
142
+ if (hnd == INVALID_HANDLE_VALUE ) {
143
+ flb_error ("unable to open valid handle for: %s" , path );
144
+ return NULL ;
145
+ }
146
+
147
+ if (list == NULL ) {
148
+ list = cfl_array_create (3 );
149
+
150
+ if (list == NULL ) {
151
+ flb_error ("unable to allocate array" );
152
+ FindClose (hnd );
153
+ return NULL ;
154
+ }
155
+
156
+ /* cfl_array_resizable is hardcoded to return 0. */
157
+ if (cfl_array_resizable (list , FLB_TRUE ) != 0 ) {
158
+ flb_error ("unable to make array resizable" );
159
+ FindClose (hnd );
160
+ cfl_array_destroy (list );
161
+ return NULL ;
162
+ }
163
+ }
164
+
165
+ do {
166
+ /* Ignore the current and parent dirs */
167
+ if (!strcmp ("." , data .cFileName ) || !strcmp (".." , data .cFileName )) {
168
+ continue ;
169
+ }
170
+
171
+ /* Avoid an infinite loop */
172
+ if (strchr (data .cFileName , '*' )) {
173
+ continue ;
174
+ }
175
+
176
+ /* Create a path (prefix + filename + suffix) */
177
+ memcpy (buf , path , p0 - path + 1 );
178
+ buf [p0 - path + 1 ] = '\0' ;
179
+
180
+ if (FAILED (StringCchCatA (buf , MAX_PATH , data .cFileName ))) {
181
+ continue ;
182
+ }
183
+
184
+ if (FAILED (StringCchCatA (buf , MAX_PATH , p1 ))) {
185
+ continue ;
186
+ }
187
+
188
+ if (strchr (p1 , '*' )) {
189
+ if (read_glob_win (path , list ) == NULL ) {
190
+ cfl_array_destroy (list );
191
+ FindClose (hnd );
192
+ return NULL ;
193
+ }
194
+ continue ;
195
+ }
196
+
197
+ ret = stat (buf , & st );
198
+
199
+ if (ret == 0 && (st .st_mode & S_IFMT ) == S_IFREG ) {
200
+ cfl_array_append_string (list , buf );
201
+ }
202
+ } while (FindNextFileA (hnd , & data ) != 0 );
203
+
204
+ FindClose (hnd );
205
+ return list ;
206
+ }
207
+
208
+ static struct cfl_array * read_glob (const char * path )
209
+ {
210
+ return read_glob_win (path , NULL );
211
+ }
212
+ #endif
213
+
35
214
static int collect_metrics (struct prom_textfile * ctx )
36
215
{
37
216
int i ;
38
217
int ret ;
39
- glob_t globbuf ;
40
218
char errbuf [256 ];
41
219
struct stat st ;
42
220
struct mk_list * head ;
43
221
struct flb_slist_entry * entry ;
44
222
struct cmt * cmt = NULL ;
45
223
struct cmt_decode_prometheus_parse_opts opts = {0 };
46
224
flb_sds_t content ;
225
+ struct cfl_array * files ;
47
226
48
227
/* cmetrics prometheus decoder options */
49
228
opts .default_timestamp = cfl_time_now ();
@@ -54,23 +233,26 @@ static int collect_metrics(struct prom_textfile *ctx)
54
233
mk_list_foreach (head , ctx -> path_list ) {
55
234
entry = mk_list_entry (head , struct flb_slist_entry , _head );
56
235
57
- globbuf .gl_pathc = 0 ;
58
- globbuf .gl_pathv = NULL ;
59
-
60
- ret = glob (entry -> str , 0 , NULL , & globbuf );
61
- if (ret != 0 ) {
62
- globfree (& globbuf );
236
+ files = read_glob (entry -> str );
237
+ if (!files ) {
238
+ flb_plg_error (ctx -> ins , "error reading glob pattern: %s" , entry -> str );
239
+ continue ;
240
+ }
241
+ if (files -> entry_count == 0 ) {
242
+ flb_plg_debug (ctx -> ins , "no files found for glob pattern: %s" , entry -> str );
243
+ cfl_array_destroy (files );
63
244
continue ;
64
245
}
65
246
66
- for (i = 0 ; i < globbuf .gl_pathc ; i ++ ) {
67
- ret = stat (globbuf .gl_pathv [i ], & st );
247
+ /* iterate files */
248
+ for (i = 0 ; i < files -> entry_count ; i ++ ) {
249
+ ret = stat (files -> entries [i ]-> data .as_string , & st );
68
250
69
251
/* only process regular files */
70
252
if (ret == 0 && S_ISREG (st .st_mode )) {
71
- content = flb_file_read (globbuf . gl_pathv [i ]);
253
+ content = flb_file_read (files -> entries [i ]-> data . as_string );
72
254
if (!content ) {
73
- flb_plg_debug (ctx -> ins , "cannot read %s" , globbuf . gl_pathv [i ]);
255
+ flb_plg_debug (ctx -> ins , "cannot read %s" , files -> entries [i ]-> data . as_string );
74
256
continue ;
75
257
}
76
258
@@ -80,6 +262,7 @@ static int collect_metrics(struct prom_textfile *ctx)
80
262
}
81
263
82
264
cmt = NULL ;
265
+ memset (errbuf , 0 , sizeof (errbuf ));
83
266
ret = cmt_decode_prometheus_create (& cmt ,
84
267
content ,
85
268
flb_sds_len (content ),
@@ -90,14 +273,18 @@ static int collect_metrics(struct prom_textfile *ctx)
90
273
flb_input_metrics_append (ctx -> ins , NULL , 0 , cmt );
91
274
cmt_decode_prometheus_destroy (cmt );
92
275
}
276
+ else {
277
+ flb_plg_error (ctx -> ins , "error parsing file %s: '%s'" ,
278
+ files -> entries [i ]-> data .as_string , errbuf );
279
+ continue ;
280
+ }
93
281
}
94
282
else if (ret != 0 ) {
95
- flb_plg_error (ctx -> ins , "error parsing %s: %s" ,
96
- globbuf .gl_pathv [i ], errbuf );
283
+ flb_plg_error (ctx -> ins , "cannot read '%s'" , files -> entries [i ]-> data .as_string );
97
284
continue ;
98
285
}
99
286
}
100
- globfree ( & globbuf );
287
+ cfl_array_destroy ( files );
101
288
}
102
289
103
290
return 0 ;
0 commit comments