1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#if 0
#include <sys/types.h>
#include <glob.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <fnmatch.h>
#include <errno.h>
#include <unistd.h>
#include "_assert.h"
int glob(const char * restrict pattern, int flags, int (*errfunc) (const char * epath, int eerrno), glob_t * restrict pglob)
{
ASSERT_NONNULL(pattern);
ASSERT_NONNULL(pglob);
int slashes = 0;
size_t i;
int fnmatch_flags = FNM_PATHNAME | FNM_PERIOD;
if (flags & GLOB_NOESCAPE) {
fnmatch_flags |= FNM_NOESCAPE;
}
if (flags & GLOB_APPEND) {
if (pglob->gl_pathc == 0) {
/* no good */
}
if (pglob->gl_offs > 0 && !(flags & GLOB_DOOFFS)) {
/* nope */
}
} else {
if (pglob->gl_pathc != 0) {
/* also no */
}
}
char *path = malloc(strlen(pattern) + 1);
strcpy(path, pattern);
for (i = 0; path[i]; i++) {
if (path[i] == '/') {
slashes++;
path[i] = '\0';
}
}
if (path[0] == '\0') {
path[0] = '/';
slashes--;
}
/* TODO: check for trailing slash to match only directories */
/* TODO: compress adjacent slashes */
/* TODO: DOOFFS */
do {
const char *p = path + strlen(path) + 1;
struct dirent *de;
DIR *d = opendir(slashes ? path : ".");
if (d == NULL) {
if (errfunc != NULL) {
if (errfunc(path, errno) != 0) {
return GLOB_ABORTED;
}
}
if (flags & GLOB_ERR) {
return GLOB_ABORTED;
}
}
while ((de = readdir(d)) != NULL) {
if (fnmatch(p, de->d_name, fnmatch_flags) == 0) {
pglob->gl_pathc++;
char **tmp = realloc(pglob->gl_pathv, sizeof(char*) * pglob->gl_pathc);
if (tmp == NULL) {
pglob->gl_pathc--;
return GLOB_NOSPACE;
}
pglob->gl_pathv = tmp;
/* FIXME: add path to front */
pglob->gl_pathv[pglob->gl_pathc - 1] = malloc(strlen(de->d_name) + 1);
strcat(pglob->gl_pathv[pglob->gl_pathc - 1], de->d_name);
/* TODO: MARK */
}
}
closedir(d);
path[strlen(path)] = '/';
slashes--;
} while (slashes);
if (pglob->gl_pathc == 0) {
if (flags & GLOB_NOCHECK) {
/* TODO: DOOFFS */
pglob->gl_pathc = 1;
pglob->gl_pathv = malloc(sizeof(char*));
pglob->gl_pathv[0] = malloc(strlen(pattern) + 1);
strcpy(pglob->gl_pathv[0], pattern);
} else {
return GLOB_NOMATCH;
}
}
if (!(flags & GLOB_NOSORT)) {
qsort(pglob->gl_pathv + pglob->gl_offs, pglob->gl_pathc,
sizeof(char*),
(int (*)(const void *, const void *))strcoll);
}
return 0;
}
/*
POSIX(2)
*/
#endif
|