Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

OS_Dirent.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: OS_Dirent.cpp,v 1.1.1.3.2.1 2003/03/13 19:44:21 chad Exp $
00003 
00004 #include "ace/OS_Dirent.h"
00005 #include "ace/OS_String.h"
00006 #include "ace/OS_Memory.h"
00007 #include "ace/Log_Msg.h"
00008 #include "ace/OS.h"
00009 
00010 ACE_RCSID(ace, OS_Dirent, "$Id: OS_Dirent.cpp,v 1.1.1.3.2.1 2003/03/13 19:44:21 chad Exp $")
00011 
00012 #if !defined (ACE_HAS_INLINED_OSCALLS)
00013 # include "ace/OS_Dirent.inl"
00014 #endif /* ACE_HAS_INLINED_OS_CALLS */
00015 
00016 ACE_DIR *
00017 ACE_OS_Dirent::opendir_emulation (const ACE_TCHAR *filename)
00018 {
00019 #if defined (ACE_WIN32)
00020   ACE_DIR *dir;
00021   ACE_TCHAR extra[3] = {0,0,0};
00022 
00023 /*
00024   Note: the semantics of the win32 function FindFirstFile take the
00025   basename(filename) as a pattern to be matched within the dirname(filename).
00026   This is contrary to the behavior of the posix function readdir which treats
00027   basename(filename) as a directory to be opened and read.
00028 
00029   For this reason, we append a slash-star or backslash-star to the supplied
00030   filename so the result is that FindFirstFile will do what we need.
00031 
00032   According to the documentation for FindFirstFile, either a '/' or a '\' may
00033   be used as a directory name separator.
00034 
00035   Of course, it is necessary to ensure that this is only done if the trailing
00036   filespec is not already there.
00037 
00038   Phil Mesnier
00039 */
00040 
00041   size_t lastchar = ACE_OS_String::strlen (filename);
00042   if (lastchar > 0)
00043     {
00044       if (filename[lastchar-1] != '*')
00045         {
00046           if (filename[lastchar-1] != '/' && filename[lastchar-1] != '\\')
00047             ACE_OS_String::strcpy (extra, ACE_LIB_TEXT ("/*"));
00048           else
00049             ACE_OS_String::strcpy (extra, ACE_LIB_TEXT ("*"));
00050         }
00051     }
00052 
00053   ACE_NEW_RETURN (dir, ACE_DIR, 0);
00054   ACE_NEW_RETURN (dir->directory_name_,
00055                   ACE_TCHAR[lastchar + ACE_OS_String::strlen (extra) + 1],
00056                   0);
00057   ACE_OS_String::strcpy (dir->directory_name_, filename);
00058   if (extra[0])
00059     ACE_OS_String::strcat (dir->directory_name_, extra);
00060   dir->current_handle_ = INVALID_HANDLE_VALUE;
00061   dir->started_reading_ = 0;
00062   dir->dirent_ = 0;
00063   return dir;
00064 #else /* ACE_WIN32 */
00065   ACE_UNUSED_ARG (filename);
00066   ACE_NOTSUP_RETURN (0);
00067 #endif /* ACE_WIN32 */
00068 }
00069 
00070 void
00071 ACE_OS_Dirent::closedir_emulation (ACE_DIR *d)
00072 {
00073 #if defined (ACE_WIN32)
00074   if (d->current_handle_ != INVALID_HANDLE_VALUE)
00075     ::FindClose (d->current_handle_);
00076 
00077   d->current_handle_ = INVALID_HANDLE_VALUE;
00078   d->started_reading_ = 0;
00079   if (d->dirent_ != 0)
00080     {
00081       ACE_OS_Memory::free (d->dirent_->d_name);
00082       ACE_OS_Memory::free (d->dirent_);
00083     }
00084 #else /* ACE_WIN32 */
00085   ACE_UNUSED_ARG (d);
00086 #endif /* ACE_WIN32 */
00087 }
00088 
00089 dirent *
00090 ACE_OS_Dirent::readdir_emulation (ACE_DIR *d)
00091 {
00092 #if defined (ACE_WIN32)
00093   if (d->dirent_ != 0)
00094     {
00095       ACE_OS_Memory::free (d->dirent_->d_name);
00096       ACE_OS_Memory::free (d->dirent_);
00097       d->dirent_ = 0;
00098     }
00099 
00100   if (!d->started_reading_)
00101     {
00102       d->current_handle_ = ACE_TEXT_FindFirstFile (d->directory_name_,
00103                                                    &d->fdata_);
00104       d->started_reading_ = 1;
00105     }
00106   else
00107     {
00108       int retval = ACE_TEXT_FindNextFile (d->current_handle_,
00109                                           &d->fdata_);
00110       if (retval == 0)
00111         {
00112           // Make sure to close the handle explicitly to avoid a leak!
00113           ::FindClose (d->current_handle_);
00114           d->current_handle_ = INVALID_HANDLE_VALUE;
00115         }
00116     }
00117 
00118   if (d->current_handle_ != INVALID_HANDLE_VALUE)
00119     {
00120       d->dirent_ = (dirent *)
00121         ACE_OS_Memory::malloc (sizeof (dirent));
00122 
00123       if (d->dirent_ != 0)
00124         {
00125           d->dirent_->d_name = (ACE_TCHAR*)
00126             ACE_OS_Memory::malloc ((ACE_OS_String::strlen (d->fdata_.cFileName) + 1)
00127                                    * sizeof (ACE_TCHAR));
00128           ACE_OS_String::strcpy (d->dirent_->d_name, d->fdata_.cFileName);
00129           d->dirent_->d_reclen = sizeof (dirent);
00130         }
00131 
00132       return d->dirent_;
00133     }
00134   else
00135     return 0;
00136 #else /* ACE_WIN32 */
00137   ACE_UNUSED_ARG (d);
00138   ACE_NOTSUP_RETURN (0);
00139 #endif /* ACE_WIN32 */
00140 }
00141 
00142 extern "C"
00143 {
00144   typedef int (*ACE_SCANDIR_COMPARATOR) (const void *, const void *);
00145 }
00146 
00147 int
00148 ACE_OS_Dirent::scandir_emulation (const ACE_TCHAR *dirname,
00149                                   dirent **namelist[],
00150                                   int (*selector) (const dirent *entry),
00151                                   int (*comparator) (const dirent **f1,
00152                                                      const dirent **f2))
00153 {
00154   ACE_DIR *dirp = ACE_OS_Dirent::opendir (dirname);
00155 
00156   if (dirp == 0)
00157     return -1;
00158   // A sanity check here.  "namelist" had better not be zero.
00159   else if (namelist == 0)
00160     return -1;
00161 
00162   dirent **vector = 0;
00163   dirent *dp;
00164   int arena_size = 0;
00165 
00166   int nfiles = 0;
00167   int fail = 0;
00168 
00169   // @@ This code shoulduse readdir_r() rather than readdir().
00170   for (dp = ACE_OS_Dirent::readdir (dirp);
00171        dp != 0;
00172        dp = ACE_OS_Dirent::readdir (dirp))
00173     {
00174       if (selector && (*selector)(dp) == 0)
00175         continue;
00176 
00177       // If we get here, we have a dirent that the user likes.
00178       if (nfiles == arena_size)
00179         {
00180           dirent **newv;
00181           if (arena_size == 0)
00182             arena_size = 10;
00183           else
00184             arena_size *= 2;
00185 
00186           newv = (dirent **) ACE_OS_Memory::realloc (vector,
00187                                                      arena_size * sizeof (dirent *));
00188           if (newv == 0)
00189             {
00190               fail = 1;
00191               break;
00192             }
00193           vector = newv;
00194         }
00195 
00196 #if defined (ACE_LACKS_STRUCT_DIR)
00197       dirent *newdp = (dirent *) ACE_OS_Memory::malloc (sizeof (dirent));
00198 #else
00199       int dsize =
00200         sizeof (dirent) +
00201         ((ACE_OS_String::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
00202       dirent *newdp = (dirent *) ACE_OS_Memory::malloc (dsize);
00203 #endif /* ACE_LACKS_STRUCT_DIR */
00204 
00205       if (newdp == 0)
00206         {
00207           fail = 1;
00208           break;
00209         }
00210 
00211 #if defined (ACE_LACKS_STRUCT_DIR)
00212       newdp->d_name = (ACE_TCHAR*) ACE_OS_Memory::malloc (
00213         (ACE_OS_String::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR));
00214 
00215       if (newdp->d_name == 0)
00216         {
00217           fail = 1;
00218           ACE_OS_Memory::free (newdp);
00219           break;
00220         }
00221 
00222       // Don't use memcpy here since d_name is now a pointer
00223       newdp->d_ino = dp->d_ino;
00224       newdp->d_off = dp->d_off;
00225       newdp->d_reclen = dp->d_reclen;
00226       ACE_OS_String::strcpy (newdp->d_name, dp->d_name);
00227       vector[nfiles++] = newdp;
00228 #else
00229       vector[nfiles++] = (dirent *) ACE_OS_String::memcpy (newdp, dp, dsize);
00230 #endif /* ACE_LACKS_STRUCT_DIR */
00231     }
00232 
00233   if (fail)
00234     {
00235       ACE_OS_Dirent::closedir (dirp);
00236       while (nfiles-- > 0)
00237         {
00238 #if defined (ACE_LACKS_STRUCT_DIR)
00239           ACE_OS_Memory::free (vector[nfiles]->d_name);
00240 #endif /* ACE_LACKS_STRUCT_DIR */
00241           ACE_OS_Memory::free (vector[nfiles]);
00242         }
00243       ACE_OS_Memory::free (vector);
00244       return -1;
00245     }
00246 
00247   ACE_OS_Dirent::closedir (dirp);
00248 
00249   *namelist = vector;
00250 
00251   if (comparator)
00252     ACE_OS::qsort (*namelist,
00253                    nfiles,
00254                    sizeof (dirent *),
00255                    (ACE_SCANDIR_COMPARATOR) comparator);
00256 
00257   return nfiles;
00258 }

Generated on Mon Jun 16 11:20:44 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002