1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
7 \brief File globbing (ala POSIX glob, but simpler)
13 #include <sys/types.h>
19 #include <yaz/wrbuf.h>
20 #include <yaz/tpath.h>
22 #include <yaz/dirent.h>
24 #include <yaz/file_glob.h>
25 #include <yaz/match_glob.h>
28 struct res_entry *next;
35 size_t number_of_entries;
36 struct res_entry **last_entry;
37 struct res_entry *entries;
40 static void add_entry(yaz_glob_res_t res, const char *str)
42 struct res_entry *ent =
43 nmem_malloc(res->nmem, sizeof(*ent));
44 ent->file = nmem_strdup(res->nmem, str);
46 *res->last_entry = ent;
47 res->last_entry = &ent->next;
48 res->number_of_entries++;
51 static void glob_r(yaz_glob_res_t res, const char *pattern, size_t off,
54 size_t prefix_len = strlen(prefix);
57 while (pattern[i] && !strchr("/\\", pattern[i]))
59 if (strchr("?*", pattern[i]))
64 if (!is_pattern && pattern[i]) /* no pattern and directory part */
66 i++; /* skip dir sep */
67 memcpy(prefix + prefix_len, pattern + off, i - off);
68 prefix[prefix_len + i - off] = '\0';
69 glob_r(res, pattern, i, prefix);
70 prefix[prefix_len] = '\0';
72 else if ((res->flags & YAZ_FILE_GLOB_FAIL_NOTEXIST) &&
73 !is_pattern && !pattern[i])
75 strcpy(prefix + prefix_len, pattern + off);
76 add_entry(res, prefix);
80 DIR * dir = opendir(*prefix ? prefix : "." );
86 while ((ent = readdir(dir)))
89 memcpy(prefix + prefix_len, pattern + off, i - off);
90 prefix[prefix_len + i - off] = '\0';
91 r = yaz_match_glob(prefix + prefix_len, ent->d_name);
92 prefix[prefix_len] = '\0';
96 strcpy(prefix + prefix_len, ent->d_name);
99 glob_r(res, pattern, i, prefix);
103 add_entry(res, prefix);
105 prefix[prefix_len] = '\0';
113 static int cmp_entry(const void *a, const void *b)
115 struct res_entry *ent_a = *(struct res_entry **) a;
116 struct res_entry *ent_b = *(struct res_entry **) b;
117 return strcmp(ent_a->file, ent_b->file);
120 static void sort_them(yaz_glob_res_t res)
123 struct res_entry **ent_p;
124 struct res_entry **ent = nmem_malloc(res->nmem, sizeof(*ent) * res->number_of_entries);
125 struct res_entry *ent_i = res->entries;
126 for (i = 0; i < res->number_of_entries; i++)
131 qsort(ent, res->number_of_entries, sizeof(*ent), cmp_entry);
132 ent_p = &res->entries;
133 for (i = 0; i < res->number_of_entries; i++)
136 ent_p = &ent[i]->next;
141 int yaz_file_glob(const char *pattern, yaz_glob_res_t *res)
143 return yaz_file_glob2(pattern, res, 0);
146 int yaz_file_glob2(const char *pattern, yaz_glob_res_t *res, unsigned flags)
148 char prefix[FILENAME_MAX+1];
149 NMEM nmem = nmem_create();
152 *res = nmem_malloc(nmem, sizeof(**res));
153 (*res)->flags = flags;
154 (*res)->number_of_entries = 0;
157 (*res)->last_entry = &(*res)->entries;
158 glob_r(*res, pattern, 0, prefix);
163 void yaz_file_globfree(yaz_glob_res_t *res)
167 /* must free entries as well */
168 nmem_destroy((*res)->nmem);
173 const char *yaz_file_glob_get_file(yaz_glob_res_t res, size_t idx)
175 struct res_entry *ent = res->entries;
186 size_t yaz_file_glob_get_num(yaz_glob_res_t res)
188 return res->number_of_entries;
194 * c-file-style: "Stroustrup"
195 * indent-tabs-mode: nil
197 * vim: shiftwidth=4 tabstop=8 expandtab