// Scan a directory for .csplugin files void InternalScanPluginDir (iStringArray*& messages, const char* dir, csRef<iStringArray>& plugins, bool recursive) { struct dirent* de; DIR* dh = opendir(dir); if (dh != 0) { while ((de = readdir(dh)) != 0) { if (!isdir(dir, de)) { int const n = strlen(de->d_name); if (n >= 9 && strcasecmp(de->d_name + n - 9, ".csplugin") == 0) { csString scffilepath; scffilepath << dir << CS_PATH_SEPARATOR << de->d_name; plugins->Push (scffilepath); } } else { if (recursive && (strcmp (de->d_name, ".") != 0) && (strcmp (de->d_name, "..") != 0)) { iStringArray* subdirMessages = 0; csString scffilepath; scffilepath << dir << CS_PATH_SEPARATOR << de->d_name; InternalScanPluginDir (subdirMessages, scffilepath, plugins, recursive); if (subdirMessages != 0) { for (size_t i = 0; i < subdirMessages->GetSize(); i++) { AppendStrVecString (messages, subdirMessages->Get (i)); } subdirMessages->DecRef(); } } } } closedir(dh); } }
void InternalScanPluginDir (iStringArray*& messages, const char* dir, csRef<iStringArray>& plugins, bool recursive) { csStringHash files; csStringHash dirs; csString filemask; // The directory sometimes has a trailing path separator attached. if (!strlen(dir) || dir[strlen(dir)-1] == CS_PATH_SEPARATOR) filemask << dir << "*.*"; else filemask << dir << CS_PATH_SEPARATOR << "*.*"; WIN32_FIND_DATA findData; HANDLE hSearch = FindFirstFile (filemask, &findData); if (hSearch != INVALID_HANDLE_VALUE) { do { if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* instead of processing them immediately, first a list of directories is filled. */ if (recursive && (strcmp (findData.cFileName, ".") != 0) && (strcmp (findData.cFileName, "..") != 0)) { // Add file names in lower case, as Win32 doesn't care about FS case. AddLower (dirs, findData.cFileName); } } else { /* instead of processing them immediately, first a list of plugin files is created. */ char* ext = strrchr (findData.cFileName, '.'); if (ext && ((strcasecmp (ext, ".dll") == 0) || (strcasecmp (ext, ".csplugin") == 0))) { AddLower (files, findData.cFileName); } } } while (FindNextFile (hSearch, &findData)); FindClose (hSearch); } else { DWORD errorCode = GetLastError(); /* The plugin paths list also contains non-existent entries - don't emit an error for those. */ if (errorCode != ERROR_PATH_NOT_FOUND) { AppendWin32Error ("FindFirst() call failed", errorCode, messages); } } // Now go over all the files. This way files in a dir will have precedence // over files a subdir. { csStringHash::GlobalIterator fileIt(files.GetIterator()); csString fullPath; csRef<iString> msg; while (fileIt.HasNext()) { csStringID id = fileIt.Next(); const char* fileName = files.Request (id); const char* ext = strrchr (fileName, '.'); // ignore .csplugins, there are checked explicitly. if ((strcasecmp (ext, ".dll") == 0)) { fullPath.Clear(); // The directory sometimes has a trailing path separator attached. if (!strlen(dir) || dir[strlen(dir)-1] == CS_PATH_SEPARATOR) fullPath << dir << fileName; else fullPath << dir << CS_PATH_SEPARATOR << fileName; /* Check whether the DLL has a companion .csplugin. */ char cspluginFile [MAX_PATH + 10]; strcpy (cspluginFile, fileName); char* dot = strrchr (cspluginFile, '.'); strcpy (dot, ".csplugin"); csStringID cspID = files.Request (cspluginFile); if (cspID != csInvalidStringID) { char cspluginPath [MAX_PATH + 10]; strcpy (cspluginPath, fullPath); char* dot = strrchr (cspluginPath, '.'); strcpy (dot, ".csplugin"); plugins->Push (cspluginPath); } else { plugins->Push (fullPath); } } } // release some memory. files.Clear(); } { csStringHash::GlobalIterator dirIt(dirs.GetIterator()); csString fullPath; while (dirIt.HasNext()) { csStringID id = dirIt.Next(); fullPath.Clear(); fullPath << dir << CS_PATH_SEPARATOR << dirs.Request (id); iStringArray* subdirMessages = 0; InternalScanPluginDir (subdirMessages, fullPath, plugins, recursive); if (subdirMessages != 0) { for (size_t i = 0; i < subdirMessages->GetSize (); i++) { AppendStrVecString (messages, subdirMessages->Get (i)); } subdirMessages->DecRef(); } } } }