diff liboctave/file-ops.cc @ 10197:4d433bd2d4dc

attempt to avoid trouble with gnulib #defines in a consistent way
author John W. Eaton <jwe@octave.org>
date Tue, 26 Jan 2010 00:45:04 -0500
parents 8fa6ce1b21f2
children 025564630c8d
line wrap: on
line diff
--- a/liboctave/file-ops.cc	Sat Jan 23 06:58:30 2010 +0100
+++ b/liboctave/file-ops.cc	Tue Jan 26 00:45:04 2010 -0500
@@ -33,7 +33,9 @@
 #include <iostream>
 #include <vector>
 
+#include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include <pathmax.h>
 
@@ -47,484 +49,38 @@
 #include "str-vec.h"
 #include "oct-locbuf.h"
 
-file_ops::static_members *file_ops::static_members::instance = 0;
-
-file_ops::static_members::static_members (void)
-  :
-#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
-  xdir_sep_char ('\\'),
-  xdir_sep_str ("\\"),
-#else
-  xdir_sep_char ('/'),
-  xdir_sep_str ("/"), 
-#endif
-#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
-  xdir_sep_chars ("/\\")
-#else
-  xdir_sep_chars (xdir_sep_str)
-#endif
-{ }
+file_ops *file_ops::instance = 0;
 
 bool
