Skip to content
Snippets Groups Projects
Commit b7054272 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

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
parent 0a276866
Branches
Tags
No related merge requests found
......@@ -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");
......
......@@ -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;
......
......@@ -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();
}
......
......@@ -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;
......
......@@ -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.
//
// \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.
// \note An empty filename is a no-op.
fileStat
(
const fileName& fName,
......
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment