1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 POSIX versions of the functions declared 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::POSIX, 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());
94 // Return null-constructed string rather than string::null
95 // to avoid cyclic dependencies in the construction of globals
108 return setenv(envName.c_str(), value.c_str(), overwrite) == 0;
112 Foam::word Foam::hostName()
115 gethostname(buffer, 256);
121 Foam::word Foam::userName()
123 struct passwd* pw = getpwuid(getuid());
136 // use $HOME environment variable or passwd info
137 Foam::fileName Foam::home()
139 char* env = getenv("HOME");
143 return fileName(env);
147 struct passwd* pw = getpwuid(getuid());
155 return fileName::null;
161 Foam::fileName Foam::home(const word& userName)
167 pw = getpwnam(userName.c_str());
171 char* env = getenv("HOME");
175 return fileName(env);
178 pw = getpwuid(getuid());
187 return fileName::null;
192 Foam::fileName Foam::cwd()
195 if (getcwd(buf, 255))
201 FatalErrorIn("Foam::cwd()")
202 << "Couldn't get the current working directory"
205 return fileName::null;
210 bool Foam::chDir(const fileName& dir)
212 return chdir(dir.c_str()) != 0;
216 Foam::fileName Foam::findEtcFile(const fileName& name, bool mandatory)
218 // Search user files:
219 // ~~~~~~~~~~~~~~~~~~
220 fileName searchDir = home()/".OpenFOAM";
221 if (isDir(searchDir))
223 // Check for user file in ~/.OpenFOAM/VERSION
224 fileName fullName = searchDir/FOAMversion/name;
225 if (isFile(fullName))
230 // Check for version-independent user file in ~/.OpenFOAM
231 fullName = searchDir/name;
232 if (isFile(fullName))
239 // Search site files:
240 // ~~~~~~~~~~~~~~~~~~
241 searchDir = getEnv("WM_PROJECT_INST_DIR");
242 if (isDir(searchDir))
244 // Check for site file in $WM_PROJECT_INST_DIR/site/VERSION
245 fileName fullName = searchDir/"site"/FOAMversion/name;
246 if (isFile(fullName))
251 // Check for version-independent site file in $WM_PROJECT_INST_DIR/site
252 fullName = searchDir/"site"/name;
253 if (isFile(fullName))
259 // Search installation files:
260 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
261 searchDir = getEnv("WM_PROJECT_DIR");
262 if (isDir(searchDir))
264 // Check for shipped OpenFOAM file in $WM_PROJECT_DIR/etc
265 fileName fullName = searchDir/"etc"/name;
266 if (isFile(fullName))
273 // abort if the file is mandatory, otherwise return null
276 cerr<< "--> FOAM FATAL ERROR in Foam::findEtcFile() :"
277 " could not find mandatory file\n '"
278 << name.c_str() << "'\n\n" << std::endl;
282 // Return null-constructed fileName rather than fileName::null
283 // to avoid cyclic dependencies in the construction of globals
288 bool Foam::mkDir(const fileName& pathName, mode_t mode)
290 // empty names are meaningless
291 if (pathName.empty())
296 // Construct instance path directory if does not exist
297 if (::mkdir(pathName.c_str(), mode) == 0)
299 // Directory made OK so return true
308 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
309 << "The filesystem containing " << pathName
310 << " does not support the creation of directories."
318 // Directory already exists so simply return true
324 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
326 << " points outside your accessible address space."
334 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
335 << "The parent directory does not allow write "
336 "permission to the process,"<< nl
337 << "or one of the directories in " << pathName
338 << " did not allow search (execute) permission."
346 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
347 << "" << pathName << " is too long."
355 // Part of the path does not exist so try to create it
356 if (pathName.path().size() && mkDir(pathName.path(), mode))
358 return mkDir(pathName, mode);
362 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
363 << "Couldn't create directory " << pathName
372 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
373 << "A component used as a directory in " << pathName
374 << " is not, in fact, a directory."
382 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
383 << "Insufficient kernel memory was available to make "
384 "directory " << pathName << '.'
392 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
394 << " refers to a file on a read-only filesystem."
402 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
403 << "Too many symbolic links were encountered in resolving "
412 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
413 << "The device containing " << pathName
414 << " has no room for the new directory or "
415 << "the user's disk quota is exhausted."
423 FatalErrorIn("Foam::mkDir(const fileName&, mode_t)")
424 << "Couldn't create directory " << pathName
435 bool Foam::chMod(const fileName& name, const mode_t m)
437 return ::chmod(name.c_str(), m) == 0;
441 // Return the file mode
442 mode_t Foam::mode(const fileName& name)
444 fileStat fileStatus(name);
445 if (fileStatus.isValid())
447 return fileStatus.status().st_mode;
456 // Return the file type: FILE or DIRECTORY
457 Foam::fileName::Type Foam::type(const fileName& name)
459 mode_t m = mode(name);
463 return fileName::FILE;
467 return fileName::DIRECTORY;
471 return fileName::UNDEFINED;
476 // Does the name exist in the filing system?
477 bool Foam::exists(const fileName& name, const bool checkGzip)
479 return mode(name) || isFile(name, checkGzip);
483 // Does the directory exist?
484 bool Foam::isDir(const fileName& name)
486 return S_ISDIR(mode(name));
490 // Does the file exist?
491 bool Foam::isFile(const fileName& name, const bool checkGzip)
493 return S_ISREG(mode(name)) || (checkGzip && S_ISREG(mode(name + ".gz")));
497 // Return size of file
498 off_t Foam::fileSize(const fileName& name)
500 fileStat fileStatus(name);
501 if (fileStatus.isValid())
503 return fileStatus.status().st_size;
512 // Return time of last file modification
513 time_t Foam::lastModified(const fileName& name)
515 fileStat fileStatus(name);
516 if (fileStatus.isValid())
518 return fileStatus.status().st_mtime;
527 // Read a directory and return the entries as a string list
528 Foam::fileNameList Foam::readDir
530 const fileName& directory,
531 const fileName::Type type,
535 // Initial filename list size
536 // also used as increment if initial size found to be insufficient
537 static const int maxNnames = 100;
541 Info<< "readDir(const fileName&, const fileType, const bool filtergz)"
542 << " : reading directory " << directory << endl;
545 // Setup empty string list MAXTVALUES long
546 fileNameList dirEntries(maxNnames);
548 // Pointers to the directory entries
552 // Temporary variables and counters
555 // Attempt to open directory and set the structure pointer
556 if ((source = opendir(directory.c_str())) == NULL)
558 dirEntries.setSize(0);
562 Info<< "readDir(const fileName&, const fileType, "
563 "const bool filtergz) : cannot open directory "
564 << directory << endl;
569 // Read and parse all the entries in the directory
570 while ((list = readdir(source)) != NULL)
572 fileName fName(list->d_name);
574 // ignore files begining with ., i.e. '.', '..' and '.*'
575 if (fName.size() && fName[0] != '.')
577 word fExt = fName.ext();
581 (type == fileName::DIRECTORY)
584 type == fileName::FILE
585 && fName[fName.size()-1] != '~'
593 if ((directory/fName).type() == type)
595 if (nEntries >= dirEntries.size())
597 dirEntries.setSize(dirEntries.size() + maxNnames);
600 if (filtergz && fExt == "gz")
602 dirEntries[nEntries++] = fName.lessExt();
606 dirEntries[nEntries++] = fName;
613 // Reset the length of the entries list
614 dirEntries.setSize(nEntries);
623 // Copy, recursively if necessary, the source to the destination
624 bool Foam::cp(const fileName& src, const fileName& dest)
626 // Make sure source exists.
632 fileName destFile(dest);
634 // Check type of source file.
635 if (src.type() == fileName::FILE)
637 // If dest is a directory, create the destination file name.
638 if (destFile.type() == fileName::DIRECTORY)
640 destFile = destFile/src.name();
643 // Make sure the destination directory exists.
644 if (!isDir(destFile.path()) && !mkDir(destFile.path()))
649 // Open and check streams.
650 std::ifstream srcStream(src.c_str());
656 std::ofstream destStream(destFile.c_str());
662 // Copy character data.
664 while (srcStream.get(ch))
670 if (!srcStream.eof() || !destStream)
675 else if (src.type() == fileName::DIRECTORY)
677 // If dest is a directory, create the destination file name.
678 if (destFile.type() == fileName::DIRECTORY)
680 destFile = destFile/src.component(src.components().size() -1);
683 // Make sure the destination directory exists.
684 if (!isDir(destFile) && !mkDir(destFile))
690 fileNameList contents = readDir(src, fileName::FILE, false);
695 Info<< "Copying : " << src/contents[i]
696 << " to " << destFile/contents[i] << endl;
700 cp(src/contents[i], destFile/contents[i]);
703 // Copy sub directories.
704 fileNameList subdirs = readDir(src, fileName::DIRECTORY);
709 Info<< "Copying : " << src/subdirs[i]
710 << " to " << destFile << endl;
714 cp(src/subdirs[i], destFile);
722 // Create a softlink. dst should not exist. Returns true if successful.
723 bool Foam::ln(const fileName& src, const fileName& dst)
727 Info<< "Create softlink from : " << src << " to " << dst
733 WarningIn("ln(const fileName&, const fileName&)")
734 << "destination " << dst << " already exists. Not linking."
741 WarningIn("ln(const fileName&, const fileName&)")
742 << "source " << src << " does not exist." << endl;
746 if (symlink(src.c_str(), dst.c_str()) == 0)
752 WarningIn("ln(const fileName&, const fileName&)")
753 << "symlink from " << src << " to " << dst << " failed." << endl;
759 // Rename srcFile dstFile
760 bool Foam::mv(const fileName& src, const fileName& dst)
764 Info<< "Move : " << src << " to " << dst << endl;
769 dst.type() == fileName::DIRECTORY
770 && src.type() != fileName::DIRECTORY
773 const fileName dstName(dst/src.name());
775 return rename(src.c_str(), dstName.c_str()) == 0;
779 return rename(src.c_str(), dst.c_str()) == 0;
784 //- Rename to a corresponding backup file
785 // If the backup file already exists, attempt with "01" .. "99" index
786 bool Foam::mvBak(const fileName& src, const std::string& ext)
790 Info<< "mvBak : " << src << " to extension " << ext << endl;
793 if (exists(src, false))
795 const int maxIndex = 99;
798 for (int n = 0; n <= maxIndex; n++)
800 fileName dstName(src + "." + ext);
803 sprintf(index, "%02d", n);
807 // avoid overwriting existing files, except for the last
808 // possible index where we have no choice
809 if (!exists(dstName, false) || n == maxIndex)
811 return rename(src.c_str(), dstName.c_str()) == 0;
817 // fall-through: nothing to do
823 // Remove a file, returning true if successful otherwise false
824 bool Foam::rm(const fileName& file)
828 Info<< "Removing : " << file << endl;
831 // Try returning plain file name; if not there, try with .gz
832 if (remove(file.c_str()) == 0)
838 return remove(string(file + ".gz").c_str()) == 0;
843 // Remove a dirctory and its contents
844 bool Foam::rmDir(const fileName& directory)
848 Info<< "rmDir(const fileName&) : "
849 << "removing directory " << directory << endl;
852 // Pointers to the directory entries
856 // Attempt to open directory and set the structure pointer
857 if ((source = opendir(directory.c_str())) == NULL)
859 WarningIn("rmDir(const fileName&)")
860 << "cannot open directory " << directory << endl;
866 // Read and parse all the entries in the directory
867 while ((list = readdir(source)) != NULL)
869 fileName fName(list->d_name);
871 if (fName != "." && fName != "..")
873 fileName path = directory/fName;
875 if (path.type() == fileName::DIRECTORY)
879 WarningIn("rmDir(const fileName&)")
880 << "failed to remove directory " << fName
881 << " while removing directory " << directory
893 WarningIn("rmDir(const fileName&)")
894 << "failed to remove file " << fName
895 << " while removing directory " << directory
909 WarningIn("rmDir(const fileName&)")
910 << "failed to remove directory " << directory << endl;
924 unsigned int Foam::sleep(const unsigned int s)
930 void Foam::fdClose(const int fd)
936 "fdClose(const int fd)"
937 ) << "close error on " << fd << endl
938 << abort(FatalError);
945 const word& destName,
946 const label destPort,
952 struct hostent *hostPtr;
954 struct sockaddr_in destAddr; // will hold the destination addr
957 if ((hostPtr = gethostbyname(destName.c_str())) == NULL)
961 "Foam::ping(const word&, const label)"
962 ) << "gethostbyname error " << h_errno << " for host " << destName
963 << abort(FatalError);
966 // Get first of the SLL of addresses
967 serverAddress = *(hostPtr->h_addr_list);
968 ptr = reinterpret_cast<struct in_addr*>(serverAddress);
972 sockfd = socket(AF_INET, SOCK_STREAM, 0);
977 "Foam::ping(const word&, const label)"
979 << abort(FatalError);
982 // Fill sockaddr_in structure with dest address and port
983 memset (reinterpret_cast<char *>(&destAddr), '\0', sizeof(destAddr));
984 destAddr.sin_family = AF_INET;
985 destAddr.sin_port = htons(ushort(destPort));
986 destAddr.sin_addr.s_addr = addr;
989 timer myTimer(timeOut);
991 if (timedOut(myTimer))
993 // Setjmp from timer jumps back to here
1003 reinterpret_cast<struct sockaddr*>(&destAddr),
1004 sizeof(struct sockaddr)
1008 // Connection refused. Check if network was actually used or not.
1010 int connectErr = errno;
1014 if (connectErr == ECONNREFUSED)
1018 //perror("connect");
1029 bool Foam::ping(const word& hostname, const label timeOut)
1031 return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut);
1035 int Foam::system(const string& command)
1037 return ::system(command.c_str());
1041 // ************************************************************************* //