diff --git a/src/OSspecific/MSwindows/Allwmake b/src/OSspecific/MSwindows/Allwmake new file mode 100755 index 0000000000..24fb418826 --- /dev/null +++ b/src/OSspecific/MSwindows/Allwmake @@ -0,0 +1,12 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +targetType=libo # Preferred library type +. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments $* + +#------------------------------------------------------------------------------ +unset COMP_FLAGS LINK_FLAGS + +# Make object (non-shared by default) +wmake $targetType + +#------------------------------------------------------------------------------ diff --git a/src/OSspecific/MSwindows/MSwindows.C b/src/OSspecific/MSwindows/MSwindows.C new file mode 100644 index 0000000000..30fb55792f --- /dev/null +++ b/src/OSspecific/MSwindows/MSwindows.C @@ -0,0 +1,1288 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2017 OpenFOAM Foundation + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "OSspecific.H" +#include "MSwindows.H" +#include "fileName.H" +#include "fileStat.H" +#include "DynamicList.H" +#include "CStringList.H" +#include "IOstreams.H" +#include "Pstream.H" +#undef DebugInfo // Windows name clash with OpenFOAM messageStream + +#include +#include +#include +#include + +// Windows headers +#define WIN32_LEAN_AND_MEAN +#include +#include // For _close +#include + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(MSwindows, 0); +} + + +namespace Foam +{ + // Don't abort under windows, causes abort dialog to popup. + // Instead just exit with exitCode. + static void sigAbortHandler(int exitCode) + { + ::exit(exitCode); + } + + static bool installAbortHandler() + { + // If it didn't succeed there's not much we can do, + // so don't check result. + ::signal(SIGABRT, &sigAbortHandler); + return true; + } + + static bool const abortHandlerInstalled = installAbortHandler(); + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace MSwindows +{ + +//- A simple directory contents iterator +class directoryIterator +{ + HANDLE handle_; + + bool exists_; + + bool hidden_; + + std::string item_; + + //- Accept file/dir name + inline bool accept() const + { + return + ( + item_.size() && item_ != "." && item_ != ".." + && (hidden_ || item_[0] != '.') + ); + } + + +public: + + //- Construct for dirName, optionally allowing hidden files/dirs + directoryIterator(const fileName& dirName, bool allowHidden = false) + : + handle_(INVALID_HANDLE_VALUE), + exists_(false), + hidden_(allowHidden), + item_() + { + if (!dirName.empty()) + { + WIN32_FIND_DATA findData; + + handle_ = ::FindFirstFile((dirName/"*").c_str(), &findData); + + if (good()) + { + exists_ = true; + item_ = findData.cFileName; + + // If first element is not acceptable, get another one + if (!accept()) + { + next(); + } + } + } + } + + + //- Destructor + ~directoryIterator() + { + close(); + } + + + // Member Functions + + //- Directory existed for opening + bool exists() const + { + return exists_; + } + + //- Directory pointer is valid + bool good() const + { + return (INVALID_HANDLE_VALUE != handle_); + } + + //- Close directory + void close() + { + if (good()) + { + ::FindClose(handle_); + handle_ = INVALID_HANDLE_VALUE; + } + } + + //- The current item + const std::string& val() const + { + return item_; + } + + //- Read next item, always ignoring "." and ".." entries. + // Normally also ignore hidden files/dirs (beginning with '.') + // Automatically close when it runs out of items + bool next() + { + if (good()) + { + WIN32_FIND_DATA findData; + + while (::FindNextFile(handle_, &findData)) + { + item_ = findData.cFileName; + + if (accept()) + { + return true; + } + } + close(); // No more items + } + + return false; + } + + + // Member Operators + + //- Same as good() + operator bool() const + { + return good(); + } + + //- Same as val() + const std::string& operator*() const + { + return val(); + } + + //- Same as next() + directoryIterator& operator++() + { + next(); + return *this; + } +}; + +} // End namespace MSwindows +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +std::string Foam::MSwindows::lastError() +{ + // Retrieve the system error message for the last-error code + + // Based on an example at: + // http://msdn2.microsoft.com/en-us/library/ms680582(VS.85).aspx + + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage + ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, // source + dw, // message-id + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // language-id + reinterpret_cast(&lpMsgBuf), + 0, NULL + ); + + const char* fmt = "Error %d: %s"; + + // Use snprintf with zero to establish the size (without '\0') required + std::string output; + + int n = ::snprintf(nullptr, 0, fmt, static_cast(lpMsgBuf)); + + if (n > 0) + { + output.resize(n+1); + + // Print directly into buffer + n = ::snprintf(&(output[0]), n+1, fmt, static_cast(lpMsgBuf)); + output.resize(n); + } + + LocalFree(lpMsgBuf); + + return output; +} + + +std::string Foam::MSwindows::userName() +{ + const DWORD bufLen = 256; + TCHAR buf[bufLen]; + DWORD len = bufLen; + + if (::GetUserName(buf, &len)) + { + return buf; + } + + std::string str; + + if + ( + ERROR_INSUFFICIENT_BUFFER == ::GetLastError() + && len < 2048 + ) + { + // The len is with trailing '\0' + str.resize(len); + + // Retrieve directly into buffer + ::GetUserName(&(str[0]), &len); + + // Without trailing '\0' + str.resize(len-1); + } + + return str; +} + + +pid_t Foam::pid() +{ + const DWORD processId = ::GetCurrentProcessId(); + return processId; +} + + +pid_t Foam::ppid() +{ + // No equivalent under windows. + + if (MSwindows::debug) + { + Info<< "ppid not supported under MSwindows" << endl; + } + + return 0; +} + + +pid_t Foam::pgid() +{ + // No equivalent under windows. + + if (MSwindows::debug) + { + Info<< "pgid not supported under MSwindows" << endl; + } + + return 0; +} + + +bool Foam::env(const std::string& envName) +{ + // An empty envName => always false + return !envName.empty() && + ::GetEnvironmentVariable(envName.c_str(), nullptr, 0); +} + + +Foam::string Foam::getEnv(const std::string& envName) +{ + std::string env; + + const auto len = ::GetEnvironmentVariable(envName.c_str(), nullptr, 0); + + if (len) + { + env.resize(len+1); + ::GetEnvironmentVariable(envName.c_str(), &(env[0]), len+1); + + env.resize(len); + return fileName::validate(env); + } + + return env; +} + + +bool Foam::setEnv +( + const word& envName, + const std::string& value, + const bool overwrite +) +{ + // Ignore an empty envName => always false + return + ( + !envName.empty() + && ::SetEnvironmentVariable(envName.c_str(), value.c_str()) + ); +} + + +Foam::string Foam::hostName(bool) +{ + const DWORD bufLen = MAX_COMPUTERNAME_LENGTH + 1; + TCHAR buf[bufLen]; + DWORD len = bufLen; + + return ::GetComputerName(buf, &len) ? buf : string(); +} + + +Foam::string Foam::domainName() +{ + // Could use ::gethostname and ::gethostbyname like POSIX.C, but would + // then need to link against ws_32. Prefer to minimize dependencies. + + return string::null; +} + + +Foam::string Foam::userName() +{ + string name = Foam::getEnv("USERNAME"); + + if (name.empty()) + { + name = MSwindows::userName(); + } + + return name; +} + + +bool Foam::isAdministrator() +{ + // Assume worst case + return true; +} + + +Foam::fileName Foam::home() +{ + fileName env = Foam::getEnv("HOME"); + + if (env.empty()) + { + env = Foam::getEnv("USERPROFILE"); + } + + return env; +} + + +Foam::fileName Foam::home(const std::string& userName) +{ + return Foam::home(); +} + + +Foam::fileName Foam::cwd() +{ + string path; + const DWORD len = ::GetCurrentDirectory(0, nullptr); + + if (len) + { + path.resize(len+1); + + ::GetCurrentDirectory(len+1, &(path[0])); + + path.resize(len); + + return fileName::validate(path); + } + + FatalErrorInFunction + << "Couldn't get the current working directory" + << exit(FatalError); + + return fileName(); +} + + +Foam::fileName Foam::cwd(bool logical) +{ + return Foam::cwd(); +} + + +bool Foam::chDir(const fileName& dir) +{ + // Ignore an empty dir name => always false + return !dir.empty() && ::SetCurrentDirectory(dir.c_str());; +} + + +bool Foam::mkDir(const fileName& pathName, const mode_t mode) +{ + // empty names are meaningless + if (pathName.empty()) + { + return false; + } + + bool ok = ::CreateDirectory(pathName.c_str(), NULL); + + if (ok) + { + Foam::chMod(pathName, mode); + return true; + } + + const DWORD error = ::GetLastError(); + switch (error) + { + case ERROR_ALREADY_EXISTS: + { + ok = true; + break; + } + + case ERROR_PATH_NOT_FOUND: + { + // Part of the path does not exist so try to create it + const fileName& parentName = pathName.path(); + + if (parentName.size() && mkDir(parentName, mode)) + { + ok = mkDir(pathName, mode); + } + break; + } + } + + if (!ok) + { + FatalErrorInFunction + << "Couldn't create directory: " << pathName + << " " << MSwindows::lastError() + << exit(FatalError); + } + + return ok; +} + + +bool Foam::chMod(const fileName& name, const mode_t m) +{ + // Ignore an empty name => always false + return !name.empty() && _chmod(name.c_str(), m) == 0; +} + + +mode_t Foam::mode(const fileName& name, const bool followLink) +{ + // Ignore an empty name => always 0 + if (!name.empty()) + { + fileStat fileStatus(name, followLink); + if (fileStatus.valid()) + { + return fileStatus.status().st_mode; + } + } + + return 0; +} + + +// Windows equivalent to S_ISDIR +#define ms_isdir(a) \ + ((m != INVALID_FILE_ATTRIBUTES) && (m & FILE_ATTRIBUTE_DIRECTORY)) + +// Windows equivalent to S_ISREG +#define ms_isreg(s) \ + ((m != INVALID_FILE_ATTRIBUTES) && !(m & FILE_ATTRIBUTE_DIRECTORY)) + + +Foam::fileName::Type Foam::type +( + const fileName& name, + const bool /* followLink */ +) +{ + // Ignore an empty name => always UNDEFINED + if (name.empty()) + { + return fileName::UNDEFINED; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + if (ms_isreg(m)) + { + return fileName::FILE; + } + else if (ms_isdir(m)) + { + return fileName::DIRECTORY; + } + + return fileName::UNDEFINED; +} + + +// Local check for gz file +static bool isGzFile(const std::string& name) +{ + const DWORD m = ::GetFileAttributes((name + ".gz").c_str()); + return ms_isreg(m); +} + + +bool Foam::exists +( + const fileName& name, + const bool checkGzip, + const bool followLink +) +{ + // Ignore an empty name => always false + if (name.empty()) + { + return false; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + return (ms_isdir(m) || ms_isreg(m) || (checkGzip && isGzFile(name))); +} + + +bool Foam::isDir(const fileName& name, const bool followLink) +{ + // Ignore an empty name => always false + if (name.empty()) + { + return false; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + return ms_isdir(m); +} + + +bool Foam::isFile +( + const fileName& name, + const bool checkGzip, + const bool followLink +) +{ + // Ignore an empty name => always false + if (name.empty()) + { + return false; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + return (ms_isreg(m) || (!ms_isdir(m) && checkGzip && isGzFile(name))); +} + + +off_t Foam::fileSize(const fileName& name, const bool followLink) +{ + // Ignore an empty name + if (!name.empty()) + { + fileStat fileStatus(name, followLink); + if (fileStatus.valid()) + { + return fileStatus.status().st_size; + } + } + + return -1; +} + + +time_t Foam::lastModified(const fileName& name, const bool followLink) +{ + // Ignore an empty name + return name.empty() ? 0 : fileStat(name, followLink).modTime(); +} + + +double Foam::highResLastModified(const fileName& name, const bool followLink) +{ + // Ignore an empty name + return name.empty() ? 0 : fileStat(name, followLink).dmodTime(); +} + + +Foam::fileNameList Foam::readDir +( + const fileName& directory, + const fileName::Type type, + const bool filtergz, + const bool followLink +) +{ + // Initial filename list size + // also used as increment if initial size found to be insufficient + static constexpr int maxNnames = 100; + + // Basic sanity: cannot strip '.gz' from directory names + const bool stripgz = filtergz && (type != fileName::DIRECTORY); + const word extgz("gz"); + + fileNameList dirEntries; + + // Iterate contents (ignores an empty directory name) + + MSwindows::directoryIterator dirIter(directory); + + if (!dirIter.exists()) + { + if (MSwindows::debug) + { + InfoInFunction + << "cannot open directory " << directory << endl; + } + + return dirEntries; + } + + if (MSwindows::debug) + { + InfoInFunction + << " : reading directory " << directory << endl; + } + + label nFailed = 0; // Entries with invalid characters + label nEntries = 0; // Number of selected entries + dirEntries.resize(maxNnames); + + // Process all the directory entries + for (/*nil*/; dirIter; ++dirIter) + { + const std::string& item = *dirIter; + + // Validate filename without quotes, etc in the name. + // No duplicate slashes to strip - dirent will not have them anyhow. + + const fileName name(fileName::validate(item)); + if (name != item) + { + ++nFailed; + } + else if + ( + (type == fileName::DIRECTORY) + || (type == fileName::FILE && !fileName::isBackup(name)) + ) + { + if ((directory/name).type() == type) + { + if (nEntries >= dirEntries.size()) + { + dirEntries.resize(dirEntries.size() + maxNnames); + } + + if (stripgz && name.hasExt(extgz)) + { + dirEntries[nEntries++] = name.lessExt(); + } + else + { + dirEntries[nEntries++] = name; + } + } + } + } + + // Finalize the length of the entries list + dirEntries.resize(nEntries); + + if (nFailed && MSwindows::debug) + { + std::cerr + << "Foam::readDir() : reading directory " << directory << nl + << nFailed << " entries with invalid characters in their name" + << std::endl; + } + + return dirEntries; +} + + +bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink) +{ + // Make sure source exists - this also handles an empty source name + if (!exists(src)) + { + return false; + } + + fileName destFile(dest); + + const fileName::Type srcType = src.type(followLink); + + // Check type of source file. + if (srcType == fileName::FILE) + { + // If dest is a directory, create the destination file name. + if (destFile.type() == fileName::DIRECTORY) + { + destFile = destFile/src.name(); + } + + // Make sure the destination directory exists. + if (!isDir(destFile.path()) && !mkDir(destFile.path())) + { + return false; + } + + // Open and check streams. + // - use binary mode to avoid any issues + std::ifstream srcStream(src, ios_base::in | ios_base::binary); + if (!srcStream) + { + return false; + } + + // - use binary mode to avoid any issues + std::ofstream destStream(destFile, ios_base::out | ios_base::binary); + if (!destStream) + { + return false; + } + + // Copy character data. + char ch; + while (srcStream.get(ch)) + { + destStream.put(ch); + } + + // Final check. + if (!srcStream.eof() || !destStream) + { + return false; + } + } + else if (srcType == fileName::DIRECTORY) + { + // If dest is a directory, create the destination file name. + if (destFile.type() == fileName::DIRECTORY) + { + destFile /= src.components().last(); + } + + // Make sure the destination directory extists. + if (!isDir(destFile) && !mkDir(destFile)) + { + return false; + } + + // Copy files + fileNameList files = readDir(src, fileName::FILE, false, followLink); + for (const fileName& item : files) + { + if (MSwindows::debug) + { + Info<< "Copying : " << src/item + << " to " << destFile/item << endl; + } + + // File to file. + Foam::cp(src/item, destFile/item); + } + + // Copy sub directories. + fileNameList dirs = readDir + ( + src, + fileName::DIRECTORY, + false, + followLink + ); + + for (const fileName& item : dirs) + { + if (MSwindows::debug) + { + Info<< "Copying : " << src/item + << " to " << destFile << endl; + } + + // Dir to Dir. + Foam::cp(src/item, destFile); + } + } + else + { + return false; + } + + return true; +} + + +bool Foam::ln(const fileName& src, const fileName& dst) +{ + // links are poorly supported, or need adminstrator privileges. + // Skip for now. + + if (MSwindows::debug) + { + Info<< "MSwindows does not support ln - softlinking" << endl; + } + + return false; +} + + +bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink) +{ + if (MSwindows::debug) + { + Info<< "Move : " << src << " to " << dst << endl; + } + + // Ignore an empty names => always false + if (src.empty() || dst.empty()) + { + return false; + } + + + if + ( + dst.type() == fileName::DIRECTORY + && src.type(followLink) != fileName::DIRECTORY + ) + { + const fileName dstName(dst/src.name()); + + return 0 == std::rename(src.c_str(), dstName.c_str()); + } + + return 0 == std::rename(src.c_str(), dst.c_str()); +} + + +bool Foam::mvBak(const fileName& src, const std::string& ext) +{ + // Ignore an empty name or extension => always false + if (src.empty() || ext.empty()) + { + return false; + } + + if (exists(src, false)) + { + const int maxIndex = 99; + char index[3]; + + for (int n = 0; n <= maxIndex; n++) + { + fileName dstName(src + "." + ext); + if (n) + { + sprintf(index, "%02d", n); + dstName += index; + } + + // avoid overwriting existing files, except for the last + // possible index where we have no choice + if (!exists(dstName, false) || n == maxIndex) + { + return (0 == std::rename(src.c_str(), dstName.c_str())); + } + } + } + + // fall-through: nothing to do + return false; +} + + +bool Foam::rm(const fileName& file) +{ + if (MSwindows::debug) + { + Info<< "Removing : " << file << endl; + } + + // Ignore an empty name => always false + if (file.empty()) + { + return false; + } + + + // If removal of plain file name failed, try with .gz + + return + ( + 0 == std::remove(file.c_str()) + || 0 == std::remove((file + ".gz").c_str()) + ); +} + + +bool Foam::rmDir(const fileName& directory, const bool silent) +{ + // Iterate contents (ignores an empty directory name) + // Also retain hidden files/dirs for removal + + MSwindows::directoryIterator dirIter(directory, true); + + if (!dirIter.exists()) + { + if (!silent) + { + WarningInFunction + << "cannot open directory " << directory << endl; + } + } + + if (MSwindows::debug) + { + InfoInFunction + << " : removing directory " << directory << endl; + } + + + // Process each directory entry, counting any errors encountered + label nErrors = 0; + + for (/*nil*/; dirIter; ++dirIter) + { + const std::string& item = *dirIter; + + // Allow invalid characters (spaces, quotes, etc), + // otherwise we cannot remove subdirs with these types of names. + // -> const fileName path = directory/name; <- + + const fileName path(fileName::concat(directory, item)); + + if (path.type(false) == fileName::DIRECTORY) + { + if (!rmDir(path, true)) // Only report errors at the top-level + { + ++nErrors; + } + } + else + { + if (!rm(path)) + { + ++nErrors; + } + } + } + + if (nErrors) + { + if (!silent) + { + WarningInFunction + << "failed to remove directory " << directory << nl + << "could not remove " << nErrors << " sub-entries" << endl; + } + } + else + { + if (!::RemoveDirectory(directory.c_str())) + { + ++nErrors; + if (!silent) + { + WarningInFunction + << "failed to remove directory " << directory << endl; + } + } + } + + return !nErrors; +} + + +unsigned int Foam::sleep(const unsigned int sec) +{ + ::Sleep(1000*sec); // in milliseconds + + return 0; +} + + +void Foam::fdClose(const int fd) +{ + if (::_close(fd) != 0) + { + FatalErrorInFunction + << "close error on " << fd << endl + << abort(FatalError); + } +} + + +bool Foam::ping +( + const std::string& destName, + const label destPort, + const label timeOut +) +{ + // Appears that socket calls require adminstrator privileges. + // Skip for now. + + if (MSwindows::debug) + { + Info<< "MSwindows does not support ping" << endl; + } + + return false; +} + + +bool Foam::ping(const std::string& host, const label timeOut) +{ + return ping(host, 222, timeOut) || ping(host, 22, timeOut); +} + + +int Foam::system(const std::string& command, const bool bg) +{ + if (MSwindows::debug && bg) + { + InfoInFunction + << "MSwindows does not support background (fork) tasks" << endl; + } + + return std::system(command.c_str()); +} + + +int Foam::system(const CStringList& command, const bool bg) +{ + if (command.empty()) + { + // Treat an empty command as a successful no-op. + // For consistency with POSIX (man sh) behaviour for (sh -c command), + // which is what is mostly being replicated here. + return 0; + } + + const int count = command.size(); + + std::string cmd; + + for (int i = 0; i < count; ++i) + { + if (i) cmd += ' '; + cmd += command[i]; + } + + return system(cmd, bg); +} + + +int Foam::system(const UList& command, const bool bg) +{ + if (command.empty()) + { + // Treat an empty command as a successful no-op. + return 0; + } + + const int count = command.size(); + + std::string cmd; + + for (int i = 0; i < count; ++i) + { + if (i) cmd += ' '; + cmd += command[i]; + } + + return system(cmd, bg); +} + + +// Explicitly track loaded libraries, rather than use +// EnumerateLoadedModules64 and have to link against +// Dbghelp.dll +// Details at http://msdn.microsoft.com/en-us/library/ms679316(v=vs.85).aspx + +static std::unordered_map libsLoaded; + + +void* Foam::dlOpen(const fileName& libName, const bool check) +{ + if (MSwindows::debug) + { + std::cout + << "dlOpen(const fileName&)" + << " : dlopen of " << libName << std::endl; + } + + // Map "libXX.so" and "libXX" to "libXX.dll" + + fileName winLibName(libName.lessExt().ext("dll")); + void* handle = ::LoadLibrary(winLibName.c_str()); + + if (handle) + { + libsLoaded[handle] = libName.lessExt(); + } + else if (check) + { + WarningInFunction + << "dlopen error : " << MSwindows::lastError() + << endl; + } + + if (MSwindows::debug) + { + std::cout + << "dlOpen(const fileName&)" + << " : dlopen of " << libName + << " handle " << handle << std::endl; + } + + return handle; +} + + +bool Foam::dlClose(void* const handle) +{ + if (MSwindows::debug) + { + std::cout + << "dlClose(void*)" + << " : dlclose of handle " << handle << std::endl; + } + + const bool ok = ::FreeLibrary(static_cast(handle)); + + if (ok) + { + libsLoaded.erase(handle); + } + + return ok; +} + + +void* Foam::dlSymFind(void* handle, const std::string& symbol, bool required) +{ + if (!required && (!handle || symbol.empty())) + { + return nullptr; + } + + if (MSwindows::debug) + { + std::cout + << "dlSymFind(void*, const std::string&, bool)" + << " : dlsym of " << symbol << std::endl; + } + + // Get address of symbol, or nullptr on failure + void* fun = + reinterpret_cast + ( + ::GetProcAddress(static_cast(handle), symbol.c_str()) + ); + + // Any error? + if (!fun && required) + { + WarningInFunction + << "Cannot lookup symbol " << symbol << " : " + << MSwindows::lastError() << endl; + } + + return fun; +} + + +Foam::fileNameList Foam::dlLoaded() +{ + DynamicList libs(libsLoaded.size()); + + for (const auto& item : libsLoaded) + { + libs.append(item.second); + } + + if (MSwindows::debug) + { + std::cout + << "dlLoaded()" + << " : determined loaded libraries :" << libs.size() << std::endl; + } + + return libs; +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/MSwindows.H b/src/OSspecific/MSwindows/MSwindows.H new file mode 100644 index 0000000000..e0f7c317b2 --- /dev/null +++ b/src/OSspecific/MSwindows/MSwindows.H @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Namespace + Foam::MSwindows + +Description + OS-specific functions implemented for MS-windows. + +SourceFiles + MSwindows.C + +\*---------------------------------------------------------------------------*/ + +#ifndef MSwindows_H +#define MSwindows_H + +#include "className.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace MSwindows +{ + //- Declare namespace and its debug switch + NamespaceName("MSwindows"); + + //- The last Windows API error from GetLastError + std::string lastError(); + + //- The user-name from Windows API GetUserName + std::string userName(); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/Make/files b/src/OSspecific/MSwindows/Make/files new file mode 100644 index 0000000000..964f34106e --- /dev/null +++ b/src/OSspecific/MSwindows/Make/files @@ -0,0 +1,21 @@ +MSwindows.C + +cpuInfo/cpuInfo.C +memInfo/memInfo.C + +signals/sigFpe.C +signals/sigInt.C +signals/sigQuit.C +signals/sigSegv.C +signals/sigStopAtWriteNow.C +signals/sigWriteNow.C +signals/timer.C + +fileStat/fileStat.C + +/* Without inotify */ +fileMonitor/fileMonitor.C + +printStack/dummyPrintStack.C + +LIB = $(FOAM_LIBBIN)/libOSspecific diff --git a/src/OSspecific/MSwindows/Make/options b/src/OSspecific/MSwindows/Make/options new file mode 100644 index 0000000000..3f86d412a6 --- /dev/null +++ b/src/OSspecific/MSwindows/Make/options @@ -0,0 +1 @@ +EXE_INC = $(COMP_FLAGS) diff --git a/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C new file mode 100644 index 0000000000..d20330b78e --- /dev/null +++ b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "cpuInfo.H" +#include "IOstreams.H" + +#include + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::cpuInfo::cpuInfo() +: + vendor_id(), + model_name(), + cpu_family(-1), + model(-1), + cpu_MHz(0), + siblings(0), + cpu_cores(std::thread::hardware_concurrency()) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::cpuInfo::write(Ostream& os) const +{ + if (!vendor_id.empty()) + { + os.writeEntry("vendor_id", vendor_id); + } + if (!model_name.empty()) + { + os.writeEntry("model_name", model_name); + } + + os.writeEntryIfDifferent("cpu_family", -1, cpu_family); + os.writeEntryIfDifferent("model", -1, model); + os.writeEntryIfDifferent("cpu_MHz", 0, cpu_MHz); + os.writeEntryIfDifferent("cpu_cores", 0, cpu_cores); + os.writeEntryIfDifferent("siblings", 0, siblings); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H new file mode 100644 index 0000000000..1dbba0b6ee --- /dev/null +++ b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::cpuInfo + +Description + General CPU characteristics. + + If the machine has multiple cpus/cores, only the characteristics + of the first core are used. + +Note + Windows variant only provides the number of cores. + +SourceFiles + cpuInfo.C + +\*---------------------------------------------------------------------------*/ + +#ifndef cpuInfo_H +#define cpuInfo_H + +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declarations +class Ostream; + +/*---------------------------------------------------------------------------*\ + Class cpuInfo Declaration +\*---------------------------------------------------------------------------*/ + +class cpuInfo +{ + // Private data + + // Various bits from /proc/cpuinfo + + std::string vendor_id; + std::string model_name; + int cpu_family; + int model; + float cpu_MHz; + int siblings; + int cpu_cores; + + + // Private Member Functions + + //- Parse /proc/cpuinfo + void parse(); + + //- No copy construct + cpuInfo(const cpuInfo&) = delete; + + //- No copy assignment + void operator=(const cpuInfo&) = delete; + +public: + + // Constructors + + //- Construct and populate with information + cpuInfo(); + + //- Destructor + ~cpuInfo() = default; + + + // Member Functions + + //- Write content as dictionary entries + void write(Ostream& os) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/cpuTime/cpuTime.H b/src/OSspecific/MSwindows/cpuTime/cpuTime.H new file mode 100644 index 0000000000..3af1aa192e --- /dev/null +++ b/src/OSspecific/MSwindows/cpuTime/cpuTime.H @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Typedef + Foam::cpuTime + +Description + Selection of preferred clock mechanism for the elapsed cpu time. + +\*---------------------------------------------------------------------------*/ + +#ifndef cpuTime_H +#define cpuTime_H + +#include "cpuTimeCxx.H" +#include "cpuTimeFwd.H" + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H b/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H new file mode 100644 index 0000000000..bc7d1885f3 --- /dev/null +++ b/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Typedef + Foam::cpuTime + +Description + Selection of preferred clock mechanism for the elapsed cpu time. + +\*---------------------------------------------------------------------------*/ + +#ifndef cpuTimeFwd_H +#define cpuTimeFwd_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + class cpuTimeCxx; + + typedef cpuTimeCxx cpuTime; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C new file mode 100644 index 0000000000..425a0c333d --- /dev/null +++ b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C @@ -0,0 +1,625 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2011, 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "fileMonitor.H" +#include "IOstreams.H" +#include "Pstream.H" +#include "PackedList.H" +#include "PstreamReduceOps.H" +#include "OSspecific.H" +#include "regIOobject.H" // for fileModificationSkew symbol + +#ifdef _WIN32 +#undef FOAM_USE_INOTIFY +#endif + +#ifdef FOAM_USE_INOTIFY + #include + #include + #include + #include + #define EVENT_SIZE ( sizeof (struct inotify_event) ) + #define EVENT_LEN (EVENT_SIZE + 16) + #define EVENT_BUF_LEN ( 1024 * EVENT_LEN ) +#endif + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::Enum +< + Foam::fileMonitor::fileState +> +Foam::fileMonitor::fileStateNames_ +({ + { fileState::UNMODIFIED, "unmodified" }, + { fileState::MODIFIED, "modified" }, + { fileState::DELETED, "deleted" }, +}); + + +namespace Foam +{ + defineTypeNameAndDebug(fileMonitor, 0); + + //- Reduction operator for PackedList of fileState + class reduceFileStates + { + public: + unsigned int operator()(const unsigned int x, const unsigned int y) + const + { + // x,y are sets of 2bits representing fileState + + unsigned int mask = 3u; + unsigned int shift = 0; + unsigned int result = 0; + + while (mask) + { + // Combine state + unsigned int xState = (x & mask) >> shift; + unsigned int yState = (y & mask) >> shift; + + // Combine and add to result. Combine is such that UNMODIFIED + // wins. + unsigned int state = min(xState, yState); + result |= (state << shift); + + shift += 2; + mask <<= 2; + } + return result; + } + }; + + //- Combine operator for PackedList of fileState + class combineReduceFileStates + { + public: + void operator()(unsigned int& x, const unsigned int y) const + { + x = reduceFileStates()(x, y); + } + }; + + + + //- Internal tracking via stat(3p) or inotify(7) + class fileMonitorWatcher + { + public: + + const bool useInotify_; + + // For inotify + + //- File descriptor for the inotify instance + int inotifyFd_; + + //- Current watchIDs and corresponding directory id + DynamicList