diff --git a/applications/test/POSIX/Test-POSIX.C b/applications/test/POSIX/Test-POSIX.C index e38899ec92..ad7639825f 100644 --- a/applications/test/POSIX/Test-POSIX.C +++ b/applications/test/POSIX/Test-POSIX.C @@ -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"); diff --git a/etc/controlDict b/etc/controlDict index 950e5adc2b..c5b0c7cd0a 100644 --- a/etc/controlDict +++ b/etc/controlDict @@ -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; diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C index 1953935f3c..05e134d9c4 100644 --- a/src/OSspecific/POSIX/POSIX.C +++ b/src/OSspecific/POSIX/POSIX.C @@ -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 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(); } diff --git a/src/OSspecific/POSIX/fileStat.C b/src/OSspecific/POSIX/fileStat.C index 0d50a72186..706640a1a0 100644 --- a/src/OSspecific/POSIX/fileStat.C +++ b/src/OSspecific/POSIX/fileStat.C @@ -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; diff --git a/src/OSspecific/POSIX/fileStat.H b/src/OSspecific/POSIX/fileStat.H index 62a61afbbf..e1a997b205 100644 --- a/src/OSspecific/POSIX/fileStat.H +++ b/src/OSspecific/POSIX/fileStat.H @@ -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, diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H index 85c84c1ae5..d8535cf8e9 100644 --- a/src/OpenFOAM/include/OSspecific.H +++ b/src/OpenFOAM/include/OSspecific.H @@ -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);