diff --git a/applications/test/fileNameOS/Make/files b/applications/test/fileNameOS/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..0e1be7b39452df98c2aaad67de59793c995c2171 --- /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 0000000000000000000000000000000000000000..18e6fe47afacb902cddccf82632772447704fd88 --- /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 0000000000000000000000000000000000000000..b8c7be1ac922a48affc1091eac3d6adc5bafa6ff --- /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 <http://www.gnu.org/licenses/>. + +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 <csignal> +#include <cstdlib> +#include <iostream> + + +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 3d6c94dd8003e42d21c61b21f81244a474c89b6d..bcc4096734edb9b0b3e008bdef5b981c7cbb9d58 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 fea9a4d1466886befe2b5afde4ec71cdb9563e72..e59392ac85f8b5c85a41e0c913d45b8a9c685533 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 25d2504dae1eee479b0210995383852f8d25f367..773d4c7fcdf4e2fd6bf2314dc7f07e14ab7db092 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 8b578d68d322363a9c8e2eb2a222175e5e77937b..b75790decc2749ea79af1879b9b2c54ba292a765 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 e2babf452d3d33afed586b33e69c819a61eed62e..86e7f9ea6ef55a334a418a6dc3843836a17a9c4f 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 413b8d0461a27dae05acac8df800e11bc47e32f8..77b06b97865befecb1117067e42910120a7926ab 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 083109b105137f43920b9700e7db2e2843da5e07..53b5592efe61b93b460d16833f765c10cc8dc437 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] == '/' + ); }