1717 * limitations under the License.
1818 */
1919
20- #include <glob.h>
21- #include <sys/stat.h>
22-
2320#include <fluent-bit/flb_info.h>
2421#include <fluent-bit/flb_input.h>
2522#include <fluent-bit/flb_input_plugin.h>
2926#include <fluent-bit/flb_time.h>
3027
3128#include <cmetrics/cmt_decode_prometheus.h>
32-
3329#include "prometheus_textfile.h"
3430
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+
35214static int collect_metrics (struct prom_textfile * ctx )
36215{
37216 int i ;
38217 int ret ;
39- glob_t globbuf ;
40218 char errbuf [256 ];
41219 struct stat st ;
42220 struct mk_list * head ;
43221 struct flb_slist_entry * entry ;
44222 struct cmt * cmt = NULL ;
45223 struct cmt_decode_prometheus_parse_opts opts = {0 };
46224 flb_sds_t content ;
225+ struct cfl_array * files ;
47226
48227 /* cmetrics prometheus decoder options */
49228 opts .default_timestamp = cfl_time_now ();
@@ -54,23 +233,26 @@ static int collect_metrics(struct prom_textfile *ctx)
54233 mk_list_foreach (head , ctx -> path_list ) {
55234 entry = mk_list_entry (head , struct flb_slist_entry , _head );
56235
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 );
63244 continue ;
64245 }
65246
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 );
68250
69251 /* only process regular files */
70252 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 );
72254 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 );
74256 continue ;
75257 }
76258
@@ -80,6 +262,7 @@ static int collect_metrics(struct prom_textfile *ctx)
80262 }
81263
82264 cmt = NULL ;
265+ memset (errbuf , 0 , sizeof (errbuf ));
83266 ret = cmt_decode_prometheus_create (& cmt ,
84267 content ,
85268 flb_sds_len (content ),
@@ -90,14 +273,18 @@ static int collect_metrics(struct prom_textfile *ctx)
90273 flb_input_metrics_append (ctx -> ins , NULL , 0 , cmt );
91274 cmt_decode_prometheus_destroy (cmt );
92275 }
276+ else {
277+ flb_plg_error (ctx -> ins , "error parsing file %s: '%s'" ,
278+ files -> entries [i ]-> data .as_string , errbuf );
279+ continue ;
280+ }
93281 }
94282 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 );
97284 continue ;
98285 }
99286 }
100- globfree ( & globbuf );
287+ cfl_array_destroy ( files );
101288 }
102289
103290 return 0 ;
0 commit comments