Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / OS_NS_dirent.cpp
blob449a0c966941cb0d07ba4094352ae68803ff80c2
1 #include "ace/OS_NS_dirent.h"
4 #if !defined (ACE_HAS_INLINED_OSCALLS)
5 # include "ace/OS_NS_dirent.inl"
6 #endif /* ACE_HAS_INLINED_OSCALLS */
8 #include "ace/OS_NS_errno.h"
9 #include "ace/OS_NS_string.h"
10 #include "ace/Log_Category.h"
11 #include "ace/OS_NS_stdlib.h"
13 #if defined (ACE_HAS_ALLOC_HOOKS)
14 # include "ace/Malloc_Base.h"
15 #endif /* ACE_HAS_ALLOC_HOOKS */
17 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
19 #if defined (ACE_LACKS_CLOSEDIR)
20 void
21 ACE_OS::closedir_emulation (ACE_DIR *d)
23 #if defined (ACE_WIN32)
24 if (d->current_handle_ != INVALID_HANDLE_VALUE)
26 ::FindClose (d->current_handle_);
27 d->current_handle_ = INVALID_HANDLE_VALUE;
30 d->started_reading_ = 0;
31 if (d->dirent_ != 0)
33 ACE_OS::free (d->dirent_->d_name);
34 ACE_OS::free (d->dirent_);
36 #else /* ACE_WIN32 */
37 ACE_UNUSED_ARG (d);
38 #endif /* ACE_WIN32 */
40 #endif /* ACE_LACKS_CLOSEDIR */
42 #if defined (ACE_LACKS_OPENDIR)
43 ACE_DIR *
44 ACE_OS::opendir_emulation (const ACE_TCHAR *filename)
46 #if defined (ACE_WIN32)
47 # if !defined (INVALID_FILE_ATTRIBUTES)
48 # define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
49 # endif
51 ACE_DIR *dir = 0;
52 ACE_TCHAR extra[3] = {0,0,0};
54 // Check if filename is a directory.
55 DWORD fileAttribute = ACE_TEXT_GetFileAttributes (filename);
56 if (fileAttribute == INVALID_FILE_ATTRIBUTES
57 || !(fileAttribute & FILE_ATTRIBUTE_DIRECTORY))
58 return 0;
61 Note: the semantics of the win32 function FindFirstFile take the
62 basename(filename) as a pattern to be matched within the dirname(filename).
63 This is contrary to the behavior of the posix function readdir which treats
64 basename(filename) as a directory to be opened and read.
66 For this reason, we append a slash-star or backslash-star to the supplied
67 filename so the result is that FindFirstFile will do what we need.
69 According to the documentation for FindFirstFile, either a '/' or a '\' may
70 be used as a directory name separator.
72 Of course, it is necessary to ensure that this is only done if the trailing
73 filespec is not already there.
75 Phil Mesnier
78 size_t const lastchar = ACE_OS::strlen (filename);
79 if (lastchar > 0)
81 if (filename[lastchar-1] != '*')
83 if (filename[lastchar-1] != '/' && filename[lastchar-1] != '\\')
84 ACE_OS::strcpy (extra, ACE_TEXT ("/*"));
85 else
86 ACE_OS::strcpy (extra, ACE_TEXT ("*"));
90 ACE_NEW_RETURN (dir, ACE_DIR, 0);
91 ACE_NEW_RETURN (dir->directory_name_,
92 ACE_TCHAR[lastchar + ACE_OS::strlen (extra) + 1],
93 0);
94 ACE_OS::strcpy (dir->directory_name_, filename);
95 if (extra[0])
96 ACE_OS::strcat (dir->directory_name_, extra);
97 dir->current_handle_ = INVALID_HANDLE_VALUE;
98 dir->started_reading_ = 0;
99 dir->dirent_ = 0;
100 return dir;
101 #else /* WIN32 */
102 ACE_UNUSED_ARG (filename);
103 ACE_NOTSUP_RETURN (0);
104 #endif /* WIN32 */
106 #endif /* ACE_LACKS_CLOSEDIR */
108 #if defined (ACE_LACKS_READDIR)
109 struct ACE_DIRENT *
110 ACE_OS::readdir_emulation (ACE_DIR *d)
112 #if defined (ACE_WIN32)
113 if (d->dirent_ != 0)
115 ACE_OS::free (d->dirent_->d_name);
116 ACE_OS::free (d->dirent_);
117 d->dirent_ = 0;
120 if (!d->started_reading_)
122 d->current_handle_ = ACE_TEXT_FindFirstFile (d->directory_name_,
123 &d->fdata_);
124 d->started_reading_ = 1;
126 else
128 int const retval = ACE_TEXT_FindNextFile (d->current_handle_, &d->fdata_);
129 if (retval == 0)
131 // Make sure to close the handle explicitly to avoid a leak!
132 ::FindClose (d->current_handle_);
133 d->current_handle_ = INVALID_HANDLE_VALUE;
137 if (d->current_handle_ != INVALID_HANDLE_VALUE)
139 d->dirent_ = (ACE_DIRENT *)
140 ACE_OS::malloc (sizeof (ACE_DIRENT));
142 if (d->dirent_ != 0)
144 d->dirent_->d_name = (ACE_TCHAR*)
145 ACE_OS::malloc ((ACE_OS::strlen (d->fdata_.cFileName) + 1)
146 * sizeof (ACE_TCHAR));
147 ACE_OS::strcpy (d->dirent_->d_name, d->fdata_.cFileName);
148 d->dirent_->d_reclen = sizeof (ACE_DIRENT);
151 return d->dirent_;
153 else
154 return 0;
155 #else /* ACE_WIN32 */
156 ACE_UNUSED_ARG (d);
157 ACE_NOTSUP_RETURN (0);
158 #endif /* ACE_WIN32 */
160 #endif /* ACE_LACKS_READDIR */
162 #if !defined (ACE_HAS_SCANDIR)
164 ACE_OS::scandir_emulation (const ACE_TCHAR *dirname,
165 ACE_DIRENT **namelist[],
166 ACE_SCANDIR_SELECTOR selector,
167 ACE_SCANDIR_COMPARATOR comparator)
169 ACE_DIR *dirp = ACE_OS::opendir (dirname);
171 if (dirp == 0)
172 return -1;
173 // A sanity check here. "namelist" had better not be zero.
174 else if (namelist == 0)
175 return -1;
177 ACE_DIRENT **vector = 0;
178 ACE_DIRENT *dp = 0;
179 int arena_size = 0;
180 int nfiles = 0;
181 int fail = 0;
183 for (dp = ACE_OS::readdir (dirp);
184 dp != 0;
185 dp = ACE_OS::readdir (dirp))
187 if (selector && (*selector)(dp) == 0)
188 continue;
190 // If we get here, we have a dirent that the user likes.
191 if (nfiles == arena_size)
193 ACE_DIRENT **newv = 0;
194 int new_arena_size;
195 if (arena_size == 0)
196 new_arena_size = 10;
197 else
198 new_arena_size = arena_size * 2;
200 #if defined (ACE_HAS_ALLOC_HOOKS)
201 newv = (ACE_DIRENT **) ACE_Allocator::instance()->malloc (new_arena_size * sizeof (ACE_DIRENT *));
202 if (newv && vector)
204 ACE_OS::memcpy (newv, vector, arena_size * sizeof (ACE_DIRENT *));
206 #else
207 newv = (ACE_DIRENT **) ACE_OS::realloc (vector,
208 new_arena_size * sizeof (ACE_DIRENT *));
209 #endif /* ACE_HAS_ALLOC_HOOKS */
211 arena_size = new_arena_size;
213 if (newv == 0)
215 fail = 1;
216 break;
218 vector = newv;
221 #if defined (ACE_LACKS_STRUCT_DIR)
222 #if defined (ACE_HAS_ALLOC_HOOKS)
223 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_Allocator::instance()->malloc (sizeof (ACE_DIRENT));
224 #else
225 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_OS::malloc (sizeof (ACE_DIRENT));
226 #endif /* ACE_HAS_ALLOC_HOOKS */
227 #else
228 size_t dsize =
229 sizeof (ACE_DIRENT) +
230 ((ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
231 #if defined (ACE_HAS_ALLOC_HOOKS)
232 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_Allocator::instance()->malloc (dsize);
233 #else
234 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_OS::malloc (dsize);
235 #endif /* ACE_HAS_ALLOC_HOOKS */
236 #endif /* ACE_LACKS_STRUCT_DIR */
238 if (newdp == 0)
240 fail = 1;
241 break;
244 #if defined (ACE_LACKS_STRUCT_DIR)
245 #if defined (ACE_HAS_ALLOC_HOOKS)
246 newdp->d_name = (ACE_TCHAR*) ACE_Allocator::instance()->malloc ((ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
247 #else
248 newdp->d_name = (ACE_TCHAR*) ACE_OS::malloc ((ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
249 #endif /* ACE_HAS_ALLOC_HOOKS */
251 if (newdp->d_name == 0)
253 fail = 1;
254 #if defined (ACE_HAS_ALLOC_HOOKS)
255 ACE_Allocator::instance()->free (newdp);
256 #else
257 ACE_OS::free (newdp);
258 #endif /* ACE_HAS_ALLOC_HOOKS */
259 break;
262 // Don't use memcpy here since d_name is now a pointer
263 newdp->d_ino = dp->d_ino;
264 newdp->d_off = dp->d_off;
265 newdp->d_reclen = dp->d_reclen;
266 ACE_OS::strcpy (newdp->d_name, dp->d_name);
267 vector[nfiles++] = newdp;
268 #else
269 vector[nfiles++] = (ACE_DIRENT *) ACE_OS::memcpy (newdp, dp, dsize);
270 #endif /* ACE_LACKS_STRUCT_DIR */
273 if (fail)
275 ACE_OS::closedir (dirp);
276 while (vector && nfiles-- > 0)
278 #if defined (ACE_LACKS_STRUCT_DIR)
279 #if defined (ACE_HAS_ALLOC_HOOKS)
280 ACE_Allocator::instance()->free (vector[nfiles]->d_name);
281 #else
282 ACE_OS::free (vector[nfiles]->d_name);
283 #endif /* ACE_HAS_ALLOC_HOOKS */
284 #endif /* ACE_LACKS_STRUCT_DIR */
285 #if defined (ACE_HAS_ALLOC_HOOKS)
286 ACE_Allocator::instance()->free (vector[nfiles]);
287 #else
288 ACE_OS::free (vector[nfiles]);
289 #endif /* ACE_HAS_ALLOC_HOOKS */
291 #if defined (ACE_HAS_ALLOC_HOOKS)
292 ACE_Allocator::instance()->free (vector);
293 #else
294 ACE_OS::free (vector);
295 #endif /* ACE_HAS_ALLOC_HOOKS */
296 return -1;
299 ACE_OS::closedir (dirp);
301 *namelist = vector;
303 if (comparator)
304 ACE_OS::qsort (*namelist,
305 nfiles,
306 sizeof (ACE_DIRENT *),
307 (ACE_COMPARE_FUNC) comparator);
309 return nfiles;
311 #endif /* !ACE_HAS_SCANDIR */
313 ACE_END_VERSIONED_NAMESPACE_DECL