YAZ 5.35.1
file_glob.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
5
9#if HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <stdio.h>
16#include <string.h>
17#include <stdlib.h>
18#include <assert.h>
19#include <yaz/wrbuf.h>
20#include <yaz/tpath.h>
21#include <yaz/log.h>
22#include <yaz/dirent.h>
23#include <yaz/nmem.h>
24#include <yaz/file_glob.h>
25#include <yaz/match_glob.h>
26
27struct res_entry {
28 struct res_entry *next;
29 char *file;
30};
31
32struct glob_res {
34 unsigned flags;
38};
39
40static void add_entry(yaz_glob_res_t res, const char *str)
41{
42 struct res_entry *ent =
43 nmem_malloc(res->nmem, sizeof(*ent));
44 ent->file = nmem_strdup(res->nmem, str);
45 ent->next = 0;
46 *res->last_entry = ent;
47 res->last_entry = &ent->next;
48 res->number_of_entries++;
49}
50
51static void glob_r(yaz_glob_res_t res, const char *pattern, size_t off,
52 char *prefix)
53{
54 size_t prefix_len = strlen(prefix);
55 int is_pattern = 0;
56 size_t i = off;
57 while (pattern[i] && !strchr("/\\", pattern[i]))
58 {
59 if (strchr("?*", pattern[i]))
60 is_pattern = 1;
61 i++;
62 }
63
64 if (!is_pattern && pattern[i]) /* no pattern and directory part */
65 {
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';
71 }
72 else if ((res->flags & YAZ_FILE_GLOB_FAIL_NOTEXIST) &&
73 !is_pattern && !pattern[i])
74 {
75 strcpy(prefix + prefix_len, pattern + off);
76 add_entry(res, prefix);
77 }
78 else
79 {
80 DIR * dir = opendir(*prefix ? prefix : "." );
81
82 if (dir)
83 {
84 struct dirent *ent;
85
86 while ((ent = readdir(dir)))
87 {
88 int r;
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';
93
94 if (r)
95 {
96 strcpy(prefix + prefix_len, ent->d_name);
97 if (pattern[i])
98 {
99 glob_r(res, pattern, i, prefix);
100 }
101 else
102 {
103 add_entry(res, prefix);
104 }
105 prefix[prefix_len] = '\0';
106 }
107 }
108 closedir(dir);
109 }
110 }
111}
112
113static int cmp_entry(const void *a, const void *b)
114{
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);
118}
119
120static void sort_them(yaz_glob_res_t res)
121{
122 size_t i;
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++)
127 {
128 ent[i] = ent_i;
129 ent_i = ent_i->next;
130 }
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++)
134 {
135 *ent_p = ent[i];
136 ent_p = &ent[i]->next;
137 }
138 *ent_p = 0;
139}
140
141int yaz_file_glob(const char *pattern, yaz_glob_res_t *res)
142{
143 return yaz_file_glob2(pattern, res, 0);
144}
145
146int yaz_file_glob2(const char *pattern, yaz_glob_res_t *res, unsigned flags)
147{
148 char prefix[FILENAME_MAX+1];
149 NMEM nmem = nmem_create();
150
151 *prefix = '\0';
152 *res = nmem_malloc(nmem, sizeof(**res));
153 (*res)->flags = flags;
154 (*res)->number_of_entries = 0;
155 (*res)->nmem = nmem;
156 (*res)->entries = 0;
157 (*res)->last_entry = &(*res)->entries;
158 glob_r(*res, pattern, 0, prefix);
159 sort_them(*res);
160 return 0;
161}
162
164{
165 if (*res)
166 {
167 /* must free entries as well */
168 nmem_destroy((*res)->nmem);
169 *res = 0;
170 }
171}
172
173const char *yaz_file_glob_get_file(yaz_glob_res_t res, size_t idx)
174{
175 struct res_entry *ent = res->entries;
176 while (idx && ent)
177 {
178 ent = ent->next;
179 idx--;
180 }
181 if (!ent)
182 return 0;
183 return ent->file;
184}
185
187{
188 return res->number_of_entries;
189}
190
191/*
192 * Local variables:
193 * c-basic-offset: 4
194 * c-file-style: "Stroustrup"
195 * indent-tabs-mode: nil
196 * End:
197 * vim: shiftwidth=4 tabstop=8 expandtab
198 */
199
wrapper for dirent.h or our own for Windows
static void add_entry(yaz_glob_res_t res, const char *str)
Definition file_glob.c:40
int yaz_file_glob(const char *pattern, yaz_glob_res_t *res)
perform glob
Definition file_glob.c:141
static int cmp_entry(const void *a, const void *b)
Definition file_glob.c:113
static void glob_r(yaz_glob_res_t res, const char *pattern, size_t off, char *prefix)
Definition file_glob.c:51
const char * yaz_file_glob_get_file(yaz_glob_res_t res, size_t idx)
return resulting matching file
Definition file_glob.c:173
size_t yaz_file_glob_get_num(yaz_glob_res_t res)
return number of matching files
Definition file_glob.c:186
void yaz_file_globfree(yaz_glob_res_t *res)
release glob result
Definition file_glob.c:163
static void sort_them(yaz_glob_res_t res)
Definition file_glob.c:120
int yaz_file_glob2(const char *pattern, yaz_glob_res_t *res, unsigned flags)
perform glob (with flags)
Definition file_glob.c:146
File globbing (ala POSIX glob, but simpler)
#define YAZ_FILE_GLOB_FAIL_NOTEXIST
Definition file_glob.h:43
Logging utility.
int yaz_match_glob(const char *glob, const char *text)
matches a glob expression against text
Definition match_glob.c:22
Glob expression matcher.
NMEM nmem_create(void)
returns new NMEM handle
Definition nmem.c:181
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
Definition nmem.c:145
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
Definition nmem.c:204
Header for Nibble Memory functions.
char * nmem_strdup(NMEM mem, const char *src)
allocates string on NMEM handle (similar strdup)
Definition nmemsdup.c:18
NMEM nmem
Definition file_glob.c:33
unsigned flags
Definition file_glob.c:34
struct res_entry * entries
Definition file_glob.c:37
size_t number_of_entries
Definition file_glob.c:35
struct res_entry ** last_entry
Definition file_glob.c:36
Definition file_glob.c:27
char * file
Definition file_glob.c:29
struct res_entry * next
Definition file_glob.c:28
File Path utilities.
Header for WRBUF (growing buffer)