OS_NS_dirent.cpp

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

Generated on Tue Feb 2 17:18:41 2010 for ACE by  doxygen 1.4.7