1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 UNIX versions of the functions declated in OSspecific.H.
28 \*---------------------------------------------------------------------------*/
34 #include "OSspecific.H"
36 #include "foamVersion.H"
50 #include <sys/types.h>
52 #include <sys/socket.h>
55 #include <netinet/in.h>
57 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
59 defineTypeNameAndDebug(Foam::Unix, 0);
61 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
78 bool Foam::env(const word& envName)
80 return getenv(envName.c_str()) != NULL;
84 Foam::string Foam::getEnv(const word& envName)
86 char* env = getenv(envName.c_str());
106 return setenv(envName.c_str(), value.c_str(), overwrite) == 0;
110 Foam::word Foam::hostName()
113 gethostname(buffer, 256);
119 Foam::word Foam::userName()
121 struct passwd* pw = getpwuid(getuid());
134 // use $HOME environment variable or passwd info
135 Foam::fileName Foam::home()
137 char* env = getenv("HOME");
141 return fileName(env);
145 struct passwd* pw = getpwuid(getuid());
153 return fileName::null;
159 Foam::fileName Foam::home(const word& userName)
165 pw = getpwnam(userName.c_str());
169 char* env = getenv("HOME");
173 return fileName(env);
176 pw = getpwuid(getuid());
185 return fileName::null;
190 Foam::fileName Foam::cwd()
193 if (getcwd(buf, 255))
199 FatalErrorIn("Foam::cwd()")
200 << "Couldn't get the current working directory"
203 return fileName::null;
208 bool Foam::chDir(const fileName& dir)
210 return chdir(dir.c_str()) != 0;
214 Foam::fileName Foam::dotFoam(const fileName& name)
216 // Search user files:
217 // ~~~~~~~~~~~~~~~~~~
218 fileName searchDir = home()/".OpenFOAM";
221 // Check for user file in ~/.OpenFOAM/VERSION
222 fileName fullName = searchDir/FOAMversion/name;
223 if (exists(fullName))
228 // Check for version-independent user file in ~/.OpenFOAM
229 fullName = searchDir/name;
230 if (exists(fullName))
237 // Search site files:
238 // ~~~~~~~~~~~~~~~~~~
239 searchDir = getEnv("WM_PROJECT_INST_DIR");
242 // Check for site file in $WM_PROJECT_INST_DIR/site/VERSION
243 fileName fullName = searchDir/"site"/FOAMversion/name;
244 if (exists(fullName))
249 // Check for version-independent site file in $WM_PROJECT_INST_DIR/site
250 fullName = searchDir/"site"/name;
251 if (exists(fullName))
257 // Search installation files:
258 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
259 searchDir = getEnv("WM_PROJECT_DIR");
262 // Check for shipped OpenFOAM file in $WM_PROJECT_DIR/etc
263 fileName fullName = searchDir/"etc"/name;
264 if (exists(fullName))
271 return fileName::null;
275 bool Foam::mkDir(const fileName& pathName, mode_t mode)
277 // empty names are meaningless
278 if (!pathName.size())
283 // Construct instance path directory if does not exist
284 if (::mkdir(pathName.c_str(), mode) == 0)
286 // Directory made OK so return true
295 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
296 << "The filesystem containing " << pathName
297 << " does not support the creation of directories."
305 // Directory already exists so simply return true
311 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
313 << " points outside your accessible address space."
321 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
322 << "The parent directory does not allow write "
323 "permission to the process,"<< nl
324 << "or one of the directories in " << pathName
325 << " did not allow search (execute) permission."
333 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
334 << "" << pathName << " is too long."
342 // Part of the path does not exist so try to create it
343 if (pathName.path().size() && mkDir(pathName.path(), mode))
345 return mkDir(pathName, mode);
349 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
350 << "Couldn't create directory " << pathName
359 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
360 << "A component used as a directory in " << pathName
361 << " is not, in fact, a directory."
369 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
370 << "Insufficient kernel memory was available to make "
371 "directory " << pathName << '.'
379 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
381 << " refers to a file on a read-only filesystem."
389 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
390 << "Too many symbolic links were encountered in resolving "
399 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
400 << "The device containing " << pathName
401 << " has no room for the new directory or "
402 << "the user's disk quota is exhausted."
410 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
411 << "Couldn't create directory " << pathName
422 bool Foam::chmod(const fileName& name, const mode_t m)
424 return ::chmod(name.c_str(), m) == 0;
428 // Return the file mode
429 mode_t Foam::mode(const fileName& name)
431 fileStat fileStatus(name);
432 if (fileStatus.isValid())
434 return fileStatus.status().st_mode;
443 // Return the file type: FILE or DIRECTORY
444 Foam::fileName::Type Foam::type(const fileName& name)
446 mode_t m = mode(name);
450 return fileName::FILE;
454 return fileName::DIRECTORY;
458 return fileName::UNDEFINED;
463 // Does the name exist in the filing system?
464 bool Foam::exists(const fileName& name)
466 return mode(name) || file(name);
470 // Does the file exist
471 bool Foam::file(const fileName& name)
473 return S_ISREG(mode(name)) || S_ISREG(mode(name + ".gz"));
477 // Does the directory exist
478 bool Foam::dir(const fileName& name)
480 return S_ISDIR(mode(name));
484 // Return size of file
485 off_t Foam::size(const fileName& name)
487 fileStat fileStatus(name);
488 if (fileStatus.isValid())
490 return fileStatus.status().st_size;
499 // Return time of last file modification
500 time_t Foam::lastModified(const fileName& name)
502 fileStat fileStatus(name);
503 if (fileStatus.isValid())
505 return fileStatus.status().st_mtime;
514 // Read a directory and return the entries as a string list
515 Foam::fileNameList Foam::readDir
517 const fileName& directory,
518 const fileName::Type type,
522 // Initial filename list size
523 // also used as increment if initial size found to be insufficient
524 static const int maxNnames = 100;
528 Info<< "readDir(const fileName&, const fileType, const bool filtergz)"
529 << " : reading directory " << directory << endl;
532 // Setup empty string list MAXTVALUES long
533 fileNameList dirEntries(maxNnames);
535 // Pointers to the Unix director system
539 // Temporary variables and counters
542 // Attempt to open directory and set the structure pointer
543 if ((source = opendir(directory.c_str())) == NULL)
545 dirEntries.setSize(0);
549 Info<< "readDir(const fileName&, const fileType, "
550 "const bool filtergz) : cannot open directory "
551 << directory << endl;
556 // Read and parse all the entries in the directory
557 while ((list = readdir(source)) != NULL)
559 fileName fName(list->d_name);
561 // ignore files begining with ., i.e. ., .. and .??*
562 if (fName.size() > 0 && fName[size_t(0)] != '.')
564 word fileNameExt = fName.ext();
568 (type == fileName::DIRECTORY)
571 type == fileName::FILE
572 && fName[fName.size()-1] != '~'
573 && fileNameExt != "bak"
574 && fileNameExt != "BAK"
575 && fileNameExt != "old"
576 && fileNameExt != "save"
580 if ((directory/fName).type() == type)
582 if (nEntries >= dirEntries.size())
584 dirEntries.setSize(dirEntries.size() + maxNnames);
587 if (filtergz && fileNameExt == "gz")
589 dirEntries[nEntries++] = fName.lessExt();
593 dirEntries[nEntries++] = fName;
600 // Reset the length of the entries list
601 dirEntries.setSize(nEntries);
610 // Copy, recursively if necessary, the source top the destination
611 bool Foam::cp(const fileName& src, const fileName& dest)
613 fileName destFile(dest);
615 // Make sure source exists.
621 // Check type of source file.
622 if (src.type() == fileName::FILE)
624 // If dest is a directory, create the destination file name.
625 if (destFile.type() == fileName::DIRECTORY)
627 destFile = destFile/src.name();
630 // Make sure the destination directory exists.
631 if (!dir(destFile.path()) && !mkDir(destFile.path()))
636 // Open and check streams.
637 std::ifstream srcStream(src.c_str());
643 std::ofstream destStream(destFile.c_str());
649 // Copy character data.
651 while (srcStream.get(ch))
657 if (!srcStream.eof() || !destStream)
662 else if (src.type() == fileName::DIRECTORY)
664 // If dest is a directory, create the destination file name.
665 if (destFile.type() == fileName::DIRECTORY)
667 destFile = destFile/src.component(src.components().size() -1);
670 // Make sure the destination directory extists.
671 if (!dir(destFile) && !mkDir(destFile))
677 fileNameList contents = readDir(src, fileName::FILE, false);
682 Info<< "Copying : " << src/contents[i]
683 << " to " << destFile/contents[i] << endl;
687 cp(src/contents[i], destFile/contents[i]);
690 // Copy sub directories.
691 fileNameList subdirs = readDir(src, fileName::DIRECTORY);
696 Info<< "Copying : " << src/subdirs[i]
697 << " to " << destFile << endl;
701 cp(src/subdirs[i], destFile);
709 // Create a softlink. destFile should not exist. Returns true if successful.
710 bool Foam::ln(const fileName& src, const fileName& dest)
714 Info<< "Create softlink from : " << src << " to " << dest
720 WarningIn("ln(const fileName&, const fileName&)")
721 << "destination " << dest << " already exists. Not linking."
728 WarningIn("ln(const fileName&, const fileName&)")
729 << "source " << src << " does not exist." << endl;
733 if (symlink(src.c_str(), dest.c_str()) == 0)
739 WarningIn("ln(const fileName&, const fileName&)")
740 << "symlink from " << src << " to " << dest << " failed." << endl;
746 // Rename srcFile destFile
747 bool Foam::mv(const fileName& srcFile, const fileName& destFile)
751 Info<< "Move : " << srcFile << " to " << destFile << endl;
756 (destFile.type() == fileName::DIRECTORY)
757 && (srcFile.type() != fileName::DIRECTORY)
760 const fileName destName(destFile/srcFile.name());
762 return rename(srcFile.c_str(), destName.c_str()) == 0;
766 return rename(srcFile.c_str(), destFile.c_str()) == 0;
771 // Remove a file returning true if successful otherwise false
772 bool Foam::rm(const fileName& file)
776 Info<< "Removing : " << file << endl;
779 // Try returning plain file name; if not there, try with .gz
780 if (remove(file.c_str()) == 0)
786 return remove(string(file + ".gz").c_str()) == 0;
791 // Remove a dirctory and its contents
792 bool Foam::rmDir(const fileName& directory)
796 Info<< "rmdir(const fileName&) : "
797 << "removing directory " << directory << endl;
800 // Pointers to the Unix director system
804 // Attempt to open directory and set the structure pointer
805 if ((source = opendir(directory.c_str())) == NULL)
807 WarningIn("rmdir(const fileName&)")
808 << "cannot open directory " << directory << endl;
814 // Read and parse all the entries in the directory
815 while ((list = readdir(source)) != NULL)
817 fileName fName(list->d_name);
819 if (fName != "." && fName != "..")
821 fileName path = directory/fName;
823 if (path.type() == fileName::DIRECTORY)
827 WarningIn("rmdir(const fileName&)")
828 << "failed to remove directory " << fName
829 << " while removing directory " << directory
841 WarningIn("rmdir(const fileName&)")
842 << "failed to remove file " << fName
843 << " while removing directory " << directory
857 WarningIn("rmdir(const fileName&)")
858 << "failed to remove directory " << directory << endl;
872 unsigned int Foam::sleep(const unsigned int s)
878 void Foam::fdClose(const int fd)
884 "fdClose(const int fd)"
885 ) << "close error on " << fd << endl
886 << abort(FatalError);
893 const word& destName,
894 const label destPort,
900 struct hostent *hostPtr;
902 struct sockaddr_in destAddr; // will hold the destination addr
905 if ((hostPtr = gethostbyname(destName.c_str())) == NULL)
909 "Foam::ping(const word&, const label)"
910 ) << "gethostbyname error " << h_errno << " for host " << destName
911 << abort(FatalError);
914 // Get first of the SLL of addresses
915 serverAddress = *(hostPtr->h_addr_list);
916 ptr = reinterpret_cast<struct in_addr*>(serverAddress);
920 sockfd = socket(AF_INET, SOCK_STREAM, 0);
925 "Foam::ping(const word&, const label)"
927 << abort(FatalError);
930 // Fill sockaddr_in structure with dest address and port
931 memset (reinterpret_cast<char *>(&destAddr), '\0', sizeof(destAddr));
932 destAddr.sin_family = AF_INET;
933 destAddr.sin_port = htons(ushort(destPort));
934 destAddr.sin_addr.s_addr = addr;
937 timer myTimer(timeOut);
939 if (timedOut(myTimer))
941 // Setjmp from timer jumps back to here
951 reinterpret_cast<struct sockaddr*>(&destAddr),
952 sizeof(struct sockaddr)
956 // Connection refused. Check if network was actually used or not.
958 int connectErr = errno;
962 if (connectErr == ECONNREFUSED)
977 bool Foam::ping(const word& hostname, const label timeOut)
979 return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut);
983 int Foam::system(const string& command)
985 return ::system(command.c_str());
989 // ************************************************************************* //