diff --git a/src/core/model/system-path.cc b/src/core/model/system-path.cc index d24bcc7de..5ebff339e 100644 --- a/src/core/model/system-path.cc +++ b/src/core/model/system-path.cc @@ -19,29 +19,18 @@ */ #include "system-path.h" #include "fatal-error.h" -#include "assert.h" #include "log.h" -#include "ns3/core-config.h" +#include "assert.h" #include -#include // getenv -#include -#include // strlen +#include // getenv +#include // strlen +#include #include - -#if defined (HAVE_DIRENT_H) && defined (HAVE_SYS_TYPES_H) -/** Do we have an \c opendir function? */ -#define HAVE_OPENDIR -#include -#include -#endif -#if defined (HAVE_SYS_STAT_H) && defined (HAVE_SYS_TYPES_H) -/** Do we have a \c makedir function? */ -#define HAVE_MKDIR_H -#include -#include -#endif #include +#include +#include + #ifdef __APPLE__ #include #endif /* __APPLE__ */ @@ -55,11 +44,17 @@ #include #endif +#ifdef __WIN32__ +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + /** * \def SYSTEM_PATH_SEP * System-specific path separator used between directory names. */ -#if defined (__win32__) +#if defined(__WIN32__) #define SYSTEM_PATH_SEP "\\" #else #define SYSTEM_PATH_SEP "/" @@ -84,43 +79,22 @@ namespace { * \param [in] path A path which identifies a directory * \return Tuple with a list of the filenames which are located in the input directory or error flag \c true if directory doesn't exist. */ -std::tuple, bool> ReadFilesNoThrow (std::string path) +std::tuple, bool> +ReadFilesNoThrow (std::string path) { NS_LOG_FUNCTION (path); std::list files; - -#if defined HAVE_OPENDIR - DIR *dp = opendir (path.c_str ()); - if (dp == NULL) + if (!std::filesystem::exists (path)) { return std::make_tuple (files, true); } - struct dirent *de = readdir (dp); - while (de != 0) + for (auto &it : std::filesystem::directory_iterator (path)) { - files.push_back (de->d_name); - de = readdir (dp); + if (!it.is_directory ()) + { + files.push_back (it.path ().filename ().string ()); + } } - closedir (dp); -#elif defined (HAVE_FIND_FIRST_FILE) - /** \todo untested */ - HANDLE hFind; - WIN32_FIND_DATA fileData; - - hFind = FindFirstFile (path.c_str (), &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) - { - return std::make_tuple (files, true); - } - do - { - files.push_back (fileData.cFileName); - } - while (FindNextFile (hFind, &fileData)); - FindClose (hFind); -#else -#error "No support for reading a directory on this platform" -#endif return std::make_tuple (files, false); } @@ -138,7 +112,8 @@ namespace SystemPath { * \param [in] path The full path to a file. * \returns The full path to the containing directory. */ -std::string Dirname (std::string path) +std::string +Dirname (std::string path) { NS_LOG_FUNCTION (path); std::list elements = Split (path); @@ -147,7 +122,8 @@ std::string Dirname (std::string path) return Join (elements.begin (), last); } -std::string FindSelfDirectory (void) +std::string +FindSelfDirectory (void) { /** * This function returns the path to the running $PREFIX. @@ -163,7 +139,7 @@ std::string FindSelfDirectory (void) #if defined(__linux__) { ssize_t size = 1024; - char *buffer = (char*)malloc (size); + char *buffer = (char *) malloc (size); memset (buffer, 0, size); int status; while (true) @@ -175,7 +151,7 @@ std::string FindSelfDirectory (void) } size *= 2; free (buffer); - buffer = (char*)malloc (size); + buffer = (char *) malloc (size); memset (buffer, 0, size); } if (status == -1) @@ -185,26 +161,24 @@ std::string FindSelfDirectory (void) filename = buffer; free (buffer); } -#elif defined (__win32__) +#elif defined(__WIN32__) { - /** \todo untested. it should work if code is compiled with - * LPTSTR = char * - */ + // LPTSTR = char * DWORD size = 1024; - LPTSTR lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size); - DWORD status = GetModuleFilename (0, lpFilename, size); + LPTSTR lpFilename = (LPTSTR) malloc (sizeof (TCHAR) * size); + DWORD status = GetModuleFileName (0, lpFilename, size); while (status == size) { size = size * 2; free (lpFilename); - lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size); - status = GetModuleFilename (0, lpFilename, size); + lpFilename = (LPTSTR) malloc (sizeof (TCHAR) * size); + status = GetModuleFileName (0, lpFilename, size); } NS_ASSERT (status != 0); filename = lpFilename; free (lpFilename); } -#elif defined (__APPLE__) +#elif defined(__APPLE__) { uint32_t bufsize = 1024; char *buffer = (char *) malloc (bufsize); @@ -220,11 +194,11 @@ std::string FindSelfDirectory (void) filename = buffer; free (buffer); } -#elif defined (__FreeBSD__) +#elif defined(__FreeBSD__) { - int mib[4]; - std::size_t bufSize = 1024; - char *buf = (char *) malloc (bufSize); + int mib[4]; + std::size_t bufSize = 1024; + char *buf = (char *) malloc (bufSize); mib[0] = CTL_KERN; mib[1] = KERN_PROC; @@ -238,7 +212,8 @@ std::string FindSelfDirectory (void) return Dirname (filename); } -std::string Append (std::string left, std::string right) +std::string +Append (std::string left, std::string right) { // removing trailing separators from 'left' NS_LOG_FUNCTION (left << right); @@ -255,7 +230,8 @@ std::string Append (std::string left, std::string right) return retval; } -std::list Split (std::string path) +std::list +Split (std::string path) { NS_LOG_FUNCTION (path); std::list retval; @@ -273,8 +249,9 @@ std::list Split (std::string path) return retval; } -std::string Join (std::list::const_iterator begin, - std::list::const_iterator end) +std::string +Join (std::list::const_iterator begin, + std::list::const_iterator end) { NS_LOG_FUNCTION (*begin << *end); std::string retval = ""; @@ -297,7 +274,8 @@ std::string Join (std::list::const_iterator begin, return retval; } -std::list ReadFiles (std::string path) +std::list +ReadFiles (std::string path) { NS_LOG_FUNCTION (path); bool err; @@ -362,30 +340,15 @@ MakeDirectories (std::string path) { NS_LOG_FUNCTION (path); - // Make sure all directories on the path exist - std::list elements = Split (path); - auto i = elements.begin (); - while (i != elements.end ()) + std::error_code ec; + if (!std::filesystem::exists (path)) { - if (*i == "") - { - NS_LOG_LOGIC ("skipping empty directory name"); - ++i; - continue; - } - NS_LOG_LOGIC ("creating directory " << *i); - ++i; // Now points to one past the directory we want to create - std::string tmp = Join (elements.begin (), i); - bool makeDirErr = false; + std::filesystem::create_directories (path, ec); + } -#if defined(HAVE_MKDIR_H) - makeDirErr = mkdir (tmp.c_str (), S_IRWXU); -#endif - - if (makeDirErr) - { - NS_LOG_ERROR ("failed creating directory " << tmp); - } + if (ec.value ()) + { + NS_FATAL_ERROR ("failed creating directory " << path); } } @@ -432,8 +395,21 @@ Exists (const std::string path) NS_LOG_LOGIC ("file itself exists: " << file); return true; -} // Exists() +} // Exists() +std::string +CreateValidSystemPath (const std::string path) +{ + // Windows and its file systems, e.g. NTFS and (ex)FAT(12|16|32), + // do not like paths with empty spaces or special symbols. + // Some of these symbols are allowed in test names, checked in TestCase::AddTestCase. + // We replace them with underlines to ensure they work on Windows. + std::regex incompatible_characters (" |:[^\\\\]|<|>|\\*"); + std::string valid_path; + std::regex_replace (std::back_inserter (valid_path), path.begin(), + path.end(), incompatible_characters, "_"); + return valid_path; +} // CreateValidSystemPath } // namespace SystemPath diff --git a/src/core/model/system-path.h b/src/core/model/system-path.h index e065adbb4..2476e1b31 100644 --- a/src/core/model/system-path.h +++ b/src/core/model/system-path.h @@ -51,6 +51,9 @@ namespace SystemPath { * \ingroup systempath * Get the file system path to the current executable. * + * This path is only equivalent to the current working directory when + * the executable is executed in its parent directory. + * * \return The directory in which the currently-executing binary is located */ std::string FindSelfDirectory (void); @@ -147,6 +150,16 @@ void MakeDirectories (std::string path); */ bool Exists (const std::string path); +/** + * \ingroup systempath + * Replace incompatible characters in a path, + * to get a path compatible with different + * file systems. + * \param [in] path The path to check. + * \returns A compatible path. + */ +std::string CreateValidSystemPath (const std::string path); + } // namespace SystemPath diff --git a/src/core/model/test.cc b/src/core/model/test.cc index ef058e2c2..677a659ea 100644 --- a/src/core/model/test.cc +++ b/src/core/model/test.cc @@ -444,6 +444,8 @@ TestCase::CreateTempDirFilename (std::string filename) current = current->m_parent; } std::string tempDir = SystemPath::Append (m_runner->GetTempDir (), SystemPath::Join (names.begin (), names.end ())); + tempDir = SystemPath::CreateValidSystemPath (tempDir); + SystemPath::MakeDirectories (tempDir); return SystemPath::Append (tempDir, filename); }