MSwindows.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2011 Symscape
10 Copyright (C) 2016-2022 OpenCFD Ltd.
11-------------------------------------------------------------------------------
12License
13 This file is part of OpenFOAM.
14
15 OpenFOAM is free software: you can redistribute it and/or modify it
16 under the terms of the GNU General Public License as published by
17 the Free Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
19
20 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27
28Description
29 MS-Windows versions of the functions declared in OSspecific.H
30
31\*---------------------------------------------------------------------------*/
32
33#include "OSspecific.H"
34#include "MSwindows.H"
35#include "fileName.H"
36#include "fileStat.H"
37#include "DynamicList.H"
38#include "CStringList.H"
39#include "IOstreams.H"
40#include "Pstream.H"
41#undef DebugInfo // Windows name clash with OpenFOAM messageStream
42
43#include <cassert>
44#include <cstdlib>
45#include <fstream>
46#include <unordered_map>
47
48// Windows headers
49#define WIN32_LEAN_AND_MEAN
50#include <csignal>
51#include <io.h> // For _close
52#include <windows.h>
53
54#define EXT_SO "dll"
55
56
57// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
58
59namespace Foam
60{
62}
63
64
65namespace Foam
66{
67 // Don't abort under windows, causes abort dialog to popup.
68 // Instead just exit with exitCode.
69 static void sigAbortHandler(int exitCode)
70 {
71 ::exit(exitCode);
72 }
73
74 static bool installAbortHandler()
75 {
76 // If it didn't succeed there's not much we can do,
77 // so don't check result.
78 ::signal(SIGABRT, &sigAbortHandler);
79 return true;
80 }
81
83
84
85 // Move file, overwriting existing
86 static bool renameFile(const std::string& src, const std::string& dst)
87 {
88 constexpr const int flags
89 (
90 MOVEFILE_COPY_ALLOWED
91 | MOVEFILE_REPLACE_EXISTING
92 | MOVEFILE_WRITE_THROUGH
93 );
94
95 // TODO: handle extra-long paths with ::MoveFileExW
96
97 return ::MoveFileExA(src.c_str(), dst.c_str(), flags);
98 }
99
100} // End namespace Foam
101
102
103// * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * //
104
105namespace Foam
106{
107namespace MSwindows
108{
109
110//- A simple directory contents iterator
112{
113 HANDLE handle_;
114
115 bool exists_;
116
117 bool hidden_;
118
119 std::string item_;
120
121 //- Accept file/dir name
122 inline bool accept() const
123 {
124 return
125 (
126 item_.size() && item_ != "." && item_ != ".."
127 && (hidden_ || item_[0] != '.')
128 );
129 }
130
131
132public:
133
134 //- Construct for dirName, optionally allowing hidden files/dirs
135 directoryIterator(const std::string& dirName, bool allowHidden = false)
136 :
137 handle_(INVALID_HANDLE_VALUE),
138 exists_(false),
139 hidden_(allowHidden),
140 item_()
141 {
142 if (!dirName.empty())
143 {
144 WIN32_FIND_DATA findData;
145
146 handle_ = ::FindFirstFile((dirName/"*").c_str(), &findData);
147
148 if (good())
149 {
150 exists_ = true;
151 item_ = findData.cFileName;
152
153 // If first element is not acceptable, get another one
154 if (!accept())
155 {
156 next();
157 }
158 }
159 }
160 }
161
162
163 //- Destructor
165 {
166 close();
167 }
168
169
170 // Member Functions
171
172 //- Directory existed for opening
173 bool exists() const noexcept
174 {
175 return exists_;
176 }
177
178 //- Directory pointer is valid
179 bool good() const noexcept
180 {
181 return (INVALID_HANDLE_VALUE != handle_);
182 }
183
184 //- Close directory
185 void close()
186 {
187 if (good())
188 {
189 ::FindClose(handle_);
190 handle_ = INVALID_HANDLE_VALUE;
191 }
192 }
193
194 //- The current item
195 const std::string& val() const noexcept
196 {
197 return item_;
198 }
199
200 //- Read next item, always ignoring "." and ".." entries.
201 // Normally also ignore hidden files/dirs (beginning with '.')
202 // Automatically close when it runs out of items
203 bool next()
204 {
205 if (good())
206 {
207 WIN32_FIND_DATA findData;
208
209 while (::FindNextFile(handle_, &findData))
210 {
211 item_ = findData.cFileName;
212
213 if (accept())
214 {
215 return true;
216 }
217 }
218 close(); // No more items
219 }
220
221 return false;
222 }
223
224
225 // Member Operators
226
227 //- Same as good()
228 operator bool() const noexcept
229 {
230 return good();
231 }
232
233 //- Same as val()
234 const std::string& operator*() const noexcept
235 {
236 return val();
237 }
238
239 //- Same as next()
241 {
242 next();
243 return *this;
244 }
245};
246
247} // End namespace MSwindows
248} // End namespace Foam
249
250
251// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
252
254{
255 // Retrieve the system error message for the last-error code
256
257 // Based on an example at:
258 // http://msdn2.microsoft.com/en-us/library/ms680582(VS.85).aspx
259
260 LPVOID lpMsgBuf;
261 DWORD dw = GetLastError();
262
263 FormatMessage
264 (
265 FORMAT_MESSAGE_ALLOCATE_BUFFER |
266 FORMAT_MESSAGE_FROM_SYSTEM |
267 FORMAT_MESSAGE_IGNORE_INSERTS,
268 NULL, // source
269 dw, // message-id
270 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // language-id
271 reinterpret_cast<LPTSTR>(&lpMsgBuf),
272 0, NULL
273 );
274
275 const char* fmt = "Error %d: %s";
276
277 // Use snprintf with zero to establish the size (without '\0') required
278 std::string output;
279
280 int n = ::snprintf(nullptr, 0, fmt, static_cast<LPCTSTR>(lpMsgBuf));
281
282 if (n > 0)
283 {
284 output.resize(n+1);
285
286 // Print directly into buffer
287 n = ::snprintf(&(output[0]), n+1, fmt, static_cast<LPCTSTR>(lpMsgBuf));
288 output.resize(n);
289 }
290
291 LocalFree(lpMsgBuf);
292
293 return output;
294}
295
296
298{
299 const DWORD bufLen = 256;
300 TCHAR buf[bufLen];
301 DWORD len = bufLen;
302
303 if (::GetUserName(buf, &len))
304 {
305 return buf;
306 }
307
308 std::string str;
309
310 if
311 (
312 ERROR_INSUFFICIENT_BUFFER == ::GetLastError()
313 && len < 2048
314 )
315 {
316 // The len is with trailing '\0'
317 str.resize(len);
318
319 // Retrieve directly into buffer
320 ::GetUserName(&(str[0]), &len);
321
322 // Without trailing '\0'
323 str.resize(len-1);
324 }
325
326 return str;
327}
328
329
331{
332 const DWORD processId = ::GetCurrentProcessId();
333 return processId;
334}
335
336
338{
339 // No equivalent under windows.
340
341 if (MSwindows::debug)
342 {
343 Info<< "ppid not supported under MSwindows" << endl;
344 }
345
346 return 0;
347}
348
349
351{
352 // No equivalent under windows.
353
354 if (MSwindows::debug)
355 {
356 Info<< "pgid not supported under MSwindows" << endl;
357 }
358
359 return 0;
360}
361
362
363bool Foam::hasEnv(const std::string& envName)
364{
365 // An empty envName => always false
366 return !envName.empty() &&
367 ::GetEnvironmentVariable(envName.c_str(), nullptr, 0);
368}
369
370
371Foam::string Foam::getEnv(const std::string& envName)
372{
373 std::string env;
374
375 auto len = ::GetEnvironmentVariable(envName.c_str(), nullptr, 0);
376
377 // len [return] = size with trailing nul char, or zero on failure
378 if (len)
379 {
380 env.resize(len);
381
382 // len [in] = size with trailing nul char
383 // len [return] = size without trailing nul char
384 len = ::GetEnvironmentVariable(envName.c_str(), &(env[0]), len);
385
386 env.resize(len);
387 return fileName::validate(env);
388 }
389
390 return env;
391}
392
393
395(
396 const word& envName,
397 const std::string& value,
398 const bool overwrite
399)
400{
401 // Ignore an empty envName => always false
402 return
403 (
404 !envName.empty()
405 && ::SetEnvironmentVariable(envName.c_str(), value.c_str())
406 );
407}
408
409
411{
412 const DWORD bufLen = MAX_COMPUTERNAME_LENGTH + 1;
413 TCHAR buf[bufLen];
414 DWORD len = bufLen;
415
416 return ::GetComputerName(buf, &len) ? buf : string();
417}
418
419
420// DEPRECATED (2022-01)
422{
423 return Foam::hostName();
424}
425
426
427// DEPRECATED (2022-01)
429{
430 // Could use ::gethostname and ::gethostbyname like POSIX.C, but would
431 // then need to link against ws_32. Prefer to minimize dependencies.
432
433 return string();
434}
435
436
438{
439 string name = Foam::getEnv("USERNAME");
440
441 if (name.empty())
442 {
443 name = MSwindows::userName();
444 }
445
446 return name;
447}
448
449
451{
452 // Assume worst case
453 return true;
454}
455
456
458{
459 fileName env = Foam::getEnv("HOME");
460
461 if (env.empty())
462 {
463 env = Foam::getEnv("USERPROFILE");
464 }
465
466 return env;
467}
468
469
470Foam::fileName Foam::home(const std::string& userName)
471{
472 return Foam::home();
473}
474
475
477{
478 string path;
479 auto len = ::GetCurrentDirectory(0, nullptr);
480
481 // len [return] = size with trailing nul char, or zero on failure
482 if (len)
483 {
484 path.resize(len);
485
486 // len [in] = size with trailing nul char
487 // len [return] = size without trailing nul char
488 len = ::GetCurrentDirectory(len, &(path[0]));
489
490 path.resize(len);
491 return fileName::validate(path);
492 }
493
495 << "Couldn't get the current working directory"
496 << exit(FatalError);
497
498 return fileName();
499}
500
501
503{
504 return Foam::cwd();
505}
506
507
508bool Foam::chDir(const fileName& dir)
509{
510 // Ignore an empty dir name => always false
511 return !dir.empty() && ::SetCurrentDirectory(dir.c_str());;
512}
513
514
515bool Foam::mkDir(const fileName& pathName, const mode_t mode)
516{
517 // empty names are meaningless
518 if (pathName.empty())
519 {
520 return false;
521 }
522
523 bool ok = ::CreateDirectory(pathName.c_str(), NULL);
524
525 if (ok)
526 {
527 Foam::chMod(pathName, mode);
528 return true;
529 }
530
531 const DWORD error = ::GetLastError();
532 switch (error)
533 {
534 case ERROR_ALREADY_EXISTS:
535 {
536 ok = true;
537 break;
538 }
539
540 case ERROR_PATH_NOT_FOUND:
541 {
542 // Part of the path does not exist so try to create it
543 const fileName& parentName = pathName.path();
544
545 if (parentName.size() && mkDir(parentName, mode))
546 {
547 ok = mkDir(pathName, mode);
548 }
549 break;
550 }
551 }
552
553 if (!ok)
554 {
556 << "Couldn't create directory: " << pathName
557 << " " << MSwindows::lastError()
558 << exit(FatalError);
559 }
560
561 return ok;
562}
563
564
565bool Foam::chMod(const fileName& name, const mode_t m)
566{
567 // Ignore an empty name => always false
568 return !name.empty() && _chmod(name.c_str(), m) == 0;
569}
570
571
572mode_t Foam::mode(const fileName& name, const bool followLink)
573{
574 // Ignore an empty name => always 0
575 if (!name.empty())
576 {
577 fileStat fileStatus(name, followLink);
578 if (fileStatus.valid())
579 {
580 return fileStatus.status().st_mode;
581 }
582 }
583
584 return 0;
585}
586
587
588// Windows equivalent to S_ISDIR
589#define ms_isdir(a) \
590 ((m != INVALID_FILE_ATTRIBUTES) && (m & FILE_ATTRIBUTE_DIRECTORY))
591
592// Windows equivalent to S_ISREG
593#define ms_isreg(s) \
594 ((m != INVALID_FILE_ATTRIBUTES) && !(m & FILE_ATTRIBUTE_DIRECTORY))
595
596
598(
599 const fileName& name,
600 const bool /* followLink */
601)
602{
603 // Ignore an empty name => always UNDEFINED
604 if (name.empty())
605 {
606 return fileName::Type::UNDEFINED;
607 }
608
609 const DWORD m = ::GetFileAttributes(name.c_str());
610
611 if (ms_isreg(m))
612 {
613 return fileName::Type::FILE;
614 }
615 else if (ms_isdir(m))
616 {
617 return fileName::Type::DIRECTORY;
618 }
619
620 return fileName::Type::UNDEFINED;
621}
622
623
624// Local check for gz file
625static bool isGzFile(const std::string& name)
626{
627 const DWORD m = ::GetFileAttributes((name + ".gz").c_str());
628 return ms_isreg(m);
629}
630
631
633(
634 const fileName& name,
635 const bool checkGzip,
636 const bool followLink
637)
638{
639 // Ignore an empty name => always false
640 if (name.empty())
641 {
642 return false;
643 }
644
645 const DWORD m = ::GetFileAttributes(name.c_str());
646
647 return (ms_isdir(m) || ms_isreg(m) || (checkGzip && isGzFile(name)));
648}
649
650
651bool Foam::isDir(const fileName& name, const bool followLink)
652{
653 // Ignore an empty name => always false
654 if (name.empty())
655 {
656 return false;
657 }
658
659 const DWORD m = ::GetFileAttributes(name.c_str());
660
661 return ms_isdir(m);
662}
663
664
666(
667 const fileName& name,
668 const bool checkGzip,
669 const bool followLink
670)
671{
672 // Ignore an empty name => always false
673 if (name.empty())
674 {
675 return false;
676 }
677
678 const DWORD m = ::GetFileAttributes(name.c_str());
679
680 return (ms_isreg(m) || (!ms_isdir(m) && checkGzip && isGzFile(name)));
681}
682
683
684off_t Foam::fileSize(const fileName& name, const bool followLink)
685{
686 // Ignore an empty name
687 if (!name.empty())
688 {
689 fileStat fileStatus(name, followLink);
690 if (fileStatus.valid())
691 {
692 return fileStatus.status().st_size;
693 }
694 }
695
696 return -1;
697}
698
699
700time_t Foam::lastModified(const fileName& name, const bool followLink)
701{
702 // Ignore an empty name
703 return name.empty() ? 0 : fileStat(name, followLink).modTime();
704}
705
706
707double Foam::highResLastModified(const fileName& name, const bool followLink)
708{
709 // Ignore an empty name
710 return name.empty() ? 0 : fileStat(name, followLink).dmodTime();
711}
712
713
715(
716 const fileName& directory,
717 const fileName::Type type,
718 const bool filtergz,
719 const bool followLink
720)
721{
722 // Initial filename list size
723 // also used as increment if initial size found to be insufficient
724 static constexpr int maxNnames = 100;
725
726 // Basic sanity: cannot strip '.gz' from directory names
727 const bool stripgz = filtergz && (type != fileName::DIRECTORY);
728 const word extgz("gz");
729
730 fileNameList dirEntries;
731
732 // Iterate contents (ignores an empty directory name)
733
734 MSwindows::directoryIterator dirIter(directory);
735
736 if (!dirIter.exists())
737 {
738 if (MSwindows::debug)
739 {
741 << "cannot open directory " << directory << endl;
742 }
743
744 return dirEntries;
745 }
746
747 if (MSwindows::debug)
748 {
750 << " : reading directory " << directory << endl;
751 }
752
753 label nFailed = 0; // Entries with invalid characters
754 label nEntries = 0; // Number of selected entries
755 dirEntries.resize(maxNnames);
756
757 // Process all the directory entries
758 for (/*nil*/; dirIter; ++dirIter)
759 {
760 const std::string& item = *dirIter;
761
762 // Validate filename without quotes, etc in the name.
763 // No duplicate slashes to strip - dirent will not have them anyhow.
764
765 const fileName name(fileName::validate(item));
766 if (name != item)
767 {
768 ++nFailed;
769 }
770 else if
771 (
772 (type == fileName::DIRECTORY)
773 || (type == fileName::FILE && !fileName::isBackup(name))
774 )
775 {
776 if ((directory/name).type() == type)
777 {
778 if (nEntries >= dirEntries.size())
779 {
780 dirEntries.resize(dirEntries.size() + maxNnames);
781 }
782
783 if (stripgz && name.hasExt(extgz))
784 {
785 dirEntries[nEntries++] = name.lessExt();
786 }
787 else
788 {
789 dirEntries[nEntries++] = name;
790 }
791 }
792 }
793 }
794
795 // Finalize the length of the entries list
796 dirEntries.resize(nEntries);
797
798 if (nFailed && MSwindows::debug)
799 {
800 std::cerr
801 << "Foam::readDir() : reading directory " << directory << nl
802 << nFailed << " entries with invalid characters in their name"
803 << std::endl;
804 }
805
806 return dirEntries;
807}
808
809
810bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink)
811{
812 // Make sure source exists - this also handles an empty source name
813 if (!exists(src))
814 {
815 return false;
816 }
817
818 fileName destFile(dest);
819
820 const fileName::Type srcType = src.type(followLink);
821
822 // Check type of source file.
823 if (srcType == fileName::FILE)
824 {
825 // If dest is a directory, create the destination file name.
826 if (destFile.type() == fileName::DIRECTORY)
827 {
828 destFile = destFile/src.name();
829 }
830
831 // Make sure the destination directory exists.
832 if (!isDir(destFile.path()) && !mkDir(destFile.path()))
833 {
834 return false;
835 }
836
837 // Open and check streams.
838 // - use binary mode to avoid any issues
839 std::ifstream srcStream(src, ios_base::in | ios_base::binary);
840 if (!srcStream)
841 {
842 return false;
843 }
844
845 // - use binary mode to avoid any issues
846 std::ofstream destStream(destFile, ios_base::out | ios_base::binary);
847 if (!destStream)
848 {
849 return false;
850 }
851
852 // Copy character data.
853 char ch;
854 while (srcStream.get(ch))
855 {
856 destStream.put(ch);
857 }
858
859 // Final check.
860 if (!srcStream.eof() || !destStream)
861 {
862 return false;
863 }
864 }
865 else if (srcType == fileName::DIRECTORY)
866 {
867 if (destFile.type() == fileName::DIRECTORY)
868 {
869 // Both are directories. Could mean copy contents or copy
870 // recursively. Don't actually know what the user wants,
871 // but assume that if names are identical == copy contents.
872 //
873 // So: "path1/foo" "path2/foo" copy contents
874 // So: "path1/foo" "path2/bar" copy directory
875
876 const word srcDirName = src.name();
877 if (destFile.name() != srcDirName)
878 {
879 destFile /= srcDirName;
880 }
881 }
882
883 // Make sure the destination directory extists.
884 if (!isDir(destFile) && !mkDir(destFile))
885 {
886 return false;
887 }
888
889 // Copy files
890 fileNameList files = readDir(src, fileName::FILE, false, followLink);
891 for (const fileName& item : files)
892 {
893 if (MSwindows::debug)
894 {
895 Info<< "Copying : " << src/item
896 << " to " << destFile/item << endl;
897 }
898
899 // File to file.
900 Foam::cp(src/item, destFile/item);
901 }
902
903 // Copy sub directories.
904 fileNameList dirs = readDir
905 (
906 src,
907 fileName::DIRECTORY,
908 false,
909 followLink
910 );
911
912 for (const fileName& item : dirs)
913 {
914 if (MSwindows::debug)
915 {
916 Info<< "Copying : " << src/item
917 << " to " << destFile << endl;
918 }
919
920 // Dir to Dir.
921 Foam::cp(src/item, destFile);
922 }
923 }
924 else
925 {
926 return false;
927 }
928
929 return true;
930}
931
932
933bool Foam::ln(const fileName& src, const fileName& dst)
934{
935 // links are poorly supported, or need administrator privileges.
936 // Skip for now.
937
938 if (MSwindows::debug)
939 {
940 Info<< "MSwindows does not support ln - softlinking" << endl;
941 }
942
943 return false;
944}
945
946
947bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
948{
949 if (MSwindows::debug)
950 {
951 Info<< "Move : " << src << " to " << dst << endl;
952 }
953
954 // Ignore an empty names => always false
955 if (src.empty() || dst.empty())
956 {
957 return false;
958 }
959
960
961 if
962 (
963 dst.type() == fileName::DIRECTORY
964 && src.type(followLink) != fileName::DIRECTORY
965 )
966 {
967 const fileName dstName(dst/src.name());
968
969 return renameFile(src, dstName);
970 }
971
972 return renameFile(src, dst);
973}
974
975
976bool Foam::mvBak(const fileName& src, const std::string& ext)
977{
978 // Ignore an empty name or extension => always false
979 if (src.empty() || ext.empty())
980 {
981 return false;
982 }
983
984 if (exists(src, false))
985 {
986 constexpr const int maxIndex = 99;
987 char index[3];
988
989 for (int n = 0; n <= maxIndex; ++n)
990 {
991 fileName dstName(src + "." + ext);
992 if (n)
993 {
994 sprintf(index, "%02d", n);
995 dstName += index;
996 }
997
998 // avoid overwriting existing files, except for the last
999 // possible index where we have no choice
1000 if (!exists(dstName, false) || n == maxIndex)
1001 {
1002 return renameFile(src, dstName);
1003 }
1004 }
1005 }
1006
1007 // fall-through: nothing to do
1008 return false;
1009}
1010
1011
1012bool Foam::rm(const fileName& file)
1013{
1014 if (MSwindows::debug)
1015 {
1016 Info<< "Removing : " << file << endl;
1017 }
1018
1019 // Ignore an empty name => always false
1020 if (file.empty())
1021 {
1022 return false;
1023 }
1024
1025
1026 // If removal of plain file name failed, try with .gz
1027
1028 return
1029 (
1030 0 == std::remove(file.c_str())
1031 || 0 == std::remove((file + ".gz").c_str())
1032 );
1033}
1034
1035
1036bool Foam::rmDir(const fileName& directory, const bool silent)
1037{
1038 // Iterate contents (ignores an empty directory name)
1039 // Also retain hidden files/dirs for removal
1040
1041 MSwindows::directoryIterator dirIter(directory, true);
1042
1043 if (!dirIter.exists())
1044 {
1045 if (!silent)
1046 {
1048 << "cannot open directory " << directory << endl;
1049 }
1050 }
1051
1052 if (MSwindows::debug)
1053 {
1055 << " : removing directory " << directory << endl;
1056 }
1057
1058
1059 // Process each directory entry, counting any errors encountered
1060 label nErrors = 0;
1061
1062 for (/*nil*/; dirIter; ++dirIter)
1063 {
1064 const std::string& item = *dirIter;
1065
1066 // Allow invalid characters (spaces, quotes, etc),
1067 // otherwise we cannot remove subdirs with these types of names.
1068 // -> const fileName path = directory/name; <-
1069
1070 const fileName path(fileName::concat(directory, item));
1071
1072 if (path.type(false) == fileName::DIRECTORY)
1073 {
1074 if (!rmDir(path, true)) // Only report errors at the top-level
1075 {
1076 ++nErrors;
1077 }
1078 }
1079 else
1080 {
1081 if (!rm(path))
1082 {
1083 ++nErrors;
1084 }
1085 }
1086 }
1087
1088 if (nErrors)
1089 {
1090 if (!silent)
1091 {
1093 << "failed to remove directory " << directory << nl
1094 << "could not remove " << nErrors << " sub-entries" << endl;
1095 }
1096 }
1097 else
1098 {
1099 if (!::RemoveDirectory(directory.c_str()))
1100 {
1101 ++nErrors;
1102 if (!silent)
1103 {
1105 << "failed to remove directory " << directory << endl;
1106 }
1107 }
1108 }
1109
1110 return !nErrors;
1111}
1112
1113
1114unsigned int Foam::sleep(const unsigned int sec)
1115{
1116 ::Sleep(1000*sec); // in milliseconds
1117
1118 return 0;
1119}
1120
1121
1122void Foam::fdClose(const int fd)
1123{
1124 if (::_close(fd) != 0)
1125 {
1127 << "close error on " << fd << endl
1128 << abort(FatalError);
1129 }
1130}
1131
1132
1134(
1135 const std::string& destName,
1136 const label destPort,
1137 const label timeOut
1138)
1139{
1140 // Appears that socket calls require administrator privileges.
1141 // Skip for now.
1142
1143 if (MSwindows::debug)
1144 {
1145 Info<< "MSwindows does not support ping" << endl;
1146 }
1147
1148 return false;
1149}
1150
1151
1152bool Foam::ping(const std::string& host, const label timeOut)
1153{
1154 return ping(host, 222, timeOut) || ping(host, 22, timeOut);
1155}
1156
1157
1158int Foam::system(const std::string& command, const bool bg)
1159{
1160 if (MSwindows::debug && bg)
1161 {
1163 << "MSwindows does not support background (fork) tasks" << endl;
1164 }
1165
1166 return std::system(command.c_str());
1167}
1168
1169
1170int Foam::system(const CStringList& command, const bool bg)
1171{
1172 if (command.empty())
1173 {
1174 // Treat an empty command as a successful no-op.
1175 // For consistency with POSIX (man sh) behaviour for (sh -c command),
1176 // which is what is mostly being replicated here.
1177 return 0;
1178 }
1179
1180 const int count = command.size();
1181
1182 std::string cmd;
1183
1184 for (int i = 0; i < count; ++i)
1185 {
1186 if (i) cmd += ' ';
1187 cmd += command[i];
1188 }
1189
1190 return system(cmd, bg);
1191}
1192
1193
1194int Foam::system(const UList<Foam::string>& command, const bool bg)
1195{
1196 if (command.empty())
1197 {
1198 // Treat an empty command as a successful no-op.
1199 return 0;
1200 }
1201
1202 const int count = command.size();
1203
1204 std::string cmd;
1205
1206 for (int i = 0; i < count; ++i)
1207 {
1208 if (i) cmd += ' ';
1209 cmd += command[i];
1210 }
1211
1212 return system(cmd, bg);
1213}
1214
1215
1216// Explicitly track loaded libraries, rather than use
1217// EnumerateLoadedModules64 and have to link against
1218// Dbghelp.dll
1219// Details at http://msdn.microsoft.com/en-us/library/ms679316(v=vs.85).aspx
1220
1221static std::unordered_map<void*, std::string> libsLoaded;
1222
1223
1224void* Foam::dlOpen(const fileName& libName, const bool check)
1225{
1226 if (MSwindows::debug)
1227 {
1228 std::cout
1229 << "dlOpen(const fileName&)"
1230 << " : dlopen of " << libName << std::endl;
1231 }
1232
1233 // Always remap "libXX.so" and "libXX" to "libXX.dll"
1234 fileName libso(libName.lessExt().ext(EXT_SO));
1235
1236 void* handle = ::LoadLibrary(libso.c_str());
1237
1238 if
1239 (
1240 !handle
1241 && libName.find('/') == std::string::npos
1242 && !libso.starts_with("lib")
1243 )
1244 {
1245 // Try with 'lib' prefix
1246 libso = "lib" + libso;
1247 handle = ::LoadLibrary(libso.c_str());
1248
1249 if (MSwindows::debug)
1250 {
1251 std::cout
1252 << "dlOpen(const fileName&)"
1253 << " : dlopen of " << libso << std::endl;
1254 }
1255 }
1256
1257 if (handle)
1258 {
1259 libsLoaded[handle] = libso.lessExt();
1260 }
1261 else if (check)
1262 {
1264 << "dlopen error : " << MSwindows::lastError() << endl;
1265 }
1266
1267 if (MSwindows::debug)
1268 {
1269 std::cout
1270 << "dlOpen(const fileName&)"
1271 << " : dlopen of " << libName
1272 << " handle " << handle << std::endl;
1273 }
1274
1275 return handle;
1276}
1277
1278
1279void* Foam::dlOpen(const fileName& libName, std::string& errorMsg)
1280{
1281 // Call without emitting error message - we capture that ourselves
1282 void* handle = Foam::dlOpen(libName, false);
1283
1284 if (!handle)
1285 {
1286 // Capture error message
1287 errorMsg = MSwindows::lastError();
1288 }
1289 else
1290 {
1291 // No errors
1292 errorMsg.clear();
1293 }
1294
1295 return handle;
1296}
1297
1298
1299Foam::label Foam::dlOpen
1300(
1301 std::initializer_list<fileName> libNames,
1302 const bool check
1303)
1304{
1305 label nLoaded = 0;
1306
1307 for (const fileName& libName : libNames)
1308 {
1309 if (Foam::dlOpen(libName, check))
1310 {
1311 ++nLoaded;
1312 }
1313 }
1314
1315 return nLoaded;
1316}
1317
1318
1319bool Foam::dlClose(void* const handle)
1320{
1321 if (MSwindows::debug)
1322 {
1323 std::cout
1324 << "dlClose(void*)"
1325 << " : dlclose of handle " << handle << std::endl;
1326 }
1327
1328 const bool ok = ::FreeLibrary(static_cast<HMODULE>(handle));
1329
1330 if (ok)
1331 {
1332 libsLoaded.erase(handle);
1333 }
1334
1335 return ok;
1336}
1337
1338
1339void* Foam::dlSymFind(void* handle, const std::string& symbol, bool required)
1340{
1341 if (!required && (!handle || symbol.empty()))
1342 {
1343 return nullptr;
1344 }
1345
1346 if (MSwindows::debug)
1347 {
1348 std::cout
1349 << "dlSymFind(void*, const std::string&, bool)"
1350 << " : dlsym of " << symbol << std::endl;
1351 }
1352
1353 // Get address of symbol, or nullptr on failure
1354 void* fun =
1355 reinterpret_cast<void *>
1356 (
1357 ::GetProcAddress(static_cast<HMODULE>(handle), symbol.c_str())
1358 );
1359
1360 // Any error?
1361 if (!fun && required)
1362 {
1364 << "Cannot lookup symbol " << symbol << " : "
1365 << MSwindows::lastError() << endl;
1366 }
1367
1368 return fun;
1369}
1370
1371
1373{
1374 DynamicList<fileName> libs(libsLoaded.size());
1375
1376 for (const auto& item : libsLoaded)
1377 {
1378 libs.append(item.second);
1379 }
1380
1381 if (MSwindows::debug)
1382 {
1383 std::cout
1384 << "dlLoaded()"
1385 << " : determined loaded libraries :" << libs.size() << std::endl;
1386 }
1387
1388 return libs;
1389}
1390
1391
1392// ************************************************************************* //
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
static std::unordered_map< void *, std::string > libsLoaded
Definition: MSwindows.C:1221
#define ms_isreg(s)
Definition: MSwindows.C:593
#define EXT_SO
Definition: MSwindows.C:54
#define ms_isdir(a)
Definition: MSwindows.C:589
static bool isGzFile(const std::string &name)
Definition: MSwindows.C:625
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
label n
An adapter for copying a list of C++ strings into a list of C-style strings for passing to C code tha...
Definition: CStringList.H:70
int size() const noexcept
Return the number of C-strings (ie, argc)
Definition: CStringListI.H:124
bool empty() const noexcept
True if the size (ie, argc) is zero.
Definition: CStringListI.H:118
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
A simple directory contents iterator.
Definition: MSwindows.C:112
bool exists() const noexcept
Directory existed for opening.
Definition: MSwindows.C:173
bool good() const noexcept
Directory pointer is valid.
Definition: MSwindows.C:179
void close()
Close directory.
Definition: MSwindows.C:185
directoryIterator(const std::string &dirName, bool allowHidden=false)
Construct for dirName, optionally allowing hidden files/dirs.
Definition: MSwindows.C:135
const std::string & val() const noexcept
The current item.
Definition: MSwindows.C:195
bool next()
Read next item, always ignoring "." and ".." entries.
Definition: MSwindows.C:203
directoryIterator & operator++()
Same as next()
Definition: MSwindows.C:240
const std::string & operator*() const noexcept
Same as val()
Definition: MSwindows.C:234
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:94
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:77
static bool binary
Write binary (default ascii)
A class for handling file names.
Definition: fileName.H:76
Type
Enumerations to handle directory entry types.
Definition: fileName.H:81
Type type(bool followLink=true, bool checkGzip=false) const
Definition: fileName.C:360
fileName lessExt() const
Return file name without extension (part before last .)
Definition: fileNameI.H:230
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:218
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:176
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:199
Wrapper for stat() and lstat() system calls.
Definition: fileStat.H:68
bool valid() const
Was file-stat successful?
Definition: fileStat.H:128
time_t modTime() const
Return the modification time in seconds.
Definition: fileStat.C:117
double dmodTime() const
Return the modification time in seconds (nanosecond resolution)
Definition: fileStat.C:123
const struct stat & status() const
Raw status.
Definition: fileStat.H:122
A class for handling character strings derived from std::string.
Definition: string.H:79
bool starts_with(const std::string &s) const
True if string starts with the given prefix (cf. C++20)
Definition: string.H:297
A class for handling words, derived from Foam::string.
Definition: word.H:68
word lessExt() const
Return word without extension (part before last .)
Definition: word.C:113
bool hasExt() const
Various checks for extensions.
Definition: stringI.H:56
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
bool
Definition: EEqn.H:20
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define WarningInFunction
Report a warning using Foam::Warning.
#define InfoInFunction
Report an information message using Foam::Info.
std::string userName()
The user-name from Windows API GetUserName.
Definition: MSwindows.C:297
std::string lastError()
The last Windows API error from GetLastError.
Definition: MSwindows.C:253
Namespace for OpenFOAM.
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition: MSwindows.C:1012
fileName cwd()
The physical or logical current working directory path name.
Definition: MSwindows.C:476
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: MSwindows.C:371
bool setEnv(const word &name, const std::string &value, const bool overwrite)
Set an environment variable, return true on success.
Definition: MSwindows.C:395
time_t lastModified(const fileName &name, const bool followLink=true)
Return time of last file modification (normally follows symbolic links).
Definition: MSwindows.C:700
void fdClose(const int fd)
Close file descriptor.
Definition: MSwindows.C:1122
bool exists(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: MSwindows.C:633
static bool const abortHandlerInstalled
Definition: MSwindows.C:82
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: MSwindows.C:1158
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:515
bool isAdministrator()
Is the current user the administrator (root)
Definition: MSwindows.C:450
bool dlClose(void *handle)
Close a dlopened library using handle. Return true if successful.
Definition: MSwindows.C:1319
bool env(const std::string &envName)
Deprecated(2020-05) check for existence of environment variable.
Definition: OSspecific.H:82
messageStream Info
Information stream (stdout output on master, null elsewhere)
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: MSwindows.C:572
unsigned int sleep(const unsigned int sec)
Sleep for the specified number of seconds.
Definition: MSwindows.C:1114
bool chMod(const fileName &name, const mode_t mode)
Set the file/directory mode, return true on success.
Definition: MSwindows.C:565
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
static bool renameFile(const std::string &src, const std::string &dst)
Definition: MSwindows.C:86
string userName()
Return the user's login name.
Definition: MSwindows.C:437
pid_t pgid()
Return the group PID of this process.
Definition: MSwindows.C:350
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
string hostName()
Return the system's host name, as per hostname(1)
Definition: MSwindows.C:410
bool rmDir(const fileName &directory, const bool silent=false)
Remove a directory and its contents (optionally silencing warnings)
Definition: MSwindows.C:1036
void * dlSymFind(void *handle, const std::string &symbol, bool required=false)
Look for symbol in a dlopened library.
Definition: MSwindows.C:1339
bool ping(const std::string &destName, const label port, const label timeOut)
Check if machine is up by pinging given port.
Definition: MSwindows.C:1134
pid_t ppid()
Return the parent PID of this process.
Definition: MSwindows.C:337
errorManip< error > abort(error &err)
Definition: errorManip.H:144
off_t fileSize(const fileName &name, const bool followLink=true)
Return size of file or -1 on failure (normally follows symbolic links).
Definition: MSwindows.C:684
double highResLastModified(const fileName &, const bool followLink=true)
Return time of last file modification.
Definition: MSwindows.C:707
static bool installAbortHandler()
Definition: MSwindows.C:74
void * dlOpen(const fileName &libName, const bool check=true)
Open a shared library and return handle to library.
Definition: MSwindows.C:1224
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: MSwindows.C:715
pid_t pid()
Return the PID of this process.
Definition: MSwindows.C:330
const direction noexcept
Definition: Scalar.H:223
bool mvBak(const fileName &src, const std::string &ext="bak")
Rename to a corresponding backup file.
Definition: MSwindows.C:976
bool isFile(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: MSwindows.C:666
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy the source to the destination (recursively if necessary).
Definition: MSwindows.C:810
fileNameList dlLoaded()
Return all loaded libraries.
Definition: MSwindows.C:1372
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
static void sigAbortHandler(int exitCode)
Definition: MSwindows.C:69
bool mv(const fileName &src, const fileName &dst, const bool followLink=false)
Rename src to dst.
Definition: MSwindows.C:947
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
fileName home()
Return home directory path name for the current user.
Definition: MSwindows.C:457
string domainName()
Deprecated(2022-01) domain name resolution may be unreliable.
Definition: MSwindows.C:428
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: MSwindows.C:933
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:651
bool hasEnv(const std::string &envName)
True if environment variable of given name is defined.
Definition: MSwindows.C:363
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
bool chDir(const fileName &dir)
Change current directory to the one specified and return true on success.
Definition: MSwindows.C:508
mkDir(pdfPath)