ze-filter  (ze-filter-0.8.0-develop-180218)
ze-fileexp.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : janvier 2002
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 #include <ze-sys.h>
26 #include <libze.h>
27 #include <ze-filter.h>
28 
29 #include "ze-fileexp.h"
30 
31 #define SZ_BLOCK 32
32 
33 #ifndef FALSE
34 #define FALSE 0
35 #endif
36 #ifndef TRUE
37 #define TRUE 1
38 #endif
39 
40 #define NEW_XFILES_DATA 1
41 
42 static int debug = 0;
43 
44 /* ****************************************************************************
45  * *
46  * *
47  **************************************************************************** */
48 
49 typedef struct fext_rec {
50  char expr[64];
51  char remark[32];
52 } fext_rec;
53 
54 
55 fext_rec *j_fext = NULL;
56 int sz_fext = 0;
57 int nb_fext = 0;
58 static pthread_mutex_t mutex_fext = PTHREAD_MUTEX_INITIALIZER;
59 
60 #define FEXT_LOCK() MUTEX_LOCK(&mutex_fext)
61 #define FEXT_UNLOCK() MUTEX_UNLOCK(&mutex_fext)
62 
63 /* ************************************
64  * *
65  * *
66  ************************************ */
67 static int
68 realloc_fext()
69 {
70  int x_sz_fext = sz_fext + SZ_BLOCK;
71  fext_rec *x_jfext;
72  int i;
73 
74  if ((x_jfext = realloc(j_fext, x_sz_fext * sizeof (fext_rec)))) {
75  sz_fext = x_sz_fext;
76  j_fext = x_jfext;
77  for (i = nb_fext; i < sz_fext; i++)
78  memset(j_fext + i, 0, sizeof (fext_rec));
79  } else
80  return 1;
81  return 0;
82 }
83 
84 /* ************************************
85  * *
86  * *
87  ************************************ */
88 int
90 {
91  FREE(j_fext);
92  sz_fext = nb_fext = 0;
93 
94  return 0;
95 }
96 
97 /* ************************************
98  * *
99  * *
100  ************************************ */
101 int
103  char *str;
104 {
105  if ((nb_fext == sz_fext) && realloc_fext())
106  return FALSE;
107 
108  strlcpy(j_fext[nb_fext].expr, str, sizeof (j_fext[nb_fext].expr));
109  nb_fext++;
110  return TRUE;
111 }
112 
113 /* ****************************************************************************
114  * *
115  * *
116  **************************************************************************** */
117 #ifndef MAX_EXT
118 #define MAX_EXT 1024
119 #endif
120 
121 char *ZE_FILE_EXT = NULL;
122 
123 static char *default_xfiles = CONF_XFILES_DEF;
124 
125 static char **sorted_ext = NULL;
126 
127 char *ZE_DEFAULT_EXT = NULL;
128 
129 /* ************************************
130  * *
131  * *
132  ************************************ */
133 int
134 sort_extensions(const void *a, const void *b)
135 {
136  char *p, *q;
137 
138  if (a == NULL && b == NULL)
139  return 0;
140  if (a == NULL)
141  return 1;
142  if (b == NULL)
143  return -1;
144 
145  p = *((char **) a);
146  q = *((char **) b);
147 
148  return strcmp(p, q);
149 }
150 
151 /* ************************************
152  * *
153  * *
154  ************************************ */
155 static char *env_ext[MAX_EXT];
156 
157 int
159  char *str;
160 {
161  int n = 0;
162  char *ptr, *s, *ts = NULL;
163 
164  if (str == NULL)
165  return n;
166 
167  memset(env_ext, 0, sizeof (env_ext));
168  if ((ts = strdup(str)) == NULL) {
169  ZE_LogSysError("strdup(%s) error", str);
170  return n;
171  }
172 
173  for (s = strtok_r(ts, ", \t\r\n", &ptr); s != NULL;
174  s = strtok_r(NULL, ", \t\r\n", &ptr)) {
175  if (n >= MAX_EXT - 1)
176  break;
177  env_ext[n++] = strdup(s);
178  }
179 
180  qsort(env_ext, n, sizeof (*env_ext), sort_extensions);
181 
182  if (n > 0) {
183  int i;
184 
185  ZE_MessageInfo(19, "** Environnement defined X-Files file extensions");
186  for (i = 0; i < n; i++)
187  ZE_MessageInfo(19, " %s", env_ext[i]);
188  }
189 
190  FREE(ts);
191  return n;
192 }
193 
194 void
196 {
197  char **p = NULL;
198  char sin[2048], sout[2048];
199  char *envext = NULL;
200 
201  FEXT_LOCK();
202 
203  if (ZE_DEFAULT_EXT == NULL) {
204  if ((envext = getenv("FILE_EXT")) != NULL) {
205  int n = 0;
206 
207  ZE_MessageInfo(11, "Using environnement FILE_EXT (%s) to define X-FILES",
208  envext);
209  n = extract_extensions(envext);
210 
211  if (n > 0) {
212  sorted_ext = env_ext;
213  p = env_ext;
214  }
215  }
216 
217  if (sorted_ext == NULL) {
218  int n = 0;
219 
220  ZE_MessageInfo(11, "Using default FILE_EXT (%s) to define X-FILES",
221  default_xfiles);
222  n = extract_extensions(default_xfiles);
223 
224  if (n > 0) {
225  sorted_ext = env_ext;
226  p = env_ext;
227  }
228  }
229 
230  *sin = '\0';
231  if (p != NULL && *p != NULL) {
232  strlcpy(sin, *p, sizeof (sin));
233  while (*++p != NULL)
234  sprintf(sin, "%s|%s", sin, *p);
235  }
236  sprintf(sout, "[.](%s)$", sin);
237 
239  ZE_DEFAULT_EXT = strdup(sout);
240  }
241  FEXT_UNLOCK();
242 }
243 
244 /* ************************************
245  * *
246  * *
247  ************************************ */
248 void
250 {
251  char sin[2048], sout[2048];
252  int i;
253 
254  if (ZE_DEFAULT_EXT == NULL)
256 
257  if ((ZE_FILE_EXT != NULL) && ZE_FILE_EXT != ZE_DEFAULT_EXT) {
258  free(ZE_FILE_EXT);
259  ZE_FILE_EXT = NULL;
260  }
261 
262  if (nb_fext == 0) {
263  char **p = sorted_ext;
264 
265  for (p = sorted_ext; *p != NULL; p++)
266  add_fext(*p);
267  }
268 
269  if (nb_fext > 0) {
270  if (strcasecmp(j_fext[0].expr, "NONE") != 0) {
271  memset(sin, 0, sizeof (sin));
272  for (i = 0; i < nb_fext; i++) {
273  if (strlen(sin) > 0) {
274  strlcat(sin, "|", sizeof (sin));
275  strlcat(sin, j_fext[i].expr, sizeof (sin));
276  } else
277  strlcpy(sin, j_fext[i].expr, sizeof (sin));
278  }
279  snprintf(sout, sizeof (sout), "[.](%s)$", sin);
280  } else
281  strlcpy(sout, "^$", sizeof (sout));
282 
283  ZE_FILE_EXT = strdup(sout);
284  if (debug) {
285  ZE_LogMsgWarning(0, " nb_fext = %d", nb_fext);
286  ZE_LogMsgWarning(0, " EXTENSIONS = %s", STRNULL(ZE_FILE_EXT, ""));
287  }
288  } else {
290  }
291 }
292 
293 /* ************************************
294  * *
295  * *
296  ************************************ */
297 void
299  int fd;
300 {
301  int i;
302  char line[128];
303  char temp[32];
304 
305  if (nb_fext > 0) {
306  strlcpy(line, "", sizeof (line));
307  for (i = 0; i < nb_fext; i++) {
308  snprintf(temp, sizeof (temp), "%-5s ", j_fext[i].expr);
309  strcat(line, temp);
310  if (strlen(line) + 16 > 64) {
311  FD_PRINTF(fd, " - EXT : %s\n", line);
312  strlcpy(line, "", sizeof (line));
313  }
314  }
315  if (strlen(line) > 0)
316  FD_PRINTF(fd, " - EXT : %s\n", line);
317  FD_PRINTF(fd, " - REGEXP : %s\n", STRNULL(ZE_FILE_EXT, "NULL"));
318  } else {
319  char **p;
320 
321  p = env_ext;
322 
323  strlcpy(line, "", sizeof (line));
324  for (; *p != NULL; p++) {
325  snprintf(temp, sizeof (temp), "%-5s ", *p);
326  strcat(line, temp);
327  if (strlen(line) + 16 > 64) {
328  FD_PRINTF(fd, " - EXT : %s\n", line);
329  strlcpy(line, "", sizeof (line));
330  }
331  }
332  if (strlen(line) > 0)
333  FD_PRINTF(fd, " - EXT : %s\n", line);
334  }
335 }
336 
337 /* ****************************************************************************
338  * *
339  * *
340  **************************************************************************** */
341 bool
343  char *fname;
344 {
345  regex_t re;
346  bool res = FALSE;
347 
348  if ((fname == NULL) || (strlen(fname) == 0))
349  return res;
350 
351  if ((ZE_FILE_EXT == NULL) || (strlen(ZE_FILE_EXT) == 0))
352  return 0;
353 
354  FEXT_LOCK();
355  if (regcomp(&re, ZE_FILE_EXT, REG_ICASE | REG_EXTENDED) == 0) {
356  res = (regexec(&re, fname, (size_t) 0, NULL, 0) == 0);
357  regfree(&re);
358  }
359  FEXT_UNLOCK();
360 
361  ZE_MessageInfo(15, " %-20s -> %d (%s)", fname, res, ZE_FILE_EXT);
362 
363  return res;
364 }
365 
366 /* ***************************************************************************
367  * *
368  * *
369  *****************************************************************************/
370 #define EXPR_LEN 256
371 
372 typedef struct {
373  char expr[EXPR_LEN];
374  char mime[EXPR_LEN];
375  char saction[EXPR_LEN];
377  bool mimecond;
378  size_t min, max;
379 } XFILE_T;
380 
381 #define XFILE_INITIALIZER {"", "", "", 0, FALSE, 0, 0}
382 
383 static XFILE_T toto = XFILE_INITIALIZER;
384 
385 static zeTbl_T htbl;
386 
387 static pthread_mutex_t st_mutex = PTHREAD_MUTEX_INITIALIZER;
388 
389 #define DATA_LOCK() MUTEX_LOCK(&st_mutex)
390 #define DATA_UNLOCK() MUTEX_UNLOCK(&st_mutex)
391 
392 
393 /* ***************************************************************************
394  * *
395  * *
396  *****************************************************************************/
397 void
399 {
400  XFILE_T p;
401 
402  printf("Let's dump x-files_table : \n");
403  DATA_LOCK();
404  if (zeTable_Get_First(&htbl, &p) == 0) {
405  do {
406  printf("-> %s %-20s %7ld/%7ld : %s\n",
407  STRBOOL(p.mimecond, " ", "!"), p.mime, (long int ) p.min, (long int ) p.max, p.expr);
408  } while (zeTable_Get_Next(&htbl, &p) == 0);
409  }
410  DATA_UNLOCK();
411 }
412 
413 /* ***************************************************************************
414  * *
415  * *
416  *****************************************************************************/
417 static int
418 xfiles_comp(pa, pb)
419  const void *pa;
420  const void *pb;
421 {
422  XFILE_T *a = (XFILE_T *) pa;
423  XFILE_T *b = (XFILE_T *) pb;
424  int r;
425 
426  if ((r = strcasecmp(a->expr, b->expr)) != 0)
427  return r;
428 
429  return strcasecmp(a->mime, b->mime);
430 }
431 
432 /* ***************************************************************************
433  * *
434  * *
435  *****************************************************************************/
436 static int
437 add_xfiles(vk, vv)
438  void *vk;
439  void *vv;
440 {
441  XFILE_T r;
442  char *k = (char *) vk;
443  char *v = (char *) vv;
444 
445  if ((k == NULL) || (v == NULL))
446  return 1;
447 
448  memset(&r, 0, sizeof (r));
449 
450  /*
451  * key part : file extensions
452  */
453  strlcpy(r.expr, k, sizeof (r.expr));
454 
455  /*
456  * value part : other conditions to be satisfied
457  */
458  r.min = 0;
459  r.max = 0;
460 
461  v = (char *) vv;
462  {
463  char *ptr, *s;
464  char *ts = strdup(v);
465 
466  if (ts != NULL) {
467  for (s = strtok_r(ts, ";", &ptr); s != NULL;
468  s = strtok_r(NULL, ";", &ptr)) {
469  long pi;
470 
471  if (zeStrRegex(s, "^SIZE=[0-9]*[km]?,[0,9]*[km]?", &pi, NULL, TRUE)) {
472  char *ps, *pmin, *pmax;
473 
474  ps = s + pi;
475  pmin = strchr(ps, '=') + 1;
476  pmax = strchr(ps, ',') + 1;
477 
478  ps = pmin + strspn(pmin, "0123456789");
479  if ((*ps == 'm') || (*ps == 'M') || (*ps == 'k') | (*ps == 'K'))
480  ps++;
481  *ps = '\0';
482  ps = pmax + strspn(pmax, "0123456789");
483  if ((*ps == 'm') || (*ps == 'M') || (*ps == 'k') | (*ps == 'K'))
484  ps++;
485  *ps = '\0';
486 
487  if (strlen(pmin) > 0)
488  r.min = zeStr2long(pmin, NULL, 0);
489 
490  if (strlen(pmax) > 0)
491  r.max = zeStr2long(pmax, NULL, 0);
492 
493  continue;
494  }
495 
496 /* JOE XXX action */
497 #if 0
498  if (zeStrRegex(s, "^ACTION=.+$", NULL, NULL, TRUE)) {
499  int argc;
500  char *argv[32];
501  int i;
502  char *opt = NULL;
503 
504  opt = strchr(s, '=');
505  if (opt == NULL)
506  continue;
507  opt++;
508 
509  argc = zeStr2Tokens(opt, 32, argv, ", ");
510  for (i = 0; i < argc; i++) {
511  bool no = FALSE;
512 
513  if (*argv[i] == '!') {
514  no = TRUE;
515  argv[i]++;
516  }
517  if (STRCASEEQUAL(argv[i], "notify")) {
518  flags |= (no ? 0 : X_NOTIFY);
519  }
520  }
521  continue;
522  }
523 #endif
524 
525  if (zeStrRegex
526  (s, "^ACTION=(notify|discard|reject|ok)$", NULL, NULL, TRUE)) {
527  char *ps;
528 
529  ps = strchr(s, '=');
530  if (ps != NULL)
531  ps++;
532  if (ps != NULL) {
533  strlcpy(r.saction, ps, sizeof (r.saction));
534  }
535 
536  continue;
537  }
538 
539  if (zeStrRegex(s, ".*/.*|ALL", NULL, NULL, TRUE)) {
540  if (*s == '!') {
541  r.mimecond = FALSE;
542  s++;
543  } else
544  r.mimecond = TRUE;
545  strlcpy(r.mime, s, sizeof (r.mime));
546 
547  continue;
548  }
549  }
550  }
551  FREE(ts);
552  }
553 
554  return zeTable_Add(&htbl, &r);
555 }
556 
557 /* ***************************************************************************
558  * *
559  * *
560  *****************************************************************************/
561 static bool
562 read_it(path, tag)
563  char *path;
564  char *tag;
565 
566 {
567  int r;
568 
569  r = zm_RdTextFile(path, RD_TWO_COLUMN, RD_REVERSE, tag, add_xfiles);
570 
571  return r >= 0;
572 }
573 
574 bool
575 load_xfiles_table(cfdir, fname)
576  char *cfdir;
577  char *fname;
578 
579 {
580  int res = 0;
581  static int htbl_ok = FALSE;
582  bool result = FALSE;
583 
584  DATA_LOCK();
585 
586  if (htbl_ok == FALSE) {
587  memset(&htbl, 0, sizeof (htbl));
588  res = zeTable_Init(&htbl, sizeof (XFILE_T), 256, xfiles_comp);
589  if (res == 0)
590  htbl_ok = TRUE;
591  }
592  if (res == 0)
593  res = zeTable_Clear(&htbl);
594 
595  if (res == 0)
596  result = read_conf_data_file(cfdir, fname, "ze-xfiles", read_it);
597 
598  DATA_UNLOCK();
599 
600  return result;
601 }
602 
603 /* ***************************************************************************
604  * *
605  * *
606  *****************************************************************************/
607 #define XFILES_DEFAULT 1
608 #define XFILES_TNEF 2
609 #define XFILES_CLSID 3
610 #define XFILES_ALL 4
611 
612 static name2id_T names[] = {
613  {"DEFAULT", XFILES_DEFAULT},
614  {"TNEF", XFILES_TNEF},
615  {"CLSID", XFILES_CLSID},
616  {"ALL", XFILES_ALL},
617  {NULL, -1}
618 };
619 
620 #define FNAME_TNEF "winmail.dat"
621 #define FNAME_CLSID \
622  "[{]?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}[}]?$"
623 
624 bool
625 check_xfiles(fname, mime, msgsize, saction, bufsize)
626  char *fname;
627  char *mime;
628  size_t msgsize;
629  char *saction;
630  size_t bufsize;
631 
632 {
633  bool res = FALSE;
634 
635  if (fname == NULL)
636  return FALSE;
637 
638  mime = STRNULL(mime, "");
639  fname = STRNULL(fname, "");
640  DATA_LOCK();
641 
642  {
643  XFILE_T *q;
644 
645  if ((q = (XFILE_T *) zeTable_Get_First_Ptr(&htbl)) != NULL) {
646  do {
647  int id = get_id_by_name(names, q->expr);
648 
649  switch (id) {
650  case XFILES_DEFAULT:
651  if (!zeStrRegex(fname, ZE_DEFAULT_EXT, NULL, NULL, TRUE))
652  continue;
653  break;
654  case XFILES_CLSID:
655  if (!zeStrRegex(fname, FNAME_CLSID, NULL, NULL, TRUE))
656  continue;
657  break;
658  case XFILES_TNEF:
659  if (!zeStrRegex(fname, FNAME_TNEF, NULL, NULL, TRUE))
660  continue;
661  break;
662  case XFILES_ALL:
663  break;
664  default:
665  if (!zeStrRegex(fname, q->expr, NULL, NULL, TRUE))
666  continue;
667  break;
668  }
669 
670  /*
671  * check message size
672  */
673  if (msgsize > 0) {
674  size_t si, sf;
675 
676  si = q->min;
677  sf = (q->max != 0 ? q->max : LONG_MAX);
678 
679  ZE_MessageInfo(11, "SIZE=%d MIN=%d MAX=%d", msgsize, si, sf);
680 
681  if (sf > si) {
682  if (msgsize < si || msgsize > sf)
683  continue;
684  }
685  }
686 
687  if (q->mimecond) {
688  if (STRCASEEQUAL(q->mime, "all") || STRCASEEQUAL(q->mime, mime))
689  res = TRUE;
690  } else {
691  if (!STRCASEEQUAL(q->mime, "all") || !STRCASEEQUAL(q->mime, mime))
692  res = TRUE;
693  }
694 
695  if (res) {
696  if (saction != NULL && bufsize > 0)
697  strlcpy(saction, q->saction, bufsize);
698  break;
699  }
700 
701  } while ((q = (XFILE_T *) zeTable_Get_Next_Ptr(&htbl)) != NULL);
702  }
703  }
704  DATA_UNLOCK();
705 
706  return res;
707 }
#define TRUE
Definition: ze-fileexp.c:37
#define DATA_LOCK()
Definition: ze-fileexp.c:389
#define STRBOOL(x, t, f)
Definition: macros.h:87
fext_rec * j_fext
Definition: ze-fileexp.c:55
#define FALSE
Definition: ze-fileexp.c:34
int sz_fext
Definition: ze-fileexp.c:56
#define XFILES_CLSID
Definition: ze-fileexp.c:609
char expr[EXPR_LEN]
Definition: ze-fileexp.c:373
#define FEXT_LOCK()
Definition: ze-fileexp.c:60
char * ZE_FILE_EXT
Definition: ze-fileexp.c:121
#define FREE(x)
Definition: macros.h:37
#define XFILES_DEFAULT
Definition: ze-fileexp.c:607
#define STRNULL(x, r)
Definition: macros.h:81
bool check_filename_xfile(char *fname)
Definition: ze-fileexp.c:342
#define FNAME_TNEF
Definition: ze-fileexp.c:620
#define strlcpy
Definition: zeString.h:32
void * zeTable_Get_Next_Ptr(zeTbl_T *)
Definition: zeTable.c:327
#define MAX_EXT
Definition: ze-fileexp.c:118
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
bool load_xfiles_table(char *cfdir, char *fname)
Definition: ze-fileexp.c:575
#define DATA_UNLOCK()
Definition: ze-fileexp.c:390
#define FD_PRINTF(fdp,...)
Definition: macros.h:45
void * zeTable_Get_First_Ptr(zeTbl_T *)
Definition: zeTable.c:305
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
int add_fext(char *str)
Definition: ze-fileexp.c:102
bool read_conf_data_file(char *cfdir, char *fname, char *dfile, read_conf_data_file_F func)
void dump_xfiles_table()
Definition: ze-fileexp.c:398
#define strlcat
Definition: zeString.h:28
#define strchr
Definition: ze-sys.h:218
size_t min
Definition: ze-fileexp.c:378
#define FNAME_CLSID
Definition: ze-fileexp.c:621
#define XFILES_TNEF
Definition: ze-fileexp.c:608
bool mimecond
Definition: ze-fileexp.c:377
void init_default_file_extensions()
Definition: ze-fileexp.c:195
int zeTable_Clear(zeTbl_T *)
Definition: zeTable.c:136
long zeStr2long(char *s, int *error, long dval)
Definition: zeStrConvert.c:35
#define EXPR_LEN
Definition: ze-fileexp.c:370
int zeTable_Add(zeTbl_T *, void *)
Definition: zeTable.c:155
int sort_extensions(const void *a, const void *b)
Definition: ze-fileexp.c:134
uint32_t action
Definition: ze-fileexp.c:376
size_t max
Definition: ze-fileexp.c:378
int zm_RdTextFile(char *, int, int, char *, int(*)(void *, void *))
int zeTable_Get_First(zeTbl_T *, void *)
Definition: zeTable.c:250
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define RD_REVERSE
Definition: ze-rdfile.h:30
#define XFILE_INITIALIZER
Definition: ze-fileexp.c:381
char saction[EXPR_LEN]
Definition: ze-fileexp.c:375
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
int zeTable_Get_Next(zeTbl_T *, void *)
Definition: zeTable.c:277
#define max(a, b)
Definition: macros.h:127
int extract_extensions(char *str)
Definition: ze-fileexp.c:158
#define SZ_BLOCK
Definition: ze-fileexp.c:31
char * ZE_DEFAULT_EXT
Definition: ze-fileexp.c:127
struct fext_rec fext_rec
#define ZE_LogMsgWarning(level,...)
Definition: zeSyslog.h:112
int zeTable_Init(zeTbl_T *, size_t, int, int(*)(const void *, const void *))
#define CONF_XFILES_DEF
Definition: defs.h:75
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
int get_id_by_name(name2id_T *, char *)
Definition: ze-name2id.c:35
char remark[32]
Definition: ze-fileexp.c:51
bool check_xfiles(char *fname, char *mime, size_t msgsize, char *saction, size_t bufsize)
Definition: ze-fileexp.c:625
char expr[64]
Definition: ze-fileexp.c:50
#define RD_TWO_COLUMN
Definition: ze-rdfile.h:27
char mime[EXPR_LEN]
Definition: ze-fileexp.c:374
long uint32_t
Definition: ze-sys.h:489
#define FEXT_UNLOCK()
Definition: ze-fileexp.c:61
int nb_fext
Definition: ze-fileexp.c:57
void init_file_extension_regex()
Definition: ze-fileexp.c:249
#define XFILES_ALL
Definition: ze-fileexp.c:610
void list_filename_extensions(int fd)
Definition: ze-fileexp.c:298
int free_fext()
Definition: ze-fileexp.c:89