-file_ops::static_members::instance_ok (void)
+file_ops::instance_ok (void)
 {
   bool retval = true;
 
   if (! instance)
-    instance = new static_members ();
-
-  if (! instance)
     {
-      (*current_liboctave_error_handler)
-        ("unable to create file_ops::static_members object!");
-
-      retval = false;
-    }
-
-  return retval;
-}
-
-// We provide a replacement for mkdir().
-
-int
-file_ops::mkdir (const std::string& nm, mode_t md)
-{
-  std::string msg;
-  return mkdir (nm, md, msg);
-}
-
-int
-file_ops::mkdir (const std::string& name, mode_t mode, std::string& msg)
-{
-  msg = std::string ();
-
-  int status = -1;
-
-  status = octave_mkdir (name.c_str (), mode);
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return status;
-}
-
-// I don't know how to emulate this on systems that don't provide it.
-
-int
-file_ops::mkfifo (const std::string& nm, mode_t md)
-{
-  std::string msg;
-  return mkfifo (nm, md, msg);
-}
-
-int
-file_ops::mkfifo (const std::string& name, mode_t mode, std::string& msg)
-{
-  msg = std::string ();
-
-  int status = -1;
-
-  // With gnulib we will always have mkfifo, but some systems like MinGW
-  // don't have working mkfifo functions.  On those systems, mkfifo will
-  // always return -1 and set errno.
-
-  status = octave_mkfifo (name.c_str (), mode);
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return status;
-}
-
-// I don't know how to emulate this on systems that don't provide it.
-
-int
-file_ops::link (const std::string& old_name, const std::string& new_name)
-{
-  std::string msg;
-  return link (old_name, new_name, msg);
-}
-
-int
-file_ops::link (const std::string& old_name,
-                const std::string& new_name, std::string& msg)
-{
-  msg = std::string ();
-
-  int status = -1;
-
-  status = octave_link (old_name.c_str (), new_name.c_str ());
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return status;
-}
-
-// I don't know how to emulate this on systems that don't provide it.
-
-int
-file_ops::symlink (const std::string& old_name, const std::string& new_name)
-{
-  std::string msg;
-  return symlink (old_name, new_name, msg);
-}
-
-int
-file_ops::symlink (const std::string& old_name,
-                   const std::string& new_name, std::string& msg)
-{
-  msg = std::string ();
-
-  int status = -1;
-
-  status = octave_symlink (old_name.c_str (), new_name.c_str ());
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return status;
-}
-
-// We provide a replacement for readlink().
-
-int
-file_ops::readlink (const std::string& path, std::string& result)
-{
-  std::string msg;
-  return readlink (path, result, msg);
-}
-
-int
-file_ops::readlink (const std::string& path, std::string& result,
-                    std::string& msg)
-{
-  int status = -1;
-
-  msg = std::string ();
-
-  char buf[MAXPATHLEN+1];
-
-  status = octave_readlink (path.c_str (), buf, MAXPATHLEN);
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-  else
-    {
-      buf[status] = '\0';
-      result = std::string (buf);
-      status = 0;
-    }
-
-  return status;
-}
-
-// We provide a replacement for rename().
-
-int
-file_ops::rename (const std::string& from, const std::string& to)
-{
-  std::string msg;
-  return rename (from, to, msg);
-}
-
-int
-file_ops::rename (const std::string& from, const std::string& to,
-                  std::string& msg)
-{
-  int status = -1;
-
-  msg = std::string ();
-
-  status = octave_rename (from.c_str (), to.c_str ());
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return status;
-}
-
-// We provide a replacement for rmdir().
-
-int
-file_ops::rmdir (const std::string& name)
-{
-  std::string msg;
-  return rmdir (name, msg);
-}
-
-int
-file_ops::rmdir (const std::string& name, std::string& msg)
-{
-  msg = std::string ();
-
-  int status = -1;
-
-  status = octave_rmdir (name.c_str ());
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return status;
-}
-
-// And a version that works recursively.
-
-int
-file_ops::recursive_rmdir (const std::string& name)
-{
-  std::string msg;
-  return recursive_rmdir (name, msg);
-}
-
-int
-file_ops::recursive_rmdir (const std::string& name, std::string& msg)
-{
-  msg = std::string ();
-
-  int status = 0;
-
-  dir_entry dir (name);
-
-  if (dir)
-    {
-      string_vector dirlist = dir.read ();
-
-      for (octave_idx_type i = 0; i < dirlist.length (); i++)
-        {
-          octave_quit ();
-
-          std::string nm = dirlist[i];
-
-          // Skip current directory and parent.
-          if (nm == "." || nm == "..")
-            continue;
-
-          std::string fullnm = name + file_ops::dir_sep_str () + nm;
-
-          // Get info about the file.  Don't follow links.
-          file_stat fs (fullnm, false);
-
-          if (fs)
-            {
-              if (fs.is_dir ())
-                {
-                  status = recursive_rmdir (fullnm, msg);
-
-                  if (status < 0)
-                    break;
-                }
-              else
-                {
-                  status = unlink (fullnm, msg);
-
-                  if (status < 0)
-                    break;
-                }
-            }
-          else
-            {
-              msg = fs.error ();
-              break;
-            }
-        }
-
-      if (status >= 0)
-        {
-          dir.close ();
-          status = file_ops::rmdir (name, msg);
-        }
-    }
-  else
-    {
-      status = -1;
-
-      msg = dir.error ();
-    }
-
-  return status;
-}
-
-std::string
-file_ops::canonicalize_file_name (const std::string& name)
-{
-  std::string msg;
-  return canonicalize_file_name (name, msg);
-}
-
-std::string
-file_ops::canonicalize_file_name (const std::string& name, std::string& msg)
-{
-  msg = std::string ();
-
-  std::string retval;
-
-#if defined (HAVE_CANONICALIZE_FILE_NAME)
-
-  char *tmp = ::canonicalize_file_name (name.c_str ());
-
-  if (tmp)
-    {
-      retval = tmp;
-      ::free (tmp);
-    }
-
-#elif defined (HAVE_RESOLVEPATH)
-
-#if !defined (errno)
-extern int errno;
+#if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
+      char system_dir_sep_char = '\\';
+      std::string system_dir_sep_str = "\\";
+#else
+      char system_dir_sep_char = '/';
+      std::string system_dir_sep_str = "/";
+#endif
+#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
+      std::string system_dir_sep_chars = "/\\";
+#else
+      std::string system_dir_sep_chars = system_dir_sep_str;
 #endif
 
-#if !defined (__set_errno)
-# define __set_errno(Val) errno = (Val)
-#endif
-
-  if (name.empty ())
-    {
-      __set_errno (ENOENT);
-      return retval;
-    }
-
-  // All known hosts with resolvepath (e.g. Solaris 7) don't turn
-  // relative names into absolute ones, so prepend the working
-  // directory if the path is not absolute.
-
-  std::string absolute_name
-    = octave_env::make_absolute (name, octave_env::getcwd ());
-
-  size_t resolved_size = absolute_name.length ();
-
-  while (true)
-    {
-      resolved_size = 2 * resolved_size + 1;
-
-      OCTAVE_LOCAL_BUFFER (char, resolved, resolved_size);
-
-      int resolved_len
-        = ::resolvepath (absolute_name.c_str (), resolved, resolved_size);
-
-      if (resolved_len < 0)
-        break;
-
-      if (resolved_len < resolved_size)
-        {
-          retval = resolved;
-          break;
-        }
-    }
-
-#elif defined (__WIN32__)
-
-  int n = 1024;
-
-  std::string win_path (n, '\0');
-
-  while (true)
-    {
-      int status = GetFullPathName (name.c_str (), n, &win_path[0], 0);
-
-      if (status == 0)
-        break;
-      else if (status < n)
-        {
-          win_path.resize (status);
-          retval = win_path;
-          break;
-        }
-      else
-        {
-          n *= 2;
-          win_path.resize (n);
-        }
-    }
-
-#elif defined (HAVE_REALPATH)
+      instance = new file_ops (system_dir_sep_char, system_dir_sep_str,
+                               system_dir_sep_chars);
 
-#if !defined (__set_errno)
-# define __set_errno(Val) errno = (Val)
-#endif
-
-  if (name.empty ())
-    {
-      __set_errno (ENOENT);
-      return retval;
-    }
-
-  OCTAVE_LOCAL_BUFFER (char, buf, PATH_MAX);
-
-  if (::realpath (name.c_str (), buf))
-    retval = buf;
-
-#else
-
-  // FIXME -- provide replacement here...
-  retval = name;
-
-#endif
-
-  if (retval.empty ())
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return retval;
-}
+      if (! instance)
+        {
+          (*current_liboctave_error_handler)
+            ("unable to create file_ops object!");
 
-// We provide a replacement for tempnam().
-
-std::string
-file_ops::tempnam (const std::string& dir, const std::string& pfx)
-{
-  std::string msg;
-  return tempnam (dir, pfx, msg);
-}
-
-std::string
-file_ops::tempnam (const std::string& dir, const std::string& pfx,
-                   std::string& msg)
-{
-  msg = std::string ();
-
-  std::string retval;
-  
-  const char *pdir = dir.empty () ? 0 : dir.c_str ();
-
-  const char *ppfx = pfx.empty () ? 0 : pfx.c_str ();
-
-  char *tmp = octave_tempnam (pdir, ppfx);
-
-  if (tmp)
-    {
-      retval = tmp;
-
-      ::free (tmp);
-    }
-  else
-    {
-      using namespace std;
-      msg = ::strerror (errno);
+          retval = false;
+        }
     }
 
   return retval;
@@ -787,42 +343,11 @@
   retval.resize (n);
 
   for (int i = 0; i < n; i++)
-    retval[i] = file_ops::tilde_expand (names[i]);
+    retval[i] = tilde_expand (names[i]);
 
   return retval;
 }
 
