GitHub Actions: Try MSVC builds with /std:c++17 and 20
[ACE_TAO.git] / ACE / ace / OS_NS_dirent.cpp
blob182667c72430ba7a2eb9562117d8290034f6143e
1 #include "ace/OS_NS_dirent.h"
5 #if !defined (ACE_HAS_INLINED_OSCALLS)
6 # include "ace/OS_NS_dirent.inl"
7 #endif /* ACE_HAS_INLINED_OSCALLS */
9 #include "ace/OS_NS_errno.h"
10 #include "ace/OS_NS_string.h"
11 #include "ace/Log_Category.h"
12 #include "ace/OS_NS_stdlib.h"
14 #if defined (ACE_HAS_ALLOC_HOOKS)
15 # include "ace/Malloc_Base.h"
16 #endif /* ACE_HAS_ALLOC_HOOKS */
18 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
20 #if defined (ACE_LACKS_CLOSEDIR)
21 void
22 ACE_OS::closedir_emulation (ACE_DIR *d)
24 #if defined (ACE_WIN32)
25 if (d->current_handle_ != INVALID_HANDLE_VALUE)
27 ::FindClose (d->current_handle_);
28 d->current_handle_ = INVALID_HANDLE_VALUE;
31 d->started_reading_ = 0;
32 if (d->dirent_ != 0)
34 ACE_OS::free (d->dirent_->d_name);
35 ACE_OS::free (d->dirent_);
37 #else /* ACE_WIN32 */
38 ACE_UNUSED_ARG (d);
39 #endif /* ACE_WIN32 */
41 #endif /* ACE_LACKS_CLOSEDIR */
43 #if defined (ACE_LACKS_OPENDIR)
44 ACE_DIR *
45 ACE_OS::opendir_emulation (const ACE_TCHAR *filename)
47 #if defined (ACE_WIN32)
48 # if !defined (INVALID_FILE_ATTRIBUTES)
49 # define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
50 # endif
52 ACE_DIR *dir = 0;
53 ACE_TCHAR extra[3] = {0,0,0};
55 // Check if filename is a directory.
56 DWORD fileAttribute = ACE_TEXT_GetFileAttributes (filename);
57 if (fileAttribute == INVALID_FILE_ATTRIBUTES
58 || !(fileAttribute & FILE_ATTRIBUTE_DIRECTORY))
59 return 0;
62 Note: the semantics of the win32 function FindFirstFile take the
63 basename(filename) as a pattern to be matched within the dirname(filename).
64 This is contrary to the behavior of the posix function readdir which treats
65 basename(filename) as a directory to be opened and read.
67 For this reason, we append a slash-star or backslash-star to the supplied
68 filename so the result is that FindFirstFile will do what we need.
70 According to the documentation for FindFirstFile, either a '/' or a '\' may
71 be used as a directory name separator.
73 Of course, it is necessary to ensure that this is only done if the trailing
74 filespec is not already there.
76 Phil Mesnier
79 size_t const lastchar = ACE_OS::strlen (filename);
80 if (lastchar > 0)
82 if (filename[lastchar-1] != '*')
84 if (filename[lastchar-1] != '/' && filename[lastchar-1] != '\\')
85 ACE_OS::strcpy (extra, ACE_TEXT ("/*"));
86 else
87 ACE_OS::strcpy (extra, ACE_TEXT ("*"));
91 ACE_NEW_RETURN (dir, ACE_DIR, 0);
92 ACE_NEW_RETURN (dir->directory_name_,
93 ACE_TCHAR[lastchar + ACE_OS::strlen (extra) + 1],
94 0);
95 ACE_OS::strcpy (dir->directory_name_, filename);
96 if (extra[0])
97 ACE_OS::strcat (dir->directory_name_, extra);
98 dir->current_handle_ = INVALID_HANDLE_VALUE;
99 dir->started_reading_ = 0;
100 dir->dirent_ = 0;
101 return dir;
102 #else /* WIN32 */
103 ACE_UNUSED_ARG (filename);
104 ACE_NOTSUP_RETURN (0);
105 #endif /* WIN32 */
107 #endif /* ACE_LACKS_CLOSEDIR */
109 #if defined (ACE_LACKS_READDIR)
110 struct ACE_DIRENT *
111 ACE_OS::readdir_emulation (ACE_DIR *d)
113 #if defined (ACE_WIN32)
114 if (d->dirent_ != 0)
116 ACE_OS::free (d->dirent_->d_name);
117 ACE_OS::free (d->dirent_);
118 d->dirent_ = 0;
121 if (!d->started_reading_)
123 d->current_handle_ = ACE_TEXT_FindFirstFile (d->directory_name_,
124 &d->fdata_);
125 d->started_reading_ = 1;
127 else
129 int const retval = ACE_TEXT_FindNextFile (d->current_handle_, &d->fdata_);
130 if (retval == 0)
132 // Make sure to close the handle explicitly to avoid a leak!
133 ::FindClose (d->current_handle_);
134 d->current_handle_ = INVALID_HANDLE_VALUE;
138 if (d->current_handle_ != INVALID_HANDLE_VALUE)
140 d->dirent_ = (ACE_DIRENT *)
141 ACE_OS::malloc (sizeof (ACE_DIRENT));
143 if (d->dirent_ != 0)
145 d->dirent_->d_name = (ACE_TCHAR*)
146 ACE_OS::malloc ((ACE_OS::strlen (d->fdata_.cFileName) + 1)
147 * sizeof (ACE_TCHAR));
148 ACE_OS::strcpy (d->dirent_->d_name, d->fdata_.cFileName);
149 d->dirent_->d_reclen = sizeof (ACE_DIRENT);
152 return d->dirent_;
154 else
155 return 0;
156 #else /* ACE_WIN32 */
157 ACE_UNUSED_ARG (d);
158 ACE_NOTSUP_RETURN (0);
159 #endif /* ACE_WIN32 */
161 #endif /* ACE_LACKS_READDIR */
163 #if !defined (ACE_HAS_SCANDIR)
165 ACE_OS::scandir_emulation (const ACE_TCHAR *dirname,
166 ACE_DIRENT **namelist[],
167 ACE_SCANDIR_SELECTOR selector,
168 ACE_SCANDIR_COMPARATOR comparator)
170 ACE_DIR *dirp = ACE_OS::opendir (dirname);
172 if (dirp == 0)
173 return -1;
174 // A sanity check here. "namelist" had better not be zero.
175 else if (namelist == 0)
176 return -1;
178 ACE_DIRENT **vector = 0;
179 ACE_DIRENT *dp = 0;
180 int arena_size = 0;
181 int nfiles = 0;
182 int fail = 0;
184 // @@ This code shoulduse readdir_r() rather than readdir().
185 for (dp = ACE_OS::readdir (dirp);
186 dp != 0;
187 dp = ACE_OS::readdir (dirp))
189 if (selector && (*selector)(dp) == 0)
190 continue;
192 // If we get here, we have a dirent that the user likes.
193 if (nfiles == arena_size)
195 ACE_DIRENT **newv = 0;
196 int new_arena_size;
197 if (arena_size == 0)
198 new_arena_size = 10;
199 else
200 new_arena_size = arena_size * 2;
202 #if defined (ACE_HAS_ALLOC_HOOKS)
203 newv = (ACE_DIRENT **) ACE_Allocator::instance()->malloc (new_arena_size * sizeof (ACE_DIRENT *));
204 if (newv && vector)
206 ACE_OS::memcpy (newv, vector, arena_size * sizeof (ACE_DIRENT *));
208 #else
209 newv = (ACE_DIRENT **) ACE_OS::realloc (vector,
210 new_arena_size * sizeof (ACE_DIRENT *));
211 #endif /* ACE_HAS_ALLOC_HOOKS */
213 arena_size = new_arena_size;
215 if (newv == 0)
217 fail = 1;
218 break;
220 vector = newv;
223 #if defined (ACE_LACKS_STRUCT_DIR)
224 #if defined (ACE_HAS_ALLOC_HOOKS)
225 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_Allocator::instance()->malloc (sizeof (ACE_DIRENT));
226 #else
227 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_OS::malloc (sizeof (ACE_DIRENT));
228 #endif /* ACE_HAS_ALLOC_HOOKS */
229 #else
230 size_t dsize =
231 sizeof (ACE_DIRENT) +
232 ((ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
233 #if defined (ACE_HAS_ALLOC_HOOKS)
234 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_Allocator::instance()->malloc (dsize);
235 #else
236 ACE_DIRENT *newdp = (ACE_DIRENT *) ACE_OS::malloc (dsize);
237 #endif /* ACE_HAS_ALLOC_HOOKS */
238 #endif /* ACE_LACKS_STRUCT_DIR */
240 if (newdp == 0)
242 fail = 1;
243 break;
246 #if defined (ACE_LACKS_STRUCT_DIR)
247 #if defined (ACE_HAS_ALLOC_HOOKS)
248 newdp->d_name = (ACE_TCHAR*) ACE_Allocator::instance()->malloc ((ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
249 #else
250 newdp->d_name = (ACE_TCHAR*) ACE_OS::malloc ((ACE_OS::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
251 #endif /* ACE_HAS_ALLOC_HOOKS */
253 if (newdp->d_name == 0)
255 fail = 1;
256 #if defined (ACE_HAS_ALLOC_HOOKS)
257 ACE_Allocator::instance()->free (newdp);
258 #else
259 ACE_OS::free (newdp);
260 #endif /* ACE_HAS_ALLOC_HOOKS */
261 break;
264 // Don't use memcpy here since d_name is now a pointer
265 newdp->d_ino = dp->d_ino;
266 newdp->d_off = dp->d_off;
267 newdp->d_reclen = dp->d_reclen;
268 ACE_OS::strcpy (newdp->d_name, dp->d_name);
269 vector[nfiles++] = newdp;
270 #else
271 vector[nfiles++] = (ACE_DIRENT *) ACE_OS::memcpy (newdp, dp, dsize);
272 #endif /* ACE_LACKS_STRUCT_DIR */
275 if (fail)
277 ACE_OS::closedir (dirp);
278 while (vector && nfiles-- > 0)
280 #if defined (ACE_LACKS_STRUCT_DIR)
281 #if defined (ACE_HAS_ALLOC_HOOKS)
282 ACE_Allocator::instance()->free (vector[nfiles]->d_name);
283 #else
284 ACE_OS::free (vector[nfiles]->d_name);
285 #endif /* ACE_HAS_ALLOC_HOOKS */
286 #endif /* ACE_LACKS_STRUCT_DIR */
287 #if defined (ACE_HAS_ALLOC_HOOKS)
288 ACE_Allocator::instance()->free (vector[nfiles]);
289 #else
290 ACE_OS::free (vector[nfiles]);
291 #endif /* ACE_HAS_ALLOC_HOOKS */
293 #if defined (ACE_HAS_ALLOC_HOOKS)
294 ACE_Allocator::instance()->free (vector);
295 #else
296 ACE_OS::free (vector);
297 #endif /* ACE_HAS_ALLOC_HOOKS */
298 return -1;
301 ACE_OS::closedir (dirp);
303 *namelist = vector;
305 if (comparator)
306 ACE_OS::qsort (*namelist,
307 nfiles,
308 sizeof (ACE_DIRENT *),
309 (ACE_COMPARE_FUNC) comparator);
311 return nfiles;
313 #endif /* !ACE_HAS_SCANDIR */
315 ACE_END_VERSIONED_NAMESPACE_DECL