6cbf5e5e3de74f5420426b85e17e054c058d714c
[profile/ivi/navit.git] / navit / navit / support / wordexp / glob.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 /*
21  * @file glob.c
22  */
23
24 #include <config.h>
25
26 #ifndef HAVE_GLOB
27 #if defined _WIN32 || defined _WIN32_WCE
28 #include <windows.h>
29 #include "glob.h"
30
31 /*
32  * @brief searches for all the pathnames matching pattern according to the rules
33  * which is similar to the rules used by common shells.
34  * here: expanding of ´*´ and ´?´ only in filenames
35  * @param pattern: no tilde expansion or parameter substitution is done.
36  * @param flags: not supported here
37  * @param errfunc: not supported here
38  * @param pglob: struct with array containing the matched files/directories
39  * @return FALSE on error.
40  */
41 int glob(const char *pattern, int flags,
42           int (*errfunc)(const char *epath, int eerrno),
43           glob_t *pglob)
44 {
45         char           *pathend,
46                        *filename;
47         int             pathlen;
48         HANDLE          hFiles;
49 #ifndef UNICODE
50         WIN32_FIND_DATA xFindData;
51         hFiles = FindFirstFile (pattern, &xFindData);
52 #else
53         int              len = strlen(pattern) * sizeof(wchar_t*);
54         wchar_t         *pathname = malloc(len);
55         WIN32_FIND_DATAW xFindData;
56         mbstowcs (pathname, pattern, len);
57         hFiles = FindFirstFile (pathname, &xFindData);
58 #endif
59
60         if(hFiles == INVALID_HANDLE_VALUE)
61         {
62                 return 1;
63         }
64         /* store the path information */
65         if (NULL == (pathend = max (strrchr (pattern, '\\'), strrchr (pattern, '/'))))
66                         pathend = (char *) pattern;
67         pathlen = pathend - pattern + 1;
68
69         /* glob */
70         pglob->gl_pathc = 0;    /* number of founded files */
71         pglob->gl_offs = 0;     /* not needed */
72         pglob->gl_pathv = malloc(sizeof(char*));        /* list of file names */
73
74         do
75         {
76                 pglob->gl_pathc++;
77                 pglob->gl_pathv = realloc (pglob->gl_pathv, pglob->gl_pathc * sizeof(char*));
78 #ifndef UNICODE
79                 filename = xFindData.cFileName;
80 #else
81                 len = wcslen(xFindData.cFileName) * sizeof(char*);
82                 filename = malloc (len);
83                 wcstombs (filename, xFindData.cFileName, len);
84 #endif
85                 pglob->gl_pathv[pglob->gl_pathc - 1] = malloc ((pathlen + strlen (filename) + 1) * sizeof(char*));
86                 strncpy (pglob->gl_pathv[pglob->gl_pathc - 1], pattern, pathlen);
87                 // strcpy (pglob->gl_pathv[pglob->gl_pathc - 1] + pathlen - 1, filename);
88                 // The above line should be uncommented later. Currently, the blow line needs to be in use.
89                 // If not, navit on WinCE / Win32 cannot "find" the maps and bookmarks folder
90                 strcpy (pglob->gl_pathv[pglob->gl_pathc - 1] + pathlen, filename);
91         } while (FindNextFile (hFiles, &xFindData));
92
93         FindClose(hFiles);
94         return 0;
95 }
96 #else
97
98 #include <dirent.h>
99 #include <string.h>
100 #include <fnmatch.h>
101 #include "debug.h"
102 #include "glob.h"
103
104 static int
105 glob_requires_match(const char *pattern, int flags)
106 {
107         for (;;) {
108                 switch (*pattern++) {
109                 case '\0':
110                         return 0;
111                 case '?':
112                 case '*':
113                 case '[':
114                         return 1;
115                 case '\\':
116                         if (!*pattern++)
117                                 return 0;
118                 }
119         }
120         return 0;
121 }
122
123 static int
124 glob_recursive(const char *path1, const char *path2, const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob)
125 {
126         const char *next;
127         char *fname,*path=malloc(strlen(path1)+strlen(path2)+2);
128         int flen;
129         strcpy(path, path1);
130         if (path1[0] && path2[0] && (path1[1] != '\0' || path1[0] != '/'))
131                 strcat(path, "/");
132         strcat(path, path2);
133         if (!strlen(pattern)) {
134                 dbg(0,"found %s\n",path);
135                 pglob->gl_pathv=realloc(pglob->gl_pathv, (pglob->gl_pathc+1)*sizeof(char *));
136                 if (!pglob->gl_pathv) {
137                         pglob->gl_pathc=0;
138                         return GLOB_NOSPACE;
139                 }
140                 pglob->gl_pathv[pglob->gl_pathc++]=path;
141                 return 0;
142         }
143         dbg(0,"searching for %s in %s\n",pattern,path);
144         flen=strcspn(pattern,"/");
145         next=pattern+flen;
146         if (*next == '/')
147                 next++;
148         fname=malloc(flen+1);
149         strncpy(fname, pattern, flen);
150         fname[flen]='\0';
151         if (glob_requires_match(fname, 0)) {
152                 DIR *dh;
153                 struct dirent *de;
154                 dbg(0,"in dir %s search for %s\n",path,fname);
155                 dh=opendir(path);
156                 if (dh) {
157                         while ((de=readdir(dh))) {
158                                 if (fnmatch(fname,de->d_name,0) == 0) {
159                                         glob_recursive(path, de->d_name, next, flags, errfunc, pglob);
160                                 }
161                         }
162                         closedir(dh);
163                 }       
164         } else {
165                 glob_recursive(path, fname, next, flags, errfunc, pglob);
166         }
167         free(fname);
168         free(path);
169         return 0;
170 }
171
172 int
173 glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob)
174 {
175         pglob->gl_pathc=0;
176         pglob->gl_pathv=NULL;
177         if (pattern[0] == '/')
178                 return glob_recursive("/", "", pattern+1, flags, errfunc, pglob);
179         else
180                 return glob_recursive("", "", pattern, flags, errfunc, pglob);
181 }
182
183 #endif     /* _WIN32 || _WIN32_WCE */
184
185 void globfree(glob_t *pglob)
186 {
187         int i;
188
189         for (i=0; i < pglob->gl_pathc; i++)
190         {
191                 free (pglob->gl_pathv[i]);
192         }
193         free (pglob->gl_pathv);
194         pglob->gl_pathc = 0;
195 }
196
197 #endif     /* HAVE_GLOB */