-int
-file_ops::umask (mode_t mode)
-{
-  return octave_umask (mode);
-}
-
-int
-file_ops::unlink (const std::string& name)
-{
-  std::string msg;
-  return unlink (name, msg);
-}
-
-int
-file_ops::unlink (const std::string& name, std::string& msg)
-{
-  msg = std::string ();
-
-  int status = -1;
-
-  status = octave_unlink (name.c_str ());
-
-  if (status < 0)
-    {
-      using namespace std;
-      msg = ::strerror (errno);
-    }
-
-  return status;
-}
-
 std::string
 file_ops::concat (const std::string& dir, const std::string& file)
 {
@@ -830,5 +355,471 @@
     ? file
     : (is_dir_sep (dir[dir.length()-1])
        ? dir + file
-       : dir + file_ops::dir_sep_char () + file);
+       : dir + dir_sep_char () + file);
+}
+
+
+std::string
+file_ops::canonicalize_file_name (const std::string& name)
+{
+  std::string msg;
+  return canonicalize_file_name (name, msg);
+}
+
+std::string
+file_ops::canonicalize_file_name (const std::string& name, std::string& msg)
+{
+  msg = std::string ();
+
+  std::string retval;
+
+#if defined (HAVE_CANONICALIZE_FILE_NAME)
+
+  char *tmp = ::canonicalize_file_name (name.c_str ());
+
+  if (tmp)
+    {
+      retval = tmp;
+      free (tmp);
+    }
+
+#elif defined (HAVE_RESOLVEPATH)
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if !defined (__set_errno)
+# define __set_errno(Val) errno = (Val)
+#endif
+
+  if (name.empty ())
+    {
+      __set_errno (ENOENT);
+      return retval;
+    }
+
+  // All known hosts with resolvepath (e.g. Solaris 7) don't turn
+  // relative names into absolute ones, so prepend the working
+  // directory if the path is not absolute.
+
+  std::string absolute_name
+    = octave_env::make_absolute (name, octave_env::getcwd ());
+
+  size_t resolved_size = absolute_name.length ();
+
+  while (true)
+    {
+      resolved_size = 2 * resolved_size + 1;
+
+      OCTAVE_LOCAL_BUFFER (char, resolved, resolved_size);
+
+      int resolved_len
+        = resolvepath (absolute_name.c_str (), resolved, resolved_size);
+
+      if (resolved_len < 0)
+        break;
+
+      if (resolved_len < resolved_size)
+        {
+          retval = resolved;
+          break;
+        }
+    }
+
+#elif defined (__WIN32__)
+
+  int n = 1024;
+
+  std::string win_path (n, '\0');
+
+  while (true)
+    {
+      int status = GetFullPathName (name.c_str (), n, &win_path[0], 0);
+
+      if (status == 0)
+        break;
+      else if (status < n)
+        {
+          win_path.resize (status);
+          retval = win_path;
+          break;
+        }
+      else
+        {
+          n *= 2;
+          win_path.resize (n);
+        }
+    }
+
+#elif defined (HAVE_REALPATH)
+
+#if !defined (__set_errno)
+# define __set_errno(Val) errno = (Val)
+#endif
+
+  if (name.empty ())
+    {
+      __set_errno (ENOENT);
+      return retval;
+    }
+
+  OCTAVE_LOCAL_BUFFER (char, buf, PATH_MAX);
+
+  if (::realpath (name.c_str (), buf))
+    retval = buf;
+
+#else
+
+  // FIXME -- provide replacement here...
+  retval = name;
+
+#endif
+
+  if (retval.empty ())
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return retval;
+}
+
+OCTAVE_API int
+octave_mkdir (const std::string& nm, mode_t md)
+{
+  std::string msg;
+  return octave_mkdir (nm, md, msg);
+}
+
+OCTAVE_API int
+octave_mkdir (const std::string& name, mode_t mode, std::string& msg)
+{
+  msg = std::string ();
+
+  int status = -1;
+
+  status = mkdir (name.c_str (), mode);
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return status;
+}
+
+OCTAVE_API int
+octave_mkfifo (const std::string& nm, mode_t md)
+{
+  std::string msg;
+  return octave_mkfifo (nm, md, msg);
+}
+
+OCTAVE_API int
+octave_mkfifo (const std::string& name, mode_t mode, std::string& msg)
+{
+  msg = std::string ();
+
+  int status = -1;
+
+  // With gnulib we will always have mkfifo, but some systems like MinGW
+  // don't have working mkfifo functions.  On those systems, mkfifo will
+  // always return -1 and set errno.
+
+  status = mkfifo (name.c_str (), mode);
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return status;
+}
+
+OCTAVE_API int
+octave_link (const std::string& old_name, const std::string& new_name)
+{
+  std::string msg;
+  return octave_link (old_name, new_name, msg);
+}
+
+OCTAVE_API int
+octave_link (const std::string& old_name,
+                const std::string& new_name, std::string& msg)
+{
+  msg = std::string ();
+
+  int status = -1;
+
+  status = link (old_name.c_str (), new_name.c_str ());
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return status;
+}
+
+OCTAVE_API int
+octave_symlink (const std::string& old_name, const std::string& new_name)
+{
+  std::string msg;
+  return octave_symlink (old_name, new_name, msg);
 }
