diff --git a/applications/test/etcFiles/Make/files b/applications/test/etcFiles/Make/files new file mode 100644 index 0000000000..8db90803ac --- /dev/null +++ b/applications/test/etcFiles/Make/files @@ -0,0 +1,3 @@ +Test-etcFiles.C + +EXE = $(FOAM_USER_APPBIN)/Test-etcFiles diff --git a/applications/test/etcFiles/Make/options b/applications/test/etcFiles/Make/options new file mode 100644 index 0000000000..e69de29bb2 diff --git a/applications/test/etcFiles/Test-etcFiles.C b/applications/test/etcFiles/Test-etcFiles.C new file mode 100644 index 0000000000..6bb741bdf2 --- /dev/null +++ b/applications/test/etcFiles/Test-etcFiles.C @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Application + Test-etcFiles + +Description + Test etcFiles functionality. + Similar to foamEtcFile script, but automatically prunes nonexistent + directories from the list. + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "etcFiles.H" + +using namespace Foam; + +void printList(const fileNameList& list) +{ + forAll(list, i) + { + Info<< list[i].c_str() << nl; + } +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noBanner(); + argList::noParallel(); + argList::noFunctionObjects(); + argList::removeOption("case"); + + argList::addBoolOption + ( + "all", + "Return all files (otherwise stop after the first match)" + ); + argList::addBoolOption + ( + "list", + "List directories or files to be checked" + ); + argList::validArgs.insert("file..."); + + argList::addNote + ( + "Locate user/group/other file with semantics similar to the " + "~OpenFOAM/fileName expansion." + ); + + argList args(argc, argv, false, true); + + // First handle no parameters + if (args.size() == 1) + { + if (args.optionFound("list")) + { + fileNameList results = findEtcDirs(); + printList(results); + return 0; + } + else + { + Info<<"Error: Missing filename" << endl; + args.printUsage(); + return 1; + } + } + + const bool listAll = (args.optionFound("all") || args.optionFound("list")); + + int error = 0; + + for (int argi = 1; argi < args.size(); ++argi) + { + const std::string file = args[argi]; + fileNameList results = findEtcFiles(file); + + if (results.empty()) + { + Info<<"Not found: " << file << nl; + error = 2; + } + else if (listAll) + { + printList(results); + } + else + { + Info< always false + return !envName.empty() && ::getenv(envName.c_str()) != nullptr; } Foam::string Foam::getEnv(const std::string& envName) { - char* env = ::getenv(envName.c_str()); + // Ignore an empty envName => always "" + char* env = envName.empty() ? nullptr : ::getenv(envName.c_str()); if (env) { @@ -126,7 +163,12 @@ bool Foam::setEnv const bool overwrite ) { - return ::setenv(envName.c_str(), value.c_str(), overwrite) == 0; + // Ignore an empty envName => always false + return + ( + !envName.empty() + && ::setenv(envName.c_str(), value.c_str(), overwrite) == 0 + ); } @@ -173,14 +215,13 @@ Foam::string Foam::domainName() Foam::string Foam::userName() { struct passwd* pw = ::getpwuid(::getuid()); - if (pw != nullptr) { return pw->pw_name; } else { - return string::null; + return string(); } } @@ -194,54 +235,39 @@ bool Foam::isAdministrator() Foam::fileName Foam::home() { char* env = ::getenv("HOME"); - - if (env != nullptr) + if (env) { return fileName(env); } + + struct passwd* pw = ::getpwuid(::getuid()); + if (pw) + { + return pw->pw_dir; + } else { - struct passwd* pw = ::getpwuid(getuid()); - - if (pw != nullptr) - { - return pw->pw_dir; - } - else - { - return fileName::null; - } + return fileName(); } } Foam::fileName Foam::home(const std::string& userName) { - struct passwd* pw; - - if (userName.size()) + // An empty userName => same as home() + if (userName.empty()) { - pw = ::getpwnam(userName.c_str()); - } - else - { - char* env = ::getenv("HOME"); - - if (env != nullptr) - { - return fileName(env); - } - - pw = ::getpwuid(::getuid()); + return Foam::home(); } - if (pw != nullptr) + struct passwd* pw = ::getpwnam(userName.c_str()); + if (pw) { return pw->pw_dir; } else { - return fileName::null; + return fileName(); } } @@ -260,7 +286,7 @@ Foam::fileName Foam::cwd() } else if (errno == ERANGE) { - // Increment path length upto the pathLengthMax limit + // Increment path length up to the pathLengthMax limit if ( (pathLengthLimit += POSIX::pathLengthChunk) @@ -291,19 +317,20 @@ Foam::fileName Foam::cwd() bool Foam::chDir(const fileName& dir) { - return ::chdir(dir.c_str()) == 0; + // Ignore an empty dir name => always false + return !dir.empty() && ::chdir(dir.c_str()) == 0; } bool Foam::mkDir(const fileName& pathName, mode_t mode) { - // empty names are meaningless + // Ignore an empty pathName => always false if (pathName.empty()) { return false; } - // Construct instance path directory if does not exist + // Construct path directory if does not exist if (::mkdir(pathName.c_str(), mode) == 0) { // Directory made OK so return true @@ -443,26 +470,35 @@ bool Foam::mkDir(const fileName& pathName, mode_t mode) bool Foam::chMod(const fileName& name, const mode_t m) { - return ::chmod(name.c_str(), m) == 0; + // Ignore an empty name => always false + return !name.empty() && ::chmod(name.c_str(), m) == 0; } mode_t Foam::mode(const fileName& name, const bool followLink) { - fileStat fileStatus(name, followLink); - if (fileStatus.isValid()) + // Ignore an empty name => always 0 + if (!name.empty()) { - return fileStatus.status().st_mode; - } - else - { - return 0; + fileStat fileStatus(name, followLink); + if (fileStatus.isValid()) + { + return fileStatus.status().st_mode; + } } + + return 0; } Foam::fileName::Type Foam::type(const fileName& name, const bool followLink) { + // Ignore an empty name => always UNDEFINED + if (name.empty()) + { + return fileName::UNDEFINED; + } + mode_t m = mode(name, followLink); if (S_ISREG(m)) @@ -477,10 +513,8 @@ Foam::fileName::Type Foam::type(const fileName& name, const bool followLink) { return fileName::DIRECTORY; } - else - { - return fileName::UNDEFINED; - } + + return fileName::UNDEFINED; } @@ -491,13 +525,19 @@ bool Foam::exists const bool followLink ) { - return mode(name, followLink) || isFile(name, checkGzip, followLink); + // Ignore an empty name => always false + return + ( + !name.empty() + && (mode(name, followLink) || isFile(name, checkGzip, followLink)) + ); } bool Foam::isDir(const fileName& name, const bool followLink) { - return S_ISDIR(mode(name, followLink)); + // Ignore an empty name => always false + return !name.empty() && S_ISDIR(mode(name, followLink)); } @@ -508,53 +548,65 @@ bool Foam::isFile const bool followLink ) { + // Ignore an empty name => always false return - S_ISREG(mode(name, followLink)) - || (checkGzip && S_ISREG(mode(name + ".gz", followLink))); + ( + !name.empty() + && ( + S_ISREG(mode(name, followLink)) + || (checkGzip && S_ISREG(mode(name + ".gz", followLink))) + ) + ); } off_t Foam::fileSize(const fileName& name, const bool followLink) { - fileStat fileStatus(name, followLink); - if (fileStatus.isValid()) + // Ignore an empty name + if (!name.empty()) { - return fileStatus.status().st_size; - } - else - { - return -1; + fileStat fileStatus(name, followLink); + if (fileStatus.isValid()) + { + return fileStatus.status().st_size; + } } + + return -1; } time_t Foam::lastModified(const fileName& name, const bool followLink) { - fileStat fileStatus(name, followLink); - if (fileStatus.isValid()) + // Ignore an empty name + if (!name.empty()) { - return fileStatus.status().st_mtime; - } - else - { - return 0; + fileStat fileStatus(name, followLink); + if (fileStatus.isValid()) + { + return fileStatus.status().st_mtime; + } } + + return 0; } double Foam::highResLastModified(const fileName& name) { - fileStat fileStatus(name); - if (fileStatus.isValid()) + // Ignore an empty name + if (!name.empty()) { - return - fileStatus.status().st_mtime - + 1e-9*fileStatus.status().st_atim.tv_nsec; - } - else - { - return 0; + fileStat fileStatus(name); + if (fileStatus.isValid()) + { + return + fileStatus.status().st_mtime + + 1e-9*fileStatus.status().st_atim.tv_nsec; + } } + + return 0; } @@ -570,92 +622,85 @@ Foam::fileNameList Foam::readDir // also used as increment if initial size found to be insufficient static const int maxNnames = 100; + // Basic sanity: cannot strip '.gz' from directory names + const bool stripgz = filtergz && (type != fileName::DIRECTORY); + const word extgz("gz"); + + // Open directory and set the structure pointer + // Do not attempt to open an empty directory name + DIR *source; + if + ( + directory.empty() + || (source = ::opendir(directory.c_str())) == nullptr + ) + { + if (POSIX::debug) + { + InfoInFunction + << "cannot open directory " << directory << endl; + } + + return fileNameList(); + } + if (POSIX::debug) { InfoInFunction << "reading directory " << directory << endl; } - // Setup empty string list MAXTVALUES long + label nEntries = 0; fileNameList dirEntries(maxNnames); - // Pointers to the directory entries - DIR *source; - struct dirent *list; - - // Temporary variables and counters - label nEntries = 0; - - // Attempt to open directory and set the structure pointer - if ((source = ::opendir(directory.c_str())) == nullptr) + // Read and parse all the entries in the directory + for (struct dirent *list; (list = ::readdir(source)) != nullptr; /*nil*/) { - dirEntries.setSize(0); + const fileName name(list->d_name); - if (POSIX::debug) + // Ignore files/directories beginning with "." + // These are the ".", ".." directories and any hidden files/dirs + if (name.empty() || name[0] == '.') { - InfoInFunction - << "cannot open directory " << directory << endl; + continue; } - } - else - { - // Read and parse all the entries in the directory - while ((list = ::readdir(source)) != nullptr) + + if + ( + (type == fileName::DIRECTORY) + || (type == fileName::FILE && !isBackupName(name)) + ) { - fileName fName(list->d_name); - - // ignore files beginning with ., i.e. '.', '..' and '.*' - if (fName.size() && fName[0] != '.') + if ((directory/name).type(followLink) == type) { - const word fExt = fName.ext(); - - if - ( - (type == fileName::DIRECTORY) - || - ( - type == fileName::FILE - && fName[fName.size()-1] != '~' - && fExt != "bak" - && fExt != "BAK" - && fExt != "old" - && fExt != "save" - ) - ) + if (nEntries >= dirEntries.size()) { - if ((directory/fName).type(followLink) == type) - { - if (nEntries >= dirEntries.size()) - { - dirEntries.setSize(dirEntries.size() + maxNnames); - } + dirEntries.setSize(dirEntries.size() + maxNnames); + } - if (filtergz && fExt == "gz") - { - dirEntries[nEntries++] = fName.lessExt(); - } - else - { - dirEntries[nEntries++] = fName; - } - } + if (stripgz && name.hasExt(extgz)) + { + dirEntries[nEntries++] = name.lessExt(); + } + else + { + dirEntries[nEntries++] = name; } } } - - // Reset the length of the entries list - dirEntries.setSize(nEntries); - - ::closedir(source); } + // Reset the length of the entries list + dirEntries.setSize(nEntries); + ::closedir(source); + return dirEntries; } bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink) { - // Make sure source exists. + // Make sure source exists - this also handles an empty source name if (!exists(src)) { return false; @@ -789,6 +834,20 @@ bool Foam::ln(const fileName& src, const fileName& dst) << endl; } + if (src.empty()) + { + WarningInFunction + << "source name is empty: not linking." << endl; + return false; + } + + if (dst.empty()) + { + WarningInFunction + << "destination name is empty: not linking." << endl; + return false; + } + if (exists(dst)) { WarningInFunction @@ -825,6 +884,12 @@ bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink) << "Move : " << src << " to " << dst << endl; } + // Ignore an empty names => always false + if (src.empty() || dst.empty()) + { + return false; + } + if ( dst.type() == fileName::DIRECTORY @@ -850,17 +915,23 @@ bool Foam::mvBak(const fileName& src, const std::string& ext) << "mvBak : " << src << " to extension " << ext << endl; } + // Ignore an empty name or extension => always false + if (src.empty() || ext.empty()) + { + return false; + } + if (exists(src, false)) { const int maxIndex = 99; char index[3]; - for (int n = 0; n <= maxIndex; n++) + for (int n = 0; n <= maxIndex; ++n) { fileName dstName(src + "." + ext); if (n) { - sprintf(index, "%02d", n); + ::sprintf(index, "%02d", n); dstName += index; } @@ -870,7 +941,6 @@ bool Foam::mvBak(const fileName& src, const std::string& ext) { return ::rename(src.c_str(), dstName.c_str()) == 0; } - } } @@ -887,6 +957,12 @@ bool Foam::rm(const fileName& file) << "Removing : " << file << endl; } + // Ignore an empty name => always false + if (file.empty()) + { + return false; + } + // Try returning plain file name; if not there, try with .gz if (::remove(file.c_str()) == 0) { @@ -899,89 +975,91 @@ bool Foam::rm(const fileName& file) } -bool Foam::rmDir(const fileName& directory) +bool Foam::rmDir(const fileName& directory, const bool silent) { + // Open directory and set the structure pointer + // Do not attempt to open an empty directory name + DIR *source; + if + ( + directory.empty() + || (source = ::opendir(directory.c_str())) == nullptr + ) + { + if (!silent) + { + WarningInFunction + << "cannot open directory " << directory << endl; + } + + return false; + } + if (POSIX::debug) { InfoInFunction << "removing directory " << directory << endl; } - // Pointers to the directory entries - DIR *source; - struct dirent *list; - - // Attempt to open directory and set the structure pointer - if ((source = ::opendir(directory.c_str())) == nullptr) + // Process each directory entry, counting any errors encountered + label nErrors = 0; + for (struct dirent *list; (list = ::readdir(source)) != nullptr; /*nil*/) { - WarningInFunction - << "cannot open directory " << directory << endl; + const fileName name(list->d_name); + if (name.empty() || name == "." || name == "..") + { + // Ignore "." and ".." directories + continue; + } - return false; + const fileName path = directory/name; + if (path.type(false) == fileName::DIRECTORY) + { + if (!rmDir(path, true)) // Only report errors at the top-level + { + ++nErrors; + } + } + else + { + if (!rm(path)) + { + ++nErrors; + } + } + } + + if (nErrors) + { + if (!silent) + { + WarningInFunction + << "failed to remove directory " << directory << nl + << "could not remove " << nErrors << " sub-entries" << endl; + } } else { - // Read and parse all the entries in the directory - while ((list = ::readdir(source)) != nullptr) - { - fileName fName(list->d_name); - - if (fName != "." && fName != "..") - { - fileName path = directory/fName; - - if (path.type(false) == fileName::DIRECTORY) - { - if (!rmDir(path)) - { - WarningInFunction - << "failed to remove directory " << fName - << " while removing directory " << directory - << endl; - - ::closedir(source); - - return false; - } - } - else - { - if (!rm(path)) - { - WarningInFunction - << "failed to remove file " << fName - << " while removing directory " << directory - << endl; - - ::closedir(source); - - return false; - } - } - } - - } - if (!rm(directory)) { - WarningInFunction - << "failed to remove directory " << directory << endl; - - ::closedir(source); - - return false; + ++nErrors; + if (!silent) + { + WarningInFunction + << "failed to remove directory " << directory << endl; + } } - - ::closedir(source); - - return true; } + + // clean up + ::closedir(source); + return !nErrors; } -unsigned int Foam::sleep(const unsigned int s) +unsigned int Foam::sleep(const unsigned int sec) { - return ::sleep(s); + return ::sleep(sec); } @@ -1161,7 +1239,7 @@ int Foam::system(const std::string& command) ( "/bin/sh", // Path of the shell "sh", // Command-name (name for the shell) - "-c", // Read commands from the command_string operand. + "-c", // Read commands from command_string operand command.c_str(), // Command string reinterpret_cast(0) ); diff --git a/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H b/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H index b27175a569..f5eae2e556 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H +++ b/src/OpenFOAM/db/dictionary/functionEntries/includeFuncEntry/includeFuncEntry.H @@ -40,7 +40,7 @@ Description - \b group (site) settings (when $WM_PROJECT_SITE is not set): - $WM_PROJECT_INST_DIR/site/\/caseDicts/postProcessing - $WM_PROJECT_INST_DIR/site/caseDicts/postProcessing - - \b other (shipped) settings: + - \b other (project) settings: - $WM_PROJECT_DIR/etc/caseDicts/postProcessing The optional field arguments included in the name are inserted in 'field' or diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H index 917c71fc28..41e6a1fd46 100644 --- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H +++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H @@ -221,7 +221,7 @@ public: // - $WM_PROJECT_DIR/etc/caseDicts/postProcessing // // \return The path of the functionObject dictionary file if found - // otherwise null + // otherwise an empty path static fileName findDict(const word& funcName); //- Read the specified functionObject configuration dictionary parsing diff --git a/src/OpenFOAM/global/etcFiles/etcFiles.C b/src/OpenFOAM/global/etcFiles/etcFiles.C index f93f3c6ef5..5271b4de48 100644 --- a/src/OpenFOAM/global/etcFiles/etcFiles.C +++ b/src/OpenFOAM/global/etcFiles/etcFiles.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,229 +27,234 @@ License #include "OSspecific.H" #include "foamVersion.H" +// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * * // + +// +// These could be exposed too (if required), but are fairly special purpose. +// +//! \cond fileScope +// +// Assign 'queried' parameter to the user resource directory. +// Return true if this directory exists. +// +// Corresponds to foamEtcFile -mode=u +// Looks for +// - ~/.OpenFOAM +static inline bool userResourceDir(Foam::fileName& queried) +{ + queried = Foam::home()/WM_USER_RESOURCE_DIRNAME; + return Foam::isDir(queried); +} + + +// Assign 'queried' parameter to the group resource directory. +// Return true if this directory exists. +// +// Corresponds to foamEtcFile -mode=g +// Looks for +// - $WM_PROJECT_SITE +// - $WM_PROJECT_INST_DIR/site +static inline bool groupResourceDir(Foam::fileName& queried) +{ + queried = Foam::getEnv("WM_PROJECT_SITE"); + if (queried.size()) + { + return Foam::isDir(queried); + } + + // Fallback (when WM_PROJECT_SITE is unset) + queried = Foam::getEnv("WM_PROJECT_INST_DIR")/"site"; + return (queried.size() > 5 && Foam::isDir(queried)); +} + + +// Assign 'queried' parameter to the OpenFOAM etc/ resource directory. +// Return true if it exists. +// +// Corresponds to foamEtcFile -mode=o +// Looks for +// - $WM_PROJECT_DIR/etc +static inline bool projectResourceDir(Foam::fileName& queried) +{ + queried = Foam::getEnv("WM_PROJECT_DIR")/"etc"; + return (queried.size() > 4 && Foam::isDir(queried)); +} + +//! \endcond + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -Foam::fileNameList Foam::findEtcDirs(const fileName& local) +Foam::fileNameList Foam::findEtcDirs +( + const fileName& name, + const bool findFirst +) { - fileNameList dirs; + fileNameList results; - // Search for user directories in - // * ~/.OpenFOAM/VERSION - // * ~/.OpenFOAM - // - fileName searchDir = home()/".OpenFOAM"; - if (isDir(searchDir)) + do { - fileName fullName = searchDir/FOAMversion/local; - if (isDir(fullName)) - { - dirs.append(fullName); - } + fileName dir, candidate; - fullName = searchDir/local; - if (isDir(fullName)) + // User resource directories + if (userResourceDir(dir)) { - dirs.append(fullName); - } - } - - // Search for group (site) directories in - // * $WM_PROJECT_SITE/VERSION - // * $WM_PROJECT_SITE - // - searchDir = getEnv("WM_PROJECT_SITE"); - if (searchDir.size()) - { - if (isDir(searchDir)) - { - fileName fullName = searchDir/FOAMversion/local; - if (isDir(fullName)) + candidate = dir/FOAMversion/name; + if (isDir(candidate)) { - dirs.append(fullName); + results.append(candidate); + if (findFirst) + { + break; + } } - fullName = searchDir/local; - if (isDir(fullName)) + candidate = dir/name; + if (isDir(candidate)) { - dirs.append(fullName); + results.append(candidate); + if (findFirst) + { + break; + } + } + } + + // Group resource directories + if (groupResourceDir(dir)) + { + candidate = dir/FOAMversion/name; + if (isDir(candidate)) + { + results.append(candidate); + if (findFirst) + { + break; + } + } + + candidate = dir/name; + if (isDir(candidate)) + { + results.append(candidate); + if (findFirst) + { + break; + } + } + } + + // Other (project) resource directory + if (projectResourceDir(dir)) + { + candidate = dir/name; + if (isDir(dir) && isDir(candidate)) + { + results.append(candidate); } } } - else - { - // Or search for group (site) files in - // * $WM_PROJECT_INST_DIR/site/VERSION - // * $WM_PROJECT_INST_DIR/site - // - searchDir = getEnv("WM_PROJECT_INST_DIR"); - if (isDir(searchDir)) - { - fileName fullName = searchDir/"site"/FOAMversion/local; - if (isDir(fullName)) - { - dirs.append(fullName); - } + while (false); // Run exactly once - fullName = searchDir/"site"/local; - if (isDir(fullName)) - { - dirs.append(fullName); - } - } - } - - // Search for other (shipped) files in - // * $WM_PROJECT_DIR/etc - // - searchDir = getEnv("WM_PROJECT_DIR"); - if (isDir(searchDir)) - { - fileName fullName = searchDir/"etc"/local; - if (isDir(fullName)) - { - dirs.append(fullName); - } - } - - return dirs; + return results; } Foam::fileNameList Foam::findEtcFiles ( const fileName& name, - bool mandatory, - bool findFirst + const bool mandatory, + const bool findFirst ) { fileNameList results; - // Search for user files in - // * ~/.OpenFOAM/VERSION - // * ~/.OpenFOAM - // - fileName searchDir = home()/".OpenFOAM"; - if (isDir(searchDir)) + do { - fileName fullName = searchDir/FOAMversion/name; - if (isFile(fullName)) - { - results.append(fullName); - if (findFirst) - { - return results; - } - } + fileName dir, candidate; - fullName = searchDir/name; - if (isFile(fullName)) + // User resource directories + if (userResourceDir(dir)) { - results.append(fullName); - if (findFirst) + candidate = dir/FOAMversion/name; + if (isFile(candidate)) { - return results; - } - } - } - - // Search for group (site) files in - // * $WM_PROJECT_SITE/VERSION - // * $WM_PROJECT_SITE - // - searchDir = getEnv("WM_PROJECT_SITE"); - if (searchDir.size()) - { - if (isDir(searchDir)) - { - fileName fullName = searchDir/FOAMversion/name; - if (isFile(fullName)) - { - results.append(fullName); + results.append(candidate); if (findFirst) { - return results; + break; } } - fullName = searchDir/name; - if (isFile(fullName)) + candidate = dir/name; + if (isFile(candidate)) { - results.append(fullName); + results.append(candidate); if (findFirst) { - return results; + break; } } } - } - else - { - // Or search for group (site) files in - // * $WM_PROJECT_INST_DIR/site/VERSION - // * $WM_PROJECT_INST_DIR/site - // - searchDir = getEnv("WM_PROJECT_INST_DIR"); - if (isDir(searchDir)) + + // Group resource directories + if (groupResourceDir(dir)) { - fileName fullName = searchDir/"site"/FOAMversion/name; - if (isFile(fullName)) + candidate = dir/FOAMversion/name; + if (isFile(candidate)) { - results.append(fullName); + results.append(candidate); if (findFirst) { - return results; + break; } } - fullName = searchDir/"site"/name; - if (isFile(fullName)) + candidate = dir/name; + if (isFile(candidate)) { - results.append(fullName); + results.append(candidate); if (findFirst) { - return results; + break; } } } - } - // Search for other (shipped) files in - // * $WM_PROJECT_DIR/etc - // - searchDir = getEnv("WM_PROJECT_DIR"); - if (isDir(searchDir)) - { - fileName fullName = searchDir/"etc"/name; - if (isFile(fullName)) + // Other (project) resource directory + if (projectResourceDir(dir)) { - results.append(fullName); - if (findFirst) + candidate = dir/name; + if (isDir(dir) && isFile(candidate)) { - return results; + results.append(candidate); } } } + while (false); // Run exactly once - // Not found - if (results.empty()) + // No name? It cannot be a file! + if (name.empty()) { - // Abort if the file is mandatory, otherwise return null - if (mandatory) - { - std::cerr - << "--> FOAM FATAL ERROR in Foam::findEtcFiles() :" - " could not find mandatory file\n '" - << name.c_str() << "'\n\n" << std::endl; - ::exit(1); - } + results.clear(); + } + + if (mandatory && results.empty()) + { + // Abort if file is mandatory but not found + std::cerr + << "--> FOAM FATAL ERROR in Foam::findEtcFiles()" + " : could not find mandatory file\n '" + << name.c_str() << "'\n\n" << std::endl; + ::exit(1); } - // Return list of matching paths or empty list if none found return results; } -Foam::fileName Foam::findEtcFile(const fileName& name, bool mandatory) +Foam::fileName Foam::findEtcFile(const fileName& name, const bool mandatory) { fileNameList results(findEtcFiles(name, mandatory, true)); @@ -257,10 +262,9 @@ Foam::fileName Foam::findEtcFile(const fileName& name, bool mandatory) { return results[0]; } - else - { - return fileName(); - } + + // Return null-constructed fileName rather than fileName::null + return fileName(); } diff --git a/src/OpenFOAM/global/etcFiles/etcFiles.H b/src/OpenFOAM/global/etcFiles/etcFiles.H index 5b064d4909..5e3532148c 100644 --- a/src/OpenFOAM/global/etcFiles/etcFiles.H +++ b/src/OpenFOAM/global/etcFiles/etcFiles.H @@ -44,7 +44,7 @@ namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -//- Search for directories from user/group/shipped directories. +//- Search for directories from user/group/other directories. // The search scheme allows for version-specific and // version-independent files using the following hierarchy: // - \b user settings: @@ -56,14 +56,19 @@ namespace Foam // - \b group (site) settings (when $WM_PROJECT_SITE is not set): // - $WM_PROJECT_INST_DIR/site/\ // - $WM_PROJECT_INST_DIR/site/ -// - \b other (shipped) settings: +// - \b other (project) settings: // - $WM_PROJECT_DIR/etc/ // // \return The list of full paths of all the matching directories or // an empty list if the name cannot be found. -fileNameList findEtcDirs(const fileName& local = fileName::null); +// Optionally stop search after the first directory has been found. +fileNameList findEtcDirs +( + const fileName& name = fileName::null, + const bool findFirst = false +); -//- Search for files from user/group/shipped directories. +//- Search for files from user/group/other directories. // The search scheme allows for version-specific and // version-independent files using the following hierarchy: // - \b user settings: @@ -75,7 +80,7 @@ fileNameList findEtcDirs(const fileName& local = fileName::null); // - \b group (site) settings (when $WM_PROJECT_SITE is not set): // - $WM_PROJECT_INST_DIR/site/\ // - $WM_PROJECT_INST_DIR/site/ -// - \b other (shipped) settings: +// - \b other (project) settings: // - $WM_PROJECT_DIR/etc/ // // \return The list of full paths of all the matching files or @@ -84,16 +89,16 @@ fileNameList findEtcDirs(const fileName& local = fileName::null); // Optionally stop search after the first file has been found. fileNameList findEtcFiles ( - const fileName&, - bool mandatory=false, - bool findFirst=false + const fileName& name, + const bool mandatory = false, + const bool findFirst = false ); -//- Search for a file using findEtcFiles. +//- Search for a single file using findEtcFiles. // \return The full path name of the first file found in the // search hierarchy or an empty fileName if the name cannot be found. -// Optionally abort if the file cannot be found. -fileName findEtcFile(const fileName&, bool mandatory=false); +// Optionally abort if the file cannot be found but is mandatory. +fileName findEtcFile(const fileName& name, const bool mandatory=false); // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/global/foamVersion.H b/src/OpenFOAM/global/foamVersion.H index 021ca03ec0..bd3386e786 100644 --- a/src/OpenFOAM/global/foamVersion.H +++ b/src/OpenFOAM/global/foamVersion.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -48,6 +48,9 @@ SourceFiles #ifndef foamVersion_H #define foamVersion_H +// The directory name for user-resources (located in the HOME directory) +#define WM_USER_RESOURCE_DIRNAME ".OpenFOAM" + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H index 3c76a14193..3d5e3bbc7b 100644 --- a/src/OpenFOAM/include/OSspecific.H +++ b/src/OpenFOAM/include/OSspecific.H @@ -57,14 +57,16 @@ pid_t ppid(); //- Return the group PID of this process pid_t pgid(); -//- Return true if environment variable of given name is defined +//- True if environment variable of given name is defined. +// Using an empty name is a no-op and always returns false. bool env(const std::string& envName); -//- Return environment variable of given name -// Return string() if the environment is undefined +//- Get environment value for given envName. +// Return string() if the environment is undefined or envName is empty. string getEnv(const std::string& envName); -//- Set an environment variable +//- Set an environment variable, return true on success. +// Using an empty name is a no-op and always returns false. bool setEnv(const word& name, const std::string& value, const bool overwrite); //- Return the system's host name, as per hostname(1) @@ -89,69 +91,84 @@ fileName home(const std::string& userName); //- Return current working directory path name fileName cwd(); -//- Change the current directory to the one given and return true, -// else return false +//- Change current directory to the one specified and return true on success. +// Using an empty name is a no-op and always returns false. bool chDir(const fileName& dir); //- Make a directory and return an error if it could not be created -// and does not already exist -bool mkDir(const fileName&, mode_t=0777); +// and does not already exist. +// Using an empty pathName is a no-op and always returns false. +bool mkDir(const fileName& pathName, mode_t mode=0777); -//- Set the file mode -bool chMod(const fileName&, const mode_t); +//- Set the file/directory mode, return true on success. +// Using an empty name is a no-op and always returns false. +bool chMod(const fileName& name, const mode_t mode); -//- Return the file mode -mode_t mode(const fileName&, const bool followLink=true); +//- Return the file mode, normally following symbolic links +// Using an empty name is a no-op and always returns 0. +mode_t mode(const fileName& name, const bool followLink=true); -//- Return the file type: DIRECTORY or FILE -fileName::Type type(const fileName&, const bool followLink=true); +//- Return the file type: DIRECTORY or FILE, normally following symbolic links +// Using an empty name is a no-op and always returns UNDEFINED. +fileName::Type type(const fileName& name, const bool followLink=true); //- Does the name exist (as DIRECTORY or FILE) in the file system? // Optionally enable/disable check for gzip file. +// Using an empty name is a no-op and always returns false. bool exists ( - const fileName&, + const fileName& name, const bool checkGzip=true, const bool followLink=true ); //- Does the name exist as a DIRECTORY in the file system? -bool isDir(const fileName&, const bool followLink=true); +// Using an empty name is a no-op and always returns false. +bool isDir(const fileName& name, const bool followLink=true); //- Does the name exist as a FILE in the file system? // Optionally enable/disable check for gzip file. +// Using an empty name is a no-op and always returns false. bool isFile ( - const fileName&, + const fileName& name, const bool checkGzip=true, const bool followLink=true ); -//- Return size of file -off_t fileSize(const fileName&, const bool followLink=true); +//- Return size of file or -1 on failure (normally follows symbolic links). +// Using an empty name is a no-op and always returns -1. +off_t fileSize(const fileName& name, const bool followLink=true); + +//- Return time of last file modification (normally follows symbolic links). +// Using an empty name is a no-op and always returns 0. +time_t lastModified(const fileName& name, const bool followLink=true); //- Return time of last file modification -time_t lastModified(const fileName&, const bool followLink=true); +// Using an empty name is a no-op and always returns 0. +double highResLastModified(const fileName& name); -//- Return time of last file modification -double highResLastModified(const fileName&); - -//- Read a directory and return the entries as a string list +//- Read a directory and return the entries as a fileName List. +// Using an empty directory name returns an empty list. fileNameList readDir ( - const fileName&, - const fileName::Type=fileName::FILE, + const fileName& directory, + const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true ); -//- Copy, recursively if necessary, the source to the destination +//- Copy the source to the destination (recursively if necessary). +// An empty source name is a no-op and always returns false. bool cp(const fileName& src, const fileName& dst, const bool followLink=true); //- Create a softlink. dst should not exist. Returns true if successful. +// An empty source or destination name is a no-op that always returns false, +// but also produces a warning. bool ln(const fileName& src, const fileName& dst); -//- Rename src to dst +//- Rename src to dst. +// An empty source or destination name is a no-op that always returns false. bool mv ( const fileName& src, @@ -161,19 +178,23 @@ bool mv //- Rename to a corresponding backup file // If the backup file already exists, attempt with "01" .. "99" suffix -bool mvBak(const fileName&, const std::string& ext = "bak"); +// An empty name or extension is a no-op that always returns false. +bool mvBak(const fileName& src, const std::string& ext = "bak"); -//- Remove a file, returning true if successful otherwise false -bool rm(const fileName&); +//- Remove a file (or its gz equivalent), returning true if successful. +// An empty name is a no-op that always returns false. +bool rm(const fileName& file); -//- Remove a dirctory and its contents -bool rmDir(const fileName&); +//- Remove a dirctory and its contents (optionally silencing warnings) +// An empty directory name is a no-op that always returns false, +// but also produces a warning. +bool rmDir(const fileName& directory, const bool silent=false); //- Sleep for the specified number of seconds -unsigned int sleep(const unsigned int); +unsigned int sleep(const unsigned int sec); //- Close file descriptor -void fdClose(const int); +void fdClose(const int fd); //- Check if machine is up by pinging given port bool ping(const std::string& destName, const label port, const label timeOut); @@ -184,23 +205,29 @@ bool ping(const std::string& host, const label timeOut=10); //- Execute the specified command via the shell. // Uses vfork/execl internally. // Where possible, use the list version instead. +// +// Treats an empty command as a successful no-op. int system(const std::string& command); //- Execute the specified command with arguments. // Uses vfork/execvp internally +// +// Treats an empty command as a successful no-op. int system(const UList& command); -//- Open a shared library. Return handle to library. Print error message -// if library cannot be loaded (check = true) +//- Open a shared library and return handle to library. +// Print error message if library cannot be loaded (suppress with check=true) void* dlOpen(const fileName& lib, const bool check = true); //- Close a dlopened library using handle. Return true if successful -bool dlClose(void*); +bool dlClose(void* handle); //- Lookup a symbol in a dlopened library using handle to library void* dlSym(void* handle, const std::string& symbol); -//- Report if symbol in a dlopened library could be found +//- Report if symbol in a dlopened library could be found. +// Using a null handle or an empty symbol name is a no-op and always +// returns false. bool dlSymFound(void* handle, const std::string& symbol); //- Return all loaded libraries