diff --git a/applications/utilities/preProcessing/createZeroDirectory/createZeroDirectory.C b/applications/utilities/preProcessing/createZeroDirectory/createZeroDirectory.C index e492bd37fffbb8536d481c11d729900a2d277ac0..17338d5799e65e016e4275124c03d1bed49ce591 100644 --- a/applications/utilities/preProcessing/createZeroDirectory/createZeroDirectory.C +++ b/applications/utilities/preProcessing/createZeroDirectory/createZeroDirectory.C @@ -217,7 +217,7 @@ int main(int argc, char *argv[]) argList::addOption ( "templateDir", - "file", + "dir", "Read case set-up templates from specified location" ); @@ -238,25 +238,34 @@ int main(int argc, char *argv[]) ) ); + // Template directory: default is from PROJECT/etc directory + // + // Can use + // - foamEtcDir("caseDicts/createZeroDirectory", 0007); + // - expand "<etc:o>/caseDicts/createZeroDirectory" + // - expand "${WM_PROJECT_DIR}/etc/caseDicts/createZeroDirectory" + // + // Use "${WM_PROJECT_DIR}/" version for nicer error message + fileName baseDir ( args.opt<fileName> ( "templateDir", - // Default is from PROJECT/etc directory - "<etc:o>/caseDicts/createZeroDirectoryTemplates" + "${WM_PROJECT_DIR}/etc/caseDicts/createZeroDirectoryTemplates" ) ); baseDir.expand(); baseDir.toAbsolute(); - if (!isDir(baseDir)) + if (!Foam::isDir(baseDir)) { FatalErrorInFunction - << "templateDir " << baseDir - << " should point to the folder containing the " - << "case set-up templates" << exit(FatalError); + << "templateDir " << baseDir << nl + << "Does not point to a folder containing case set-up templates" + << nl + << exit(FatalError); } // Keep variable substitutions - delay until after creation of controlDict diff --git a/bin/foamEtcFile b/bin/foamEtcFile index e45a7fd86df0a04dd2e963e3d5fe609299759f0e..b1dfc4efd0b4aa1329fc2dc184ccb49b944f1a16 100755 --- a/bin/foamEtcFile +++ b/bin/foamEtcFile @@ -205,7 +205,7 @@ do -config) optConfig=true ;; - -mode=[ugo]*) + -mode=[ugoa]*) optMode="${1#*=}" ;; -m | -mode) @@ -213,7 +213,7 @@ do shift # Sanity check. Handles missing argument too. case "$optMode" in - ([ugo]*) + ([ugoa]*) ;; (*) die "invalid mode '$optMode'" @@ -290,17 +290,17 @@ fi # Define the various places to be searched: unset dirList -case "$optMode" in (*u*) # (U)ser +case "$optMode" in (*[au]*) # (A)ll or (U)ser dirList="$dirList $userDir/$projectApi $userDir" ;; esac -case "$optMode" in (*g*) # (G)roup == site +case "$optMode" in (*[ag]*) # (A)ll or (G)roup == site dirList="$dirList $groupDir/$projectApi/etc $groupDir/etc" ;; esac -case "$optMode" in (*o*) # (O)ther == shipped +case "$optMode" in (*[ao]*) # (A)ll or (O)ther == shipped dirList="$dirList $projectDir/etc" ;; esac diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H index a2d8f1be7bec7979ab1007bf909a3575e285348b..6be997b51697c293373f6b2075288914577c0182 100644 --- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H +++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H @@ -203,7 +203,7 @@ public: // - $WM_PROJECT_DIR/etc/"caseDicts/postProcessing" // // Where {PROJECT_API} is the value of the OPENFOAM define. - // See further notes in Foam::findEtcFiles() + // See further notes in Foam::findEtcEntries() static void list(); //- Find a functionObject dictionary file in the case diff --git a/src/OpenFOAM/global/etcFiles/etcFiles.C b/src/OpenFOAM/global/etcFiles/etcFiles.C index 2b941f5fc3cb09df03a9cd81b31843e29551659f..e8f0af9da9740cebaf7145e3469a99c43dcf5661 100644 --- a/src/OpenFOAM/global/etcFiles/etcFiles.C +++ b/src/OpenFOAM/global/etcFiles/etcFiles.C @@ -42,7 +42,6 @@ namespace // - u : location mask 0700 // - g : location mask 0070 // - o : location mask 0007 -// static inline std::string locationToString(unsigned short location) { std::string mode; @@ -56,6 +55,27 @@ static inline std::string locationToString(unsigned short location) } +// Error handling when a mandatory entry is not found +static inline void errorMandatoryNotFound +( + const std::string& name, + unsigned short location +) +{ + // Abort when mandatory entry was not found. + // Use a direct exit, since this could occur before anything is + // setup at all. + + std::cerr + << "--> FOAM FATAL ERROR :\n " + "Could not find mandatory etc entry (mode=" + << locationToString(location) << ")\n '" + << name << "'\n" + << std::endl; + ::exit(1); +} + + // Assign 'queried' parameter to the user resource directory. // Return true if this directory exists. // @@ -141,20 +161,87 @@ static inline bool projectResourceDir(Foam::fileName& queried) } -Foam::fileNameList searchEtc +// Check if the named file/directory matches the type required. +// +// - typeRequired (UNDEFINED) => accept either FILE or DIRECTORY +// - typeRequired (FILE | DIRECTORY) => accept only that type +static inline bool accept ( const Foam::fileName& name, - unsigned short location, - const bool findFirst, - bool (*accept)(const Foam::fileName&) + const Foam::fileName::Type typeRequired ) +{ + // followLink(true), checkGzip(true) + // -> returns (UNDEFINED | FILE | DIRECTORY), no need to check for (LINK) + const auto t = name.type(true, true); + + return + ( + // Found something? + Foam::fileName::Type::UNDEFINED != t + && + ( + // Any particular type required? + Foam::fileName::Type::UNDEFINED == typeRequired + ? (Foam::fileName::Type::UNDEFINED != t) + : (typeRequired == t) + ) + ); +} + +} // End anonymous namespace + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +Foam::fileNameList Foam::etcDirs(bool test) { // Use foamVersion::api (instead of the OPENFOAM define) to ensure this // stays properly synchronized with the build information const Foam::fileName version(std::to_string(Foam::foamVersion::api)); - Foam::fileNameList list; - Foam::fileName queried, candidate; + Foam::fileNameList list(5); + Foam::fileName queried; + label nDirs = 0; + + // User resource directories + if (userResourceDir(queried) || (!test && queried.size())) + { + list[nDirs++] = queried/version; + list[nDirs++] = queried; + } + + // Group (site) resource directories + if (groupResourceDir(queried) || (!test && queried.size())) + { + list[nDirs++] = queried/version; + list[nDirs++] = queried; + } + + // Other (project) resource directory + if (projectResourceDir(queried) || (!test && queried.size())) + { + list[nDirs++] = queried; + } + + list.resize(nDirs); + + return list; +} + + +Foam::fileNameList Foam::findEtcEntries +( + const Foam::fileName& name, + unsigned short location, + const Foam::fileName::Type typeRequired, + const bool findFirst +) +{ + // Debug Tracing + // std::cerr + // << "search ("<< locationToString(location) << "): " + // << name.c_str() << '\n'; if (!(location & 0777)) { @@ -166,12 +253,25 @@ Foam::fileNameList searchEtc << name.c_str() << "'\n\n" << std::endl; } + // Use foamVersion::api (instead of the OPENFOAM define) to ensure this + // stays properly synchronized with the build information + const Foam::fileName version(std::to_string(Foam::foamVersion::api)); + + Foam::fileNameList list; + Foam::fileName queried, candidate; + + if (fileName::Type::FILE == typeRequired && name.empty()) + { + // FILE must have a name to be found! + return list; + } + // User resource directories if ((location & 0700) && userResourceDir(queried)) { candidate = queried/version/name; - if (accept(candidate)) + if (accept(candidate, typeRequired)) { list.append(std::move(candidate)); if (findFirst) @@ -181,7 +281,7 @@ Foam::fileNameList searchEtc } candidate = queried/name; - if (accept(candidate)) + if (accept(candidate, typeRequired)) { list.append(std::move(candidate)); if (findFirst) @@ -191,11 +291,12 @@ Foam::fileNameList searchEtc } } + // Group (site) resource directories if ((location & 0070) && groupResourceDir(queried)) { candidate = queried/version/name; - if (accept(candidate)) + if (accept(candidate, typeRequired)) { list.append(std::move(candidate)); if (findFirst) @@ -205,7 +306,7 @@ Foam::fileNameList searchEtc } candidate = queried/name; - if (accept(candidate)) + if (accept(candidate, typeRequired)) { list.append(std::move(candidate)); if (findFirst) @@ -215,11 +316,12 @@ Foam::fileNameList searchEtc } } + // Other (project) resource directory if ((location & 0007) && projectResourceDir(queried)) { candidate = queried/name; - if (accept(candidate)) + if (accept(candidate, typeRequired)) { list.append(std::move(candidate)); } @@ -228,62 +330,15 @@ Foam::fileNameList searchEtc return list; } -} // End anonymous namespace - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -Foam::fileNameList Foam::etcDirs(bool test) -{ - // Use foamVersion::api (instead of the OPENFOAM define) to ensure this - // stays properly synchronized with the build information - const Foam::fileName version(std::to_string(Foam::foamVersion::api)); - - Foam::fileNameList list(5); - Foam::fileName queried; - label nDirs = 0; - - // User resource directories - if (userResourceDir(queried) || (!test && queried.size())) - { - list[nDirs++] = queried/version; - list[nDirs++] = queried; - } - - // Group (site) resource directories - if (groupResourceDir(queried) || (!test && queried.size())) - { - list[nDirs++] = queried/version; - list[nDirs++] = queried; - } - - // Other (project) resource directory - if (projectResourceDir(queried) || (!test && queried.size())) - { - list[nDirs++] = queried; - } - - list.resize(nDirs); - - return list; -} - Foam::fileNameList Foam::findEtcDirs ( const fileName& name, - const bool findFirst, - unsigned short location + unsigned short location, + const bool findFirst ) { - return - searchEtc - ( - name, - location, - findFirst, - [](const fileName& f){ return Foam::isDir(f); } - ); + return findEtcEntries(name, location, fileName::Type::DIRECTORY, findFirst); } @@ -291,50 +346,34 @@ Foam::fileNameList Foam::findEtcFiles ( const fileName& name, const bool mandatory, - const bool findFirst, - unsigned short location + unsigned short location, + const bool findFirst ) { - fileNameList list; - - if (name.size()) - { - // A file must have a name! - list = searchEtc - ( - name, - location, - findFirst, - [](const fileName& f){ return Foam::isFile(f); } - ); - } + // Note: findEtcEntries checks name.size() for FILE + fileNameList list + ( + findEtcEntries(name, location, fileName::Type::FILE, findFirst) + ); if (mandatory && list.empty()) { - // Abort if file is mandatory but not found. - // Use a direct exit, since this could occur before anything is - // setup at all. - - std::cerr - << "--> FOAM FATAL ERROR :\n " - "Could not find mandatory etc file (mode=" - << locationToString(location) << ")\n '" - << name.c_str() << "'\n" - << std::endl; - ::exit(1); + errorMandatoryNotFound(name, location); } return list; } -Foam::fileName Foam::findEtcDir +Foam::fileName Foam::findEtcEntry ( const fileName& name, - unsigned short location + unsigned short location, + const Foam::fileName::Type typeRequired ) { - fileNameList list(findEtcDirs(name, true, location)); + // With findFirst(true) + fileNameList list(findEtcEntries(name, location, typeRequired, true)); fileName found; @@ -347,6 +386,16 @@ Foam::fileName Foam::findEtcDir } +Foam::fileName Foam::findEtcDir +( + const fileName& name, + unsigned short location +) +{ + return findEtcEntry(name, location, fileName::Type::DIRECTORY); +} + + Foam::fileName Foam::findEtcFile ( const fileName& name, @@ -354,13 +403,11 @@ Foam::fileName Foam::findEtcFile unsigned short location ) { - fileNameList list(findEtcFiles(name, mandatory, true, location)); + fileName found(findEtcEntry(name, location, fileName::Type::FILE)); - fileName found; - - if (list.size()) + if (mandatory && found.empty()) { - found = std::move(list.first()); + errorMandatoryNotFound(name, location); } return found; diff --git a/src/OpenFOAM/global/etcFiles/etcFiles.H b/src/OpenFOAM/global/etcFiles/etcFiles.H index 7143756441b8a5c815f17c9e39f555d46a42e232..5dc8f166cf3324f131f01ecd65368977061d2d31 100644 --- a/src/OpenFOAM/global/etcFiles/etcFiles.H +++ b/src/OpenFOAM/global/etcFiles/etcFiles.H @@ -52,30 +52,7 @@ namespace Foam fileNameList etcDirs(bool test=true); -//- Search for directories from user/group/other directories. -// Uses search hierarchy as per findEtcFiles(). -// -// \return The list of full paths of all the matching directories or -// an empty list if the name cannot be found. -fileNameList findEtcDirs -( - const fileName& name, //!< The directory to search for - const bool findFirst=false, //!< Stop after locating the first directory - unsigned short location=0777 //!< User/group/other location -); - - -//- Search for a single directory using findEtcDirs(). -// -// \return The full path name of the first directory found in the -// search hierarchy or an empty fileName if the name cannot be found. -fileName findEtcDir -( - const fileName& name, //!< The directory to search for - unsigned short location=0777 //!< User/group/other location -); - -//- Search for files from user/group/other directories. +//- Search for files or directories from user/group/other etc locations. // // The search hierarchy corresponds to that of the \c foamEtcFile script, // which allows for version-specific and version-independent files. @@ -90,29 +67,120 @@ fileName findEtcDir // - $WM_PROJECT_DIR/etc/ // // Where {PROJECT_API} corresponds to the foamVersion::api value. +// When \c \$WM_PROJECT_SITE is unset, uses \c $WM_PROJECT_DIR/site +// +// \param name The entry to search for. For a FILE search, +// this should be non-empty. For a DIRECTORY search or a general +// (UNDEFINED) search, this can be an empty string. +// \param location The search locations as a numerical mode. +// The default (0777) searches user/group/other locations. +// \param typeRequired restricts the search to the specified type. +// The default (UNDEFINED) accepts FILE or DIRECTORY entries. +// \param findFirst Optionally stop after locating the first entry. +// +// \return The list of full paths of all the matching files or directories +// or an empty list if the name cannot be resolved. +fileNameList findEtcEntries +( + const fileName& name, + unsigned short location=0777, + const fileName::Type typeRequired = fileName::Type::UNDEFINED, + const bool findFirst=false +); + + +//- Search for directories from user/group/other etc locations. +// The search hierarchy corresponds to that of the \c foamEtcFile script, +// which allows for version-specific and version-independent files. +// +// This function corresponds to using Foam::findEtcEntries() +// with (DIRECTORY) for the type required. +// +// \param name The directory to search for. This can be an empty string. +// \param location The search locations as a numerical mode. +// The default (0777) searches user/group/other locations. +// \param findFirst Optionally stop after locating the first entry. +// +// \return The list of full paths of all the matching directories or +// an empty list if the name cannot be found. +fileNameList findEtcDirs +( + const fileName& name, + unsigned short location=0777, + const bool findFirst=false +); + +//- Search for files from user/group/other etc locations. +// The search hierarchy corresponds to that of the \c foamEtcFile script, +// which allows for version-specific and version-independent files. +// +// This function corresponds to using Foam::findEtcEntries() +// with (FILE) for the type required, but has an additional +// check for mandatory files. // -// \note When \c \$WM_PROJECT_SITE is unset, uses \c $WM_PROJECT_DIR/site +// \param name The file to search for. If this is an empty string, +// nothing will be matched. +// \param mandatory Abort if the mandatory file cannot be found. +// \param location The search locations as a numerical mode. +// The default (0777) searches user/group/other locations. +// \param findFirst Optionally stop after locating the first entry. // // \return The list of full paths of all the matching files or // an empty list if the name cannot be found. fileNameList findEtcFiles ( - const fileName& name, //!< The file to search for - const bool mandatory=false, //!< Abort if the file cannot be found - const bool findFirst=false, //!< Stop after locating the first directory - unsigned short location=0777 //!< User/group/other location + const fileName& name, + const bool mandatory=false, + unsigned short location=0777, + const bool findFirst=false +); + + +//- Search for a single FILE or DIRECTORY within the etc directories +// +// \param name The entry to search for. For a FILE search, +// this should be non-empty. For a DIRECTORY search or a general +// (UNDEFINED) search, this can be an empty string. +// \param location The search locations as a numerical mode. +// The default (0777) searches user/group/other locations. +// \param typeRequired restricts the search to the specified type. +// The default (UNDEFINED) accepts FILE or DIRECTORY entries. +// +// \return The full path name of the first entry found in the +// search hierarchy or an empty fileName if the name cannot be found. +// +// \sa Foam::findEtcEntries() +fileName findEtcEntry +( + const fileName& name, + unsigned short location=0777, + const fileName::Type typeRequired = fileName::Type::UNDEFINED ); -//- Search for a single file using findEtcFiles(). +//- Search for a single FILE within the etc directories +// +// \return The full path name of the first directory found in the +// search hierarchy or an empty fileName if the name cannot be found. +// +// \sa Foam::findEtcEntries(), Foam::findEtcDirs() +fileName findEtcDir +( + const fileName& name, //!< The directory to search for + unsigned short location=0777 //!< User/group/other location +); + +//- Search for a single FILE within the etc directories // // \return The full path name of the first file found in the // search hierarchy or an empty fileName if the name cannot be found. +// +// \sa Foam::findEtcEntries(), Foam::findEtcFiles() fileName findEtcFile ( - const fileName& name, //!< The file to search for - const bool mandatory=false, //!< Abort if the file cannot be found - unsigned short location=0777 //!< User/group/other location + const fileName& name, //!< The file to search for + const bool mandatory=false, //!< Abort if the file cannot be found + unsigned short location=0777 //!< User/group/other location ); diff --git a/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C b/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C index 32d6869592b9ca11408d3455d6266c8ccddc357a..4178d814f1f9dfe1d62421eb299dafd557195c95 100644 --- a/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C +++ b/src/OpenFOAM/meshes/meshShapes/cellModel/cellModels.C @@ -58,7 +58,7 @@ void Foam::cellModel::constructModels() << exit(FatalError); } - IFstream is(findEtcFile("cellModels", true)); + IFstream is(findEtcFile("cellModels", true)); // Mandatory file PtrList<cellModel> newPtrs(is); models_.swap(newPtrs); diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C index eaf82965124285bfa3fb85bc2145e5ad04d2ef8f..f5ea1152c6cf616a95767c628117eed468f7bd2f 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C @@ -42,6 +42,7 @@ namespace Foam // - u : location mask 0700 // - g : location mask 0070 // - o : location mask 0007 +// - a : location mask 0777 // static inline unsigned short modeToLocation ( @@ -54,6 +55,7 @@ static inline unsigned short modeToLocation if (std::string::npos != mode.find('u', pos)) { where |= 0700; } // User if (std::string::npos != mode.find('g', pos)) { where |= 0070; } // Group if (std::string::npos != mode.find('o', pos)) { where |= 0007; } // Other + if (std::string::npos != mode.find('a', pos)) { where |= 0777; } // All return where; } @@ -62,8 +64,8 @@ static inline unsigned short modeToLocation // Expand a leading <tag>/ // Convenient for frequently used directories // -// <etc>/ => user/group/other etc - findEtcFile() -// <etc(:[ugo]+)?>/ => user/group/other etc - findEtcFile() +// <etc>/ => user/group/other etc - findEtcEntry() +// <etc(:[ugoa]+)?>/ => user/group/other etc - findEtcEntry() // <case>/ => FOAM_CASE directory // <constant>/ => FOAM_CASE/constant directory // <system>/ => FOAM_CASE/system directory @@ -102,7 +104,7 @@ static void expandLeadingTag(std::string& s, const char b, const char e) if (tag == "etc") { - s = findEtcFile(file); + s = findEtcEntry(file); } else if (tag == "case") { @@ -114,9 +116,9 @@ static void expandLeadingTag(std::string& s, const char b, const char e) } else if (tagLen >= 4 && tag.compare(0, 4, "etc:") == 0) { - // <etc:ugo> type of tag - convert "ugo" to numeric + // <etc:[ugoa]+> type of tag - convert "ugo" to numeric - s = findEtcFile(file, false, modeToLocation(tag, 4)); + s = findEtcEntry(file, modeToLocation(tag,4)); } } diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H index 74d11b051b7fa90d50aee476c7bdd6c52527238e..f2f2864e02baf91babcddd7b4d67ccbaa99ebf6c 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H @@ -224,7 +224,7 @@ namespace stringOps // -# leading tag expansion for commonly used directories // - <b> \<etc\>/ </b> // : user/group/other OpenFOAM etc directory - // - <b> \<etc:</b><em>[ugo]+</em>)<b>\>/ </b> + // - <b> \<etc:</b><em>[ugoa]+</em>)<b>\>/ </b> // : user/group/other etc with specified location mode // - <b> \<case\>/ </b> // : The \c $FOAM_CASE directory @@ -263,7 +263,7 @@ namespace stringOps // "~OpenFOAM" expansion // // \sa - // Foam::findEtcFile + // Foam::findEtcEntry(), Foam::findEtcEntries(), string expand ( const string& original, @@ -280,7 +280,7 @@ namespace stringOps // -# leading tag expansion for commonly used directories // - <b> \<etc\>/ </b> // : user/group/other OpenFOAM etc directory - // - <b> \<etc:</b><em>[ugo]+</em>)<b>\>/ </b> + // - <b> \<etc:</b><em>[ugoa]+</em>)<b>\>/ </b> // : user/group/other etc with specified location mode // - <b> \<case\>/ </b> // : The \c $FOAM_CASE directory @@ -312,7 +312,7 @@ namespace stringOps // "~OpenFOAM" expansion // // \sa - // Foam::findEtcFile + // Foam::findEtcEntry(), Foam::findEtcEntries(), void inplaceExpand ( std::string& s,