X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Ffile_glob.c;h=a2e903105c2a5214a183596ba679b224c59b943f;hp=2f3ff7f12cb8899a6884a8b08c18f3695fc5e315;hb=7fc72f3ae149e416a297ef1f55c09271056e98f1;hpb=39c353b281dd91c145e122110d516fce7bbde8c6 diff --git a/src/file_glob.c b/src/file_glob.c index 2f3ff7f..a2e9031 100644 --- a/src/file_glob.c +++ b/src/file_glob.c @@ -1,10 +1,10 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2010 Index Data + * Copyright (C) Index Data * See the file LICENSE for details. */ -/** \file - \brief File globbing (ala POSIX glob) +/** \file + \brief File globbing (ala POSIX glob, but simpler) */ #if HAVE_CONFIG_H #include @@ -14,36 +14,180 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include +#include struct res_entry { struct res_entry *next; + char *file; }; struct glob_res { + NMEM nmem; + unsigned flags; + size_t number_of_entries; + struct res_entry **last_entry; struct res_entry *entries; }; -typedef struct glob_res *yaz_glob_res_t; +static void add_entry(yaz_glob_res_t res, const char *str) +{ + struct res_entry *ent = + nmem_malloc(res->nmem, sizeof(*ent)); + ent->file = nmem_strdup(res->nmem, str); + ent->next = 0; + *res->last_entry = ent; + res->last_entry = &ent->next; + res->number_of_entries++; +} -static void glob_r(const char *pattern, yaz_glob_res_t res, size_t off) +static void glob_r(yaz_glob_res_t res, const char *pattern, size_t off, + char *prefix) { + size_t prefix_len = strlen(prefix); + int is_pattern = 0; size_t i = off; while (pattern[i] && !strchr("/\\", pattern[i])) + { + if (strchr("?*", pattern[i])) + is_pattern = 1; i++; + } + + if (!is_pattern && pattern[i]) /* no pattern and directory part */ + { + i++; /* skip dir sep */ + memcpy(prefix + prefix_len, pattern + off, i - off); + prefix[prefix_len + i - off] = '\0'; + glob_r(res, pattern, i, prefix); + prefix[prefix_len] = '\0'; + } + else if ((res->flags & YAZ_FILE_GLOB_FAIL_NOTEXIST) && + !is_pattern && !pattern[i]) + { + strcpy(prefix + prefix_len, pattern + off); + add_entry(res, prefix); + } + else + { + DIR * dir = opendir(*prefix ? prefix : "." ); + + if (dir) + { + struct dirent *ent; + + while ((ent = readdir(dir))) + { + int r; + memcpy(prefix + prefix_len, pattern + off, i - off); + prefix[prefix_len + i - off] = '\0'; + r = yaz_match_glob(prefix + prefix_len, ent->d_name); + prefix[prefix_len] = '\0'; + + if (r) + { + strcpy(prefix + prefix_len, ent->d_name); + if (pattern[i]) + { + glob_r(res, pattern, i, prefix); + } + else + { + add_entry(res, prefix); + } + prefix[prefix_len] = '\0'; + } + } + closedir(dir); + } + } +} + +static int cmp_entry(const void *a, const void *b) +{ + struct res_entry *ent_a = *(struct res_entry **) a; + struct res_entry *ent_b = *(struct res_entry **) b; + return strcmp(ent_a->file, ent_b->file); +} + +static void sort_them(yaz_glob_res_t res) +{ + size_t i; + struct res_entry **ent_p; + struct res_entry **ent = nmem_malloc(res->nmem, sizeof(*ent) * res->number_of_entries); + struct res_entry *ent_i = res->entries; + for (i = 0; i < res->number_of_entries; i++) + { + ent[i] = ent_i; + ent_i = ent_i->next; + } + qsort(ent, res->number_of_entries, sizeof(*ent), cmp_entry); + ent_p = &res->entries; + for (i = 0; i < res->number_of_entries; i++) + { + *ent_p = ent[i]; + ent_p = &ent[i]->next; + } + *ent_p = 0; } int yaz_file_glob(const char *pattern, yaz_glob_res_t *res) { - *res = xmalloc(sizeof(**res)); + return yaz_file_glob2(pattern, res, 0); +} + +int yaz_file_glob2(const char *pattern, yaz_glob_res_t *res, unsigned flags) +{ + char prefix[FILENAME_MAX+1]; + NMEM nmem = nmem_create(); + + *prefix = '\0'; + *res = nmem_malloc(nmem, sizeof(**res)); + (*res)->flags = flags; + (*res)->number_of_entries = 0; + (*res)->nmem = nmem; (*res)->entries = 0; - glob_r(pattern, *res, 0); + (*res)->last_entry = &(*res)->entries; + glob_r(*res, pattern, 0, prefix); + sort_them(*res); return 0; } +void yaz_file_globfree(yaz_glob_res_t *res) +{ + if (*res) + { + /* must free entries as well */ + nmem_destroy((*res)->nmem); + *res = 0; + } +} + +const char *yaz_file_glob_get_file(yaz_glob_res_t res, size_t idx) +{ + struct res_entry *ent = res->entries; + while (idx && ent) + { + ent = ent->next; + idx--; + } + if (!ent) + return 0; + return ent->file; +} + +size_t yaz_file_glob_get_num(yaz_glob_res_t res) +{ + return res->number_of_entries; +} + /* * Local variables: * c-basic-offset: 4