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-2021 OpenCFD Ltd.
11 -------------------------------------------------------------------------------
12 License
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 
28 Description
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 
59 namespace Foam
60 {
61  defineTypeNameAndDebug(MSwindows, 0);
62 }
63 
64 
65 namespace 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 fileName& src, const fileName& 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 
105 namespace Foam
106 {
107 namespace 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 
132 public:
133 
134  //- Construct for dirName, optionally allowing hidden files/dirs
135  directoryIterator(const fileName& 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
174  {
175  return exists_;
176  }
177 
178  //- Directory pointer is valid
179  bool good() const
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
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
229  {
230  return good();
231  }
232 
233  //- Same as val()
234  const std::string& operator*() const
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 
330 pid_t Foam::pid()
331 {
332  const DWORD processId = ::GetCurrentProcessId();
333  return processId;
334 }
335 
336 
337 pid_t Foam::ppid()
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 
350 pid_t Foam::pgid()
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 
363 bool 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 
371 Foam::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 
394 bool Foam::setEnv
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 
421 {
422  // Could use ::gethostname and ::gethostbyname like POSIX.C, but would
423  // then need to link against ws_32. Prefer to minimize dependencies.
424 
425  return string::null;
426 }
427 
428 
430 {
431  string name = Foam::getEnv("USERNAME");
432 
433  if (name.empty())
434  {
436  }
437 
438  return name;
439 }
440 
441 
443 {
444  // Assume worst case
445  return true;
446 }
447 
448 
450 {
451  fileName env = Foam::getEnv("HOME");
452 
453  if (env.empty())
454  {
455  env = Foam::getEnv("USERPROFILE");
456  }
457 
458  return env;
459 }
460 
461 
462 Foam::fileName Foam::home(const std::string& userName)
463 {
464  return Foam::home();
465 }
466 
467 
469 {
470  string path;
471  auto len = ::GetCurrentDirectory(0, nullptr);
472 
473  // len [return] = size with trailing nul char, or zero on failure
474  if (len)
475  {
476  path.resize(len);
477 
478  // len [in] = size with trailing nul char
479  // len [return] = size without trailing nul char
480  len = ::GetCurrentDirectory(len, &(path[0]));
481 
482  path.resize(len);
483  return fileName::validate(path);
484  }
485 
487  << "Couldn't get the current working directory"
488  << exit(FatalError);
489 
490  return fileName();
491 }
492 
493 
495 {
496  return Foam::cwd();
497 }
498 
499 
500 bool Foam::chDir(const fileName& dir)
501 {
502  // Ignore an empty dir name => always false
503  return !dir.empty() && ::SetCurrentDirectory(dir.c_str());;
504 }
505 
506 
507 bool Foam::mkDir(const fileName& pathName, const mode_t mode)
508 {
509  // empty names are meaningless
510  if (pathName.empty())
511  {
512  return false;
513  }
514 
515  bool ok = ::CreateDirectory(pathName.c_str(), NULL);
516 
517  if (ok)
518  {
519  Foam::chMod(pathName, mode);
520  return true;
521  }
522 
523  const DWORD error = ::GetLastError();
524  switch (error)
525  {
526  case ERROR_ALREADY_EXISTS:
527  {
528  ok = true;
529  break;
530  }
531 
532  case ERROR_PATH_NOT_FOUND:
533  {
534  // Part of the path does not exist so try to create it
535  const fileName& parentName = pathName.path();
536 
537  if (parentName.size() && mkDir(parentName, mode))
538  {
539  ok = mkDir(pathName, mode);
540  }
541  break;
542  }
543  }
544 
545  if (!ok)
546  {
548  << "Couldn't create directory: " << pathName
549  << " " << MSwindows::lastError()
550  << exit(FatalError);
551  }
552 
553  return ok;
554 }
555 
556 
557 bool Foam::chMod(const fileName& name, const mode_t m)
558 {
559  // Ignore an empty name => always false
560  return !name.empty() && _chmod(name.c_str(), m) == 0;
561 }
562 
563 
564 mode_t Foam::mode(const fileName& name, const bool followLink)
565 {
566  // Ignore an empty name => always 0
567  if (!name.empty())
568  {
569  fileStat fileStatus(name, followLink);
570  if (fileStatus.valid())
571  {
572  return fileStatus.status().st_mode;
573  }
574  }
575 
576  return 0;
577 }
578 
579 
580 // Windows equivalent to S_ISDIR
581 #define ms_isdir(a) \
582  ((m != INVALID_FILE_ATTRIBUTES) && (m & FILE_ATTRIBUTE_DIRECTORY))
583 
584 // Windows equivalent to S_ISREG
585 #define ms_isreg(s) \
586  ((m != INVALID_FILE_ATTRIBUTES) && !(m & FILE_ATTRIBUTE_DIRECTORY))
587 
588 
590 (
591  const fileName& name,
592  const bool /* followLink */
593 )
594 {
595  // Ignore an empty name => always UNDEFINED
596  if (name.empty())
597  {
598  return fileName::UNDEFINED;
599  }
600 
601  const DWORD m = ::GetFileAttributes(name.c_str());
602 
603  if (ms_isreg(m))
604  {
605  return fileName::FILE;
606  }
607  else if (ms_isdir(m))
608  {
609  return fileName::DIRECTORY;
610  }
611 
612  return fileName::UNDEFINED;
613 }
614 
615 
616 // Local check for gz file
617 static bool isGzFile(const std::string& name)
618 {
619  const DWORD m = ::GetFileAttributes((name + ".gz").c_str());
620  return ms_isreg(m);
621 }
622 
623 
624 bool Foam::exists
625 (
626  const fileName& name,
627  const bool checkGzip,
628  const bool followLink
629 )
630 {
631  // Ignore an empty name => always false
632  if (name.empty())
633  {
634  return false;
635  }
636 
637  const DWORD m = ::GetFileAttributes(name.c_str());
638 
639  return (ms_isdir(m) || ms_isreg(m) || (checkGzip && isGzFile(name)));
640 }
641 
642 
643 bool Foam::isDir(const fileName& name, const bool followLink)
644 {
645  // Ignore an empty name => always false
646  if (name.empty())
647  {
648  return false;
649  }
650 
651  const DWORD m = ::GetFileAttributes(name.c_str());
652 
653  return ms_isdir(m);
654 }
655 
656 
657 bool Foam::isFile
658 (
659  const fileName& name,
660  const bool checkGzip,
661  const bool followLink
662 )
663 {
664  // Ignore an empty name => always false
665  if (name.empty())
666  {
667  return false;
668  }
669 
670  const DWORD m = ::GetFileAttributes(name.c_str());
671 
672  return (ms_isreg(m) || (!ms_isdir(m) && checkGzip && isGzFile(name)));
673 }
674 
675 
676 off_t Foam::fileSize(const fileName& name, const bool followLink)
677 {
678  // Ignore an empty name
679  if (!name.empty())
680  {
681  fileStat fileStatus(name, followLink);
682  if (fileStatus.valid())
683  {
684  return fileStatus.status().st_size;
685  }
686  }
687 
688  return -1;
689 }
690 
691 
692 time_t Foam::lastModified(const fileName& name, const bool followLink)
693 {
694  // Ignore an empty name
695  return name.empty() ? 0 : fileStat(name, followLink).modTime();
696 }
697 
698 
699 double Foam::highResLastModified(const fileName& name, const bool followLink)
700 {
701  // Ignore an empty name
702  return name.empty() ? 0 : fileStat(name, followLink).dmodTime();
703 }
704 
705 
707 (
708  const fileName& directory,
709  const fileName::Type type,
710  const bool filtergz,
711  const bool followLink
712 )
713 {
714  // Initial filename list size
715  // also used as increment if initial size found to be insufficient
716  static constexpr int maxNnames = 100;
717 
718  // Basic sanity: cannot strip '.gz' from directory names
719  const bool stripgz = filtergz && (type != fileName::DIRECTORY);
720  const word extgz("gz");
721 
722  fileNameList dirEntries;
723 
724  // Iterate contents (ignores an empty directory name)
725 
726  MSwindows::directoryIterator dirIter(directory);
727 
728  if (!dirIter.exists())
729  {
730  if (MSwindows::debug)
731  {
733  << "cannot open directory " << directory << endl;
734  }
735 
736  return dirEntries;
737  }
738 
739  if (MSwindows::debug)
740  {
742  << " : reading directory " << directory << endl;
743  }
744 
745  label nFailed = 0; // Entries with invalid characters
746  label nEntries = 0; // Number of selected entries
747  dirEntries.resize(maxNnames);
748 
749  // Process all the directory entries
750  for (/*nil*/; dirIter; ++dirIter)
751  {
752  const std::string& item = *dirIter;
753 
754  // Validate filename without quotes, etc in the name.
755  // No duplicate slashes to strip - dirent will not have them anyhow.
756 
757  const fileName name(fileName::validate(item));
758  if (name != item)
759  {
760  ++nFailed;
761  }
762  else if
763  (
764  (type == fileName::DIRECTORY)
765  || (type == fileName::FILE && !fileName::isBackup(name))
766  )
767  {
768  if ((directory/name).type() == type)
769  {
770  if (nEntries >= dirEntries.size())
771  {
772  dirEntries.resize(dirEntries.size() + maxNnames);
773  }
774 
775  if (stripgz && name.hasExt(extgz))
776  {
777  dirEntries[nEntries++] = name.lessExt();
778  }
779  else
780  {
781  dirEntries[nEntries++] = name;
782  }
783  }
784  }
785  }
786 
787  // Finalize the length of the entries list
788  dirEntries.resize(nEntries);
789 
790  if (nFailed && MSwindows::debug)
791  {
792  std::cerr
793  << "Foam::readDir() : reading directory " << directory << nl
794  << nFailed << " entries with invalid characters in their name"
795  << std::endl;
796  }
797 
798  return dirEntries;
799 }
800 
801 
802 bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink)
803 {
804  // Make sure source exists - this also handles an empty source name
805  if (!exists(src))
806  {
807  return false;
808  }
809 
810  fileName destFile(dest);
811 
812  const fileName::Type srcType = src.type(followLink);
813 
814  // Check type of source file.
815  if (srcType == fileName::FILE)
816  {
817  // If dest is a directory, create the destination file name.
818  if (destFile.type() == fileName::DIRECTORY)
819  {
820  destFile = destFile/src.name();
821  }
822 
823  // Make sure the destination directory exists.
824  if (!isDir(destFile.path()) && !mkDir(destFile.path()))
825  {
826  return false;
827  }
828 
829  // Open and check streams.
830  // - use binary mode to avoid any issues
831  std::ifstream srcStream(src, ios_base::in | ios_base::binary);
832  if (!srcStream)
833  {
834  return false;
835  }
836 
837  // - use binary mode to avoid any issues
838  std::ofstream destStream(destFile, ios_base::out | ios_base::binary);
839  if (!destStream)
840  {
841  return false;
842  }
843 
844  // Copy character data.
845  char ch;
846  while (srcStream.get(ch))
847  {
848  destStream.put(ch);
849  }
850 
851  // Final check.
852  if (!srcStream.eof() || !destStream)
853  {
854  return false;
855  }
856  }
857  else if (srcType == fileName::DIRECTORY)
858  {
859  if (destFile.type() == fileName::DIRECTORY)
860  {
861  // Both are directories. Could mean copy contents or copy
862  // recursively. Don't actually know what the user wants,
863  // but assume that if names are identical == copy contents.
864  //
865  // So: "path1/foo" "path2/foo" copy contents
866  // So: "path1/foo" "path2/bar" copy directory
867 
868  const word srcDirName = src.name();
869  if (destFile.name() != srcDirName)
870  {
871  destFile /= srcDirName;
872  }
873  }
874 
875  // Make sure the destination directory extists.
876  if (!isDir(destFile) && !mkDir(destFile))
877  {
878  return false;
879  }
880 
881  // Copy files
882  fileNameList files = readDir(src, fileName::FILE, false, followLink);
883  for (const fileName& item : files)
884  {
885  if (MSwindows::debug)
886  {
887  Info<< "Copying : " << src/item
888  << " to " << destFile/item << endl;
889  }
890 
891  // File to file.
892  Foam::cp(src/item, destFile/item);
893  }
894 
895  // Copy sub directories.
896  fileNameList dirs = readDir
897  (
898  src,
899  fileName::DIRECTORY,
900  false,
901  followLink
902  );
903 
904  for (const fileName& item : dirs)
905  {
906  if (MSwindows::debug)
907  {
908  Info<< "Copying : " << src/item
909  << " to " << destFile << endl;
910  }
911 
912  // Dir to Dir.
913  Foam::cp(src/item, destFile);
914  }
915  }
916  else
917  {
918  return false;
919  }
920 
921  return true;
922 }
923 
924 
925 bool Foam::ln(const fileName& src, const fileName& dst)
926 {
927  // links are poorly supported, or need administrator privileges.
928  // Skip for now.
929 
930  if (MSwindows::debug)
931  {
932  Info<< "MSwindows does not support ln - softlinking" << endl;
933  }
934 
935  return false;
936 }
937 
938 
939 bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
940 {
941  if (MSwindows::debug)
942  {
943  Info<< "Move : " << src << " to " << dst << endl;
944  }
945 
946  // Ignore an empty names => always false
947  if (src.empty() || dst.empty())
948  {
949  return false;
950  }
951 
952 
953  if
954  (
955  dst.type() == fileName::DIRECTORY
956  && src.type(followLink) != fileName::DIRECTORY
957  )
958  {
959  const fileName dstName(dst/src.name());
960 
961  return renameFile(src, dstName);
962  }
963 
964  return renameFile(src, dst);
965 }
966 
967 
968 bool Foam::mvBak(const fileName& src, const std::string& ext)
969 {
970  // Ignore an empty name or extension => always false
971  if (src.empty() || ext.empty())
972  {
973  return false;
974  }
975 
976  if (exists(src, false))
977  {
978  constexpr const int maxIndex = 99;
979  char index[3];
980 
981  for (int n = 0; n <= maxIndex; ++n)
982  {
983  fileName dstName(src + "." + ext);
984  if (n)
985  {
986  sprintf(index, "%02d", n);
987  dstName += index;
988  }
989 
990  // avoid overwriting existing files, except for the last
991  // possible index where we have no choice
992  if (!exists(dstName, false) || n == maxIndex)
993  {
994  return renameFile(src, dstName);
995  }
996  }
997  }
998 
999  // fall-through: nothing to do
1000  return false;
1001 }
1002 
1003 
1004 bool Foam::rm(const fileName& file)
1005 {
1006  if (MSwindows::debug)
1007  {
1008  Info<< "Removing : " << file << endl;
1009  }
1010 
1011  // Ignore an empty name => always false
1012  if (file.empty())
1013  {
1014  return false;
1015  }
1016 
1017 
1018  // If removal of plain file name failed, try with .gz
1019 
1020  return
1021  (
1022  0 == std::remove(file.c_str())
1023  || 0 == std::remove((file + ".gz").c_str())
1024  );
1025 }
1026 
1027 
1028 bool Foam::rmDir(const fileName& directory, const bool silent)
1029 {
1030  // Iterate contents (ignores an empty directory name)
1031  // Also retain hidden files/dirs for removal
1032 
1033  MSwindows::directoryIterator dirIter(directory, true);
1034 
1035  if (!dirIter.exists())
1036  {
1037  if (!silent)
1038  {
1040  << "cannot open directory " << directory << endl;
1041  }
1042  }
1043 
1044  if (MSwindows::debug)
1045  {
1047  << " : removing directory " << directory << endl;
1048  }
1049 
1050 
1051  // Process each directory entry, counting any errors encountered
1052  label nErrors = 0;
1053 
1054  for (/*nil*/; dirIter; ++dirIter)
1055  {
1056  const std::string& item = *dirIter;
1057 
1058  // Allow invalid characters (spaces, quotes, etc),
1059  // otherwise we cannot remove subdirs with these types of names.
1060  // -> const fileName path = directory/name; <-
1061 
1062  const fileName path(fileName::concat(directory, item));
1063 
1064  if (path.type(false) == fileName::DIRECTORY)
1065  {
1066  if (!rmDir(path, true)) // Only report errors at the top-level
1067  {
1068  ++nErrors;
1069  }
1070  }
1071  else
1072  {
1073  if (!rm(path))
1074  {
1075  ++nErrors;
1076  }
1077  }
1078  }
1079 
1080  if (nErrors)
1081  {
1082  if (!silent)
1083  {
1085  << "failed to remove directory " << directory << nl
1086  << "could not remove " << nErrors << " sub-entries" << endl;
1087  }
1088  }
1089  else
1090  {
1091  if (!::RemoveDirectory(directory.c_str()))
1092  {
1093  ++nErrors;
1094  if (!silent)
1095  {
1097  << "failed to remove directory " << directory << endl;
1098  }
1099  }
1100  }
1101 
1102  return !nErrors;
1103 }
1104 
1105 
1106 unsigned int Foam::sleep(const unsigned int sec)
1107 {
1108  ::Sleep(1000*sec); // in milliseconds
1109 
1110  return 0;
1111 }
1112 
1113 
1114 void Foam::fdClose(const int fd)
1115 {
1116  if (::_close(fd) != 0)
1117  {
1119  << "close error on " << fd << endl
1120  << abort(FatalError);
1121  }
1122 }
1123 
1124 
1125 bool Foam::ping
1127  const std::string& destName,
1128  const label destPort,
1129  const label timeOut
1130 )
1131 {
1132  // Appears that socket calls require administrator privileges.
1133  // Skip for now.
1134 
1135  if (MSwindows::debug)
1136  {
1137  Info<< "MSwindows does not support ping" << endl;
1138  }
1139 
1140  return false;
1141 }
1142 
1143 
1144 bool Foam::ping(const std::string& host, const label timeOut)
1145 {
1146  return ping(host, 222, timeOut) || ping(host, 22, timeOut);
1147 }
1148 
1149 
1150 int Foam::system(const std::string& command, const bool bg)
1151 {
1152  if (MSwindows::debug && bg)
1153  {
1155  << "MSwindows does not support background (fork) tasks" << endl;
1156  }
1157 
1158  return std::system(command.c_str());
1159 }
1160 
1161 
1162 int Foam::system(const CStringList& command, const bool bg)
1163 {
1164  if (command.empty())
1165  {
1166  // Treat an empty command as a successful no-op.
1167  // For consistency with POSIX (man sh) behaviour for (sh -c command),
1168  // which is what is mostly being replicated here.
1169  return 0;
1170  }
1171 
1172  const int count = command.size();
1173 
1174  std::string cmd;
1175 
1176  for (int i = 0; i < count; ++i)
1177  {
1178  if (i) cmd += ' ';
1179  cmd += command[i];
1180  }
1181 
1182  return system(cmd, bg);
1183 }
1184 
1185 
1186 int Foam::system(const UList<Foam::string>& command, const bool bg)
1187 {
1188  if (command.empty())
1189  {
1190  // Treat an empty command as a successful no-op.
1191  return 0;
1192  }
1193 
1194  const int count = command.size();
1195 
1196  std::string cmd;
1197 
1198  for (int i = 0; i < count; ++i)
1199  {
1200  if (i) cmd += ' ';
1201  cmd += command[i];
1202  }
1203 
1204  return system(cmd, bg);
1205 }
1206 
1207 
1208 // Explicitly track loaded libraries, rather than use
1209 // EnumerateLoadedModules64 and have to link against
1210 // Dbghelp.dll
1211 // Details at http://msdn.microsoft.com/en-us/library/ms679316(v=vs.85).aspx
1212 
1213 static std::unordered_map<void*, std::string> libsLoaded;
1214 
1215 
1216 void* Foam::dlOpen(const fileName& libName, const bool check)
1217 {
1218  if (MSwindows::debug)
1219  {
1220  std::cout
1221  << "dlOpen(const fileName&)"
1222  << " : dlopen of " << libName << std::endl;
1223  }
1224 
1225  // Always remap "libXX.so" and "libXX" to "libXX.dll"
1226  fileName libso(libName.lessExt().ext(EXT_SO));
1227 
1228  void* handle = ::LoadLibrary(libso.c_str());
1229 
1230  if
1231  (
1232  !handle
1233  && libName.find('/') == std::string::npos
1234  && !libso.starts_with("lib")
1235  )
1236  {
1237  // Try with 'lib' prefix
1238  libso = "lib" + libso;
1239  handle = ::LoadLibrary(libso.c_str());
1240 
1241  if (MSwindows::debug)
1242  {
1243  std::cout
1244  << "dlOpen(const fileName&)"
1245  << " : dlopen of " << libso << std::endl;
1246  }
1247  }
1248 
1249  if (handle)
1250  {
1251  libsLoaded[handle] = libso.lessExt();
1252  }
1253  else if (check)
1254  {
1256  << "dlopen error : " << MSwindows::lastError() << endl;
1257  }
1258 
1259  if (MSwindows::debug)
1260  {
1261  std::cout
1262  << "dlOpen(const fileName&)"
1263  << " : dlopen of " << libName
1264  << " handle " << handle << std::endl;
1265  }
1266 
1267  return handle;
1268 }
1269 
1270 
1271 void* Foam::dlOpen(const fileName& libName, std::string& errorMsg)
1272 {
1273  // Call without emitting error message - we capture that ourselves
1274  void* handle = Foam::dlOpen(libName, false);
1275 
1276  if (!handle)
1277  {
1278  // Capture error message
1279  errorMsg = MSwindows::lastError();
1280  }
1281  else
1282  {
1283  // No errors
1284  errorMsg.clear();
1285  }
1286 
1287  return handle;
1288 }
1289 
1290 
1291 Foam::label Foam::dlOpen
1293  std::initializer_list<fileName> libNames,
1294  const bool check
1295 )
1296 {
1297  label nLoaded = 0;
1298 
1299  for (const fileName& libName : libNames)
1300  {
1301  if (Foam::dlOpen(libName, check))
1302  {
1303  ++nLoaded;
1304  }
1305  }
1306 
1307  return nLoaded;
1308 }
1309 
1310 
1311 bool Foam::dlClose(void* const handle)
1312 {
1313  if (MSwindows::debug)
1314  {
1315  std::cout
1316  << "dlClose(void*)"
1317  << " : dlclose of handle " << handle << std::endl;
1318  }
1319 
1320  const bool ok = ::FreeLibrary(static_cast<HMODULE>(handle));
1321 
1322  if (ok)
1323  {
1324  libsLoaded.erase(handle);
1325  }
1326 
1327  return ok;
1328 }
1329 
1330 
1331 void* Foam::dlSymFind(void* handle, const std::string& symbol, bool required)
1332 {
1333  if (!required && (!handle || symbol.empty()))
1334  {
1335  return nullptr;
1336  }
1337 
1338  if (MSwindows::debug)
1339  {
1340  std::cout
1341  << "dlSymFind(void*, const std::string&, bool)"
1342  << " : dlsym of " << symbol << std::endl;
1343  }
1344 
1345  // Get address of symbol, or nullptr on failure
1346  void* fun =
1347  reinterpret_cast<void *>
1348  (
1349  ::GetProcAddress(static_cast<HMODULE>(handle), symbol.c_str())
1350  );
1351 
1352  // Any error?
1353  if (!fun && required)
1354  {
1356  << "Cannot lookup symbol " << symbol << " : "
1357  << MSwindows::lastError() << endl;
1358  }
1359 
1360  return fun;
1361 }
1362 
1363 
1365 {
1366  DynamicList<fileName> libs(libsLoaded.size());
1367 
1368  for (const auto& item : libsLoaded)
1369  {
1370  libs.append(item.second);
1371  }
1372 
1373  if (MSwindows::debug)
1374  {
1375  std::cout
1376  << "dlLoaded()"
1377  << " : determined loaded libraries :" << libs.size() << std::endl;
1378  }
1379 
1380  return libs;
1381 }
1382 
1383 
1384 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::word::lessExt
word lessExt() const
Return word without extension (part before last .)
Definition: word.C:113
Foam::domainName
string domainName()
Return the system's domain name, as per hostname(1) with the '-d' option.
Definition: MSwindows.C:420
InfoInFunction
#define InfoInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:350
Foam::abortHandlerInstalled
static const bool abortHandlerInstalled
Definition: MSwindows.C:82
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
ms_isdir
#define ms_isdir(a)
Definition: MSwindows.C:581
Foam::installAbortHandler
static bool installAbortHandler()
Definition: MSwindows.C:74
IOstreams.H
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
Foam::exists
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:625
Foam::output
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
Foam::MSwindows::directoryIterator::next
bool next()
Read next item, always ignoring "." and ".." entries.
Definition: MSwindows.C:203
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::chMod
bool chMod(const fileName &name, const mode_t mode)
Set the file/directory mode, return true on success.
Definition: MSwindows.C:557
Foam::List::resize
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::fileName::path
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:176
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:55
Foam::string::starts_with
bool starts_with(const std::string &s) const
True if string starts with the given prefix (cf. C++20)
Definition: string.H:297
ms_isreg
#define ms_isreg(s)
Definition: MSwindows.C:585
Foam::MSwindows::directoryIterator::close
void close()
Close directory.
Definition: MSwindows.C:185
Foam::fileName::name
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:199
Foam::MSwindows::directoryIterator::exists
bool exists() const
Directory existed for opening.
Definition: MSwindows.C:173
Foam::system
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: MSwindows.C:1150
Foam::sigAbortHandler
static void sigAbortHandler(int exitCode)
Definition: MSwindows.C:69
Foam::fileName::Type
Type
Enumerations to handle directory entry types.
Definition: fileName.H:80
Foam::fileStat
Wrapper for stat() and lstat() system calls.
Definition: fileStat.H:67
Foam::isFile
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:658
Foam::rm
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition: MSwindows.C:1004
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::fdClose
void fdClose(const int fd)
Close file descriptor.
Definition: MSwindows.C:1114
Foam::setEnv
bool setEnv(const word &name, const std::string &value, const bool overwrite)
Set an environment variable, return true on success.
Definition: MSwindows.C:395
Foam::fileName::lessExt
fileName lessExt() const
Return file name without extension (part before last .)
Definition: fileNameI.H:230
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:76
Foam::getEnv
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: MSwindows.C:371
Foam::pgid
pid_t pgid()
Return the group PID of this process.
Definition: MSwindows.C:350
Foam::isAdministrator
bool isAdministrator()
Is the current user the administrator (root)
Definition: MSwindows.C:442
Foam::mode
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: MSwindows.C:564
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::hasEnv
bool hasEnv(const std::string &envName)
True if environment variable of given name is defined.
Definition: MSwindows.C:363
Foam::MSwindows::directoryIterator::directoryIterator
directoryIterator(const fileName &dirName, bool allowHidden=false)
Construct for dirName, optionally allowing hidden files/dirs.
Definition: MSwindows.C:135
Foam::userName
string userName()
Return the user's login name.
Definition: MSwindows.C:429
Foam::fileSize
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:676
Foam::check
static void check(const int retVal, const char *what)
Definition: ptscotchDecomp.C:80
Foam::word::hasExt
bool hasExt() const
Various checks for extensions.
Definition: stringI.H:56
Foam::dlSymFind
void * dlSymFind(void *handle, const std::string &symbol, bool required=false)
Look for symbol in a dlopened library.
Definition: MSwindows.C:1331
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
Foam::pid
pid_t pid()
Return the PID of this process.
Definition: MSwindows.C:330
Foam::MSwindows::directoryIterator::good
bool good() const
Directory pointer is valid.
Definition: MSwindows.C:179
Foam::fileName::type
Type type(bool followLink=true, bool checkGzip=false) const
Definition: fileName.C:360
Foam::ppid
pid_t ppid()
Return the parent PID of this process.
Definition: MSwindows.C:337
fileName.H
Foam::highResLastModified
double highResLastModified(const fileName &, const bool followLink=true)
Return time of last file modification.
Definition: MSwindows.C:699
EXT_SO
#define EXT_SO
Definition: MSwindows.C:54
Foam::MSwindows::directoryIterator::operator++
directoryIterator & operator++()
Same as next()
Definition: MSwindows.C:240
Foam::ping
bool ping(const std::string &destName, const label port, const label timeOut)
Check if machine is up by pinging given port.
Definition: MSwindows.C:1126
Foam::fileStat::valid
bool valid() const
Was file-stat successful?
Definition: fileStat.H:128
Foam::UList::empty
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
Foam::FatalError
error FatalError
Foam::mv
bool mv(const fileName &src, const fileName &dst, const bool followLink=false)
Rename src to dst.
Definition: MSwindows.C:939
Foam::MSwindows::directoryIterator
A simple directory contents iterator.
Definition: MSwindows.C:111
Pstream.H
Foam::fileName::ext
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:218
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::MSwindows::lastError
std::string lastError()
The last Windows API error from GetLastError.
Definition: MSwindows.C:253
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
isGzFile
static bool isGzFile(const std::string &name)
Definition: MSwindows.C:617
Foam::MSwindows::directoryIterator::operator*
const std::string & operator*() const
Same as val()
Definition: MSwindows.C:234
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::mvBak
bool mvBak(const fileName &src, const std::string &ext="bak")
Rename to a corresponding backup file.
Definition: MSwindows.C:968
Foam::chDir
bool chDir(const fileName &dir)
Change current directory to the one specified and return true on success.
Definition: MSwindows.C:500
CStringList.H
Foam::home
fileName home()
Return home directory path name for the current user.
Definition: MSwindows.C:449
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::fileStat::status
const struct stat & status() const
Raw status.
Definition: fileStat.H:122
Foam::cp
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy the source to the destination (recursively if necessary).
Definition: MSwindows.C:802
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::fileStat::dmodTime
double dmodTime() const
Return the modification time in seconds (nanosecond resolution)
Definition: fileStat.C:123
Foam::rmDir
bool rmDir(const fileName &directory, const bool silent=false)
Remove a directory and its contents (optionally silencing warnings)
Definition: MSwindows.C:1028
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:77
Foam::env
bool env(const std::string &envName)
Deprecated(2020-05) check for existence of environment variable.
Definition: OSspecific.H:82
Foam::CStringList::size
int size() const noexcept
Return the number of C-strings (ie, argc)
Definition: CStringListI.H:122
Foam::fileStat::modTime
time_t modTime() const
Return the modification time in seconds.
Definition: fileStat.C:117
Foam::List< fileName >
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::MSwindows::userName
std::string userName()
The user-name from Windows API GetUserName.
Definition: MSwindows.C:297
Foam::hostName
string hostName(bool full=false)
Return the system's host name, as per hostname(1)
Definition: MSwindows.C:410
bool
bool
Definition: EEqn.H:20
Foam::dlClose
bool dlClose(void *handle)
Close a dlopened library using handle. Return true if successful.
Definition: MSwindows.C:1311
Foam::renameFile
static bool renameFile(const fileName &src, const fileName &dst)
Definition: MSwindows.C:86
Foam::roots::type
type
Types of root.
Definition: Roots.H:54
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::ln
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: MSwindows.C:925
Foam::cwd
fileName cwd()
The physical or logical current working directory path name.
Definition: MSwindows.C:468
DynamicList.H
libsLoaded
static std::unordered_map< void *, std::string > libsLoaded
Definition: MSwindows.C:1213
Foam::dlLoaded
fileNameList dlLoaded()
Return all loaded libraries.
Definition: MSwindows.C:1364
MSwindows.H
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Foam::MSwindows::directoryIterator::~directoryIterator
~directoryIterator()
Destructor.
Definition: MSwindows.C:164
Foam::stringOps::validate
StringType validate(const std::string &str, const UnaryPredicate &accept, const bool invert=false)
Return a copy of the input string with validated characters.
Definition: stringOpsTemplates.C:71
Foam::mkDir
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:507
Foam::readDir
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:707
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::error
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:73
Foam::sleep
unsigned int sleep(const unsigned int sec)
Sleep for the specified number of seconds.
Definition: MSwindows.C:1106
Foam::dlOpen
void * dlOpen(const fileName &libName, const bool check=true)
Open a shared library and return handle to library.
Definition: MSwindows.C:1216
Foam::CStringList::empty
bool empty() const noexcept
True if the size is zero.
Definition: CStringListI.H:116
Foam::lastModified
time_t lastModified(const fileName &name, const bool followLink=true)
Return time of last file modification (normally follows symbolic links).
Definition: MSwindows.C:692
Foam::MSwindows::directoryIterator::val
const std::string & val() const
The current item.
Definition: MSwindows.C:195
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643
Foam::CStringList
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:69