From 89245fa79618cd8c88ba95585c334dcd177cb27d Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Mon, 1 Apr 2019 16:40:22 +0200 Subject: [PATCH] ENH: allow space char in fileName is now configurable (#1008) - having whitespace in fileName can be somewhat fragile since it means that the fileName components do not necessarily correspond to a 'Foam::word'. But in many cases it will work provided that spaces are not present in the final portion of the simulation directory itself. InfoSwitches { // Allow space character in fileName (use with caution) allowSpaceInFileName 0; } - now use doClean=true as default for fileName::validate(). Was false. Unlike fileName::clean() this requires no internal string rewrite since the characters are being copied. Also handle any path separator transformations (ie, backslash => forward slash) at the same time. This makes it resemble the std::filesystem a bit more. --- applications/test/fileNameOS/Make/files | 3 + applications/test/fileNameOS/Make/options | 2 + .../test/fileNameOS/Test-fileNameOS.C | 106 ++++++++++++++++++ etc/controlDict | 3 + src/OpenFOAM/global/argList/argList.C | 2 +- src/OpenFOAM/primitives/chars/char/char.H | 17 ++- src/OpenFOAM/primitives/chars/char/charIO.C | 10 +- .../primitives/strings/fileName/fileName.C | 23 +++- .../primitives/strings/fileName/fileName.H | 15 ++- .../primitives/strings/fileName/fileNameI.H | 11 +- 10 files changed, 166 insertions(+), 26 deletions(-) create mode 100644 applications/test/fileNameOS/Make/files create mode 100644 applications/test/fileNameOS/Make/options create mode 100644 applications/test/fileNameOS/Test-fileNameOS.C diff --git a/applications/test/fileNameOS/Make/files b/applications/test/fileNameOS/Make/files new file mode 100644 index 0000000000..0e1be7b394 --- /dev/null +++ b/applications/test/fileNameOS/Make/files @@ -0,0 +1,3 @@ +Test-fileNameOS.C + +EXE = $(FOAM_USER_APPBIN)/Test-fileNameOS diff --git a/applications/test/fileNameOS/Make/options b/applications/test/fileNameOS/Make/options new file mode 100644 index 0000000000..18e6fe47af --- /dev/null +++ b/applications/test/fileNameOS/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = */ +/* EXE_LIBS = */ diff --git a/applications/test/fileNameOS/Test-fileNameOS.C b/applications/test/fileNameOS/Test-fileNameOS.C new file mode 100644 index 0000000000..b8c7be1ac9 --- /dev/null +++ b/applications/test/fileNameOS/Test-fileNameOS.C @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 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-fileNameOS + +Description + Test fileName behaviour, potential OS capabilities etc. + + In the distant future could possibly replace parts with C++ filesystem + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "fileName.H" +#include "OSspecific.H" +#include "Switch.H" + +#include +#include +#include + + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void testDirname(const std::string& rawInput) +{ + fileName input(fileName::validate(rawInput)); + + Info<< nl + << "input: " << rawInput << nl + << "fileName:" << input << nl + << " path:" << input.path() + << " name:\"" << input.name() << '"' + << " ext:\"" << input.ext() << '"' + << " components: " << flatOutput(input.components()) << nl; + + if (rawInput.size() != input.size()) + { + Info<< " This would be Fatal with debug > 1" << nl; + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + argList::addBoolOption("no-space", "allowSpaceInFileName = false"); + argList::addBoolOption("with-space", "set allowSpaceInFileName = true"); + + #include "setRootCase.H" + + if (args.found("with-space")) + { + fileName::allowSpaceInFileName = true; + } + + if (args.found("no-space")) + { + fileName::allowSpaceInFileName = false; + + } + + + Info<<"fileName with spaces? : " + << Switch(bool(fileName::allowSpaceInFileName)) << nl << nl; + + + { + testDirname("/abc"); + testDirname("/abc/with space/name"); + testDirname("/abc/with space/more space"); + } + + + Info<< "\nEnd\n" << endl; + return 0; +} + + +// ************************************************************************* // diff --git a/etc/controlDict b/etc/controlDict index 3d6c94dd80..bcc4096734 100644 --- a/etc/controlDict +++ b/etc/controlDict @@ -64,6 +64,9 @@ InfoSwitches // Allow case-supplied C++ code (#codeStream, codedFixedValue) allowSystemOperations 1; + + // Allow space character in fileName (use with caution) + allowSpaceInFileName 0; } diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index 1e4abbb172..8a100b33cb 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -648,7 +648,7 @@ void Foam::argList::setCasePaths() if (optIter.found()) { - caseDir = optIter.val(); + caseDir = fileName::validate(optIter.val()); caseDir.clean(); if (caseDir.empty() || caseDir == ".") diff --git a/src/OpenFOAM/primitives/chars/char/char.H b/src/OpenFOAM/primitives/chars/char/char.H index e42043ad72..9c5cb5f315 100644 --- a/src/OpenFOAM/primitives/chars/char/char.H +++ b/src/OpenFOAM/primitives/chars/char/char.H @@ -47,11 +47,19 @@ class Ostream; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -char readChar(Istream&); -Istream& operator>>(Istream&, char&); -Ostream& operator<<(Ostream&, const char); -Ostream& operator<<(Ostream&, const char*); +//- Read single character +char readChar(Istream& is); +//- Read single character +Istream& operator>>(Istream& is, char& c); + +//- Write single character +Ostream& operator<<(Ostream& os, const char c); + +//- Write a nul-terminated C-string +Ostream& operator<<(Ostream& os, const char* str); + +//- Test for \em horizontal whitespace inline bool isspace(char c) { return @@ -63,6 +71,7 @@ inline bool isspace(char c) ); } + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/primitives/chars/char/charIO.C b/src/OpenFOAM/primitives/chars/char/charIO.C index c15a71b002..24b02ecb90 100644 --- a/src/OpenFOAM/primitives/chars/char/charIO.C +++ b/src/OpenFOAM/primitives/chars/char/charIO.C @@ -32,9 +32,9 @@ License char Foam::readChar(Istream& is) { - char c; - is.read(c); - return c; + char c; + is.read(c); + return c; } @@ -54,9 +54,9 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const char c) } -Foam::Ostream& Foam::operator<<(Ostream& os, const char* s) +Foam::Ostream& Foam::operator<<(Ostream& os, const char* str) { - os.write(s); + os.write(str); os.check(FUNCTION_NAME); return os; } diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.C b/src/OpenFOAM/primitives/strings/fileName/fileName.C index 7002ebd7a2..c06a1d3d05 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileName.C +++ b/src/OpenFOAM/primitives/strings/fileName/fileName.C @@ -36,7 +36,11 @@ License // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // const char* const Foam::fileName::typeName = "fileName"; -int Foam::fileName::debug(debug::debugSwitch(fileName::typeName, 0)); +int Foam::fileName::debug(Foam::debug::debugSwitch(fileName::typeName, 0)); +int Foam::fileName::allowSpaceInFileName +( + Foam::debug::infoSwitch("allowSpaceInFileName", 0) +); const Foam::fileName Foam::fileName::null; @@ -48,16 +52,27 @@ Foam::fileName Foam::fileName::validate const bool doClean ) { + // The logic is very similar to stripInvalid, + // but silently removes bad characters + fileName out; out.resize(s.size()); - char prev = 0; std::string::size_type len = 0; - // Largely as per stripInvalid + char prev = 0; for (auto iter = s.cbegin(); iter != s.cend(); ++iter) { - const char c = *iter; + char c = *iter; + + // Treat raw backslash like a path separator. There is no "normal" + // way for these to be there (except for an OS that uses them), but + // could also cause issues when writing strings, shell commands etc. + + if (c == '\\') + { + c = '/'; + } if (fileName::valid(c)) { diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.H b/src/OpenFOAM/primitives/strings/fileName/fileName.H index 824345ad09..b87d6a3b80 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileName.H +++ b/src/OpenFOAM/primitives/strings/fileName/fileName.H @@ -90,6 +90,9 @@ public: //- Debugging static int debug; + //- Allow space character in fileName. To be used with caution. + static int allowSpaceInFileName; + //- An empty fileName static const fileName null; @@ -141,14 +144,10 @@ public: //- Is this character valid for a fileName? inline static bool valid(char c); - //- Construct validated fileName (no invalid characters). - // Optionally perform some additional cleanup such as removing - // duplicate or trailing slashes. - static fileName validate - ( - const std::string& s, - const bool doClean=false - ); + //- Construct fileName with no invalid characters, possibly applying + //- other transformations such as changing the path separator, + //- removing duplicate or trailing slashes, etc. + static fileName validate(const std::string& s, const bool doClean=true); //- This is a specialized (possibly slower) version of compare() //- that ignores duplicate or trailing slashes. diff --git a/src/OpenFOAM/primitives/strings/fileName/fileNameI.H b/src/OpenFOAM/primitives/strings/fileName/fileNameI.H index fb23263c8c..2eefa95f72 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileNameI.H +++ b/src/OpenFOAM/primitives/strings/fileName/fileNameI.H @@ -102,9 +102,9 @@ inline bool Foam::fileName::valid(char c) { return ( - !isspace(c) - && c != '"' // string quote - && c != '\'' // string quote + c != '"' // string quote + && c != '\'' // string quote + && (!isspace(c) || (allowSpaceInFileName && c == ' ')) ); } @@ -134,7 +134,10 @@ inline void Foam::fileName::stripInvalid() inline bool Foam::fileName::isAbsolute(const std::string& str) { - return !str.empty() && str[0] == '/'; + return + ( + !str.empty() && str[0] == '/' + ); }