ENH: various general improvments to the POSIX functions

- ensure proper and sensible handling of empty names.
  Eg, isDir(""), isFile("") are no-ops, and avoid file-stat

- rmDir:
  * optional 'silent' option to suppress messages.
  * removes all possible sub-entries, instead of just giving up on
    the first problem encountered.

- reduced code duplication in etcFiles

ENH: provide WM_USER_RESOURCE_DIRNAME define (in foamVersion.H)

- this is still a hard-coded value, but at least centrally available
This commit is contained in:
Mark Olesen
2017-03-30 11:45:25 +02:00
parent 446b8e7188
commit 836d04ffc1
10 changed files with 660 additions and 418 deletions

View File

@ -0,0 +1,3 @@
Test-etcFiles.C
EXE = $(FOAM_USER_APPBIN)/Test-etcFiles

View File

View File

@ -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 <http://www.gnu.org/licenses/>.
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<<results[0].c_str() << nl;
}
}
return error;
}
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -76,6 +76,41 @@ namespace Foam
}
// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * * //
//
//! \cond fileScope
//
// Return true if filename appears to be a backup file
//
static inline bool isBackupName(const Foam::fileName& name)
{
if (name.empty())
{
return false;
}
else if (name[name.size()-1] == '~')
{
return true;
}
// Now check the extension
const Foam::word ext = name.ext();
if (ext.empty())
{
return false;
}
return
(
ext == "bak" || ext == "BAK"
|| ext == "old" || ext == "save"
);
}
//! \endcond
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
pid_t Foam::pid()
@ -98,13 +133,15 @@ pid_t Foam::pgid()
bool Foam::env(const std::string& envName)
{
return ::getenv(envName.c_str()) != nullptr;
// An empty envName => 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<char *>(0)
);

View File

@ -40,7 +40,7 @@ Description
- \b group (site) settings (when $WM_PROJECT_SITE is not set):
- $WM_PROJECT_INST_DIR/site/\<VERSION\>/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

View File

@ -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

View File

@ -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();
}

View File

@ -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/\<VERSION\>
// - $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/\<VERSION\>
// - $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);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -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

View File

@ -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<string>& 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