From 19230524e7055db5e0608a70ea84e97dc90a1acd Mon Sep 17 00:00:00 2001
From: Julien Schueller <schueller@phimeca.com>
Date: Mon, 29 Aug 2016 10:30:29 +0200
Subject: [PATCH] Add Os::IsDirectory, IsFile

In particular use IsFile in Path::FindFileByNameInDirectoryList
instead of just 'stat' to check for a regular file.
This allows to work around what seems a bug compiling on conda/osx
with libcpp where this function returns a directory.
---
 lib/src/Base/Common/Os.cxx           | 22 +++++++++++++++-------
 lib/src/Base/Common/Path.cxx         | 26 +++++++++++---------------
 lib/src/Base/Common/openturns/Os.hxx |  4 ++++
 3 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/lib/src/Base/Common/Os.cxx b/lib/src/Base/Common/Os.cxx
index ee9bb0b..fcd3b62 100644
--- lib/src/Base/Common/Os.cxx
+++ lib/src/Base/Common/Os.cxx
@@ -43,6 +43,9 @@
 # if !defined(S_ISDIR)
 #  define S_ISDIR(mode) (((mode) & S_IFDIR) != 0)
 # endif
+# if !defined(S_ISREG)
+#  define S_ISREG(mode) (((mode) & S_IFREG) != 0)
+# endif
 #elif defined(WIN32)
 # define MKDIR(p, mode)  mkdir(p)
 #else
@@ -177,20 +180,25 @@ convert_backslashes(String & path)
 #endif
 }
 
-// Function helper for Os::MakeDirectory
-static bool
-is_directory(const char * name)
+Bool Os::IsDirectory(const String & fileName)
 {
   struct stat dir_stat;
-  if(stat(name, &dir_stat) != 0) return false;
+  if(stat(fileName.c_str(), &dir_stat) != 0) return false;
   return S_ISDIR(dir_stat.st_mode);
 }
 
+Bool Os::IsFile(const String & fileName)
+{
+  struct stat dir_stat;
+  if(stat(fileName.c_str(), &dir_stat) != 0) return false;
+  return S_ISREG(dir_stat.st_mode);
+}
+
 // Returns 0 if no error
 int Os::MakeDirectory(const String & path)
 {
   if (path.empty()) return 1;
-  if (is_directory(path.c_str())) return 0;
+  if (IsDirectory(path)) return 0;
 
   String slashPath(path);
   convert_backslashes(slashPath);
@@ -200,7 +208,7 @@ int Os::MakeDirectory(const String & path)
   {
     String current_dir(path.substr(0, pos));
     const char * cpath = current_dir.c_str();
-    if (!is_directory(cpath) && (0 != MKDIR(cpath, 0777))) return 1;
+    if (!IsDirectory(current_dir) && (0 != MKDIR(cpath, 0777))) return 1;
     pos++;
   }
 
@@ -241,7 +249,7 @@ static int deleteRegularFileOrDirectory(const char * path,
 int Os::DeleteDirectory(const String & path)
 {
   if (path.empty()) return 1;
-  if (!is_directory(path.c_str())) return 1;
+  if (!IsDirectory(path)) return 1;
 
   // Refuse to delete root directory (/) and current directory (.)
   if (path == "/" || path == ".") return 1;
diff --git a/lib/src/Base/Common/Path.cxx b/lib/src/Base/Common/Path.cxx
index f80391d..3c4c47f 100644
--- lib/src/Base/Common/Path.cxx
+++ lib/src/Base/Common/Path.cxx
@@ -31,10 +31,11 @@
 #define mkdir(p)  _mkdir(p)
 #endif /* _MSC_VER */
 #endif /* WIN32 */
-#include <sys/types.h>            // for stat
-#include <sys/stat.h>             // for stat
-#include <unistd.h>               // for stat
+
+// Include OTConfig that defines OPENTURNS_HAVE_XXX
+// It also defines INSTALL_PATH, SYSCONFIG_PATH, DATA_PATH, OPENTURNS_HOME_ENV_VAR
 #include "openturns/OTconfig.hxx"
+
 #include "openturns/OTthread.hxx"
 #include "openturns/OSS.hxx"
 #include "openturns/Path.hxx"
@@ -102,8 +103,7 @@ FileName Path::GetInstallationDirectory()
   if (otHome)
   {
     directory = String(otHome);
-    struct stat status;
-    dirExists = (stat( directory.c_str(), &status ) == 0 && ( status.st_mode & S_IFDIR ));
+    dirExists = Os::IsDirectory(directory);
   }
   if (!dirExists)
   {
@@ -210,8 +210,7 @@ Path::DirectoryList Path::GetConfigDirectoryList()
     directory += "/etc";
     directory += PrefixConfigSubdirectory_;
 #endif
-    struct stat status;
-    dirExists = (stat( directory.c_str(), &status ) == 0 && ( status.st_mode & S_IFDIR ));
+    dirExists = Os::IsDirectory(directory);
   }
   if (!dirExists)
   {
@@ -250,17 +249,15 @@ FileName Path::FindFileByNameInDirectoryList(const FileName & name,
 
   // We create the full path name of the file with each directory
   // of the list in turn, and then we check if this file exists
-  FileName fullPathForFile;
   DirectoryList::const_iterator currentDirectory;
   for(currentDirectory  = dirList.begin();
       currentDirectory != dirList.end();
-      currentDirectory++)
+      ++ currentDirectory)
   {
     LOGDEBUG(OSS() << "Searching '" << name << "' in directory : " << *currentDirectory);
 
-    fullPathForFile = *currentDirectory + Os::GetDirectorySeparator() + name;
-    struct stat fileStatBuffer;
-    if (!stat(fullPathForFile.c_str(), &fileStatBuffer)) // file is found
+    FileName fullPathForFile(*currentDirectory + Os::GetDirectorySeparator() + name);
+    if (Os::IsFile(fullPathForFile))
       return fullPathForFile;
   }
 
@@ -272,7 +269,7 @@ FileName Path::FindFileByNameInDirectoryList(const FileName & name,
                << "' was found in any of those directories :";
   for(currentDirectory  = dirList.begin();
       currentDirectory != dirList.end();
-      currentDirectory++)
+      ++ currentDirectory)
   {
     errorMessage << " " << *currentDirectory;
   }
@@ -366,8 +363,7 @@ FileName Path::BuildTemporaryFileName(const FileName & pattern)
                   0,                     // create unique name
                   temporaryFileName);    // buffer for name
   // check temporary filename
-  struct stat dir_stat;
-  if (stat(temporaryFileName, &dir_stat) != 0)
+  if (!Os::IsFile(String(temporaryFileName)))
     LOGERROR(OSS() << "Temporary file name " << temporaryFileName << " does NOT exists. Check your temporary directory.");
   // add "/" to the directory
   String slashedTemporaryFileName(temporaryFileName);
diff --git a/lib/src/Base/Common/openturns/Os.hxx b/lib/src/Base/Common/openturns/Os.hxx
index 47fa40f..05b9e5f 100644
--- lib/src/Base/Common/openturns/Os.hxx
+++ lib/src/Base/Common/openturns/Os.hxx
@@ -77,6 +77,10 @@ public:
    */
   static int ExecuteCommand(const String & command);
 
+  static Bool IsDirectory(const String & fileName);
+
+  static Bool IsFile(const String & fileName);
+
 private:
 
   /** Default constructor */
-- 
2.7.4

