1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 POSIX versions of the functions declared in OSspecific.H
27 \*---------------------------------------------------------------------------*/
33 #include "OSspecific.H"
35 #include "foamVersion.H"
49 #include <sys/types.h>
51 #include <sys/socket.h>
54 #include <netinet/in.h>
56 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
58 defineTypeNameAndDebug(Foam::POSIX, 0);
60 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
77 bool Foam::env(const word& envName)
79 return getenv(envName.c_str()) != NULL;
83 Foam::string Foam::getEnv(const word& envName)
85 char* env = getenv(envName.c_str());
93 // Return null-constructed string rather than string::null
94 // to avoid cyclic dependencies in the construction of globals
107 return setenv(envName.c_str(), value.c_str(), overwrite) == 0;
111 Foam::word Foam::hostName()
114 gethostname(buffer, 256);
120 Foam::word Foam::userName()
122 struct passwd* pw = getpwuid(getuid());
135 // use $HOME environment variable or passwd info
136 Foam::fileName Foam::home()
138 char* env = getenv("HOME");
142 return fileName(env);
146 struct passwd* pw = getpwuid(getuid());
154 return fileName::null;
160 Foam::fileName Foam::home(const word& userName)
166 pw = getpwnam(userName.c_str());
170 char* env = getenv("HOME");
174 return fileName(env);
177 pw = getpwuid(getuid());
186 return fileName::null;
191 Foam::fileName Foam::cwd()
194 if (getcwd(buf, 255))
200 FatalErrorIn("Foam::cwd()")
201 << "Couldn't get the current working directory"
204 return fileName::null;
209 bool Foam::chDir(const fileName& dir)
211 return chdir(dir.c_str()) != 0;
215 Foam::fileName Foam::findEtcFile(const fileName& name, bool mandatory)
217 // Search user files: deprecated. HJ, 11/Dec/2013
219 // Search site files:
220 fileName searchDir = getEnv("WM_PROJECT_INST_DIR");
221 if (isDir(searchDir))
223 // Check for site file in $WM_PROJECT_INST_DIR/site/VERSION
224 fileName fullName = searchDir/"site"/FOAMversion/name;
225 if (isFile(fullName))
230 // Check for version-independent site file in $WM_PROJECT_INST_DIR/site
231 fullName = searchDir/"site"/name;
232 if (isFile(fullName))
238 // Search installation files:
239 searchDir = getEnv("WM_PROJECT_DIR");
240 if (isDir(searchDir))
242 // Check for shipped FOAM file in $WM_PROJECT_DIR/etc
243 fileName fullName = searchDir/"etc"/name;
244 if (isFile(fullName))
251 // abort if the file is mandatory, otherwise return null
254 cerr<< "--> FOAM FATAL ERROR in Foam::findEtcFile() :"
255 " could not find mandatory file\n '"
256 << name.c_str() << "'\n\n" << std::endl;
260 // Return null-constructed fileName rather than fileName::null
261 // to avoid cyclic dependencies in the construction of globals
266 bool Foam::mkDir(const fileName& pathName, mode_t mode)
268 // empty names are meaningless
269 if (pathName.empty())
274 // Construct instance path directory if does not exist
275 if (::mkdir(pathName.c_str(), mode) == 0)
277 // Directory made OK so return true
286 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
287 << "The filesystem containing " << pathName
288 << " does not support the creation of directories."
296 // Directory already exists so simply return true
302 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
304 << " points outside your accessible address space."
312 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
313 << "The parent directory does not allow write "
314 "permission to the process,"<< nl
315 << "or one of the directories in " << pathName
316 << " did not allow search (execute) permission."
324 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
325 << "" << pathName << " is too long."
333 // Part of the path does not exist so try to create it
334 if (pathName.path().size() && mkDir(pathName.path(), mode))
336 return mkDir(pathName, mode);
340 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
341 << "Couldn't create directory " << pathName
350 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
351 << "A component used as a directory in " << pathName
352 << " is not, in fact, a directory."
360 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
361 << "Insufficient kernel memory was available to make "
362 "directory " << pathName << '.'
370 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
372 << " refers to a file on a read-only filesystem."
380 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
381 << "Too many symbolic links were encountered in resolving "
390 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
391 << "The device containing " << pathName
392 << " has no room for the new directory or "
393 << "the user's disk quota is exhausted."
401 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
402 << "Couldn't create directory " << pathName
413 bool Foam::chMod(const fileName& name, const mode_t m)
415 return ::chmod(name.c_str(), m) == 0;
419 // Return the file mode
420 mode_t Foam::mode(const fileName& name)
422 fileStat fileStatus(name);
423 if (fileStatus.isValid())
425 return fileStatus.status().st_mode;
434 // Return the file type: FILE or DIRECTORY
435 Foam::fileName::Type Foam::type(const fileName& name)
437 mode_t m = mode(name);
441 return fileName::FILE;
445 return fileName::DIRECTORY;
449 return fileName::UNDEFINED;
454 // Does the name exist in the filing system?
455 bool Foam::exists(const fileName& name, const bool checkGzip)
457 return mode(name) || isFile(name, checkGzip);
461 // Does the directory exist?
462 bool Foam::isDir(const fileName& name)
464 return S_ISDIR(mode(name));
468 // Does the file exist?
469 bool Foam::isFile(const fileName& name, const bool checkGzip)
471 return S_ISREG(mode(name)) || (checkGzip && S_ISREG(mode(name + ".gz")));
475 // Return size of file
476 off_t Foam::fileSize(const fileName& name)
478 fileStat fileStatus(name);
479 if (fileStatus.isValid())
481 return fileStatus.status().st_size;
490 // Return time of last file modification
491 time_t Foam::lastModified(const fileName& name)
493 fileStat fileStatus(name);
494 if (fileStatus.isValid())
496 return fileStatus.status().st_mtime;
505 // Read a directory and return the entries as a string list
506 Foam::fileNameList Foam::readDir
508 const fileName& directory,
509 const fileName::Type type,
513 // Initial filename list size
514 // also used as increment if initial size found to be insufficient
515 static const int maxNnames = 100;
519 Info<< "readDir(const fileName&, const fileType, const bool filtergz)"
520 << " : reading directory " << directory << endl;
523 // Setup empty string list MAXTVALUES long
524 fileNameList dirEntries(maxNnames);
526 // Pointers to the directory entries
530 // Temporary variables and counters
533 // Attempt to open directory and set the structure pointer
534 if ((source = opendir(directory.c_str())) == NULL)
536 dirEntries.setSize(0);
540 Info<< "readDir(const fileName&, const fileType, "
541 "const bool filtergz) : cannot open directory "
542 << directory << endl;
547 // Read and parse all the entries in the directory
548 while ((list = readdir(source)) != NULL)
550 fileName fName(list->d_name);
552 // Ignore files begining with ., i.e. '.', '..' and '.*'
553 if (fName.size() && fName[0] != '.')
555 word fExt = fName.ext();
559 (type == fileName::DIRECTORY)
562 type == fileName::FILE
563 && fName[fName.size() - 1] != '~'
572 if ((directory/fName).type() == type)
574 if (nEntries >= dirEntries.size())
576 dirEntries.setSize(dirEntries.size() + maxNnames);
579 if (filtergz && fExt == "gz")
581 dirEntries[nEntries++] = fName.lessExt();
585 dirEntries[nEntries++] = fName;
592 // Reset the length of the entries list
593 dirEntries.setSize(nEntries);
602 // Copy, recursively if necessary, the source to the destination
603 bool Foam::cp(const fileName& src, const fileName& dest)
605 // Make sure source exists.
611 fileName destFile(dest);
613 // Check type of source file.
614 if (src.type() == fileName::FILE)
616 // If dest is a directory, create the destination file name.
617 if (destFile.type() == fileName::DIRECTORY)
619 destFile = destFile/src.name();
622 // Make sure the destination directory exists.
623 if (!isDir(destFile.path()) && !mkDir(destFile.path()))
628 // Open and check streams.
629 std::ifstream srcStream(src.c_str());
635 std::ofstream destStream(destFile.c_str());
641 // Copy character data.
643 while (srcStream.get(ch))
649 if (!srcStream.eof() || !destStream)
654 else if (src.type() == fileName::DIRECTORY)
656 // If dest is a directory, create the destination file name.
657 if (destFile.type() == fileName::DIRECTORY)
659 destFile = destFile/src.component(src.components().size() -1);
662 // Make sure the destination directory exists.
663 if (!isDir(destFile) && !mkDir(destFile))
669 fileNameList contents = readDir(src, fileName::FILE, false);
674 Info<< "Copying : " << src/contents[i]
675 << " to " << destFile/contents[i] << endl;
679 cp(src/contents[i], destFile/contents[i]);
682 // Copy sub directories.
683 fileNameList subdirs = readDir(src, fileName::DIRECTORY);
688 Info<< "Copying : " << src/subdirs[i]
689 << " to " << destFile << endl;
693 cp(src/subdirs[i], destFile);
701 // Create a softlink. dst should not exist. Returns true if successful.
702 bool Foam::ln(const fileName& src, const fileName& dst)
706 Info<< "Create softlink from : " << src << " to " << dst
712 WarningIn("ln(const fileName&, const fileName&)")
713 << "destination " << dst << " already exists. Not linking."
720 WarningIn("ln(const fileName&, const fileName&)")
721 << "source " << src << " does not exist." << endl;
725 if (symlink(src.c_str(), dst.c_str()) == 0)
731 WarningIn("ln(const fileName&, const fileName&)")
732 << "symlink from " << src << " to " << dst << " failed." << endl;
738 // Rename srcFile dstFile
739 bool Foam::mv(const fileName& src, const fileName& dst)
743 Info<< "Move : " << src << " to " << dst << endl;
748 dst.type() == fileName::DIRECTORY
749 && src.type() != fileName::DIRECTORY
752 const fileName dstName(dst/src.name());
754 return rename(src.c_str(), dstName.c_str()) == 0;
758 return rename(src.c_str(), dst.c_str()) == 0;
763 //- Rename to a corresponding backup file
764 // If the backup file already exists, attempt with "01" .. "99" index
765 bool Foam::mvBak(const fileName& src, const std::string& ext)
769 Info<< "mvBak : " << src << " to extension " << ext << endl;
772 if (exists(src, false))
774 const int maxIndex = 99;
777 for (int n = 0; n <= maxIndex; n++)
779 fileName dstName(src + "." + ext);
782 sprintf(index, "%02d", n);
786 // avoid overwriting existing files, except for the last
787 // possible index where we have no choice
788 if (!exists(dstName, false) || n == maxIndex)
790 return rename(src.c_str(), dstName.c_str()) == 0;
796 // fall-through: nothing to do
802 // Remove a file, returning true if successful otherwise false
803 bool Foam::rm(const fileName& file)
807 Info<< "Removing : " << file << endl;
810 // Try returning plain file name; if not there, try with .gz
811 if (remove(file.c_str()) == 0)
817 return remove(string(file + ".gz").c_str()) == 0;
822 // Remove a dirctory and its contents
823 bool Foam::rmDir(const fileName& directory)
827 Info<< "rmDir(const fileName&) : "
828 << "removing directory " << directory << endl;
831 // Pointers to the directory entries
835 // Attempt to open directory and set the structure pointer
836 if ((source = opendir(directory.c_str())) == NULL)
838 WarningIn("rmDir(const fileName&)")
839 << "cannot open directory " << directory << endl;
845 // Read and parse all the entries in the directory
846 while ((list = readdir(source)) != NULL)
848 fileName fName(list->d_name);
850 if (fName != "." && fName != "..")
852 fileName path = directory/fName;
854 if (path.type() == fileName::DIRECTORY)
858 WarningIn("rmDir(const fileName&)")
859 << "failed to remove directory " << fName
860 << " while removing directory " << directory
872 WarningIn("rmDir(const fileName&)")
873 << "failed to remove file " << fName
874 << " while removing directory " << directory
888 WarningIn("rmDir(const fileName&)")
889 << "failed to remove directory " << directory << endl;
903 unsigned int Foam::sleep(const unsigned int s)
909 void Foam::fdClose(const int fd)
915 "fdClose(const int fd)"
916 ) << "close error on " << fd << endl
917 << abort(FatalError);
924 const word& destName,
925 const label destPort,
931 struct hostent *hostPtr;
933 struct sockaddr_in destAddr; // will hold the destination addr
936 if ((hostPtr = gethostbyname(destName.c_str())) == NULL)
940 "Foam::ping(const word&, const label)"
941 ) << "gethostbyname error " << h_errno << " for host " << destName
942 << abort(FatalError);
945 // Get first of the SLL of addresses
946 serverAddress = *(hostPtr->h_addr_list);
947 ptr = reinterpret_cast<struct in_addr*>(serverAddress);
951 sockfd = socket(AF_INET, SOCK_STREAM, 0);
956 "Foam::ping(const word&, const label)"
958 << abort(FatalError);
961 // Fill sockaddr_in structure with dest address and port
962 memset (reinterpret_cast<char *>(&destAddr), '\0', sizeof(destAddr));
963 destAddr.sin_family = AF_INET;
964 destAddr.sin_port = htons(ushort(destPort));
965 destAddr.sin_addr.s_addr = addr;
968 timer myTimer(timeOut);
970 if (timedOut(myTimer))
972 // Setjmp from timer jumps back to here
982 reinterpret_cast<struct sockaddr*>(&destAddr),
983 sizeof(struct sockaddr)
987 // Connection refused. Check if network was actually used or not.
989 int connectErr = errno;
993 if (connectErr == ECONNREFUSED)
1008 bool Foam::ping(const word& hostname, const label timeOut)
1010 return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut);
1014 int Foam::system(const string& command)
1016 return ::system(command.c_str());
1020 void Foam::osRandomSeed(const label seed)
1023 srandom((unsigned int)seed);
1030 Foam::label Foam::osRandomInteger()
1040 Foam::scalar Foam::osRandomDouble()
1043 return (scalar)random()/INT_MAX;
1050 // ************************************************************************* //