1 /* $Id$
2  *  Provides compiler-independent functions to read directory contents
3  *
4  *  Copyright (C) 1998-1999
5  *
6  *  Matthias Tichy
7  *
8  *  Fido:     2:2433/1245 2:2433/1247 2:2432/605.14
9  *  Internet: mtt@tichy.de
10  *
11  *  Grimmestr. 12         Buchholzer Weg 4
12  *  33098 Paderborn       40472 Duesseldorf
13  *  Germany               Germany
14  *
15  *  Latest version may be foind on http://husky.sourceforge.net
16  *
17  *
18  * HUSKYLIB: common defines, types and functions for HUSKY
19  *
20  * This is part of The HUSKY Fidonet Software project:
21  * see http://husky.sourceforge.net for details
22  *
23  *
24  * HUSKYLIB is free software; you can redistribute it and/or
25  * modify it under the terms of the GNU Lesser General Public
26  * License as published by the Free Software Foundation; either
27  * version 2 of the License, or (at your option) any later version.
28  *
29  * HUSKYLIB is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
32  * General Public License for more details.
33  *
34  * You should have received a copy of the GNU Lesser General Public
35  * License along with this library; see file COPYING. If not, write to the
36  * Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37  *
38  * See also http://www.gnu.org, license may be found here.
39  */
40 
41 /* standard headers */
42 #include <stdlib.h>
43 #include <string.h>
44 #include <errno.h>
45 
46 
47 /* huskylib: compiler.h */
48 #include <compiler.h>
49 
50 
51 /* compiler-dependent headers */
52 #ifdef HAS_IO_H
53 #include <io.h>
54 #endif
55 
56 #ifdef HAS_DIR_H
57 #include <dir.h>
58 #endif
59 
60 #ifdef HAS_DIRENT_H
61 #include <dirent.h>
62 #endif
63 
64 #ifdef HAS_DIRECT_H
65 #include <direct.h>
66 #endif
67 
68 
69 /* huskylib headers */
70 #define DLLEXPORT
71 #include <huskyext.h>
72 
73 /* huskylib headers */
74 #include <dirlayer.h>
75 #include <memory.h>
76 #include <strext.h>
77 #ifndef HAS_DIRENT_H
78 #include <ffind.h>
79 #endif
80 #include <fexist.h>
81 
82 /***  Implementation  *******************************************************/
83 
84 #ifdef HAS_DIRENT_H
85 /* use compiler or system library: opendir/readdir/closedir */
86 
husky_opendir(const char * mask)87 husky_DIR* husky_opendir(const char* mask)
88 { husky_DIR dir;
89 
90   if(!mask) return NULL;
91   memset(&dir,0,sizeof(dir));
92 
93   strncpy( dir.d_mask, mask, sizeof(dir.d_mask)-3 ); /* preserve two chars for "\\*"
94                                                 d_mask filled by zero in previous source line */
95 #if 0
96   {
97     char *ch, *ch2;
98     ch = strrchr(d_mask,'/');
99     ch2 = strrchr(d_mask,'\\');
100     ch = max(ch,ch2);
101     if (ch && ch[1]=='\0') strcat(dir->d_mask,"*");
102                           else strcat(dir->d_mask,"\\*");
103   }
104 #endif
105   dir.internal_DIR = opendir(mask);
106   if(!dir.internal_DIR) return NULL;
107 
108   return memdup(&dir,sizeof(dir));
109 }
110 
husky_readdir(husky_DIR * dir)111 char* husky_readdir(husky_DIR* dir)
112 { struct dirent *de;
113   if(!dir || !dir->internal_DIR) return 0;
114 
115   do{
116     de = readdir(dir->internal_DIR);
117     if(!de || !de->d_name) return NULL;
118   }while( strcmp(de->d_name,".")==0 || strcmp(de->d_name,"..")==0 );
119   strnzcpy(dir->d_name, de->d_name, sizeof(dir->d_name));
120   dir->d_attr = 0;       /* Use stat() for this! */
121   dir->d_size = -1;
122 
123   return dir->d_name;
124 }
125 
husky_closedir(husky_DIR * dir)126 int  husky_closedir(husky_DIR* dir)
127 { int rc;
128 
129   if(!dir || !dir->internal_DIR) return 0;
130 
131   rc = closedir(dir->internal_DIR);
132   if(!rc){
133     free(dir);
134   }
135 
136   return rc;
137 }
138 
husky_rewinddir(husky_DIR * dir)139 void  husky_rewinddir(husky_DIR* dir)
140 {
141   if(!dir || !dir->internal_DIR) return;
142 
143   rewinddir(dir->internal_DIR);
144   dir->d_name[0] = '\0';
145 }
146 
147 #else  /* Use ffind.c */
148 
husky_opendir(const char * mask)149 husky_DIR* husky_opendir(const char* mask)
150 { husky_DIR dir;
151 
152   if(!mask) return NULL;
153 
154   if(!direxist(mask)){
155     errno = ENOENT;
156     return NULL;
157   }
158   memset(&dir,0,sizeof(dir));
159 
160   strncpy( dir.d_mask, mask, sizeof(dir.d_mask)-3 ); /* preserve two chars for "\\*"
161                                                 d_mask filled by zero in previous source line */
162   {
163     char *ch, *ch2;
164     ch = strrchr(dir.d_mask,'/');
165     ch2 = strrchr(dir.d_mask,'\\');
166     ch = max(ch,ch2);
167     if (ch && ch[1]=='\0') strcat(dir.d_mask,"*");
168                           else strcat(dir.d_mask,"\\*");
169   }
170   dir.d_first++;
171   return memdup(&dir,sizeof(dir));
172 }
173 
174 /* Note: FFindInfo/FFindNext skips "." and ".." entries */
husky_readdir(husky_DIR * dir)175 char* husky_readdir(husky_DIR* dir)
176 {
177   if(!dir) return 0;
178 
179   dir->d_name[0] = '\0';
180   dir->d_attr = 0;
181   dir->d_size = 0;
182 
183   if(dir->d_first){
184     dir->ff = FFindInfo(dir->d_mask);
185     if((dir->ff)==NULL) return NULL;
186     dir->d_first=0;
187   }else{
188     if(FFindNext(dir->ff)) return NULL;
189   }
190 
191   strnzcpy(dir->d_name, dir->ff->ff_name, sizeof(dir->d_name));
192   dir->d_attr = dir->ff->ff_attrib;
193   dir->d_size = dir->ff->ff_fsize;
194 
195   return dir->d_name;
196 }
197 
198 
husky_closedir(husky_DIR * dir)199 int  husky_closedir(husky_DIR* dir)
200 {
201   if(!dir) return -1;
202 
203   FFindClose(dir->ff);
204   free(dir);
205 
206   return 0;
207 }
208 
209 
husky_rewinddir(husky_DIR * dir)210 void  husky_rewinddir(husky_DIR* dir)
211 {
212   if(!dir) return;
213 
214   if(dir->ff) FFindClose(dir->ff);
215   dir->ff = NULL;
216   dir->d_first = 1;
217   dir->d_name[0] = '\0';
218   dir->d_attr = 0;
219   dir->d_size = 0;
220 }
221 
222 #endif
223 
224 #ifdef TEST
225 
main(int argc,char ** argv)226 int main(int argc, char **argv){
227   husky_DIR *dd;
228   char *name=".";
229 
230   if(argc>1) name = argv[1];
231 
232   dd=husky_opendir(name);
233   while( (name=husky_readdir(dd)) )
234     printf("%s\n",name);
235 
236   husky_closedir(dd);
237   return 0;
238 }
239 #endif
240