POSIX.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) 2016-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Description
28  POSIX versions of the functions declared in OSspecific.H
29 
30 \*---------------------------------------------------------------------------*/
31 
32 #if defined(__sun__) && defined(__GNUC__)
33  // Not certain if this is still required
34  #define _SYS_VNODE_H
35 #endif
36 
37 #include "OSspecific.H"
38 #include "POSIX.H"
39 #include "fileName.H"
40 #include "fileStat.H"
41 #include "timer.H"
42 #include "DynamicList.H"
43 #include "CStringList.H"
44 #include "stringOps.H"
45 #include "IOstreams.H"
46 #include "Pstream.H"
47 
48 #include <fstream>
49 #include <cstdlib>
50 #include <cctype>
51 
52 #include <cstdio>
53 #include <unistd.h>
54 #include <dirent.h>
55 #include <pwd.h>
56 #include <errno.h>
57 #include <sys/types.h>
58 #include <sys/wait.h>
59 #include <sys/stat.h>
60 #include <sys/socket.h>
61 #include <netdb.h>
62 #include <netinet/in.h>
63 #include <dlfcn.h>
64 
65 #ifdef __APPLE__
66  #define EXT_SO "dylib"
67  #include <mach-o/dyld.h>
68 #else
69  #define EXT_SO "so"
70 
71  // PGI does not have __int128_t
72  #ifdef __PGIC__
73  #define __ILP32__
74  #endif
75 
76  #include <link.h>
77 #endif
78 
79 
80 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
81 
82 namespace Foam
83 {
84  defineTypeNameAndDebug(POSIX, 0);
85 }
86 
87 static bool cwdPreference_(Foam::debug::optimisationSwitch("cwd", 0));
88 
89 
90 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
91 
92 // After a fork in system(), before the exec() do the following
93 // - close stdin when executing in background (daemon-like)
94 // - redirect stdout to stderr when infoDetailLevel == 0
95 static inline void redirects(const bool bg)
96 {
97  if (bg)
98  {
99  // Close stdin(0) - unchecked return value
100  (void) ::close(STDIN_FILENO);
101  }
102 
103  // Redirect stdout(1) to stderr(2) '1>&2'
104  if (Foam::infoDetailLevel == 0)
105  {
106  // This is correct. 1>&2 means dup2(2, 1);
107  (void) ::dup2(STDERR_FILENO, STDOUT_FILENO);
108  }
109 }
110 
112 // Library loading is normally simply via dlopen(),
113 // but SIP (System Integrity Protection) on Apple will generally
114 // clear out the DYLD_LIBRARY_PATH set from shell scripts.
115 // We thus have FOAM_LD_LIBRARY_PATH as a shadow parameter and use
116 // that to attempt loading ourselves
117 static inline void* loadLibrary(const Foam::fileName& libName)
118 {
119  constexpr int ldflags = (RTLD_LAZY|RTLD_GLOBAL);
120 
121 #ifdef __APPLE__
122  using namespace Foam;
123 
124  const char* normal = nullptr;
125  const char* shadow = nullptr;
126 
127  if
128  (
129  !libName.isAbsolute()
130  && ((normal = ::getenv("DYLD_LIBRARY_PATH")) == nullptr || !*normal)
131  && ((shadow = ::getenv("FOAM_LD_LIBRARY_PATH")) != nullptr && *shadow)
132  )
133  {
134  // SIP appears to have cleared DYLD_LIBRARY_PATH but the
135  // shadow parameter is available
136 
137  const std::string ldPaths(shadow);
138  const auto paths = Foam::stringOps::split(ldPaths, ':');
139 
140  for (const auto& p : paths)
141  {
142  if (p.length()) // Split removes empty, but be paranoid
143  {
144  const Foam::fileName fullPath(p.str()/libName);
145  void* handle = ::dlopen(fullPath.c_str(), ldflags);
146  if (handle)
147  {
148  return handle;
149  }
150  }
151  }
152  }
153 #endif
154 
155  // Regular loading
156  return ::dlopen(libName.c_str(), ldflags);
157 }
159 
160 // * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * //
161 
162 namespace Foam
163 {
164 namespace POSIX
165 {
166 
167 //- A simple directory contents iterator
168 class directoryIterator
169 {
170  DIR* dirptr_;
171 
172  bool exists_;
173 
174  bool hidden_;
175 
176  std::string item_;
177 
178  //- Accept file/dir name
179  inline bool accept() const
180  {
181  return
182  (
183  item_.size() && item_ != "." && item_ != ".."
184  && (hidden_ || item_[0] != '.')
185  );
186  }
187 
188 
189 public:
190 
191  // Constructors
192 
193  //- Construct for dirName, optionally allowing hidden files/dirs
194  directoryIterator(const std::string& dirName, bool allowHidden = false)
195  :
196  dirptr_(nullptr),
197  exists_(false),
198  hidden_(allowHidden),
199  item_()
200  {
201  if (!dirName.empty())
202  {
203  dirptr_ = ::opendir(dirName.c_str());
204  exists_ = (dirptr_ != nullptr);
205  next(); // Move to first element
206  }
207  }
208 
209 
210  //- Destructor
212  {
213  close();
214  }
215 
216 
217  // Member Functions
218 
219  //- Directory open succeeded
220  bool exists() const noexcept
221  {
222  return exists_;
223  }
225  //- Directory pointer is valid
226  bool good() const noexcept
227  {
228  return dirptr_;
229  }
230 
231  //- Close directory
232  void close()
233  {
234  if (dirptr_)
235  {
236  ::closedir(dirptr_);
237  dirptr_ = nullptr;
238  }
239  }
241  //- The current item
242  const std::string& val() const noexcept
243  {
244  return item_;
245  }
246 
247  //- Read next item, always ignoring "." and ".." entries.
248  // Normally also ignore hidden files/dirs (beginning with '.')
249  // Automatically close when there are no more items
250  bool next()
251  {
252  struct dirent *list;
253 
254  while (dirptr_ && (list = ::readdir(dirptr_)) != nullptr)
255  {
256  item_ = list->d_name;
257 
258  if (accept())
259  {
260  return true;
261  }
262  }
263  close(); // No more items
264 
265  return false;
266  }
267 
268 
269  // Member Operators
270 
271  //- Same as good()
272  operator bool() const noexcept
273  {
274  return good();
275  }
276 
277  //- Same as val()
278  const std::string& operator*() const noexcept
279  {
280  return val();
281  }
282 
283  //- Same as next()
285  {
286  next();
287  return *this;
288  }
289 };
290 
291 } // End namespace POSIX
292 } // End namespace Foam
293 
294 
295 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
296 
297 pid_t Foam::pid()
298 {
299  return ::getpid();
300 }
301 
302 
303 pid_t Foam::ppid()
304 {
305  return ::getppid();
306 }
307 
308 
309 pid_t Foam::pgid()
310 {
311  return ::getpgrp();
312 }
313 
314 
315 bool Foam::hasEnv(const std::string& envName)
316 {
317  // An empty envName => always false
318  return !envName.empty() && ::getenv(envName.c_str()) != nullptr;
319 }
320 
321 
322 Foam::string Foam::getEnv(const std::string& envName)
323 {
324  // Ignore an empty envName => always ""
325  char* env = envName.empty() ? nullptr : ::getenv(envName.c_str());
326 
327  if (env)
328  {
329  return string(env);
330  }
331 
332  // Return null-constructed string rather than string::null
333  // to avoid cyclic dependencies in the construction of globals
334  return string();
335 }
336 
337 
338 bool Foam::setEnv
339 (
340  const word& envName,
341  const std::string& value,
342  const bool overwrite
343 )
344 {
345  // Ignore an empty envName => always false
346  return
347  (
348  !envName.empty()
349  && ::setenv(envName.c_str(), value.c_str(), overwrite) == 0
350  );
351 }
352 
353 
355 {
356  char buf[128];
357  ::gethostname(buf, sizeof(buf));
358  return buf;
359 }
360 
361 
362 // DEPRECATED (2022-01)
363 Foam::string Foam::hostName(bool full)
364 {
365  // implementation as per hostname from net-tools
366  if (full)
367  {
368  char buf[128];
369  ::gethostname(buf, sizeof(buf));
370 
371  struct hostent *hp = ::gethostbyname(buf);
372  if (hp)
373  {
374  return hp->h_name;
375  }
376  return buf;
377  }
378 
379  return Foam::hostName();
380 }
381 
383 // DEPRECATED (2022-01)
385 {
386  char buf[128];
387  ::gethostname(buf, sizeof(buf));
388 
389  // implementation as per hostname from net-tools
390  struct hostent *hp = ::gethostbyname(buf);
391  if (hp)
392  {
393  char *p = ::strchr(hp->h_name, '.');
394  if (p)
395  {
396  ++p;
397  return p;
398  }
399  }
400 
401  return string();
402 }
404 
406 {
407  struct passwd* pw = ::getpwuid(::getuid());
408  if (pw != nullptr)
409  {
410  return pw->pw_name;
411  }
412 
413  return string();
414 }
415 
416 
418 {
419  return (::geteuid() == 0);
420 }
421 
422 
424 {
425  char* env = ::getenv("HOME");
426  if (env)
427  {
428  return fileName(env);
429  }
430 
431  struct passwd* pw = ::getpwuid(::getuid());
432  if (pw)
433  {
434  return pw->pw_dir;
435  }
437  return fileName();
438 }
439 
440 
441 Foam::fileName Foam::home(const std::string& userName)
442 {
443  // An empty userName => same as home()
444  if (userName.empty())
445  {
446  return Foam::home();
447  }
448 
449  struct passwd* pw = ::getpwnam(userName.c_str());
450  if (pw)
451  {
452  return pw->pw_dir;
453  }
454 
455  return fileName();
456 }
457 
458 
459 namespace Foam
460 {
461 
462 //- The physical current working directory path name (pwd -P).
463 static Foam::fileName cwd_P()
464 {
465  label pathLengthLimit = POSIX::pathLengthChunk;
466  List<char> path(pathLengthLimit);
467 
468  // Resize path if getcwd fails with an ERANGE error
469  while (pathLengthLimit == path.size())
470  {
471  if (::getcwd(path.data(), path.size()))
472  {
473  return path.data();
474  }
475  else if (errno == ERANGE)
476  {
477  // Increment path length up to the pathLengthMax limit
478  if
479  (
480  (pathLengthLimit += POSIX::pathLengthChunk)
482  )
483  {
485  << "Attempt to increase path length beyond limit of "
487  << exit(FatalError);
488  }
489 
490  path.resize(pathLengthLimit);
491  }
492  else
493  {
494  break;
495  }
496  }
497 
499  << "Couldn't get the current working directory"
500  << exit(FatalError);
501 
502  return fileName();
503 }
504 
505 
506 //- The logical current working directory path name.
507 // From the PWD environment, same as pwd -L.
508 static Foam::fileName cwd_L()
509 {
510  const char* env = ::getenv("PWD");
511 
512  // Basic check
513  if (!env || env[0] != '/')
514  {
516  << "PWD is invalid - reverting to physical description"
517  << nl;
518 
519  return cwd_P();
520  }
521 
522  fileName dir(env);
523 
524  // Check for "/."
525  for
526  (
528  std::string::npos != (pos = dir.find("/.", pos));
529  /*nil*/
530  )
531  {
532  pos += 2;
533 
534  if
535  (
536  // Ends in "/." or has "/./"
537  !dir[pos] || dir[pos] == '/'
538 
539  // Ends in "/.." or has "/../"
540  || (dir[pos] == '.' && (!dir[pos+1] || dir[pos+1] == '/'))
541  )
542  {
544  << "PWD contains /. or /.. - reverting to physical description"
545  << nl;
546 
547  return cwd_P();
548  }
549  }
550 
551  // Finally, verify that PWD actually corresponds to the "." directory
552  if (!fileStat(dir, true).sameINode(fileStat(".", true)))
553  {
555  << "PWD is not the cwd() - reverting to physical description"
556  << nl;
557 
558  return cwd_P();
559  }
560 
561 
562  return fileName(dir);
563 }
564 
565 } // End namespace Foam
566 
567 
569 {
570  return cwd(cwdPreference_);
571 }
572 
573 
574 Foam::fileName Foam::cwd(bool logical)
575 {
576  if (logical)
577  {
578  return cwd_L();
579  }
580 
581  return cwd_P();
582 }
583 
584 
585 bool Foam::chDir(const fileName& dir)
586 {
587  // Ignore an empty dir name => always false
588  return !dir.empty() && ::chdir(dir.c_str()) == 0;
589 }
590 
591 
592 bool Foam::mkDir(const fileName& pathName, mode_t mode)
593 {
594  if (POSIX::debug)
595  {
596  Pout<< FUNCTION_NAME << " : pathName:" << pathName << " mode:" << mode
597  << endl;
598  if ((POSIX::debug & 2) && !Pstream::master())
599  {
600  error::printStack(Pout);
601  }
602  }
603 
604  // empty names are meaningless
605  if (pathName.empty())
606  {
607  return false;
608  }
610  // Construct path directory if does not exist
611  if (::mkdir(pathName.c_str(), mode) == 0)
612  {
613  // Directory made OK so return true
614  return true;
615  }
617  switch (errno)
618  {
619  case EPERM:
620  {
622  << "The filesystem containing " << pathName
623  << " does not support the creation of directories."
624  << exit(FatalError);
625  break;
626  }
627 
628  case EEXIST:
629  {
630  // Directory already exists so simply return true
631  return true;
632  }
633 
634  case EFAULT:
635  {
637  << "" << pathName
638  << " points outside your accessible address space."
639  << exit(FatalError);
640  break;
641  }
642 
643  case EACCES:
644  {
646  << "The parent directory does not allow write "
647  "permission to the process,"<< nl
648  << " or one of the directories in " << pathName
649  << " did not allow search (execute) permission."
650  << exit(FatalError);
651  break;
652  }
653 
654  case ENAMETOOLONG:
655  {
657  << "" << pathName << " is too long."
658  << exit(FatalError);
659  break;
660  }
661 
662  case ENOENT:
663  {
664  // Part of the path does not exist so try to create it
665  if (pathName.path().size() && mkDir(pathName.path(), mode))
666  {
667  return mkDir(pathName, mode);
668  }
669 
671  << "Couldn't create directory " << pathName
672  << exit(FatalError);
673  break;
674  }
675 
676  case ENOTDIR:
677  {
679  << "A component used as a directory in " << pathName
680  << " is not, in fact, a directory."
681  << exit(FatalError);
682  break;
683  }
684 
685  case ENOMEM:
686  {
688  << "Insufficient kernel memory was available to make directory "
689  << pathName << '.'
690  << exit(FatalError);
691  break;
692  }
693 
694  case EROFS:
695  {
697  << "" << pathName
698  << " refers to a file on a read-only filesystem."
699  << exit(FatalError);
700  break;
701  }
702 
703  case ELOOP:
704  {
706  << "Too many symbolic links were encountered in resolving "
707  << pathName << '.'
708  << exit(FatalError);
709  break;
710  }
711 
712  case ENOSPC:
713  {
715  << "The device containing " << pathName
716  << " has no room for the new directory or "
717  << "the user's disk quota is exhausted."
718  << exit(FatalError);
719  break;
720  }
721 
722  default:
723  {
725  << "Couldn't create directory " << pathName
726  << exit(FatalError);
727  break;
728  }
729  }
730 
731  return false;
732 }
733 
734 
735 bool Foam::chMod(const fileName& name, const mode_t m)
736 {
737  if (POSIX::debug)
738  {
739  Pout<< FUNCTION_NAME << " : name:" << name << endl;
740  if ((POSIX::debug & 2) && !Pstream::master())
741  {
742  error::printStack(Pout);
743  }
744  }
745 
746  // Ignore an empty name => always false
747  return !name.empty() && ::chmod(name.c_str(), m) == 0;
748 }
749 
750 
751 mode_t Foam::mode(const fileName& name, const bool followLink)
752 {
753  if (POSIX::debug)
754  {
755  Pout<< FUNCTION_NAME << " : name:" << name << endl;
756  if ((POSIX::debug & 2) && !Pstream::master())
757  {
758  error::printStack(Pout);
759  }
760  }
761 
762  // Ignore an empty name => always 0
763  if (!name.empty())
764  {
765  fileStat fileStatus(name, followLink);
766  if (fileStatus.good())
767  {
768  return fileStatus.status().st_mode;
769  }
770  }
771 
772  return 0;
773 }
774 
777 (
778  const fileName& name,
779  const bool followLink
780 )
781 {
782  // Ignore an empty name => always UNDEFINED
783  if (name.empty())
784  {
785  return fileName::Type::UNDEFINED;
786  }
787 
788  if (POSIX::debug)
789  {
790  Pout<< FUNCTION_NAME << " : name:" << name << endl;
791  }
792 
793  mode_t m = mode(name, followLink);
794 
795  if (S_ISREG(m))
796  {
797  return fileName::Type::FILE;
798  }
799  else if (S_ISLNK(m))
800  {
801  return fileName::Type::SYMLINK;
802  }
803  else if (S_ISDIR(m))
804  {
805  return fileName::Type::DIRECTORY;
806  }
807 
808  return fileName::Type::UNDEFINED;
809 }
810 
811 
812 bool Foam::exists
813 (
814  const fileName& name,
815  const bool checkGzip,
816  const bool followLink
817 )
818 {
819  if (POSIX::debug)
820  {
821  Pout<< FUNCTION_NAME << " : name:" << name << " checkGzip:" << checkGzip
822  << endl;
823  if ((POSIX::debug & 2) && !Pstream::master())
824  {
825  error::printStack(Pout);
826  }
827  }
828 
829  // Ignore an empty name => always false
830  return
831  (
832  !name.empty()
833  && (mode(name, followLink) || isFile(name, checkGzip, followLink))
834  );
835 }
836 
838 bool Foam::isDir(const fileName& name, const bool followLink)
839 {
840  if (POSIX::debug)
841  {
842  Pout<< FUNCTION_NAME << " : name:" << name << endl;
843  if ((POSIX::debug & 2) && !Pstream::master())
844  {
845  error::printStack(Pout);
846  }
847  }
848 
849  // Ignore an empty name => always false
850  return !name.empty() && S_ISDIR(mode(name, followLink));
851 }
852 
853 
854 bool Foam::isFile
855 (
856  const fileName& name,
857  const bool checkGzip,
858  const bool followLink
859 )
860 {
861  if (POSIX::debug)
862  {
863  Pout<< FUNCTION_NAME << " : name:" << name << " checkGzip:" << checkGzip
864  << endl;
865  if ((POSIX::debug & 2) && !Pstream::master())
866  {
867  error::printStack(Pout);
868  }
869  }
870 
871  // Ignore an empty name => always false
872  return
873  (
874  !name.empty()
875  && (
876  S_ISREG(mode(name, followLink))
877  || (checkGzip && S_ISREG(mode(name + ".gz", followLink)))
878  )
879  );
880 }
881 
882 
883 off_t Foam::fileSize(const fileName& name, const bool followLink)
884 {
885  if (POSIX::debug)
886  {
887  Pout<< FUNCTION_NAME << " : name:" << name << endl;
888  if ((POSIX::debug & 2) && !Pstream::master())
889  {
890  error::printStack(Pout);
891  }
892  }
893 
894  // Ignore an empty name
895  if (!name.empty())
896  {
897  fileStat fileStatus(name, followLink);
898  if (fileStatus.good())
899  {
900  return fileStatus.status().st_size;
901  }
902  }
903 
904  return -1;
905 }
906 
908 time_t Foam::lastModified(const fileName& name, const bool followLink)
909 {
910  if (POSIX::debug)
911  {
912  Pout<< FUNCTION_NAME << " : name:" << name << endl;
913  if ((POSIX::debug & 2) && !Pstream::master())
914  {
915  error::printStack(Pout);
916  }
917  }
918 
919  // Ignore an empty name
920  return name.empty() ? 0 : fileStat(name, followLink).modTime();
921 }
922 
923 
924 double Foam::highResLastModified(const fileName& name, const bool followLink)
925 {
926  if (POSIX::debug)
927  {
928  Pout<< FUNCTION_NAME << " : name:" << name << endl;
929  if ((POSIX::debug & 2) && !Pstream::master())
930  {
931  error::printStack(Pout);
932  }
933  }
934 
935  // Ignore an empty name
936  return name.empty() ? 0 : fileStat(name, followLink).dmodTime();
937 }
938 
939 
941 (
942  const fileName& directory,
943  const fileName::Type type,
944  const bool filtergz,
945  const bool followLink
946 )
947 {
948  // Initial filename list size and the increment when resizing the list
949  constexpr int maxNnames = 100;
950 
951  fileNameList dirEntries;
952 
953  // Iterate contents (ignores an empty directory name)
954 
955  POSIX::directoryIterator dirIter(directory);
956  if (!dirIter.exists())
957  {
958  if (POSIX::debug)
959  {
961  << "cannot open directory " << directory << endl;
962  }
963 
964  return dirEntries;
965  }
966 
967  if (POSIX::debug)
968  {
969  // InfoInFunction
970  Pout<< FUNCTION_NAME << " : reading directory " << directory << endl;
971  if ((POSIX::debug & 2) && !Pstream::master())
972  {
973  error::printStack(Pout);
974  }
975  }
976 
977  label nFailed = 0; // Entries with invalid characters
978  label nEntries = 0; // Number of selected entries
979  dirEntries.resize(maxNnames);
980 
981  // Process the directory entries
982  for (/*nil*/; dirIter; ++dirIter)
983  {
984  const std::string& item = *dirIter;
985 
986  // Validate filename without spaces, quotes, etc in the name.
987  // No duplicate slashes to strip - dirent will not have them anyhow.
988 
990  if (name != item)
991  {
992  ++nFailed;
993  }
994  else if
995  (
996  (type == fileName::Type::DIRECTORY)
997  || (type == fileName::Type::FILE && !fileName::isBackup(name))
998  )
999  {
1000  fileName::Type detected = (directory/name).type(followLink);
1001 
1002  if (detected == type)
1003  {
1004  // Only strip '.gz' from non-directory names
1005  if
1006  (
1007  filtergz
1008  && (detected != fileName::Type::DIRECTORY)
1009  && name.has_ext("gz")
1010  )
1011  {
1012  name.remove_ext();
1013  }
1014 
1015  if (nEntries >= dirEntries.size())
1016  {
1017  dirEntries.resize(dirEntries.size() + maxNnames);
1018  }
1019 
1020  dirEntries[nEntries] = std::move(name);
1021  ++nEntries;
1022  }
1023  }
1024  }
1025 
1026  // Finalize the length of the entries list
1027  dirEntries.resize(nEntries);
1028 
1029  if (nFailed && POSIX::debug)
1030  {
1031  std::cerr
1032  << "Foam::readDir() : reading directory " << directory << nl
1033  << nFailed << " entries with invalid characters in their name"
1034  << std::endl;
1035  }
1036 
1037  return dirEntries;
1038 }
1039 
1040 
1041 bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink)
1042 {
1043  if (POSIX::debug)
1044  {
1045  Pout<< FUNCTION_NAME << " : src:" << src << " dest:" << dest << endl;
1046  if ((POSIX::debug & 2) && !Pstream::master())
1047  {
1048  error::printStack(Pout);
1049  }
1050  }
1051 
1052  // Make sure source exists - this also handles an empty source name
1053  if (!exists(src))
1054  {
1055  return false;
1056  }
1057 
1058  const fileName::Type srcType = src.type(followLink);
1059 
1060  fileName destFile(dest);
1061 
1062  // Check type of source file.
1063  if (srcType == fileName::FILE)
1064  {
1065  // If dest is a directory, create the destination file name.
1066  if (destFile.type() == fileName::DIRECTORY)
1067  {
1068  destFile /= src.name();
1069  }
1070 
1071  // Make sure the destination directory exists.
1072  if (!isDir(destFile.path()) && !mkDir(destFile.path()))
1073  {
1074  return false;
1075  }
1076 
1077  // Open and check streams. Enforce binary for extra safety
1078  std::ifstream srcStream(src, ios_base::in | ios_base::binary);
1079  if (!srcStream)
1080  {
1081  return false;
1082  }
1083 
1084  std::ofstream destStream(destFile, ios_base::out | ios_base::binary);
1085  if (!destStream)
1086  {
1087  return false;
1088  }
1089 
1090  // Copy character data.
1091  char ch;
1092  while (srcStream.get(ch))
1093  {
1094  destStream.put(ch);
1095  }
1096 
1097  // Final check.
1098  if (!srcStream.eof() || !destStream)
1099  {
1100  return false;
1101  }
1102  }
1103  else if (srcType == fileName::SYMLINK)
1104  {
1105  // If dest is a directory, create the destination file name.
1106  if (destFile.type() == fileName::DIRECTORY)
1107  {
1108  destFile /= src.name();
1109  }
1110 
1111  // Make sure the destination directory exists.
1112  if (!isDir(destFile.path()) && !mkDir(destFile.path()))
1113  {
1114  return false;
1115  }
1116 
1117  Foam::ln(src, destFile);
1118  }
1119  else if (srcType == fileName::DIRECTORY)
1120  {
1121  if (destFile.type() == fileName::DIRECTORY)
1122  {
1123  // Both are directories. Could mean copy contents or copy
1124  // recursively. Don't actually know what the user wants,
1125  // but assume that if names are identical == copy contents.
1126  //
1127  // So: "path1/foo" "path2/foo" copy contents
1128  // So: "path1/foo" "path2/bar" copy directory
1129 
1130  const word srcDirName = src.name();
1131  if (destFile.name() != srcDirName)
1132  {
1133  destFile /= srcDirName;
1134  }
1135  }
1136 
1137  // Make sure the destination directory exists.
1138  if (!isDir(destFile) && !mkDir(destFile))
1139  {
1140  return false;
1141  }
1142 
1143  char* realSrcPath = realpath(src.c_str(), nullptr);
1144  char* realDestPath = realpath(destFile.c_str(), nullptr);
1145  const bool samePath = strcmp(realSrcPath, realDestPath) == 0;
1146 
1147  if (POSIX::debug && samePath)
1148  {
1150  << "Attempt to copy " << realSrcPath << " to itself" << endl;
1151  }
1152 
1153  if (realSrcPath)
1154  {
1155  free(realSrcPath);
1156  }
1157 
1158  if (realDestPath)
1159  {
1160  free(realDestPath);
1161  }
1162 
1163  // Do not copy over self when src is actually a link to dest
1164  if (samePath)
1165  {
1166  return false;
1167  }
1168 
1169  // Copy files
1170  fileNameList files = readDir(src, fileName::FILE, false, followLink);
1171  for (const fileName& item : files)
1172  {
1173  if (POSIX::debug)
1174  {
1176  << "Copying : " << src/item
1177  << " to " << destFile/item << endl;
1178  }
1179 
1180  // File to file.
1181  Foam::cp(src/item, destFile/item, followLink);
1182  }
1183 
1184  // Copy sub directories.
1185  fileNameList dirs = readDir
1186  (
1187  src,
1188  fileName::DIRECTORY,
1189  false,
1190  followLink
1191  );
1192 
1193  for (const fileName& item : dirs)
1194  {
1195  if (POSIX::debug)
1196  {
1198  << "Copying : " << src/item
1199  << " to " << destFile << endl;
1200  }
1201 
1202  // Dir to Dir.
1203  Foam::cp(src/item, destFile, followLink);
1204  }
1205  }
1206  else
1207  {
1208  return false;
1209  }
1210 
1211  return true;
1212 }
1213 
1214 
1215 bool Foam::ln(const fileName& src, const fileName& dst)
1216 {
1217  if (POSIX::debug)
1218  {
1219  //InfoInFunction
1221  << " : Create symlink from : " << src << " to " << dst << endl;
1222  if ((POSIX::debug & 2) && !Pstream::master())
1223  {
1224  error::printStack(Pout);
1225  }
1226  }
1227 
1228  if (src.empty())
1229  {
1231  << "source name is empty: not linking." << endl;
1232  return false;
1233  }
1234 
1235  if (dst.empty())
1236  {
1238  << "destination name is empty: not linking." << endl;
1239  return false;
1240  }
1241 
1242  if (exists(dst))
1243  {
1245  << "destination " << dst << " already exists. Not linking."
1246  << endl;
1247  return false;
1248  }
1249 
1250  if (src.isAbsolute() && !exists(src))
1251  {
1253  << "source " << src << " does not exist." << endl;
1254  return false;
1255  }
1256 
1257  if (::symlink(src.c_str(), dst.c_str()) == 0)
1258  {
1259  return true;
1260  }
1261 
1263  << "symlink from " << src << " to " << dst << " failed." << endl;
1264  return false;
1265 }
1266 
1267 
1269 {
1270  if (POSIX::debug)
1271  {
1272  //InfoInFunction
1274  << " : Returning symlink destination for : " << link << endl;
1275  if ((POSIX::debug & 2) && !Pstream::master())
1276  {
1277  error::printStack(Pout);
1278  }
1279  }
1280 
1281  if (link.empty())
1282  {
1283  // Treat an empty path as a no-op.
1284  return fileName();
1285  }
1286 
1287  fileName result;
1288  result.resize(1024); // Should be large enough (mostly relative anyhow)
1289 
1290  ssize_t len = ::readlink(link.c_str(), &(result.front()), result.size());
1291  if (len > 0)
1292  {
1293  result.resize(len);
1294  return result;
1295  }
1296 
1297  // Failure: return empty result
1298  return fileName();
1299 }
1300 
1301 
1302 bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
1303 {
1304  if (POSIX::debug)
1305  {
1306  //InfoInFunction
1307  Pout<< FUNCTION_NAME << " : Move : " << src << " to " << dst << endl;
1308  if ((POSIX::debug & 2) && !Pstream::master())
1309  {
1310  error::printStack(Pout);
1311  }
1312  }
1313 
1314  // Ignore empty names => always false
1315  if (src.empty() || dst.empty())
1316  {
1317  return false;
1318  }
1319 
1320  if
1321  (
1322  dst.type() == fileName::DIRECTORY
1323  && src.type(followLink) != fileName::DIRECTORY
1324  )
1325  {
1326  const fileName dstName(dst/src.name());
1327 
1328  return (0 == std::rename(src.c_str(), dstName.c_str()));
1329  }
1330 
1331  return (0 == std::rename(src.c_str(), dst.c_str()));
1332 }
1333 
1334 
1335 bool Foam::mvBak(const fileName& src, const std::string& ext)
1336 {
1337  if (POSIX::debug)
1338  {
1339  //InfoInFunction
1341  << " : moving : " << src << " to extension " << ext << endl;
1342  if ((POSIX::debug & 2) && !Pstream::master())
1343  {
1344  error::printStack(Pout);
1345  }
1346  }
1347 
1348  // Ignore an empty name or extension => always false
1349  if (src.empty() || ext.empty())
1350  {
1351  return false;
1352  }
1353 
1354  if (exists(src, false))
1355  {
1356  constexpr const int maxIndex = 99;
1357  char index[4];
1358 
1359  for (int n = 0; n <= maxIndex; ++n)
1360  {
1361  fileName dstName(src + "." + ext);
1362  if (n)
1363  {
1364  ::snprintf(index, 4, "%02d", n);
1365  dstName += index;
1366  }
1367 
1368  // avoid overwriting existing files, except for the last
1369  // possible index where we have no choice
1370  if (!exists(dstName, false) || n == maxIndex)
1371  {
1372  return (0 == std::rename(src.c_str(), dstName.c_str()));
1373  }
1374  }
1375  }
1376 
1377  // fallthrough: nothing to do
1378  return false;
1379 }
1380 
1381 
1382 bool Foam::rm(const fileName& file)
1383 {
1384  if (POSIX::debug)
1385  {
1386  //InfoInFunction
1387  Pout<< FUNCTION_NAME << " : Removing : " << file << endl;
1388  if ((POSIX::debug & 2) && !Pstream::master())
1389  {
1390  error::printStack(Pout);
1391  }
1392  }
1393 
1394  // Ignore an empty name => always false
1395  if (file.empty())
1396  {
1397  return false;
1398  }
1399 
1400  // If removal of plain file name fails, try with .gz
1401 
1402  return
1403  (
1404  0 == ::remove(file.c_str())
1405  || 0 == ::remove((file + ".gz").c_str())
1406  );
1407 }
1408 
1409 
1410 bool Foam::rmDir
1411 (
1412  const fileName& directory,
1413  const bool silent,
1414  const bool emptyOnly
1415 )
1416 {
1417  if (directory.empty())
1418  {
1419  return false;
1420  }
1421 
1422  // Iterate contents (ignores an empty directory name)
1423  // Also retain hidden files/dirs for removal
1424 
1425  POSIX::directoryIterator dirIter(directory, true);
1426  if (!dirIter.exists())
1427  {
1428  if (!silent && !emptyOnly)
1429  {
1431  << "Cannot open directory " << directory << endl;
1432  }
1433 
1434  return false;
1435  }
1436 
1437  if (POSIX::debug)
1438  {
1439  //InfoInFunction
1440  Pout<< FUNCTION_NAME << " : removing directory " << directory << endl;
1441  if ((POSIX::debug & 2) && !Pstream::master())
1442  {
1443  error::printStack(Pout);
1444  }
1445  }
1446 
1447  // Process each directory entry, counting any errors encountered
1448  int nErrors = 0;
1449 
1450  for (/*nil*/; dirIter; ++dirIter)
1451  {
1452  const std::string& item = *dirIter;
1453 
1454  // Allow invalid characters (spaces, quotes, etc),
1455  // otherwise we cannot remove subdirs with these types of names.
1456  // -> const fileName path = directory/name; <-
1457 
1458  const fileName path(fileName::concat(directory, item));
1459 
1460  fileName::Type detected = path.type(false); // No followLink
1461 
1462  if (detected == fileName::Type::DIRECTORY)
1463  {
1464  // Call silently for lower levels
1465  if (!rmDir(path, true, emptyOnly))
1466  {
1467  ++nErrors;
1468  }
1469  }
1470  else if (emptyOnly)
1471  {
1472  // Only remove empty directories (not files)
1473  ++nErrors;
1474 
1475  // Check for dead symlinks
1476  if (detected == fileName::Type::SYMLINK)
1477  {
1478  detected = path.type(true); // followLink
1479 
1480  if (detected == fileName::Type::UNDEFINED)
1481  {
1482  --nErrors;
1483 
1484  if (!rm(path))
1485  {
1486  ++nErrors;
1487  }
1488  }
1489  }
1490  }
1491  else
1492  {
1493  if (!rm(path))
1494  {
1495  ++nErrors;
1496  }
1497  }
1498  }
1499 
1500  if (nErrors == 0)
1501  {
1502  // No errors encountered - try to remove the top-level
1503 
1504  if (!rm(directory))
1505  {
1506  nErrors = -1; // A top-level error
1507  }
1508  }
1509 
1510  if (nErrors && !silent && !emptyOnly)
1511  {
1513  << "Failed to remove directory " << directory << endl;
1514 
1515  if (nErrors > 0)
1516  {
1517  Info<< "could not remove " << nErrors << " sub-entries" << endl;
1518  }
1519  }
1520 
1521  return (nErrors == 0);
1522 }
1523 
1524 
1525 unsigned int Foam::sleep(const unsigned int sec)
1526 {
1527  return ::sleep(sec);
1528 }
1529 
1530 
1531 void Foam::fdClose(const int fd)
1532 {
1533  if (close(fd) != 0)
1534  {
1536  << "close error on " << fd << endl
1537  << abort(FatalError);
1538  }
1539 }
1540 
1541 
1542 bool Foam::ping
1543 (
1544  const std::string& destName,
1545  const label destPort,
1546  const label timeOut
1547 )
1548 {
1549  struct hostent *hostPtr;
1550  volatile int sockfd;
1551  struct sockaddr_in destAddr; // will hold the destination addr
1552  u_int addr;
1553 
1554  if ((hostPtr = ::gethostbyname(destName.c_str())) == nullptr)
1555  {
1557  << "gethostbyname error " << h_errno << " for host " << destName
1558  << abort(FatalError);
1559  }
1560 
1561  // Get first of the SLL of addresses
1562  addr = (reinterpret_cast<struct in_addr*>(*(hostPtr->h_addr_list)))->s_addr;
1563 
1564  // Allocate socket
1565  sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
1566  if (sockfd < 0)
1567  {
1569  << "socket error"
1570  << abort(FatalError);
1571  }
1572 
1573  // Fill sockaddr_in structure with dest address and port
1574  std::memset(reinterpret_cast<char *>(&destAddr), '\0', sizeof(destAddr));
1575  destAddr.sin_family = AF_INET;
1576  destAddr.sin_port = htons(ushort(destPort));
1577  destAddr.sin_addr.s_addr = addr;
1578 
1579 
1580  timer myTimer(timeOut);
1581 
1582  if (timedOut(myTimer))
1583  {
1584  // Setjmp from timer jumps back to here
1585  fdClose(sockfd);
1586  return false;
1587  }
1588 
1589  if
1590  (
1591  ::connect
1592  (
1593  sockfd,
1594  reinterpret_cast<struct sockaddr*>(&destAddr),
1595  sizeof(struct sockaddr)
1596  ) != 0
1597  )
1598  {
1599  // Connection refused. Check if network was actually used or not.
1600 
1601  int connectErr = errno;
1602 
1603  fdClose(sockfd);
1604 
1605  if (connectErr == ECONNREFUSED)
1606  {
1607  return true;
1608  }
1609  //perror("connect");
1610 
1611  return false;
1612  }
1613 
1614  fdClose(sockfd);
1615 
1616  return true;
1617 }
1618 
1619 
1620 bool Foam::ping(const std::string& host, const label timeOut)
1621 {
1622  return ping(host, 222, timeOut) || ping(host, 22, timeOut);
1623 }
1624 
1625 
1626 namespace Foam
1627 {
1629 static int waitpid(const pid_t pid)
1630 {
1631  // child status, return code from the exec etc.
1632  int status = 0;
1633 
1634  // in parent - blocking wait
1635  // modest treatment of signals (in child)
1636  // treat 'stopped' like exit (suspend/continue)
1637 
1638  while (true)
1639  {
1640  pid_t wpid = ::waitpid(pid, &status, WUNTRACED);
1641 
1642  if (wpid == -1)
1643  {
1645  << "some error occurred in child"
1646  << exit(FatalError);
1647  break;
1648  }
1649 
1650  if (WIFEXITED(status))
1651  {
1652  // child exited, get its return status
1653  return WEXITSTATUS(status);
1654  }
1655 
1656  if (WIFSIGNALED(status))
1657  {
1658  // child terminated by some signal
1659  return WTERMSIG(status);
1660  }
1661 
1662  if (WIFSTOPPED(status))
1663  {
1664  // child stopped by some signal
1665  return WSTOPSIG(status);
1666  }
1667 
1669  << "programming error, status from waitpid() not handled: "
1670  << status
1671  << exit(FatalError);
1672  }
1673 
1674  return -1; // should not happen
1675 }
1677 }
1678 
1679 
1680 int Foam::system(const std::string& command, const bool bg)
1681 {
1682  if (command.empty())
1683  {
1684  // Treat an empty command as a successful no-op.
1685  // From 'man sh' POSIX (man sh):
1686  // "If the command_string operand is an empty string,
1687  // sh shall exit with a zero exit status."
1688  return 0;
1689  }
1690 
1691  // TBD: vfork is deprecated as of macOS 12.0
1692  const pid_t child_pid = ::vfork(); // NB: vfork, not fork!
1693 
1694  if (child_pid == -1)
1695  {
1697  << "vfork() failed for system command " << command
1698  << exit(FatalError);
1699 
1700  return -1; // fallback error value
1701  }
1702  else if (child_pid == 0)
1703  {
1704  // In child
1705 
1706  // Close or redirect file descriptors
1707  redirects(bg);
1708 
1709  // execl uses the current environ
1710  (void) ::execl
1711  (
1712  "/bin/sh", // Path of the shell
1713  "sh", // Command-name (name for the shell)
1714  "-c", // Read commands from command_string operand
1715  command.c_str(), // Command string
1716  reinterpret_cast<char*>(0)
1717  );
1718 
1719  // Obviously failed, since exec should not return
1721  << "exec failed: " << command
1722  << exit(FatalError);
1723 
1724  return -1; // fallback error value
1725  }
1726 
1727 
1728  // In parent
1729  // - started as background process, or blocking wait for the child
1730 
1731  return (bg ? 0 : waitpid(child_pid));
1732 }
1733 
1734 
1735 int Foam::system(const CStringList& command, const bool bg)
1736 {
1737  if (command.empty())
1738  {
1739  // Treat an empty command as a successful no-op.
1740  // For consistency with POSIX (man sh) behaviour for (sh -c command),
1741  // which is what is mostly being replicated here.
1742  return 0;
1743  }
1744 
1745  // NB: use vfork, not fork!
1746  // vfork behaves more like a thread and avoids copy-on-write problems
1747  // triggered by fork.
1748  // The normal system() command has a fork buried in it that causes
1749  // issues with infiniband and openmpi etc.
1750 
1751  // TBD: vfork is deprecated as of macOS 12.0
1752  const pid_t child_pid = ::vfork();
1753 
1754  if (child_pid == -1)
1755  {
1757  << "vfork() failed for system command " << command[0]
1758  << exit(FatalError);
1760  return -1; // fallback error value
1761  }
1762  else if (child_pid == 0)
1763  {
1764  // In child
1765 
1766  // Close or redirect file descriptors
1767  redirects(bg);
1768 
1769  // execvp searches the path, uses the current environ
1770  (void) ::execvp(command[0], command.strings());
1771 
1772  // Obviously failed, since exec should not return
1774  << "exec(" << command[0] << ", ...) failed"
1775  << exit(FatalError);
1776 
1777  return -1; // fallback error value
1778  }
1779 
1780 
1781  // In parent
1782  // - started as background process, or blocking wait for the child
1783 
1784  return (bg ? 0 : waitpid(child_pid));
1785 }
1786 
1787 
1788 int Foam::system(const Foam::UList<Foam::string>& command, const bool bg)
1789 {
1790  if (command.empty())
1791  {
1792  // Treat an empty command as a successful no-op.
1793  return 0;
1794  }
1795 
1796  // Make a deep copy as C-strings
1797  const CStringList cmd(command);
1798  return Foam::system(cmd, bg);
1799 }
1800 
1801 
1802 void* Foam::dlOpen(const fileName& libName, const bool check)
1803 {
1804  if (POSIX::debug)
1805  {
1806  std::cout
1807  << "dlopen() of " << libName << std::endl;
1808  }
1809 
1810  void* handle = loadLibrary(libName);
1811 
1812  if (!handle)
1813  {
1814  fileName libso;
1815 
1816  if (!libName.has_path() && !libName.starts_with("lib"))
1817  {
1818  // Try with 'lib' prefix
1819  libso = "lib" + libName;
1820  handle = loadLibrary(libso);
1821 
1822  if (POSIX::debug)
1823  {
1824  std::cout
1825  << " dlopen() as " << libso << std::endl;
1826  }
1827  }
1828  else
1829  {
1830  libso = libName;
1831  }
1832 
1833  // With canonical library extension ("so" or "dylib"), which remaps
1834  // "libXX" to "libXX.so" as well as "libXX.so" -> "libXX.dylib"
1835  if (!handle && !libso.has_ext(EXT_SO))
1836  {
1837  libso.replace_ext(EXT_SO);
1838  handle = loadLibrary(libso);
1839 
1840  if (POSIX::debug)
1841  {
1842  std::cout
1843  << " dlopen() as " << libso << std::endl;
1844  }
1845  }
1846  }
1847 
1848  if (!handle && check)
1849  {
1851  << "dlopen error : " << ::dlerror() << endl;
1852  }
1853 
1854  if (POSIX::debug)
1855  {
1856  std::cout
1857  << "dlopen() of " << libName
1858  << " handle " << handle << std::endl;
1859  }
1860 
1861  return handle;
1862 }
1863 
1864 
1865 void* Foam::dlOpen(const fileName& libName, std::string& errorMsg)
1866 {
1867  // Call without emitting error message - we capture that ourselves
1868  void* handle = Foam::dlOpen(libName, false);
1869 
1870  if (!handle)
1871  {
1872  // Capture error message
1873  errorMsg = ::dlerror();
1874  }
1875  else
1876  {
1877  // No errors
1878  errorMsg.clear();
1879  }
1880 
1881  return handle;
1882 }
1883 
1884 
1885 Foam::label Foam::dlOpen
1886 (
1887  std::initializer_list<fileName> libNames,
1888  const bool check
1890 {
1891  label nLoaded = 0;
1892 
1893  for (const fileName& libName : libNames)
1894  {
1895  if (Foam::dlOpen(libName, check))
1896  {
1897  ++nLoaded;
1898  }
1899  }
1900 
1901  return nLoaded;
1902 }
1903 
1904 
1905 bool Foam::dlClose(void* handle)
1906 {
1907  if (POSIX::debug)
1908  {
1909  std::cout
1910  << "dlClose(void*)"
1911  << " : dlclose of handle " << handle << std::endl;
1912  }
1913  return ::dlclose(handle) == 0;
1914 }
1915 
1916 
1917 void* Foam::dlSymFind(void* handle, const std::string& symbol, bool required)
1918 {
1919  if (!required && (!handle || symbol.empty()))
1920  {
1921  return nullptr;
1922  }
1923 
1924  if (POSIX::debug)
1925  {
1926  std::cout
1927  << "dlSymFind(void*, const std::string&, bool)"
1928  << " : dlsym of " << symbol << std::endl;
1929  }
1930 
1931  // Clear any old errors - see manpage dlopen
1932  (void) ::dlerror();
1933 
1934  // Get address of symbol
1935  void* fun = ::dlsym(handle, symbol.c_str());
1936 
1937  // Any error?
1938  char *err = ::dlerror();
1939 
1940  if (err)
1941  {
1942  if (!required)
1943  {
1944  return nullptr;
1945  }
1946 
1948  << "Cannot lookup symbol " << symbol << " : " << err
1949  << endl;
1950  }
1951 
1952  return fun;
1953 }
1954 
1955 
1956 #ifndef __APPLE__
1957 static int collectLibsCallback
1958 (
1959  struct dl_phdr_info *info,
1960  size_t size,
1961  void *data
1962 )
1963 {
1965  reinterpret_cast<Foam::DynamicList<Foam::fileName>*>(data);
1966  ptr->append(info->dlpi_name);
1967  return 0;
1968 }
1969 #endif
1970 
1971 
1973 {
1974  DynamicList<fileName> libs;
1975  #ifdef __APPLE__
1976  for (uint32_t i=0; i < _dyld_image_count(); ++i)
1977  {
1978  libs.append(_dyld_get_image_name(i));
1979  }
1980  #else
1981  dl_iterate_phdr(collectLibsCallback, &libs);
1982  #endif
1983 
1984  if (POSIX::debug)
1985  {
1986  std::cout
1987  << "dlLoaded()"
1988  << " : determined loaded libraries :" << libs.size() << std::endl;
1989  }
1990  return libs;
1991 }
1992 
1993 
1994 // ************************************************************************* //
void * dlSymFind(void *handle, const std::string &symbol, bool required=false)
Look for symbol in a dlopened library.
Definition: POSIX.C:1941
bool mvBak(const fileName &src, const std::string &ext="bak")
Rename to a corresponding backup file.
Definition: POSIX.C:1359
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
type
Types of root.
Definition: Roots.H:52
bool mv(const fileName &src, const fileName &dst, const bool followLink=false)
Rename src to dst.
Definition: POSIX.C:1326
A class for handling file names.
Definition: fileName.H:72
off_t fileSize(const fileName &name, const bool followLink=true)
Return size of file or -1 on failure (normally follows symbolic links).
Definition: POSIX.C:907
fileName readLink(const fileName &link)
Return the contents (target) of a symlink.
Definition: POSIX.C:1292
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void close()
Close directory.
Definition: POSIX.C:240
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:150
bool hasEnv(const std::string &envName)
True if environment variable of given name is defined.
Definition: POSIX.C:334
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
int infoDetailLevel
Global for selective suppression of Info output.
pid_t ppid()
Return the parent PID of this process.
Definition: POSIX.C:322
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Implements a timeout mechanism via sigalarm.
Definition: timer.H:82
Foam::SubStrings split(const std::string &str, const char delim, std::string::size_type pos=0, const bool keepEmpty=false)
Split string into sub-strings at the delimiter character.
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:697
Type type(bool followLink=true, bool checkGzip=false) const
Return the directory entry type: UNDEFINED, FILE, DIRECTORY (or SYMLINK).
Definition: fileName.C:353
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy the source to the destination (recursively if necessary).
Definition: POSIX.C:1065
bool dlClose(void *handle)
Close a dlopened library using handle. Return true if successful.
Definition: POSIX.C:1929
bool chDir(const fileName &dir)
Change current directory to the one specified and return true on success.
Definition: POSIX.C:609
bool empty() const noexcept
True if the size (ie, argc) is zero.
Definition: CStringList.H:188
fileNameList dlLoaded()
Return all loaded libraries.
Definition: POSIX.C:1996
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
static bool isAbsolute(const std::string &str)
Return true if filename starts with a &#39;/&#39; or &#39;\&#39; or (windows-only) with a filesystem-root.
Definition: fileNameI.H:129
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: POSIX.C:341
~directoryIterator()
Destructor.
Definition: POSIX.C:213
fileName home()
Return home directory path name for the current user.
Definition: POSIX.C:442
static int collectLibsCallback(struct dl_phdr_info *info, size_t size, void *data)
Definition: POSIX.C:1982
fileName & replace_ext(const word &ending)
Remove extension (if any) and append a new one.
Definition: fileNameI.H:230
bool ping(const std::string &destName, const label port, const label timeOut)
Check if machine is up by pinging given port.
Definition: POSIX.C:1567
bool good() const noexcept
True if file-stat was successful.
Definition: fileStat.H:130
bool has_path() const
True if it contains a &#39;/&#39; character.
Definition: fileNameI.H:163
StringType validate(const std::string &str, const UnaryPredicate &accept, const bool invert=false)
Return a copy of the input string with validated characters.
bool env(const std::string &envName)
Deprecated(2020-05) check for existence of environment variable.
Definition: OSspecific.H:96
static Foam::fileName cwd_P()
The physical current working directory path name (pwd -P).
Definition: POSIX.C:484
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
const struct stat & status() const noexcept
The raw status.
Definition: fileStat.H:146
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:862
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
dimensionedScalar pos(const dimensionedScalar &ds)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:801
constexpr label pathLengthChunk
Definition: POSIX.H:52
const std::string & val() const noexcept
The current item.
Definition: POSIX.C:252
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:616
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
bool has_ext() const
Various checks for extensions.
Definition: stringI.H:43
directoryIterator(const std::string &dirName, bool allowHidden=false)
Construct for dirName, optionally allowing hidden files/dirs.
Definition: POSIX.C:194
A class for handling words, derived from Foam::string.
Definition: word.H:63
static void * loadLibrary(const Foam::fileName &libName)
Definition: POSIX.C:111
string domainName()
Deprecated(2022-01) domain name resolution may be unreliable.
Definition: POSIX.C:403
double dmodTime() const
The modification time in seconds (nanosecond resolution), 0 for an invalid file-stat.
Definition: fileStat.C:106
directoryIterator & operator++()
Same as next()
Definition: POSIX.C:303
time_t modTime() const
The modification time in seconds, 0 for an invalid file-stat.
Definition: fileStat.C:100
static bool cwdPreference_(Foam::debug::optimisationSwitch("cwd", 0))
void fdClose(const int fd)
Close file descriptor.
Definition: POSIX.C:1555
time_t lastModified(const fileName &name, const bool followLink=true)
Return time of last file modification (normally follows symbolic links).
Definition: POSIX.C:932
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: POSIX.C:837
string userName()
Return the user&#39;s login name.
Definition: POSIX.C:424
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:609
const std::string & operator*() const noexcept
Same as val()
Definition: POSIX.C:295
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:67
errorManip< error > abort(error &err)
Definition: errorManip.H:139
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:105
string hostName()
Return the system&#39;s host name, as per hostname(1)
Definition: POSIX.C:373
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: POSIX.C:1239
bool rmDir(const fileName &directory, const bool silent=false, const bool emptyOnly=false)
Remove a directory and its contents recursively,.
Definition: POSIX.C:1435
unsigned int sleep(const unsigned int sec)
Sleep for the specified number of seconds.
Definition: POSIX.C:1549
pid_t pid()
Return the PID of this process.
Definition: POSIX.C:316
const direction noexcept
Definition: scalarImpl.H:255
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:234
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:192
int debug
Static debugging option.
#define FUNCTION_NAME
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
defineTypeNameAndDebug(combustionModel, 0)
Wrapper for stat() and lstat() system calls.
Definition: fileStat.H:63
static void check(const int retVal, const char *what)
#define timedOut(x)
Check if timeout has occurred.
Definition: timer.H:72
pid_t pgid()
Return the group PID of this process.
Definition: POSIX.C:328
bool chMod(const fileName &name, const mode_t mode)
Set the file/directory mode, return true on success.
Definition: POSIX.C:759
bool isAdministrator()
Is the current user the administrator (root)
Definition: POSIX.C:436
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: POSIX.C:879
static void redirects(const bool bg)
Definition: POSIX.C:89
bool starts_with(char c) const
True if string starts with given character (cf. C++20)
Definition: string.H:435
#define WarningInFunction
Report a warning using Foam::Warning.
void * dlOpen(const fileName &libName, const bool check=true)
Open a shared library and return handle to library.
Definition: POSIX.C:1826
#define EXT_SO
Definition: POSIX.C:63
fileName cwd()
The physical or logical current working directory path name.
Definition: POSIX.C:592
bool good() const noexcept
Directory pointer is valid.
Definition: POSIX.C:232
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
bool has_ext() const
Various checks for extensions.
Definition: stringI.H:43
constexpr label pathLengthMax
Definition: POSIX.H:53
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:64
char ** strings() const noexcept
Return the list of C-strings (ie, argv)
Definition: CStringList.H:226
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: POSIX.C:1704
bool next()
Read next item, always ignoring "." and ".." entries.
Definition: POSIX.C:263
volScalarField & p
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::Type::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: POSIX.C:965
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: POSIX.C:775
static Foam::fileName cwd_L()
The logical current working directory path name.
Definition: POSIX.C:532
A class for handling character strings derived from std::string.
Definition: string.H:72
bool setEnv(const word &name, const std::string &value, const bool overwrite)
Set an environment variable, return true on success.
Definition: POSIX.C:358
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Type
Enumerations to handle directory entry types.
Definition: fileName.H:81
bool exists() const noexcept
Directory open succeeded.
Definition: POSIX.C:224
bool remove_ext()
Remove extension, return true if string changed.
Definition: stringI.H:93
Namespace for OpenFOAM.
double highResLastModified(const fileName &, const bool followLink=true)
Return time of last file modification.
Definition: POSIX.C:948
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition: POSIX.C:1406
A simple directory contents iterator.
Definition: POSIX.C:164
#define InfoInFunction
Report an information message using Foam::Info.