+
+OCTAVE_API int
+octave_symlink (const std::string& old_name,
+                   const std::string& new_name, std::string& msg)
+{
+  msg = std::string ();
+
+  int status = -1;
+
+  status = symlink (old_name.c_str (), new_name.c_str ());
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return status;
+}
+
+OCTAVE_API int
+octave_readlink (const std::string& path, std::string& result)
+{
+  std::string msg;
+  return octave_readlink (path, result, msg);
+}
+
+OCTAVE_API int
+octave_readlink (const std::string& path, std::string& result,
+                    std::string& msg)
+{
+  int status = -1;
+
+  msg = std::string ();
+
+  char buf[MAXPATHLEN+1];
+
+  status = readlink (path.c_str (), buf, MAXPATHLEN);
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+  else
+    {
+      buf[status] = '\0';
+      result = std::string (buf);
+      status = 0;
+    }
+
+  return status;
+}
+
+OCTAVE_API int
+octave_rename (const std::string& from, const std::string& to)
+{
+  std::string msg;
+  return octave_rename (from, to, msg);
+}
+
+OCTAVE_API int
+octave_rename (const std::string& from, const std::string& to,
+                  std::string& msg)
+{
+  int status = -1;
+
+  msg = std::string ();
+
+  status = rename (from.c_str (), to.c_str ());
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return status;
+}
+
+OCTAVE_API int
+octave_rmdir (const std::string& name)
+{
+  std::string msg;
+  return octave_rmdir (name, msg);
+}
+
+OCTAVE_API int
+octave_rmdir (const std::string& name, std::string& msg)
+{
+  msg = std::string ();
+
+  int status = -1;
+
+  status = rmdir (name.c_str ());
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return status;
+}
+
+// And a version that works recursively.
+
+OCTAVE_API int
+octave_recursive_rmdir (const std::string& name)
+{
+  std::string msg;
+  return octave_recursive_rmdir (name, msg);
+}
+
+OCTAVE_API int
+octave_recursive_rmdir (const std::string& name, std::string& msg)
+{
+  msg = std::string ();
+
+  int status = 0;
+
+  dir_entry dir (name);
+
+  if (dir)
+    {
+      string_vector dirlist = dir.read ();
+
+      for (octave_idx_type i = 0; i < dirlist.length (); i++)
+        {
+          octave_quit ();
+
+          std::string nm = dirlist[i];
+
+          // Skip current directory and parent.
+          if (nm == "." || nm == "..")
+            continue;
+
+          std::string fullnm = name + file_ops::dir_sep_str () + nm;
+
+          // Get info about the file.  Don't follow links.
+          file_stat fs (fullnm, false);
+
+          if (fs)
+            {
+              if (fs.is_dir ())
+                {
+                  status = octave_recursive_rmdir (fullnm, msg);
+
+                  if (status < 0)
+                    break;
+                }
+              else
+                {
+                  status = octave_unlink (fullnm, msg);
+
+                  if (status < 0)
+                    break;
+                }
+            }
+          else
+            {
+              msg = fs.error ();
+              break;
+            }
+        }
+
+      if (status >= 0)
+        {
+          dir.close ();
+          status = octave_rmdir (name, msg);
+        }
+    }
+  else
+    {
+      status = -1;
+
+      msg = dir.error ();
+    }
+
+  return status;
+}
+
+OCTAVE_API int
+octave_umask (mode_t mode)
+{
+#if defined (HAVE_UMASK)
+  return umask (mode);
+#else
+  return 0;
+#endif
+}
+
+OCTAVE_API int
+octave_unlink (const std::string& name)
+{
+  std::string msg;
+  return octave_unlink (name, msg);
+}
+
+OCTAVE_API int
+octave_unlink (const std::string& name, std::string& msg)
+{
+  msg = std::string ();
+
+  int status = -1;
+
+  status = unlink (name.c_str ());
+
+  if (status < 0)
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return status;
+}
+
+OCTAVE_API std::string
+octave_tempnam (const std::string& dir, const std::string& pfx)
+{
+  std::string msg;
+  return octave_tempnam (dir, pfx, msg);
+}
+
+OCTAVE_API std::string
+octave_tempnam (const std::string& dir, const std::string& pfx,
+                std::string& msg)
+{
+  msg = std::string ();
+
+  std::string retval;
+  
+  const char *pdir = dir.empty () ? 0 : dir.c_str ();
+
+  const char *ppfx = pfx.empty () ? 0 : pfx.c_str ();
+
+  char *tmp = tempnam (pdir, ppfx);
+
+  if (tmp)
+    {
+      retval = tmp;
+
+      free (tmp);
+    }
+  else
+    {
+      using namespace std;
+      msg = strerror (errno);
+    }
+
+  return retval;
+}