ENH: make cwd() behaviour user-adjustable (issue #1007)

- with the 'cwd' optimization switch it is possible to select the
  preferred behaviour for the cwd() function.

  A value of 0 causes cwd() to return the physical directory,
  which is what getcwd() and `pwd -P` return.
  Until now, this was always the standard behaviour.

  With a value of 1, cwd() instead returns the logical directory,
  which what $PWD contains and `pwd -L` returns.
  If any of the sanity checks fail (eg, PWD points to something other
  than ".", etc), a warning is emitted and the physical cwd() is
  returned instead.

  Apart from the optical difference in the output, this additional
  control helps workaround file systems with whitespace or other
  characters in the directory that normally cause OpenFOAM to balk.
  Using a cleaner symlink elsewhere should skirt this issue.

  Eg,
      cd $HOME
      ln -s "/mounted volume/user/workdir"  workdir
      cd workdir
      # start working with OpenFOAM
This commit is contained in:
Mark Olesen 2018-10-16 01:30:44 +02:00
parent 50852b3392
commit 7864672c78
6 changed files with 140 additions and 17 deletions

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) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,6 +37,10 @@ using namespace Foam;
int main(int argc, char *argv[])
{
Info<<"cwd() " << cwd() << nl;
Info<<"cwd(-P) " << cwd(false) << nl;
Info<<"cwd(-L) " << cwd(true) << nl;
Info<<"rmDir" << nl;
rmDir("hmm");

View File

@ -69,6 +69,9 @@ InfoSwitches
OptimisationSwitches
{
// Use physical (0) or logical (1) value for the cwd.
cwd 0;
// On NFS mounted file system: maximum wait for files to appear/get
// updated. Set to 0 on distributed case.
fileModificationSkew 10;

View File

@ -74,6 +74,8 @@ namespace Foam
defineTypeNameAndDebug(POSIX, 0);
}
static bool cwdPreference_(Foam::debug::optimisationSwitch("cwd", 0));
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@ -280,7 +282,11 @@ Foam::fileName Foam::home(const std::string& userName)
}
Foam::fileName Foam::cwd()
namespace Foam
{
//- The physical current working directory path name (pwd -P).
static Foam::fileName cwd_P()
{
label pathLengthLimit = POSIX::pathLengthChunk;
List<char> path(pathLengthLimit);
@ -307,7 +313,7 @@ Foam::fileName Foam::cwd()
<< exit(FatalError);
}
path.setSize(pathLengthLimit);
path.resize(pathLengthLimit);
}
else
{
@ -319,7 +325,86 @@ Foam::fileName Foam::cwd()
<< "Couldn't get the current working directory"
<< exit(FatalError);
return fileName::null;
return fileName();
}
//- The logical current working directory path name.
// From the PWD environment, same as pwd -L.
static Foam::fileName cwd_L()
{
const char* env = ::getenv("PWD");
// Basic check
if (!env || env[0] != '/')
{
WarningInFunction
<< "PWD is invalid - reverting to physical description"
<< nl;
return cwd_P();
}
fileName dir(env);
// Check for "/."
for
(
std::string::size_type pos = 0;
std::string::npos != (pos = dir.find("/.", pos));
/*nil*/
)
{
pos += 2;
if
(
// Ends in "/." or has "/./"
!dir[pos] || dir[pos] == '/'
// Ends in "/.." or has "/../"
|| (dir[pos] == '.' && (!dir[pos+1] || dir[pos+1] == '/'))
)
{
WarningInFunction
<< "PWD contains /. or /.. - reverting to physical description"
<< nl;
return cwd_P();
}
}
// Finally, verify that PWD actually corresponds to the "." directory
if (!fileStat(dir, true).sameINode(fileStat(".", true)))
{
WarningInFunction
<< "PWD is not the cwd() - reverting to physical description"
<< nl;
return cwd_P();
}
return fileName(dir);
}
} // End namespace Foam
Foam::fileName Foam::cwd()
{
return cwd(cwdPreference_);
}
Foam::fileName Foam::cwd(bool logical)
{
if (logical)
{
return cwd_L();
}
return cwd_P();
}

View File

@ -43,14 +43,14 @@ Foam::fileStat::fileStat()
Foam::fileStat::fileStat
(
const fileName& fName,
const char* fName,
const bool followLink,
const unsigned int maxTime
)
:
isValid_(false)
{
if (fName.empty())
if (!fName || !fName[0])
{
return;
}
@ -64,11 +64,11 @@ Foam::fileStat::fileStat
{
if (followLink)
{
locIsValid = (::stat(fName.c_str(), &status_) == 0);
locIsValid = (::stat(fName, &status_) == 0);
}
else
{
locIsValid = (::lstat(fName.c_str(), &status_) == 0);
locIsValid = (::lstat(fName, &status_) == 0);
}
}
@ -77,6 +77,17 @@ Foam::fileStat::fileStat
}
Foam::fileStat::fileStat
(
const fileName& fName,
const bool followLink,
const unsigned int maxTime
)
:
fileStat(fName.c_str(), followLink, maxTime)
{}
Foam::fileStat::fileStat(Istream& is)
{
is >> *this;

View File

@ -28,7 +28,7 @@ Description
Wrapper for stat() and lstat() system calls.
Warning
on Linux (an maybe on others) a stat() of an nfs mounted (remote)
On Linux (an maybe on others) a stat() of an nfs mounted (remote)
file does never timeout and cannot be interrupted!
So e.g. Foam::ping first and hope nfs is running.
@ -79,16 +79,28 @@ public:
fileStat();
//- Construct from components.
// \param fName \n
// The file name or directory name to stat.
//
// \param followLink \n
// If it is a link, get the status of the source file/directory.
// \param fName The file name or directory name to stat.
// \param followLink If it is a link, get the status of the source
// file/directory.
// \param maxTime The timeout value.
//
// \param maxTime \n
// The timeout value.
// \note An empty filename is a no-op.
fileStat
(
const char* fName,
const bool followLink = true,
const unsigned int maxTime = 0
);
//- Construct from components.
//
// \note an empty filename is a no-op.
// \param fName The file name or directory name to stat.
// \param followLink If it is a link, get the status of the source
// file/directory.
// \param maxTime The timeout value.
//
// \note An empty filename is a no-op.
fileStat
(
const fileName& fName,

View File

@ -92,9 +92,17 @@ fileName home();
//- Return home directory path name for a particular user
fileName home(const std::string& userName);
//- Return current working directory path name
//- The physical or logical current working directory path name.
// The behaviour is controlled by the \c cwd optimisation Switch
// A value of 0 corresponds to the physical value, which is identical
// to what getcwd and pwd -P would deliver.
// A value of 1 corresponds to the logical value, which corresponds
// to the PWD environment value and to what pwd -L would deliver.
fileName cwd();
//- The physical or logical current working directory path name.
fileName cwd(bool logical);
//- 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);