1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
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>
60 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
62 defineTypeNameAndDebug(Foam::POSIX, 0);
64 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
81 bool Foam::env(const word& envName)
83 return ::getenv(envName.c_str()) != NULL;
87 Foam::string Foam::getEnv(const word& envName)
89 char* env = ::getenv(envName.c_str());
97 // Return null-constructed string rather than string::null
98 // to avoid cyclic dependencies in the construction of globals
107 const std::string& value,
111 return setenv(envName.c_str(), value.c_str(), overwrite) == 0;
115 Foam::word Foam::hostName(bool full)
118 ::gethostname(buf, sizeof(buf));
120 // implementation as per hostname from net-tools
123 struct hostent *hp = ::gethostbyname(buf);
134 Foam::word Foam::domainName()
137 ::gethostname(buf, sizeof(buf));
139 // implementation as per hostname from net-tools
140 struct hostent *hp = ::gethostbyname(buf);
143 char *p = ::strchr(hp->h_name, '.');
155 Foam::word Foam::userName()
157 struct passwd* pw = ::getpwuid(::getuid());
170 bool Foam::isAdministrator()
172 return (::geteuid() == 0);
176 // use $HOME environment variable or passwd info
177 Foam::fileName Foam::home()
179 char* env = ::getenv("HOME");
183 return fileName(env);
187 struct passwd* pw = ::getpwuid(getuid());
195 return fileName::null;
201 Foam::fileName Foam::home(const word& userName)
207 pw = ::getpwnam(userName.c_str());
211 char* env = ::getenv("HOME");
215 return fileName(env);
218 pw = ::getpwuid(::getuid());
227 return fileName::null;
232 Foam::fileName Foam::cwd()
235 if (::getcwd(buf, sizeof(buf)))
241 FatalErrorIn("Foam::cwd()")
242 << "Couldn't get the current working directory"
245 return fileName::null;
250 bool Foam::chDir(const fileName& dir)
252 return ::chdir(dir.c_str()) == 0;
256 Foam::fileName Foam::findEtcFile(const fileName& name, bool mandatory)
259 // search for user files in
260 // * ~/.OpenFOAM/VERSION
263 fileName searchDir = home()/".OpenFOAM";
264 if (isDir(searchDir))
266 fileName fullName = searchDir/FOAMversion/name;
267 if (isFile(fullName))
272 fullName = searchDir/name;
273 if (isFile(fullName))
281 // search for group (site) files in
282 // * $WM_PROJECT_SITE/VERSION
283 // * $WM_PROJECT_SITE
285 searchDir = getEnv("WM_PROJECT_SITE");
286 if (searchDir.size())
288 if (isDir(searchDir))
290 fileName fullName = searchDir/FOAMversion/name;
291 if (isFile(fullName))
296 fullName = searchDir/name;
297 if (isFile(fullName))
306 // OR search for group (site) files in
307 // * $WM_PROJECT_INST_DIR/site/VERSION
308 // * $WM_PROJECT_INST_DIR/site
310 searchDir = getEnv("WM_PROJECT_INST_DIR");
311 if (isDir(searchDir))
313 fileName fullName = searchDir/"site"/FOAMversion/name;
314 if (isFile(fullName))
319 fullName = searchDir/"site"/name;
320 if (isFile(fullName))
329 // search for other (shipped) files in
330 // * $WM_PROJECT_DIR/etc
332 searchDir = getEnv("WM_PROJECT_DIR");
333 if (isDir(searchDir))
335 fileName fullName = searchDir/"etc"/name;
336 if (isFile(fullName))
343 // abort if the file is mandatory, otherwise return null
347 << "--> FOAM FATAL ERROR in Foam::findEtcFile() :"
348 " could not find mandatory file\n '"
349 << name.c_str() << "'\n\n" << std::endl;
353 // Return null-constructed fileName rather than fileName::null
354 // to avoid cyclic dependencies in the construction of globals
359 bool Foam::mkDir(const fileName& pathName, mode_t mode)
361 // empty names are meaningless
362 if (pathName.empty())
367 // Construct instance path directory if does not exist
368 if (::mkdir(pathName.c_str(), mode) == 0)
370 // Directory made OK so return true
379 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
380 << "The filesystem containing " << pathName
381 << " does not support the creation of directories."
389 // Directory already exists so simply return true
395 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
397 << " points outside your accessible address space."
405 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
406 << "The parent directory does not allow write "
407 "permission to the process,"<< nl
408 << "or one of the directories in " << pathName
409 << " did not allow search (execute) permission."
417 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
418 << "" << pathName << " is too long."
426 // Part of the path does not exist so try to create it
427 if (pathName.path().size() && mkDir(pathName.path(), mode))
429 return mkDir(pathName, mode);
433 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
434 << "Couldn't create directory " << pathName
443 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
444 << "A component used as a directory in " << pathName
445 << " is not, in fact, a directory."
453 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
454 << "Insufficient kernel memory was available to make "
455 "directory " << pathName << '.'
463 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
465 << " refers to a file on a read-only filesystem."
473 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
474 << "Too many symbolic links were encountered in resolving "
483 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
484 << "The device containing " << pathName
485 << " has no room for the new directory or "
486 << "the user's disk quota is exhausted."
494 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
495 << "Couldn't create directory " << pathName
506 bool Foam::chMod(const fileName& name, const mode_t m)
508 return ::chmod(name.c_str(), m) == 0;
512 // Return the file mode
513 mode_t Foam::mode(const fileName& name)
515 fileStat fileStatus(name);
516 if (fileStatus.isValid())
518 return fileStatus.status().st_mode;
527 // Return the file type: FILE or DIRECTORY
528 Foam::fileName::Type Foam::type(const fileName& name)
530 mode_t m = mode(name);
534 return fileName::FILE;
538 return fileName::DIRECTORY;
542 return fileName::UNDEFINED;
547 // Does the name exist in the filing system?
548 bool Foam::exists(const fileName& name, const bool checkGzip)
550 return mode(name) || isFile(name, checkGzip);
554 // Does the directory exist?
555 bool Foam::isDir(const fileName& name)
557 return S_ISDIR(mode(name));
561 // Does the file exist?
562 bool Foam::isFile(const fileName& name, const bool checkGzip)
564 return S_ISREG(mode(name)) || (checkGzip && S_ISREG(mode(name + ".gz")));
568 // Return size of file
569 off_t Foam::fileSize(const fileName& name)
571 fileStat fileStatus(name);
572 if (fileStatus.isValid())
574 return fileStatus.status().st_size;
583 // Return time of last file modification
584 time_t Foam::lastModified(const fileName& name)
586 fileStat fileStatus(name);
587 if (fileStatus.isValid())
589 return fileStatus.status().st_mtime;
598 // Read a directory and return the entries as a string list
599 Foam::fileNameList Foam::readDir
601 const fileName& directory,
602 const fileName::Type type,
606 // Initial filename list size
607 // also used as increment if initial size found to be insufficient
608 static const int maxNnames = 100;
612 Info<< "readDir(const fileName&, const fileType, const bool filtergz)"
613 << " : reading directory " << directory << endl;
616 // Setup empty string list MAXTVALUES long
617 fileNameList dirEntries(maxNnames);
619 // Pointers to the directory entries
623 // Temporary variables and counters
626 // Attempt to open directory and set the structure pointer
627 if ((source = ::opendir(directory.c_str())) == NULL)
629 dirEntries.setSize(0);
633 Info<< "readDir(const fileName&, const fileType, "
634 "const bool filtergz) : cannot open directory "
635 << directory << endl;
640 // Read and parse all the entries in the directory
641 while ((list = ::readdir(source)) != NULL)
643 fileName fName(list->d_name);
645 // ignore files begining with ., i.e. '.', '..' and '.*'
646 if (fName.size() && fName[0] != '.')
648 word fExt = fName.ext();
652 (type == fileName::DIRECTORY)
655 type == fileName::FILE
656 && fName[fName.size()-1] != '~'
664 if ((directory/fName).type() == type)
666 if (nEntries >= dirEntries.size())
668 dirEntries.setSize(dirEntries.size() + maxNnames);
671 if (filtergz && fExt == "gz")
673 dirEntries[nEntries++] = fName.lessExt();
677 dirEntries[nEntries++] = fName;
684 // Reset the length of the entries list
685 dirEntries.setSize(nEntries);
694 // Copy, recursively if necessary, the source to the destination
695 bool Foam::cp(const fileName& src, const fileName& dest)
697 // Make sure source exists.
703 fileName destFile(dest);
705 // Check type of source file.
706 if (src.type() == fileName::FILE)
708 // If dest is a directory, create the destination file name.
709 if (destFile.type() == fileName::DIRECTORY)
711 destFile = destFile/src.name();
714 // Make sure the destination directory exists.
715 if (!isDir(destFile.path()) && !mkDir(destFile.path()))
720 // Open and check streams.
721 std::ifstream srcStream(src.c_str());
727 std::ofstream destStream(destFile.c_str());
733 // Copy character data.
735 while (srcStream.get(ch))
741 if (!srcStream.eof() || !destStream)
746 else if (src.type() == fileName::DIRECTORY)
748 // If dest is a directory, create the destination file name.
749 if (destFile.type() == fileName::DIRECTORY)
751 destFile = destFile/src.component(src.components().size() -1);
754 // Make sure the destination directory exists.
755 if (!isDir(destFile) && !mkDir(destFile))
761 fileNameList contents = readDir(src, fileName::FILE, false);
766 Info<< "Copying : " << src/contents[i]
767 << " to " << destFile/contents[i] << endl;
771 cp(src/contents[i], destFile/contents[i]);
774 // Copy sub directories.
775 fileNameList subdirs = readDir(src, fileName::DIRECTORY);
780 Info<< "Copying : " << src/subdirs[i]
781 << " to " << destFile << endl;
785 cp(src/subdirs[i], destFile);
793 // Create a softlink. dst should not exist. Returns true if successful.
794 bool Foam::ln(const fileName& src, const fileName& dst)
798 Info<< "Create softlink from : " << src << " to " << dst
804 WarningIn("ln(const fileName&, const fileName&)")
805 << "destination " << dst << " already exists. Not linking."
812 WarningIn("ln(const fileName&, const fileName&)")
813 << "source " << src << " does not exist." << endl;
817 if (::symlink(src.c_str(), dst.c_str()) == 0)
823 WarningIn("ln(const fileName&, const fileName&)")
824 << "symlink from " << src << " to " << dst << " failed." << endl;
830 // Rename srcFile dstFile
831 bool Foam::mv(const fileName& src, const fileName& dst)
835 Info<< "Move : " << src << " to " << dst << endl;
840 dst.type() == fileName::DIRECTORY
841 && src.type() != fileName::DIRECTORY
844 const fileName dstName(dst/src.name());
846 return ::rename(src.c_str(), dstName.c_str()) == 0;
850 return ::rename(src.c_str(), dst.c_str()) == 0;
855 //- Rename to a corresponding backup file
856 // If the backup file already exists, attempt with "01" .. "99" index
857 bool Foam::mvBak(const fileName& src, const std::string& ext)
861 Info<< "mvBak : " << src << " to extension " << ext << endl;
864 if (exists(src, false))
866 const int maxIndex = 99;
869 for (int n = 0; n <= maxIndex; n++)
871 fileName dstName(src + "." + ext);
874 sprintf(index, "%02d", n);
878 // avoid overwriting existing files, except for the last
879 // possible index where we have no choice
880 if (!exists(dstName, false) || n == maxIndex)
882 return ::rename(src.c_str(), dstName.c_str()) == 0;
888 // fall-through: nothing to do
894 // Remove a file, returning true if successful otherwise false
895 bool Foam::rm(const fileName& file)
899 Info<< "Removing : " << file << endl;
902 // Try returning plain file name; if not there, try with .gz
903 if (remove(file.c_str()) == 0)
909 return ::remove(string(file + ".gz").c_str()) == 0;
914 // Remove a dirctory and its contents
915 bool Foam::rmDir(const fileName& directory)
919 Info<< "rmDir(const fileName&) : "
920 << "removing directory " << directory << endl;
923 // Pointers to the directory entries
927 // Attempt to open directory and set the structure pointer
928 if ((source = ::opendir(directory.c_str())) == NULL)
930 WarningIn("rmDir(const fileName&)")
931 << "cannot open directory " << directory << endl;
937 // Read and parse all the entries in the directory
938 while ((list = ::readdir(source)) != NULL)
940 fileName fName(list->d_name);
942 if (fName != "." && fName != "..")
944 fileName path = directory/fName;
946 if (path.type() == fileName::DIRECTORY)
950 WarningIn("rmDir(const fileName&)")
951 << "failed to remove directory " << fName
952 << " while removing directory " << directory
964 WarningIn("rmDir(const fileName&)")
965 << "failed to remove file " << fName
966 << " while removing directory " << directory
980 WarningIn("rmDir(const fileName&)")
981 << "failed to remove directory " << directory << endl;
995 unsigned int Foam::sleep(const unsigned int s)
1001 void Foam::fdClose(const int fd)
1007 "fdClose(const int fd)"
1008 ) << "close error on " << fd << endl
1009 << abort(FatalError);
1016 const word& destName,
1017 const label destPort,
1021 struct hostent *hostPtr;
1022 volatile int sockfd;
1023 struct sockaddr_in destAddr; // will hold the destination addr
1026 if ((hostPtr = ::gethostbyname(destName.c_str())) == NULL)
1030 "Foam::ping(const word&, ...)"
1031 ) << "gethostbyname error " << h_errno << " for host " << destName
1032 << abort(FatalError);
1035 // Get first of the SLL of addresses
1036 addr = (reinterpret_cast<struct in_addr*>(*(hostPtr->h_addr_list)))->s_addr;
1039 sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
1044 "Foam::ping(const word&, const label)"
1046 << abort(FatalError);
1049 // Fill sockaddr_in structure with dest address and port
1050 memset(reinterpret_cast<char *>(&destAddr), '\0', sizeof(destAddr));
1051 destAddr.sin_family = AF_INET;
1052 destAddr.sin_port = htons(ushort(destPort));
1053 destAddr.sin_addr.s_addr = addr;
1056 timer myTimer(timeOut);
1058 if (timedOut(myTimer))
1060 // Setjmp from timer jumps back to here
1070 reinterpret_cast<struct sockaddr*>(&destAddr),
1071 sizeof(struct sockaddr)
1075 // Connection refused. Check if network was actually used or not.
1077 int connectErr = errno;
1081 if (connectErr == ECONNREFUSED)
1085 //perror("connect");
1096 bool Foam::ping(const word& hostname, const label timeOut)
1098 return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut);
1102 int Foam::system(const std::string& command)
1104 return ::system(command.c_str());
1108 void* Foam::dlOpen(const fileName& lib)
1112 std::cout<< "dlOpen(const fileName&)"
1113 << " : dlopen of " << lib << std::endl;
1115 void* handle = ::dlopen(lib.c_str(), RTLD_LAZY|RTLD_GLOBAL);
1120 << "dlOpen(const fileName&)"
1121 << " : dlopen of " << lib
1122 << " handle " << handle << std::endl;
1129 bool Foam::dlClose(void* handle)
1135 << " : dlclose of handle " << handle << std::endl;
1137 return ::dlclose(handle) == 0;
1141 void* Foam::dlSym(void* handle, const std::string& symbol)
1146 << "dlSym(void*, const std::string&)"
1147 << " : dlsym of " << symbol << std::endl;
1149 // clear any old errors - see manpage dlopen
1152 // get address of symbol
1153 void* fun = ::dlsym(handle, symbol.c_str());
1155 // find error (if any)
1156 char *error = ::dlerror();
1160 WarningIn("dlSym(void*, const std::string&)")
1161 << "Cannot lookup symbol " << symbol << " : " << error
1169 bool Foam::dlSymFound(void* handle, const std::string& symbol)
1171 if (handle && !symbol.empty())
1176 << "dlSymFound(void*, const std::string&)"
1177 << " : dlsym of " << symbol << std::endl;
1180 // clear any old errors - see manpage dlopen
1183 // get address of symbol
1184 (void) ::dlsym(handle, symbol.c_str());
1186 // symbol can be found if there was no error
1187 return !::dlerror();
1196 static int collectLibsCallback
1198 struct dl_phdr_info *info,
1203 Foam::DynamicList<Foam::fileName>* ptr =
1204 reinterpret_cast<Foam::DynamicList<Foam::fileName>*>(data);
1205 ptr->append(info->dlpi_name);
1210 Foam::fileNameList Foam::dlLoaded()
1212 DynamicList<fileName> libs;
1213 dl_iterate_phdr(collectLibsCallback, &libs);
1218 << " : determined loaded libraries :" << libs.size() << std::endl;
1224 // ************************************************************************* //