opt_conf.c
#define _GNU_SOURCE 1
#define EX_UTILS_NO_FUNCS 1
#include "ex_utils.h"
#include "opt_conf.h"
#include "glibc-strverscmp.h"
#define OPT_CONF_DIR_CHR_(x, y) ((*x)->d_name[y] == '_')
static int opt_conf__sort_conf_files(const void *passed_a, const void *passed_b)
{
const struct dirent * const *a = passed_a;
const struct dirent * const *b = passed_b;
unsigned int scan = 0;
while (OPT_CONF_DIR_CHR_(a, scan) && OPT_CONF_DIR_CHR_(b, scan))
++scan;
ASSERT((*a)->d_name[scan] && (*b)->d_name[scan]);
if (OPT_CONF_DIR_CHR_(a, scan) || OPT_CONF_DIR_CHR_(b, scan))
return (OPT_CONF_DIR_CHR_(b, scan) - OPT_CONF_DIR_CHR_(a, scan));
return (strverscmp((*a)->d_name, (*b)->d_name));
}
#if 0
#include <stdio.h>
static int opt_conf__dbg_sort_conf_files(const void *passed_a,
const void *passed_b)
{
const struct dirent * const *a = passed_a;
const struct dirent * const *b = passed_b;
int ret = opt_conf__sort_conf_files(passed_a, passed_b);
fprintf(stderr, " DBG: cmp(\"%s\", \"%s\") = %d\n",
(*a)->d_name, (*b)->d_name, ret);
return (ret);
}
#define opt_conf__sort_conf_files opt_conf__dbg_sort_conf_files
#endif
static int opt_conf__filt_conf_files(const struct dirent *dent)
{
size_t len = _D_EXACT_NAMLEN(dent);
ASSERT(!dent->d_name[len]);
if (dent->d_name[0] == '.')
return (FALSE);
if (len < strlen("a.conf"))
return (FALSE);
if (!CSTREQ(dent->d_name + len - strlen(".conf"), ".conf"))
return (FALSE);
return (TRUE);
}
int opt_conf_sc_scan_dir(const char *dir, struct dirent ***dents)
{
int num = -1;
if (!dir[0])
{
errno = ENOENT;
return (-1);
}
num = scandir(dir, dents,
opt_conf__filt_conf_files, opt_conf__sort_conf_files);
return (num);
}