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 
111 
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 }
158 
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  }
224 
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  }
240 
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 
382 
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 }
403 
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  }
436 
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  }
609 
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  }
616 
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 
775 
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 
837 
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 
907 
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 // ************************************************************************* //
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
static bool cwdPreference_(Foam::debug::optimisationSwitch("cwd", 0))
static void * loadLibrary(const Foam::fileName &libName)
Definition: POSIX.C:111
#define EXT_SO
Definition: POSIX.C:63
static void redirects(const bool bg)
Definition: POSIX.C:89
static int collectLibsCallback(struct dl_phdr_info *info, size_t size, void *data)
Definition: POSIX.C:1982
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:67
label n
An adapter for copying a list of C++ strings into a list of C-style strings for passing to C code tha...
Definition: CStringList.H:65
char ** strings() const noexcept
Return the list of C-strings (ie, argv)
Definition: CStringList.H:226
bool empty() const noexcept
True if the size (ie, argc) is zero.
Definition: CStringList.H:188
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:609
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:150
A simple directory contents iterator.
Definition: POSIX.C:165
~directoryIterator()
Destructor.
Definition: POSIX.C:213
const std::string & val() const noexcept
The current item.
Definition: POSIX.C:252
directoryIterator & operator++()
Same as next()
Definition: POSIX.C:303
bool exists() const noexcept
Directory open succeeded.
Definition: POSIX.C:224
bool good() const noexcept
Directory pointer is valid.
Definition: POSIX.C:232
void close()
Close directory.
Definition: POSIX.C:240
directoryIterator(const std::string &dirName, bool allowHidden=false)
Construct for dirName, optionally allowing hidden files/dirs.
Definition: POSIX.C:194
bool next()
Read next item, always ignoring "." and ".." entries.
Definition: POSIX.C:263
const std::string & operator*() const noexcept
Same as val()
Definition: POSIX.C:295
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:85
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:697
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A class for handling file names.
Definition: fileName.H:75
fileName & replace_ext(const word &ending)
Remove extension (if any) and append a new one.
Definition: fileNameI.H:230
Type
Enumerations to handle directory entry types.
Definition: fileName.H:82
Type type(bool followLink=true, bool checkGzip=false) const
Return the directory entry type: UNDEFINED, FILE, DIRECTORY (or SYMLINK).
Definition: fileName.C:353
bool has_path() const
True if it contains a '/' character.
Definition: fileNameI.H:163
bool has_ext() const
Various checks for extensions.
Definition: stringI.H:43
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:192
static bool isAbsolute(const std::string &str)
Return true if filename starts with a '/' or '\' or (windows-only) with a filesystem-root.
Definition: fileNameI.H:129
Wrapper for stat() and lstat() system calls.
Definition: fileStat.H:64
const struct stat & status() const noexcept
The raw status.
Definition: fileStat.H:146
time_t modTime() const
The modification time in seconds, 0 for an invalid file-stat.
Definition: fileStat.C:100
bool good() const noexcept
True if file-stat was successful.
Definition: fileStat.H:130
double dmodTime() const
The modification time in seconds (nanosecond resolution), 0 for an invalid file-stat.
Definition: fileStat.C:106
A class for handling character strings derived from std::string.
Definition: string.H:75
bool starts_with(char c) const
True if string starts with given character (cf. C++20)
Definition: string.H:435
Implements a timeout mechanism via sigalarm.
Definition: timer.H:83
A class for handling words, derived from Foam::string.
Definition: word.H:66
bool remove_ext()
Remove extension, return true if string changed.
Definition: stringI.H:93
bool has_ext() const
Various checks for extensions.
Definition: stringI.H:43
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
volScalarField & p
bool
Definition: EEqn.H:20
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
#define WarningInFunction
Report a warning using Foam::Warning.
#define FUNCTION_NAME
#define InfoInFunction
Report an information message using Foam::Info.
constexpr label pathLengthChunk
Definition: POSIX.H:52
constexpr label pathLengthMax
Definition: POSIX.H:53
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:234
int debug
Static debugging option.
type
Types of root.
Definition: Roots.H:53
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.
StringType validate(const std::string &str, const UnaryPredicate &accept, const bool invert=false)
Return a copy of the input string with validated characters.
Namespace for OpenFOAM.
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition: POSIX.C:1406
static void check(const int retVal, const char *what)
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
fileName cwd()
The physical or logical current working directory path name.
Definition: POSIX.C:592
dimensionedScalar pos(const dimensionedScalar &ds)
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: POSIX.C:341
bool setEnv(const word &name, const std::string &value, const bool overwrite)
Set an environment variable, return true on success.
Definition: POSIX.C:358
time_t lastModified(const fileName &name, const bool followLink=true)
Return time of last file modification (normally follows symbolic links).
Definition: POSIX.C:932
void fdClose(const int fd)
Close file descriptor.
Definition: POSIX.C:1555
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
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: POSIX.C:1704
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
bool isAdministrator()
Is the current user the administrator (root)
Definition: POSIX.C:436
bool dlClose(void *handle)
Close a dlopened library using handle. Return true if successful.
Definition: POSIX.C:1929
errorManip< error > abort(error &err)
Definition: errorManip.H:139
messageStream Info
Information stream (stdout output on master, null elsewhere)
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: POSIX.C:775
unsigned int sleep(const unsigned int sec)
Sleep for the specified number of seconds.
Definition: POSIX.C:1549
bool chMod(const fileName &name, const mode_t mode)
Set the file/directory mode, return true on success.
Definition: POSIX.C:759
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
string userName()
Return the user's login name.
Definition: POSIX.C:424
pid_t pgid()
Return the group PID of this process.
Definition: POSIX.C:328
bool env(const std::string &envName)
Deprecated(2020-05) check for existence of environment variable.
Definition: OSspecific.H:96
string hostName()
Return the system's host name, as per hostname(1)
Definition: POSIX.C:373
void * dlSymFind(void *handle, const std::string &symbol, bool required=false)
Look for symbol in a dlopened library.
Definition: POSIX.C:1941
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
static Foam::fileName cwd_P()
The physical current working directory path name (pwd -P).
Definition: POSIX.C:484
defineTypeNameAndDebug(combustionModel, 0)
pid_t ppid()
Return the parent PID of this process.
Definition: POSIX.C:322
static Foam::fileName cwd_L()
The logical current working directory path name.
Definition: POSIX.C:532
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
bool rmDir(const fileName &directory, const bool silent=false, const bool emptyOnly=false)
Remove a directory and its contents recursively,.
Definition: POSIX.C:1435
double highResLastModified(const fileName &, const bool followLink=true)
Return time of last file modification.
Definition: POSIX.C:948
void * dlOpen(const fileName &libName, const bool check=true)
Open a shared library and return handle to library.
Definition: POSIX.C:1826
pid_t pid()
Return the PID of this process.
Definition: POSIX.C:316
int infoDetailLevel
Global for selective suppression of Info output.
const direction noexcept
Definition: scalarImpl.H:255
bool mvBak(const fileName &src, const std::string &ext="bak")
Rename to a corresponding backup file.
Definition: POSIX.C:1359
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
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
fileNameList dlLoaded()
Return all loaded libraries.
Definition: POSIX.C:1996
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
bool mv(const fileName &src, const fileName &dst, const bool followLink=false)
Rename src to dst.
Definition: POSIX.C:1326
fileName home()
Return home directory path name for the current user.
Definition: POSIX.C:442
string domainName()
Deprecated(2022-01) domain name resolution may be unreliable.
Definition: POSIX.C:403
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: POSIX.C:1239
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:862
bool hasEnv(const std::string &envName)
True if environment variable of given name is defined.
Definition: POSIX.C:334
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
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:50
bool chDir(const fileName &dir)
Change current directory to the one specified and return true on success.
Definition: POSIX.C:609
#define timedOut(x)
Check if timeout has occurred.
Definition: timer.H:72