1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. 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"
40 #include "DynamicList.H"
51 #include <sys/types.h>
53 #include <sys/socket.h>
58 #include <netinet/in.h>
62 # if INT_MAX != 2147483647
63 # error "INT_MAX != 2147483647"
64 # error "The random number generator may not work!"
68 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
70 defineTypeNameAndDebug(Foam::POSIX, 0);
72 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
92 bool Foam::env(const word& envName)
94 return ::getenv(envName.c_str()) != NULL;
98 Foam::string Foam::getEnv(const word& envName)
100 char* env = ::getenv(envName.c_str());
108 // Return null-constructed string rather than string::null
109 // to avoid cyclic dependencies in the construction of globals
118 const std::string& value,
122 return setenv(envName.c_str(), value.c_str(), overwrite) == 0;
126 Foam::word Foam::hostName(bool full)
129 ::gethostname(buf, sizeof(buf));
131 // implementation as per hostname from net-tools
134 struct hostent *hp = ::gethostbyname(buf);
145 Foam::word Foam::domainName()
148 ::gethostname(buf, sizeof(buf));
150 // implementation as per hostname from net-tools
151 struct hostent *hp = ::gethostbyname(buf);
154 char *p = ::strchr(hp->h_name, '.');
166 Foam::word Foam::userName()
168 struct passwd* pw = ::getpwuid(::getuid());
181 bool Foam::isAdministrator()
183 return (::geteuid() == 0);
187 // use $HOME environment variable or passwd info
188 Foam::fileName Foam::home()
190 char* env = ::getenv("HOME");
194 return fileName(env);
198 struct passwd* pw = ::getpwuid(getuid());
206 return fileName::null;
212 Foam::fileName Foam::home(const word& userName)
218 pw = ::getpwnam(userName.c_str());
222 char* env = ::getenv("HOME");
226 return fileName(env);
229 pw = ::getpwuid(::getuid());
238 return fileName::null;
243 Foam::fileName Foam::cwd()
246 if (::getcwd(buf, sizeof(buf)))
252 FatalErrorIn("Foam::cwd()")
253 << "Couldn't get the current working directory"
256 return fileName::null;
261 bool Foam::chDir(const fileName& dir)
263 return ::chdir(dir.c_str()) == 0;
267 Foam::fileNameList Foam::findEtcFiles(const fileName& name, bool mandatory)
269 fileNameList results;
271 // Search for user files in
272 // * ~/.OpenFOAM/VERSION
275 fileName searchDir = home()/".OpenFOAM";
276 if (isDir(searchDir))
278 fileName fullName = searchDir/FOAMversion/name;
279 if (isFile(fullName))
281 results.append(fullName);
284 fullName = searchDir/name;
285 if (isFile(fullName))
287 results.append(fullName);
291 // Search for group (site) files in
292 // * $WM_PROJECT_SITE/VERSION
293 // * $WM_PROJECT_SITE
295 searchDir = getEnv("WM_PROJECT_SITE");
296 if (searchDir.size())
298 if (isDir(searchDir))
300 fileName fullName = searchDir/FOAMversion/name;
301 if (isFile(fullName))
303 results.append(fullName);
306 fullName = searchDir/name;
307 if (isFile(fullName))
309 results.append(fullName);
315 // OR search for group (site) files in
316 // * $WM_PROJECT_INST_DIR/site/VERSION
317 // * $WM_PROJECT_INST_DIR/site
319 searchDir = getEnv("WM_PROJECT_INST_DIR");
320 if (isDir(searchDir))
322 fileName fullName = searchDir/"site"/FOAMversion/name;
323 if (isFile(fullName))
325 results.append(fullName);
328 fullName = searchDir/"site"/name;
329 if (isFile(fullName))
331 results.append(fullName);
336 // Search for other (shipped) files in
337 // * $WM_PROJECT_DIR/etc
339 searchDir = getEnv("WM_PROJECT_DIR");
340 if (isDir(searchDir))
342 fileName fullName = searchDir/"etc"/name;
343 if (isFile(fullName))
345 results.append(fullName);
352 // Abort if the file is mandatory, otherwise return null
356 << "--> FOAM FATAL ERROR in Foam::findEtcFiles() :"
357 " could not find mandatory file\n '"
358 << name.c_str() << "'\n\n" << std::endl;
363 // Return list of matching paths or empty list if none found
368 Foam::fileName Foam::findEtcFile(const fileName& name, bool mandatory)
370 fileNameList results(findEtcFiles(name, mandatory));
383 bool Foam::mkDir(const fileName& pathName, mode_t mode)
385 // empty names are meaningless
386 if (pathName.empty())
391 // Construct instance path directory if does not exist
392 if (::mkdir(pathName.c_str(), mode) == 0)
394 // Directory made OK so return true
403 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
404 << "The filesystem containing " << pathName
405 << " does not support the creation of directories."
413 // Directory already exists so simply return true
419 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
421 << " points outside your accessible address space."
429 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
430 << "The parent directory does not allow write "
431 "permission to the process,"<< nl
432 << "or one of the directories in " << pathName
433 << " did not allow search (execute) permission."
441 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
442 << "" << pathName << " is too long."
450 // Part of the path does not exist so try to create it
451 if (pathName.path().size() && mkDir(pathName.path(), mode))
453 return mkDir(pathName, mode);
457 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
458 << "Couldn't create directory " << pathName
467 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
468 << "A component used as a directory in " << pathName
469 << " is not, in fact, a directory."
477 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
478 << "Insufficient kernel memory was available to make "
479 "directory " << pathName << '.'
487 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
489 << " refers to a file on a read-only filesystem."
497 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
498 << "Too many symbolic links were encountered in resolving "
507 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
508 << "The device containing " << pathName
509 << " has no room for the new directory or "
510 << "the user's disk quota is exhausted."
518 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
519 << "Couldn't create directory " << pathName
530 bool Foam::chMod(const fileName& name, const mode_t m)
532 return ::chmod(name.c_str(), m) == 0;
536 // Return the file mode
537 mode_t Foam::mode(const fileName& name)
539 fileStat fileStatus(name);
540 if (fileStatus.isValid())
542 return fileStatus.status().st_mode;
551 // Return the file type: FILE or DIRECTORY
552 Foam::fileName::Type Foam::type(const fileName& name)
554 mode_t m = mode(name);
558 return fileName::FILE;
562 return fileName::DIRECTORY;
566 return fileName::UNDEFINED;
571 // Does the name exist in the filing system?
572 bool Foam::exists(const fileName& name, const bool checkGzip)
574 return mode(name) || isFile(name, checkGzip);
578 // Does the directory exist?
579 bool Foam::isDir(const fileName& name)
581 return S_ISDIR(mode(name));
585 // Does the file exist?
586 bool Foam::isFile(const fileName& name, const bool checkGzip)
588 return S_ISREG(mode(name)) || (checkGzip && S_ISREG(mode(name + ".gz")));
592 // Return size of file
593 off_t Foam::fileSize(const fileName& name)
595 fileStat fileStatus(name);
596 if (fileStatus.isValid())
598 return fileStatus.status().st_size;
607 // Return time of last file modification
608 time_t Foam::lastModified(const fileName& name)
610 fileStat fileStatus(name);
611 if (fileStatus.isValid())
613 return fileStatus.status().st_mtime;
622 // Read a directory and return the entries as a string list
623 Foam::fileNameList Foam::readDir
625 const fileName& directory,
626 const fileName::Type type,
630 // Initial filename list size
631 // also used as increment if initial size found to be insufficient
632 static const int maxNnames = 100;
636 Info<< "readDir(const fileName&, const fileType, const bool filtergz)"
637 << " : reading directory " << directory << endl;
640 // Setup empty string list MAXTVALUES long
641 fileNameList dirEntries(maxNnames);
643 // Pointers to the directory entries
647 // Temporary variables and counters
650 // Attempt to open directory and set the structure pointer
651 if ((source = ::opendir(directory.c_str())) == NULL)
653 dirEntries.setSize(0);
657 Info<< "readDir(const fileName&, const fileType, "
658 "const bool filtergz) : cannot open directory "
659 << directory << endl;
664 // Read and parse all the entries in the directory
665 while ((list = ::readdir(source)) != NULL)
667 fileName fName(list->d_name);
669 // ignore files begining with ., i.e. '.', '..' and '.*'
670 if (fName.size() && fName[0] != '.')
672 word fExt = fName.ext();
676 (type == fileName::DIRECTORY)
679 type == fileName::FILE
680 && fName[fName.size()-1] != '~'
688 if ((directory/fName).type() == type)
690 if (nEntries >= dirEntries.size())
692 dirEntries.setSize(dirEntries.size() + maxNnames);
695 if (filtergz && fExt == "gz")
697 dirEntries[nEntries++] = fName.lessExt();
701 dirEntries[nEntries++] = fName;
708 // Reset the length of the entries list
709 dirEntries.setSize(nEntries);
718 // Copy, recursively if necessary, the source to the destination
719 bool Foam::cp(const fileName& src, const fileName& dest)
721 // Make sure source exists.
727 fileName destFile(dest);
729 // Check type of source file.
730 if (src.type() == fileName::FILE)
732 // If dest is a directory, create the destination file name.
733 if (destFile.type() == fileName::DIRECTORY)
735 destFile = destFile/src.name();
738 // Make sure the destination directory exists.
739 if (!isDir(destFile.path()) && !mkDir(destFile.path()))
744 // Open and check streams.
745 std::ifstream srcStream(src.c_str());
751 std::ofstream destStream(destFile.c_str());
757 // Copy character data.
759 while (srcStream.get(ch))
765 if (!srcStream.eof() || !destStream)
770 else if (src.type() == fileName::DIRECTORY)
772 // If dest is a directory, create the destination file name.
773 if (destFile.type() == fileName::DIRECTORY)
775 destFile = destFile/src.component(src.components().size() -1);
778 // Make sure the destination directory exists.
779 if (!isDir(destFile) && !mkDir(destFile))
785 fileNameList contents = readDir(src, fileName::FILE, false);
790 Info<< "Copying : " << src/contents[i]
791 << " to " << destFile/contents[i] << endl;
795 cp(src/contents[i], destFile/contents[i]);
798 // Copy sub directories.
799 fileNameList subdirs = readDir(src, fileName::DIRECTORY);
804 Info<< "Copying : " << src/subdirs[i]
805 << " to " << destFile << endl;
809 cp(src/subdirs[i], destFile);
817 // Create a softlink. dst should not exist. Returns true if successful.
818 bool Foam::ln(const fileName& src, const fileName& dst)
822 Info<< "Create softlink from : " << src << " to " << dst
828 WarningIn("ln(const fileName&, const fileName&)")
829 << "destination " << dst << " already exists. Not linking."
836 WarningIn("ln(const fileName&, const fileName&)")
837 << "source " << src << " does not exist." << endl;
841 if (::symlink(src.c_str(), dst.c_str()) == 0)
847 WarningIn("ln(const fileName&, const fileName&)")
848 << "symlink from " << src << " to " << dst << " failed." << endl;
854 // Rename srcFile dstFile
855 bool Foam::mv(const fileName& src, const fileName& dst)
859 Info<< "Move : " << src << " to " << dst << endl;
864 dst.type() == fileName::DIRECTORY
865 && src.type() != fileName::DIRECTORY
868 const fileName dstName(dst/src.name());
870 return ::rename(src.c_str(), dstName.c_str()) == 0;
874 return ::rename(src.c_str(), dst.c_str()) == 0;
879 //- Rename to a corresponding backup file
880 // If the backup file already exists, attempt with "01" .. "99" index
881 bool Foam::mvBak(const fileName& src, const std::string& ext)
885 Info<< "mvBak : " << src << " to extension " << ext << endl;
888 if (exists(src, false))
890 const int maxIndex = 99;
893 for (int n = 0; n <= maxIndex; n++)
895 fileName dstName(src + "." + ext);
898 sprintf(index, "%02d", n);
902 // avoid overwriting existing files, except for the last
903 // possible index where we have no choice
904 if (!exists(dstName, false) || n == maxIndex)
906 return ::rename(src.c_str(), dstName.c_str()) == 0;
912 // fall-through: nothing to do
917 // Remove a file, returning true if successful otherwise false
918 bool Foam::rm(const fileName& file)
922 Info<< "Removing : " << file << endl;
925 // Try returning plain file name; if not there, try with .gz
926 if (remove(file.c_str()) == 0)
932 return ::remove(string(file + ".gz").c_str()) == 0;
937 // Remove a dirctory and its contents
938 bool Foam::rmDir(const fileName& directory)
942 Info<< "rmDir(const fileName&) : "
943 << "removing directory " << directory << endl;
946 // Pointers to the directory entries
950 // Attempt to open directory and set the structure pointer
951 if ((source = ::opendir(directory.c_str())) == NULL)
953 WarningIn("rmDir(const fileName&)")
954 << "cannot open directory " << directory << endl;
960 // Read and parse all the entries in the directory
961 while ((list = ::readdir(source)) != NULL)
963 fileName fName(list->d_name);
965 if (fName != "." && fName != "..")
967 fileName path = directory/fName;
969 if (path.type() == fileName::DIRECTORY)
973 WarningIn("rmDir(const fileName&)")
974 << "failed to remove directory " << fName
975 << " while removing directory " << directory
987 WarningIn("rmDir(const fileName&)")
988 << "failed to remove file " << fName
989 << " while removing directory " << directory
1003 WarningIn("rmDir(const fileName&)")
1004 << "failed to remove directory " << directory << endl;
1018 unsigned int Foam::sleep(const unsigned int s)
1024 void Foam::fdClose(const int fd)
1030 "fdClose(const int fd)"
1031 ) << "close error on " << fd << endl
1032 << abort(FatalError);
1039 const word& destName,
1040 const label destPort,
1044 struct hostent *hostPtr;
1045 volatile int sockfd;
1046 struct sockaddr_in destAddr; // will hold the destination addr
1049 if ((hostPtr = ::gethostbyname(destName.c_str())) == NULL)
1053 "Foam::ping(const word&, ...)"
1054 ) << "gethostbyname error " << h_errno << " for host " << destName
1055 << abort(FatalError);
1058 // Get first of the SLL of addresses
1059 addr = (reinterpret_cast<struct in_addr*>(*(hostPtr->h_addr_list)))->s_addr;
1062 sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
1067 "Foam::ping(const word&, const label)"
1069 << abort(FatalError);
1072 // Fill sockaddr_in structure with dest address and port
1073 memset(reinterpret_cast<char *>(&destAddr), '\0', sizeof(destAddr));
1074 destAddr.sin_family = AF_INET;
1075 destAddr.sin_port = htons(ushort(destPort));
1076 destAddr.sin_addr.s_addr = addr;
1079 timer myTimer(timeOut);
1081 if (timedOut(myTimer))
1083 // Setjmp from timer jumps back to here
1093 reinterpret_cast<struct sockaddr*>(&destAddr),
1094 sizeof(struct sockaddr)
1098 // Connection refused. Check if network was actually used or not.
1100 int connectErr = errno;
1104 if (connectErr == ECONNREFUSED)
1108 //perror("connect");
1119 bool Foam::ping(const word& hostname, const label timeOut)
1121 return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut);
1125 int Foam::system(const std::string& command)
1127 return ::system(command.c_str());
1131 void* Foam::dlOpen(const fileName& lib)
1135 std::cout<< "dlOpen(const fileName&)"
1136 << " : dlopen of " << lib << std::endl;
1138 void* handle = ::dlopen(lib.c_str(), RTLD_LAZY|RTLD_GLOBAL);
1143 << "dlOpen(const fileName&)"
1144 << " : dlopen of " << lib
1145 << " handle " << handle << std::endl;
1152 bool Foam::dlClose(void* handle)
1158 << " : dlclose of handle " << handle << std::endl;
1160 return ::dlclose(handle) == 0;
1164 void* Foam::dlSym(void* handle, const std::string& symbol)
1169 << "dlSym(void*, const std::string&)"
1170 << " : dlsym of " << symbol << std::endl;
1172 // clear any old errors - see manpage dlopen
1175 // get address of symbol
1176 void* fun = ::dlsym(handle, symbol.c_str());
1178 // find error (if any)
1179 char *error = ::dlerror();
1183 WarningIn("dlSym(void*, const std::string&)")
1184 << "Cannot lookup symbol " << symbol << " : " << error
1192 bool Foam::dlSymFound(void* handle, const std::string& symbol)
1194 if (handle && !symbol.empty())
1199 << "dlSymFound(void*, const std::string&)"
1200 << " : dlsym of " << symbol << std::endl;
1203 // clear any old errors - see manpage dlopen
1206 // get address of symbol
1207 (void) ::dlsym(handle, symbol.c_str());
1209 // symbol can be found if there was no error
1210 return !::dlerror();
1219 static int collectLibsCallback
1221 struct dl_phdr_info *info,
1226 Foam::DynamicList<Foam::fileName>* ptr =
1227 reinterpret_cast<Foam::DynamicList<Foam::fileName>*>(data);
1228 ptr->append(info->dlpi_name);
1233 Foam::fileNameList Foam::dlLoaded()
1235 DynamicList<fileName> libs;
1236 dl_iterate_phdr(collectLibsCallback, &libs);
1241 << " : determined loaded libraries :" << libs.size() << std::endl;
1247 void Foam::osRandomSeed(const label seed)
1250 srandom((unsigned int)seed);
1257 Foam::label Foam::osRandomInteger()
1267 Foam::scalar Foam::osRandomDouble()
1270 return (scalar)random()/INT_MAX;
1277 // ************************************************************************* //