1 : #define _GNU_SOURCE 1 /* strverscmp() */
2 :
3 : #define EX_UTILS_NO_FUNCS 1
4 : #include "ex_utils.h"
5 :
6 : #include "opt_conf.h"
7 :
8 : #include "glibc-strverscmp.h"
9 :
10 : #define OPT_CONF_DIR_CHR_(x, y) ((*x)->d_name[y] == '_')
11 : static int opt_conf__sort_conf_files(const void *passed_a, const void *passed_b)
12 132 : {
13 132 : const struct dirent * const *a = passed_a;
14 132 : const struct dirent * const *b = passed_b;
15 132 : unsigned int scan = 0;
16 :
17 : /* treat any leading '_'s as system conf.d files and process those first...
18 : * Ie. if a is _y and b is x, then (a is < b), hence return -1
19 : * if a is __y and b is _x, then (a is < b), hence return -1 */
20 354 : while (OPT_CONF_DIR_CHR_(a, scan) && OPT_CONF_DIR_CHR_(b, scan))
21 90 : ++scan;
22 :
23 : /* would have been filtered otherwise */
24 66 : ASSERT((*a)->d_name[scan] && (*b)->d_name[scan]);
25 :
26 132 : if (OPT_CONF_DIR_CHR_(a, scan) || OPT_CONF_DIR_CHR_(b, scan))
27 48 : return (OPT_CONF_DIR_CHR_(b, scan) - OPT_CONF_DIR_CHR_(a, scan));
28 :
29 : /* the rest is POSIX, but do numbers "right" */
30 84 : return (strverscmp((*a)->d_name, (*b)->d_name));
31 : }
32 :
33 : #if 0
34 : #include <stdio.h>
35 : static int opt_conf__dbg_sort_conf_files(const void *passed_a,
36 : const void *passed_b)
37 : {
38 : const struct dirent * const *a = passed_a;
39 : const struct dirent * const *b = passed_b;
40 : int ret = opt_conf__sort_conf_files(passed_a, passed_b);
41 :
42 : fprintf(stderr, " DBG: cmp(\"%s\", \"%s\") = %d\n",
43 : (*a)->d_name, (*b)->d_name, ret);
44 :
45 : return (ret);
46 : }
47 : #define opt_conf__sort_conf_files opt_conf__dbg_sort_conf_files
48 : #endif
49 :
50 : /* filter to files that:
51 : * 1. _don't_ start with a '.'
52 : * 1. _do_ end with a ".conf"
53 : */
54 : static int opt_conf__filt_conf_files(const struct dirent *dent)
55 738 : {
56 738 : size_t len = _D_EXACT_NAMLEN(dent);
57 :
58 370 : ASSERT(!dent->d_name[len]);
59 :
60 738 : if (dent->d_name[0] == '.') /* filters . .. _and_ .foo.conf */
61 30 : return (FALSE);
62 :
63 708 : if (len < strlen("a.conf"))
64 6 : return (FALSE);
65 702 : if (!CSTREQ(dent->d_name + len - strlen(".conf"), ".conf"))
66 624 : return (FALSE);
67 :
68 78 : return (TRUE);
69 : }
70 :
71 : int opt_conf_sc_scan_dir(const char *dir, struct dirent ***dents)
72 14 : {
73 14 : int num = -1;
74 :
75 14 : if (!dir[0])
76 : {
77 4 : errno = ENOENT;
78 4 : return (-1);
79 : }
80 :
81 10 : num = scandir(dir, dents,
82 : opt_conf__filt_conf_files, opt_conf__sort_conf_files);
83 :
84 10 : return (num);
85 : }
|