#include <gimp-print/gimp-print.h>
#include "gimp-print-internal.h"
#include <gimp-print/gimp-print-intl-internal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static int stpi_path_check(const struct dirent *module);
static char *stpi_path_merge(const char *path,
const char *file);
static int stpi_scandir (const char *dir,
struct dirent ***namelist,
int (*sel) (const struct dirent *),
int (*cmp) (const void *, const void *));
static const char *path_check_path;
static const char *path_check_suffix;
static int
dirent_sort(const void *a,
const void *b)
{
return strcoll ((*(const struct dirent **) a)->d_name,
(*(const struct dirent **) b)->d_name);
}
stp_list_t *
stp_path_search(stp_list_t *dirlist,
const char *suffix)
{
stp_list_t *findlist;
stp_list_item_t *diritem;
struct dirent** module_dir;
char *module_name;
int n;
if (!dirlist)
return NULL;
path_check_suffix = suffix;
findlist = stp_list_create();
if (!findlist)
return NULL;
stp_list_set_freefunc(findlist, stp_list_node_free_data);
diritem = stp_list_get_start(dirlist);
while (diritem)
{
path_check_path = (const char *) stp_list_item_get_data(diritem);
stp_deprintf(STP_DBG_PATH, "stp-path: directory: %s\n",
(const char *) stp_list_item_get_data(diritem));
n = stpi_scandir ((const char *) stp_list_item_get_data(diritem),
&module_dir, stpi_path_check, dirent_sort);
if (n >= 0)
{
int idx;
for (idx = 0; idx < n; ++idx)
{
module_name = stpi_path_merge((const char *) stp_list_item_get_data(diritem),
module_dir[idx]->d_name);
stp_list_item_create(findlist, NULL, module_name);
free (module_dir[idx]);
}
free (module_dir);
}
diritem = stp_list_item_next(diritem);
}
return findlist;
}
static int
stpi_path_check(const struct dirent *module)
{
int namelen;
int status = 0;
int savederr;
char *filename;
struct stat modstat;
savederr = errno;
filename = stpi_path_merge(path_check_path, module->d_name);
namelen = strlen(filename);
if (namelen >= strlen(path_check_suffix) + 1)
{
if (!stat (filename, &modstat))
{
if (S_ISREG(modstat.st_mode))
status = 1;
if (strncmp(filename + (namelen - strlen(path_check_suffix)),
path_check_suffix,
strlen(path_check_suffix)))
{
status = 0;
}
}
}
if (status)
stp_deprintf(STP_DBG_PATH, "stp-path: file: `%s'\n", filename);
stp_free(filename);
filename = NULL;
errno = savederr;
return status;
}
static char *
stpi_path_merge(const char *path,
const char *file)
{
char *filename;
int namelen = strlen(path) + strlen(file) + 2;
filename = (char *) stp_malloc(namelen * sizeof(char));
strcpy (filename, path);
strcat (filename, "/");
strcat (filename, file);
filename[namelen - 1] = '\0';
return filename;
}
void
stp_path_split(stp_list_t *list,
const char *path)
{
const char *start = path;
const char *end = NULL;
char *dir = NULL;
int len;
while (start)
{
end = (const char *) strchr(start, ':');
if (!end)
len = strlen(start) + 1;
else
len = (end - start);
if (len && !(len == 1 && !end))
{
dir = (char *) stp_malloc(len + 1);
strncpy(dir, start, len);
dir[len] = '\0';
stp_list_item_create(list, NULL, dir);
}
if (!end)
{
start = NULL;
break;
}
start = end + 1;
}
}
#ifdef _DIRENT_HAVE_D_NAMLEN
# ifndef _D_EXACT_NAMLEN
# define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
# endif
# ifndef _D_ALLOC_NAMLEN
# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
# endif
#else
# ifndef _D_EXACT_NAMLEN
# define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name))
# endif
# ifndef _D_ALLOC_NAMLEN
# ifdef _DIRENT_HAVE_D_RECLEN
# define _D_ALLOC_NAMLEN(d) (((char *) (d) + (d)->d_reclen) - &(d)->d_name[0])
# else
# define _D_ALLOC_NAMLEN(d) (sizeof (d)->d_name > 1 ? sizeof (d)->d_name : \
_D_EXACT_NAMLEN (d) + 1)
# endif
# endif
#endif
static int
stpi_scandir (const char *dir,
struct dirent ***namelist,
int (*sel) (const struct dirent *),
int (*cmp) (const void *, const void *))
{
DIR *dp = opendir (dir);
struct dirent **v = NULL;
size_t vsize = 0, i;
struct dirent *d;
int save;
if (dp == NULL)
return -1;
save = errno;
errno = 0;
i = 0;
while ((d = readdir (dp)) != NULL)
if (sel == NULL || (*sel) (d))
{
struct dirent *vnew;
size_t dsize;
errno = 0;
if (i == vsize)
{
struct dirent **new;
if (vsize == 0)
vsize = 10;
else
vsize *= 2;
new = (struct dirent **) realloc (v, vsize * sizeof (*v));
if (new == NULL)
break;
v = new;
}
dsize = &d->d_name[_D_ALLOC_NAMLEN (d)] - (char *) d;
vnew = (struct dirent *) malloc (dsize);
if (vnew == NULL)
break;
v[i++] = (struct dirent *) memcpy (vnew, d, dsize);
}
if (errno != 0)
{
save = errno;
while (i > 0)
free (v[--i]);
free (v);
i = -1;
}
else
{
if (cmp != NULL)
qsort (v, i, sizeof (*v), cmp);
*namelist = v;
}
(void) closedir (dp);
errno = save;
return i;
}