changeset 14679:a543ed02e673

Allow the builtin function mkdir to create missing parent directories * bootstrap.conf : Add the mkdir-p and savewd gnulib modules. * file-ops.cc (static int make_ancestor (const char*, const char*, void*)): New function. (int octave_mkdir (const std::string&, mode_t, std::string&, bool): Add fourth argument and use it to conditionally select whether to make the missing parent directories. * file-ops.h (int octave_mkdir (const std::string&, mode_t, std::string&, bool): Add fourth argument. * lo-cutils.c (struct mkdir_options): New structure (static void announce_mkdir (const char*, void*), static int process_dir (char *, struct savewd *, void *), int octave_mkdir_parents (const char *, mode_t, int (*make_ancestor) (const char *, const char *, void *)): New functions. * lo-cutils.h (int octave_mkdir_parents (const char *, mode_t, int (*make_ancestor) (const char *, const char *, void *)): New function. * dirfns.cc (Fmkdir): Call octave_mkdir with the make_parents argument set to true.
author David Bateman <dbateman@free.fr>
date Wed, 23 May 2012 22:34:37 +0200
parents 757f729fd41d
children 57569a35765c
files build-aux/bootstrap.conf liboctave/file-ops.cc liboctave/file-ops.h liboctave/lo-cutils.c liboctave/lo-cutils.h src/dirfns.cc
diffstat 6 files changed, 70 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/build-aux/bootstrap.conf	Wed May 23 13:36:24 2012 -0400
+++ b/build-aux/bootstrap.conf	Wed May 23 22:34:37 2012 +0200
@@ -40,6 +40,7 @@
   link
   lstat
   mkdir
+  mkdir-p
   mkfifo
   mkostemp
   mkstemp
@@ -56,6 +57,7 @@
   rmdir
   round
   roundf
+  savewd
   sigaction
   signal
   sigprocmask
--- a/liboctave/file-ops.cc	Wed May 23 13:36:24 2012 -0400
+++ b/liboctave/file-ops.cc	Wed May 23 22:34:37 2012 +0200
@@ -48,6 +48,7 @@
 #include "quit.h"
 #include "singleton-cleanup.h"
 #include "str-vec.h"
+#include "lo-cutils.h"
 
 file_ops *file_ops::instance = 0;
 
@@ -361,22 +362,32 @@
        : dir + dir_sep_char () + file);
 }
 
+static int 
+make_ancestor (const char *, const char *component, void *options)
+{
+  mode_t* mode = reinterpret_cast<mode_t *>(options);
+  return gnulib::mkdir (component, *mode);
+}
 
 int
 octave_mkdir (const std::string& nm, mode_t md)
 {
   std::string msg;
-  return octave_mkdir (nm, md, msg);
+  return octave_mkdir (nm, md, msg, false);
 }
 
 int
-octave_mkdir (const std::string& name, mode_t mode, std::string& msg)
+octave_mkdir (const std::string& name, mode_t mode, std::string& msg, 
+              bool make_parents)
 {
   msg = std::string ();
 
   int status = -1;
 
-  status = gnulib::mkdir (name.c_str (), mode);
+  if (make_parents)
+    status = octave_mkdir_parents (name.c_str (), mode, make_ancestor);
+  else
+    status = gnulib::mkdir (name.c_str (), mode);
 
   if (status < 0)
     msg = gnulib::strerror (errno);
--- a/liboctave/file-ops.h	Wed May 23 13:36:24 2012 -0400
+++ b/liboctave/file-ops.h	Wed May 23 22:34:37 2012 +0200
@@ -122,7 +122,8 @@
 octave_mkdir (const std::string& nm, mode_t md);
 
 extern OCTAVE_API int
-octave_mkdir (const std::string& nm, mode_t md, std::string& msg);
+octave_mkdir (const std::string& nm, mode_t md, std::string& msg,
+              bool make_parents = false);
 
 extern OCTAVE_API int
 octave_mkfifo (const std::string& nm, mode_t md);
--- a/liboctave/lo-cutils.c	Wed May 23 13:36:24 2012 -0400
+++ b/liboctave/lo-cutils.c	Wed May 23 22:34:37 2012 +0200
@@ -32,6 +32,7 @@
 #endif
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include <stdlib.h>
@@ -41,6 +42,9 @@
 #include "lo-cutils.h"
 #include "syswait.h"
 
+#include "savewd.h"
+#include "mkdir-p.h"
+
 OCTAVE_API void
 octave_qsort (void *base, size_t n, size_t size,
               int (*cmp) (const void *, const void *))
@@ -76,3 +80,46 @@
 {
   return WAITPID (pid, status, options);
 }
+
+struct mkdir_options
+{
+  int (*make_ancestor_function) (const char *, const char *, void *);
+  mode_t ancestor_mode;
+  mode_t mode;
+  mode_t mode_bits;
+};
+
+static void
+announce_mkdir (const char *dir, void *options)
+{
+  /* Do nothing */
+}
+
+static int
+process_dir (char *dir, struct savewd *wd, void *options)
+{
+  struct mkdir_options const *o = options;
+  mode_t ancestor_mode = o->ancestor_mode;
+  return (make_dir_parents (dir, wd, o->make_ancestor_function, &ancestor_mode,
+                            o->mode, announce_mkdir, o->mode_bits, 
+                            (uid_t) -1, (gid_t) -1, false) ? 0 : -1);
+}
+
+OCTAVE_API int
+octave_mkdir_parents (const char *dir, mode_t mode,
+                      int (*make_ancestor) (const char *, const char *, void *))
+{
+  char *argv[1];
+  int retval;
+  char *dir2 = malloc (strlen (dir) + 1);
+  strcpy (dir2, dir); /* Make a copy to avoid passing a const char* as char* */
+  argv[0] = dir2;
+  struct mkdir_options o;
+  o.make_ancestor_function = make_ancestor;
+  o.ancestor_mode = mode | S_IWUSR | S_IXUSR; 
+  o.mode = mode | umask(0);
+  o.mode_bits = ~(mode & umask(0));
+  retval = (savewd_process_files (1, argv, process_dir, &o));
+  free (dir2);
+  return retval;
+}
--- a/liboctave/lo-cutils.h	Wed May 23 13:36:24 2012 -0400
+++ b/liboctave/lo-cutils.h	Wed May 23 22:34:37 2012 +0200
@@ -50,6 +50,10 @@
 OCTAVE_API pid_t
 octave_waitpid (pid_t pid, int *status, int options);
 
+OCTAVE_API int
+octave_mkdir_parents (const char *dir, mode_t mode,
+                      int (*make_ancestor) (char const *, char const *, void *));
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/dirfns.cc	Wed May 23 13:36:24 2012 -0400
+++ b/src/dirfns.cc	Wed May 23 22:34:37 2012 +0200
@@ -271,7 +271,7 @@
         }
       else
         {
-          int status = octave_mkdir (dirname, 0777, msg);
+          int status = octave_mkdir (dirname, 0777, msg, true);
 
           if (status < 0)
             {