1 /* $Id$
2 * Provides functions to file and directory existence check
3 *
4 * HUSKYLIB: common defines, types and functions for HUSKY
5 *
6 * This is part of The HUSKY Fidonet Software project:
7 * see http://husky.sourceforge.net for details
8 *
9 *
10 * HUSKYLIB is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * HUSKYLIB is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; see file COPYING. If not, write to the
22 * Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * See also http://www.gnu.org, license may be found here.
25 */
26
27 /* These are compilers that have both a working stat() and (important!) the
28 S_ISREG and S_ISDIR macros. The problem is that while stat() is POSIX, those
29 macros are not. For compilers that do not provide these macros, we revert to
30 the old "ffind" method. */
31
32 /* standard headers */
33 #include <ctype.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37
38 /* huskylib: compiler.h */
39 #include <compiler.h>
40
41 /* standard headers */
42 #ifdef HAS_UNISTD_H
43 # include <unistd.h>
44 #endif
45
46 #ifdef HAS_DIRECT_H
47 # include <direct.h>
48 #endif
49
50 #ifdef HAS_DOS_H
51 # include <dos.h>
52 #endif
53
54 #ifdef USE_STAT_MACROS
55 /* These are compilers that have both a working stat() and (important!) the
56 S_ISREG and S_ISDIR macros. The problem is that while stat() is POSIX, those
57 macros are not. For compilers that do not provide these macros, we revert to
58 the old "ffind" method. */
59 # include <sys/types.h>
60 # include <sys/stat.h>
61 #endif
62
63 /* huskylib headers */
64 #define DLLEXPORT
65 #include <huskyext.h>
66 #include <fexist.h>
67
68 #ifdef USE_STAT_MACROS
69
70 /* This is the nice code that works on UNIX and every other decent platform.
71 It has been contributed by Alex S. Aganichev */
72
fexist(const char * filename)73 int _fast fexist(const char *filename)
74 {
75 struct stat s;
76
77 if (stat (filename, &s))
78 return FALSE;
79 return S_ISREG(s.st_mode);
80 }
81
fsize(const char * filename)82 long _fast fsize(const char *filename)
83 {
84 struct stat s;
85
86 if (stat (filename, &s))
87 return -1L;
88 return s.st_size;
89 }
90
fmtime(const char * filename)91 time_t _fast fmtime(const char *filename)
92 {
93 struct stat s;
94
95 if (stat (filename, &s))
96 return -1L;
97 return s.st_mtime;
98 }
99
direxist(const char * directory)100 int _fast direxist(const char *directory)
101 {
102 struct stat s;
103 int rc;
104
105 #if !defined(__WATCOMC__) && !defined(__MSVC__) && !defined(__MINGW32__)
106 rc = stat (directory, &s);
107 #else
108 char *tempstr, *p;
109 size_t l;
110 tempstr = strdup(directory);
111 if (tempstr == NULL) {
112 return FALSE;
113 }
114
115 /* Root directory of any drive always exists! */
116
117 if ((isalpha((int)tempstr[0]) && tempstr[1] == ':' && (tempstr[2] == '\\' || tempstr[2] == '/') &&
118 !tempstr[3]) || (strcmp(tempstr, "\\")==0) ) {
119 free(tempstr);
120 return TRUE;
121 }
122
123 l = strlen(tempstr);
124 if (tempstr[l - 1] == '\\' || tempstr[l - 1] == '/')
125 {
126 /* remove trailing backslash */
127 tempstr[l - 1] = '\0';
128 }
129
130 for (p=tempstr; *p; p++)
131 {
132 if (*p == '/')
133 *p='\\';
134 }
135
136 rc = stat (tempstr, &s);
137
138 free(tempstr);
139 #endif
140 if (rc)
141 return FALSE;
142 return S_ISDIR(s.st_mode);
143 }
144
145 #else /* USE_STAT_MACROS not defined */
146
147 /* Here comes the ugly platform specific and sometimes even slow code. */
148
fexist(const char * filename)149 int _fast fexist(const char *filename)
150 {
151 FFIND *ff;
152
153 ff = FFindInfo(filename);
154
155 if (ff)
156 {
157 FFindClose(ff);
158 return TRUE;
159 }
160 else
161 {
162 return FALSE;
163 }
164 }
165
fsize(const char * filename)166 long _fast fsize(const char *filename)
167 {
168 FFIND *ff;
169 FILE *fp;
170 long ret = -1L;
171
172 ff = FFindInfo(filename);
173
174 if (ff)
175 {
176 #ifndef __UNIX__
177 ret = ff->ff_fsize;
178 if (ret == -1L)
179 #endif
180 { fp = fopen(filename, "rb");
181 fseek(fp, 0, SEEK_END);
182 ret = ftell(fp);
183 fclose(fp);
184 }
185 FFindClose(ff);
186 }
187
188 return ret;
189 }
190
fmtime(const char * filename)191 time_t _fast fmtime(const char *filename)
192 {
193 #ifdef __UNIX__
194 return -1L;
195 #else
196 FFIND *ff;
197 FILE *fp;
198 time_t ret = -1L;
199
200 ff = FFindInfo(filename);
201
202 if (ff)
203 {
204 struct tm t;
205 t.tm_sec = ff->ff_ftime & 0x1f;
206 t.tm_min = (ff->ff_ftime >> 5) & 0x3f;
207 t.tm_hour = (ff->ff_ftime >> 11) & 0x1f;
208 t.tm_mday = ff->ff_fdate & 0x1f;
209 t.tm_mon = ((ff->ff_fdate >> 5) & 0x0f) - 1;
210 t.tm_year = ((ff->ff_fdate >> 9) & 0x07f) + 1980 - 1900;
211 t.tm_isdst = -1;
212 FFindClose(ff);
213 return mktime(&t);
214 }
215
216 return ret;
217 #endif
218 }
219
220 #if defined(__DOS__) || defined(__DPMI__)
221
direxist(const char * directory)222 int _fast direxist(const char *directory)
223 {
224 FFIND *ff;
225 char *tempstr;
226 int ret;
227
228 tempstr = (char *)malloc(strlen(directory) + 5);
229 if (tempstr == NULL)
230 {
231 return FALSE;
232 }
233
234 strcpy(tempstr, directory);
235
236 Add_Trailing(tempstr, '\\');
237
238 /* Root directory of any drive always exists! */
239
240 if ((isalpha(tempstr[0]) && tempstr[1] == ':' && ((tempstr[2] == '\0') || ((tempstr[2] == '\\' ||
241 tempstr[2] == '/') && tempstr[3] == '\0'))) || (stricmp(tempstr, "\\")==0) )
242 {
243 ret = TRUE;
244 }
245 else
246 {
247 Strip_Trailing(tempstr, '\\');
248
249 ff = FFindOpen(tempstr, MSDOS_SUBDIR | MSDOS_HIDDEN | MSDOS_READONLY);
250
251 ret = ff != NULL && (ff->ff_attrib & MSDOS_SUBDIR);
252
253 if (ff)
254 {
255 FFindClose(ff);
256 }
257 }
258
259 free(tempstr);
260 return ret;
261
262 }
263
264 #elif defined(__OS2__) || defined(__NT__)
265
266 #ifdef __OS2__
267 #define INCL_DOSFILEMGR
268 #include <os2.h>
269 #else
270 #define WIN32_LEAN_AND_MEAN
271 #define NOGDI
272 #define NOUSER
273 #define NOMSG
274 #include <windows.h>
275 #endif
276
direxist(const char * directory)277 int _fast direxist(const char *directory)
278 {
279 char *tempstr, *p;
280 size_t l;
281 #if defined(__NT__) || defined(__CYGWIN__)
282 DWORD attr;
283 #else
284 FILESTATUS3 s;
285 #endif
286
287
288 tempstr = strdup(directory);
289 if (tempstr == NULL)
290 {
291 return FALSE;
292 }
293
294 /* Root directory of any drive always exists! */
295
296 if ((isalpha((int)tempstr[0]) && tempstr[1] == ':' && (tempstr[2] == '\\' || tempstr[2] == '/') &&
297 !tempstr[3]) || (strcmp(tempstr, "\\")==0) )
298 {
299 free(tempstr);
300 return TRUE;
301 }
302
303 l = strlen(tempstr);
304 if (tempstr[l - 1] == '\\' || tempstr[l - 1] == '/')
305 {
306 /* remove trailing backslash */
307 tempstr[l - 1] = '\0';
308 }
309
310 for (p=tempstr; *p; p++)
311 {
312 if (*p == '/')
313 *p='\\';
314 }
315
316 #ifdef __OS2__
317 if (DosQueryPathInfo((PSZ)tempstr, FIL_STANDARD,
318 (PVOID)&s, sizeof(s)) == 0)
319 {
320 free (tempstr);
321 if (s.attrFile & FILE_DIRECTORY)
322 return TRUE;
323 else
324 return FALSE;
325 }
326 free (tempstr);
327 return FALSE;
328 #else
329 attr = GetFileAttributes(tempstr);
330 free(tempstr);
331 if ((attr != 0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY))
332 return TRUE;
333 else
334 return FALSE;
335 #endif
336 }
337
338 #elif defined(__UNIX__)
339
direxist(const char * directory)340 int _fast direxist(const char *directory)
341 {
342 FILE *fp;
343
344 fp = fopen(directory, "rb");
345 if (fp != NULL)
346 {
347 fclose(fp);
348 return 1;
349 }
350 return 0;
351 }
352
353 #else
354
355 #error Unknown compiler!
356
357 #endif
358
359 #endif
360
_createDirectoryTree(const char * pathName)361 int _createDirectoryTree(const char *pathName) {
362
363 char *start, *slash;
364 char limiter=PATH_DELIM;
365 int i;
366
367 if (!pathName)
368 return 1;
369
370 start = (char *) malloc(strlen(pathName)+2);
371 if (!start)
372 return 1;
373
374 strcpy(start, pathName);
375 i = strlen(start)-1;
376 if (start[i] != limiter) {
377 start[i+1] = limiter;
378 start[i+2] = '\0';
379 }
380 slash = start;
381
382 #ifndef __UNIX__
383 /* if there is a drivename, jump over it */
384 if (slash[1] == ':') slash += 2;
385 #endif
386
387 /* jump over first limiter */
388 slash++;
389
390 while ((slash = strchr(slash, limiter)) != NULL) {
391 *slash = '\0';
392
393 if (!direxist(start)) {
394 if (!fexist(start)) {
395 /* this part of the path does not exist, create it */
396 if (mymkdir(start) != 0) {
397 free(start);
398 return 1;
399 }
400 } else {
401 free(start);
402 return 1;
403 }
404 }
405
406 *slash++ = limiter;
407 }
408
409 free(start);
410
411 return 0;
412 }
413
414
415 #ifdef TEST
416
main(void)417 int main(void)
418 {
419 printf("asdfe=%d\n", direxist("c:\\asdfe"));
420 printf("blank=%d\n", direxist("c:\\blank"));
421 printf("tc=%d\n", direxist("c:\\tc"));
422 printf("c:\\=%d\n", direxist("c:\\"));
423 printf("d:\\=%d\n", direxist("d:\\"));
424 printf("e:\\=%d\n", direxist("e:\\"));
425 printf("f:\\=%d\n", direxist("f:\\"));
426 return 0;
427 }
428
429 #endif
430