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-2020 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 dest is a directory, create the destination file name.
860  if (destFile.type() == fileName::DIRECTORY)
861  {
862  destFile /= src.components().last();
863  }
864 
865  // Make sure the destination directory extists.
866  if (!isDir(destFile) && !mkDir(destFile))
867  {
868  return false;
869  }
870 
871  // Copy files
872  fileNameList files = readDir(src, fileName::FILE, false, followLink);
873  for (const fileName& item : files)
874  {
875  if (MSwindows::debug)
876  {
877  Info<< "Copying : " << src/item
878  << " to " << destFile/item << endl;
879  }
880 
881  // File to file.
882  Foam::cp(src/item, destFile/item);
883  }
884 
885  // Copy sub directories.
886  fileNameList dirs = readDir
887  (
888  src,
889  fileName::DIRECTORY,
890  false,
891  followLink
892  );
893 
894  for (const fileName& item : dirs)
895  {
896  if (MSwindows::debug)
897  {
898  Info<< "Copying : " << src/item
899  << " to " << destFile << endl;
900  }
901 
902  // Dir to Dir.
903  Foam::cp(src/item, destFile);
904  }
905  }
906  else
907  {
908  return false;
909  }
910 
911  return true;
912 }
913 
914 
915 bool Foam::ln(const fileName& src, const fileName& dst)
916 {
917  // links are poorly supported, or need administrator privileges.
918  // Skip for now.
919 
920  if (MSwindows::debug)
921  {
922  Info<< "MSwindows does not support ln - softlinking" << endl;
923  }
924 
925  return false;
926 }
927 
928 
929 bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
930 {
931  if (MSwindows::debug)
932  {
933  Info<< "Move : " << src << " to " << dst << endl;
934  }
935 
936  // Ignore an empty names => always false
937  if (src.empty() || dst.empty())
938  {
939  return false;
940  }
941 
942 
943  if
944  (
945  dst.type() == fileName::DIRECTORY
946  && src.type(followLink) != fileName::DIRECTORY
947  )
948  {
949  const fileName dstName(dst/src.name());
950 
951  return renameFile(src, dstName);
952  }
953 
954  return renameFile(src, dst);
955 }
956 
957 
958 bool Foam::mvBak(const fileName& src, const std::string& ext)
959 {
960  // Ignore an empty name or extension => always false
961  if (src.empty() || ext.empty())
962  {
963  return false;
964  }
965 
966  if (exists(src, false))
967  {
968  constexpr const int maxIndex = 99;
969  char index[3];
970 
971  for (int n = 0; n <= maxIndex; ++n)
972  {
973  fileName dstName(src + "." + ext);
974  if (n)
975  {
976  sprintf(index, "%02d", n);
977  dstName += index;
978  }
979 
980  // avoid overwriting existing files, except for the last
981  // possible index where we have no choice
982  if (!exists(dstName, false) || n == maxIndex)
983  {
984  return renameFile(src, dstName);
985  }
986  }
987  }
988 
989  // fall-through: nothing to do
990  return false;
991 }
992 
993 
994 bool Foam::rm(const fileName& file)
995 {
996  if (MSwindows::debug)
997  {
998  Info<< "Removing : " << file << endl;
999  }
1000 
1001  // Ignore an empty name => always false
1002  if (file.empty())
1003  {
1004  return false;
1005  }
1006 
1007 
1008  // If removal of plain file name failed, try with .gz
1009 
1010  return
1011  (
1012  0 == std::remove(file.c_str())
1013  || 0 == std::remove((file + ".gz").c_str())
1014  );
1015 }
1016 
1017 
1018 bool Foam::rmDir(const fileName& directory, const bool silent)
1019 {
1020  // Iterate contents (ignores an empty directory name)
1021  // Also retain hidden files/dirs for removal
1022 
1023  MSwindows::directoryIterator dirIter(directory, true);
1024 
1025  if (!dirIter.exists())
1026  {
1027  if (!silent)
1028  {
1030  << "cannot open directory " << directory << endl;
1031  }
1032  }
1033 
1034  if (MSwindows::debug)
1035  {
1037  << " : removing directory " << directory << endl;
1038  }
1039 
1040 
1041  // Process each directory entry, counting any errors encountered
1042  label nErrors = 0;
1043 
1044  for (/*nil*/; dirIter; ++dirIter)
1045  {
1046  const std::string& item = *dirIter;
1047 
1048  // Allow invalid characters (spaces, quotes, etc),
1049  // otherwise we cannot remove subdirs with these types of names.
1050  // -> const fileName path = directory/name; <-
1051 
1052  const fileName path(fileName::concat(directory, item));
1053 
1054  if (path.type(false) == fileName::DIRECTORY)
1055  {
1056  if (!rmDir(path, true)) // Only report errors at the top-level
1057  {
1058  ++nErrors;
1059  }
1060  }
1061  else
1062  {
1063  if (!rm(path))
1064  {
1065  ++nErrors;
1066  }
1067  }
1068  }
1069 
1070  if (nErrors)
1071  {
1072  if (!silent)
1073  {
1075  << "failed to remove directory " << directory << nl
1076  << "could not remove " << nErrors << " sub-entries" << endl;
1077  }
1078  }
1079  else
1080  {
1081  if (!::RemoveDirectory(directory.c_str()))
1082  {
1083  ++nErrors;
1084  if (!silent)
1085  {
1087  << "failed to remove directory " << directory << endl;
1088  }
1089  }
1090  }
1091 
1092  return !nErrors;
1093 }
1094 
1095 
1096 unsigned int Foam::sleep(const unsigned int sec)
1097 {
1098  ::Sleep(1000*sec); // in milliseconds
1099 
1100  return 0;
1101 }
1102 
1103 
1104 void Foam::fdClose(const int fd)
1105 {
1106  if (::_close(fd) != 0)
1107  {
1109  << "close error on " << fd << endl
1110  << abort(FatalError);
1111  }
1112 }
1113 
1114 
1115 bool Foam::ping
1117  const std::string& destName,
1118  const label destPort,
1119  const label timeOut
1120 )
1121 {
1122  // Appears that socket calls require administrator privileges.
1123  // Skip for now.
1124 
1125  if (MSwindows::debug)
1126  {
1127  Info<< "MSwindows does not support ping" << endl;
1128  }
1129 
1130  return false;
1131 }
1132 
1133 
1134 bool Foam::ping(const std::string& host, const label timeOut)
1135 {
1136  return ping(host, 222, timeOut) || ping(host, 22, timeOut);
1137 }
1138 
1139 
1140 int Foam::system(const std::string& command, const bool bg)
1141 {
1142  if (MSwindows::debug && bg)
1143  {
1145  << "MSwindows does not support background (fork) tasks" << endl;
1146  }
1147 
1148  return std::system(command.c_str());
1149 }
1150 
1151 
1152 int Foam::system(const CStringList& command, const bool bg)
1153 {
1154  if (command.empty())
1155  {
1156  // Treat an empty command as a successful no-op.
1157  // For consistency with POSIX (man sh) behaviour for (sh -c command),
1158  // which is what is mostly being replicated here.
1159  return 0;
1160  }
1161 
1162  const int count = command.size();
1163 
1164  std::string cmd;
1165 
1166  for (int i = 0; i < count; ++i)
1167  {
1168  if (i) cmd += ' ';
1169  cmd += command[i];
1170  }
1171 
1172  return system(cmd, bg);
1173 }
1174 
1175 
1176 int Foam::system(const UList<Foam::string>& command, const bool bg)
1177 {
1178  if (command.empty())
1179  {
1180  // Treat an empty command as a successful no-op.
1181  return 0;
1182  }
1183 
1184  const int count = command.size();
1185 
1186  std::string cmd;
1187 
1188  for (int i = 0; i < count; ++i)
1189  {
1190  if (i) cmd += ' ';
1191  cmd += command[i];
1192  }
1193 
1194  return system(cmd, bg);
1195 }
1196 
1197 
1198 // Explicitly track loaded libraries, rather than use
1199 // EnumerateLoadedModules64 and have to link against
1200 // Dbghelp.dll
1201 // Details at http://msdn.microsoft.com/en-us/library/ms679316(v=vs.85).aspx
1202 
1203 static std::unordered_map<void*, std::string> libsLoaded;
1204 
1205 
1206 void* Foam::dlOpen(const fileName& libName, const bool check)
1207 {
1208  if (MSwindows::debug)
1209  {
1210  std::cout
1211  << "dlOpen(const fileName&)"
1212  << " : dlopen of " << libName << std::endl;
1213  }
1214 
1215  // Always remap "libXX.so" and "libXX" to "libXX.dll"
1216  fileName libso(libName.lessExt().ext(EXT_SO));
1217 
1218  void* handle = ::LoadLibrary(libso.c_str());
1219 
1220  if
1221  (
1222  !handle
1223  && libName.find('/') == std::string::npos
1224  && !libso.starts_with("lib")
1225  )
1226  {
1227  // Try with 'lib' prefix
1228  libso = "lib" + libso;
1229  handle = ::LoadLibrary(libso.c_str());
1230 
1231  if (MSwindows::debug)
1232  {
1233  std::cout
1234  << "dlOpen(const fileName&)"
1235  << " : dlopen of " << libso << std::endl;
1236  }
1237  }
1238 
1239  if (handle)
1240  {
1241  libsLoaded[handle] = libso.lessExt();
1242  }
1243  else if (check)
1244  {
1246  << "dlopen error : " << MSwindows::lastError() << endl;
1247  }
1248 
1249  if (MSwindows::debug)
1250  {
1251  std::cout
1252  << "dlOpen(const fileName&)"
1253  << " : dlopen of " << libName
1254  << " handle " << handle << std::endl;
1255  }
1256 
1257  return handle;
1258 }
1259 
1260 
1261 void* Foam::dlOpen(const fileName& libName, std::string& errorMsg)
1262 {
1263  // Call without emitting error message - we capture that ourselves
1264  void* handle = Foam::dlOpen(libName, false);
1265 
1266  if (!handle)
1267  {
1268  // Capture error message
1269  errorMsg = MSwindows::lastError();
1270  }
1271  else
1272  {
1273  // No errors
1274  errorMsg.clear();
1275  }
1276 
1277  return handle;
1278 }
1279 
1280 
1281 Foam::label Foam::dlOpen
1283  std::initializer_list<fileName> libNames,
1284  const bool check
1285 )
1286 {
1287  label nLoaded = 0;
1288 
1289  for (const fileName& libName : libNames)
1290  {
1291  if (Foam::dlOpen(libName, check))
1292  {
1293  ++nLoaded;
1294  }
1295  }
1296 
1297  return nLoaded;
1298 }
1299 
1300 
1301 bool Foam::dlClose(void* const handle)
1302 {
1303  if (MSwindows::debug)
1304  {
1305  std::cout
1306  << "dlClose(void*)"
1307  << " : dlclose of handle " << handle << std::endl;
1308  }
1309 
1310  const bool ok = ::FreeLibrary(static_cast<HMODULE>(handle));
1311 
1312  if (ok)
1313  {
1314  libsLoaded.erase(handle);
1315  }
1316 
1317  return ok;
1318 }
1319 
1320 
1321 void* Foam::dlSymFind(void* handle, const std::string& symbol, bool required)
1322 {
1323  if (!required && (!handle || symbol.empty()))
1324  {
1325  return nullptr;
1326  }
1327 
1328  if (MSwindows::debug)
1329  {
1330  std::cout
1331  << "dlSymFind(void*, const std::string&, bool)"
1332  << " : dlsym of " << symbol << std::endl;
1333  }
1334 
1335  // Get address of symbol, or nullptr on failure
1336  void* fun =
1337  reinterpret_cast<void *>
1338  (
1339  ::GetProcAddress(static_cast<HMODULE>(handle), symbol.c_str())
1340  );
1341 
1342  // Any error?
1343  if (!fun && required)
1344  {
1346  << "Cannot lookup symbol " << symbol << " : "
1347  << MSwindows::lastError() << endl;
1348  }
1349 
1350  return fun;
1351 }
1352 
1353 
1355 {
1356  DynamicList<fileName> libs(libsLoaded.size());
1357 
1358  for (const auto& item : libsLoaded)
1359  {
1360  libs.append(item.second);
1361  }
1362 
1363  if (MSwindows::debug)
1364  {
1365  std::cout
1366  << "dlLoaded()"
1367  << " : determined loaded libraries :" << libs.size() << std::endl;
1368  }
1369 
1370  return libs;
1371 }
1372 
1373 
1374 // ************************************************************************* //
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:325
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::fileName::components
wordList components(const char delim='/') const
Return path components as wordList.
Definition: fileName.C:473
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
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::fileName::path
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:186
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:299
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:209
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:1140
validate
thermo validate(args.executable(), "h")
Foam::sigAbortHandler
static void sigAbortHandler(int exitCode)
Definition: MSwindows.C:69
Foam::fileName::Type
Type
Enumerations to handle directory entry types.
Definition: fileName.H:76
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:994
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::fdClose
void fdClose(const int fd)
Close file descriptor.
Definition: MSwindows.C:1104
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:240
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:73
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::word::hasExt
bool hasExt() const
Return true if it has an extension or simply ends with a '.'.
Definition: wordI.H:165
Foam::dlSymFind
void * dlSymFind(void *handle, const std::string &symbol, bool required=false)
Look for symbol in a dlopened library.
Definition: MSwindows.C:1321
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:474
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:268
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:1116
Foam::fileStat::valid
bool valid() const
Was file-stat successful?
Definition: fileStat.H:128
Foam::List::resize
void resize(const label newSize)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::UList::empty
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:374
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:929
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:228
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:958
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:381
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:385
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:1018
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
Foam::hostName
string hostName(const bool full=false)
Return the system's host name, as per hostname(1)
Definition: MSwindows.C:410
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
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:1301
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::UList::size
void size(const label n) noexcept
Override size to be inconsistent with allocated storage.
Definition: UListI.H:360
Foam::ln
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: MSwindows.C:915
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:1203
Foam::dlLoaded
fileNameList dlLoaded()
Return all loaded libraries.
Definition: MSwindows.C:1354
MSwindows.H
Foam::MSwindows::directoryIterator::~directoryIterator
~directoryIterator()
Destructor.
Definition: MSwindows.C:164
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:303
Foam::error
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:70
Foam::sleep
unsigned int sleep(const unsigned int sec)
Sleep for the specified number of seconds.
Definition: MSwindows.C:1096
Foam::dlOpen
void * dlOpen(const fileName &libName, const bool check=true)
Open a shared library and return handle to library.
Definition: MSwindows.C:1206
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