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