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