New function. Creates a directory including intermediate parent
authorTor Lillqvist <tml@novell.com>
Wed, 22 Jun 2005 09:43:37 +0000 (09:43 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Wed, 22 Jun 2005 09:43:37 +0000 (09:43 +0000)
2005-06-22  Tor Lillqvist  <tml@novell.com>

* glib/gfileutils.c (g_makepath): New function. Creates a
directory including intermediate parent directories as
needed. (#60509)

* glib/gfileutils.h: Declare it.

* glib/glib.symbols: Add it.

* tests/testglib.c: Test it.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-8
glib/gfileutils.c
glib/gfileutils.h
glib/glib.symbols
tests/testglib.c

index 0f7bb90..19902d7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,22 @@
 2005-06-22  Tor Lillqvist  <tml@novell.com>
 
+       * glib/gfileutils.c (g_makepath): New function. Creates a
+       directory including intermediate parent directories as
+       needed. (#60509)
+
+       * glib/gfileutils.h: Declare it.
+
        * glib/gutils.c (g_get_host_name): New function. Returns the
        machine's name, or one of its names. Document that it is
        best-effort only, and not guaranteed to be unique or anything.
        (g_get_any_init): Get the host name here. On Unix use
        gethostname(), on Windows use GetComputerName(). (#5200)
 
-       * glib/gutils.h
-       * glib/glib.symbols: Add here, too.
+       * glib/gutils.h: Declare it.
+
+       * glib/glib.symbols: Add new functions.
 
-       * tests/testglib.c: Test it.
+       * tests/testglib.c: Test g_makepath() and g_get_host_name().
        
 2005-06-18  Matthias Clasen  <mclasen@redhat.com>
 
index 0f7bb90..19902d7 100644 (file)
@@ -1,15 +1,22 @@
 2005-06-22  Tor Lillqvist  <tml@novell.com>
 
+       * glib/gfileutils.c (g_makepath): New function. Creates a
+       directory including intermediate parent directories as
+       needed. (#60509)
+
+       * glib/gfileutils.h: Declare it.
+
        * glib/gutils.c (g_get_host_name): New function. Returns the
        machine's name, or one of its names. Document that it is
        best-effort only, and not guaranteed to be unique or anything.
        (g_get_any_init): Get the host name here. On Unix use
        gethostname(), on Windows use GetComputerName(). (#5200)
 
-       * glib/gutils.h
-       * glib/glib.symbols: Add here, too.
+       * glib/gutils.h: Declare it.
+
+       * glib/glib.symbols: Add new functions.
 
-       * tests/testglib.c: Test it.
+       * tests/testglib.c: Test g_makepath() and g_get_host_name().
        
 2005-06-18  Matthias Clasen  <mclasen@redhat.com>
 
index 0f7bb90..19902d7 100644 (file)
@@ -1,15 +1,22 @@
 2005-06-22  Tor Lillqvist  <tml@novell.com>
 
+       * glib/gfileutils.c (g_makepath): New function. Creates a
+       directory including intermediate parent directories as
+       needed. (#60509)
+
+       * glib/gfileutils.h: Declare it.
+
        * glib/gutils.c (g_get_host_name): New function. Returns the
        machine's name, or one of its names. Document that it is
        best-effort only, and not guaranteed to be unique or anything.
        (g_get_any_init): Get the host name here. On Unix use
        gethostname(), on Windows use GetComputerName(). (#5200)
 
-       * glib/gutils.h
-       * glib/glib.symbols: Add here, too.
+       * glib/gutils.h: Declare it.
+
+       * glib/glib.symbols: Add new functions.
 
-       * tests/testglib.c: Test it.
+       * tests/testglib.c: Test g_makepath() and g_get_host_name().
        
 2005-06-18  Matthias Clasen  <mclasen@redhat.com>
 
index 0f7bb90..19902d7 100644 (file)
@@ -1,15 +1,22 @@
 2005-06-22  Tor Lillqvist  <tml@novell.com>
 
+       * glib/gfileutils.c (g_makepath): New function. Creates a
+       directory including intermediate parent directories as
+       needed. (#60509)
+
+       * glib/gfileutils.h: Declare it.
+
        * glib/gutils.c (g_get_host_name): New function. Returns the
        machine's name, or one of its names. Document that it is
        best-effort only, and not guaranteed to be unique or anything.
        (g_get_any_init): Get the host name here. On Unix use
        gethostname(), on Windows use GetComputerName(). (#5200)
 
-       * glib/gutils.h
-       * glib/glib.symbols: Add here, too.
+       * glib/gutils.h: Declare it.
+
+       * glib/glib.symbols: Add new functions.
 
-       * tests/testglib.c: Test it.
+       * tests/testglib.c: Test g_makepath() and g_get_host_name().
        
 2005-06-18  Matthias Clasen  <mclasen@redhat.com>
 
index d0dd3ce..a236a54 100644 (file)
 #include "galias.h"
 
 /**
+ * g_makepath:
+ * @pathname: a pathname in the GLib file name encoding
+ * @mode: permissions to use for newly created directories
+ *
+ * Create a directory if it doesn't already exist. Create intermediate
+ * parent directories as needed, too.
+ *
+ * Returns: 0 if the directoty already exists, or was successfully
+ * created. Returns -1 if an error occurred, with errno set.
+ *
+ * Since: 2.8
+ */
+int
+g_makepath (const gchar *pathname,
+           int          mode)
+{
+  gchar *fn, *p;
+
+  if (pathname == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  fn = g_strdup (pathname);
+
+  if (g_path_is_absolute (fn))
+    p = (gchar *) g_path_skip_root (fn);
+  else
+    p = fn;
+
+  do
+    {
+      while (*p && !G_IS_DIR_SEPARATOR (*p))
+       p++;
+      
+      if (!*p)
+       p = NULL;
+      else
+       *p = '\0';
+      
+      if (!g_file_test (fn, G_FILE_TEST_EXISTS))
+       {
+         if (g_mkdir (fn, mode) == -1)
+           {
+             int errno_save = errno;
+             g_free (fn);
+             errno = errno_save;
+             return -1;
+           }
+       }
+      else if (!g_file_test (fn, G_FILE_TEST_IS_DIR))
+       {
+         g_free (fn);
+         errno = ENOTDIR;
+         return -1;
+       }
+      if (p)
+       {
+         *p++ = G_DIR_SEPARATOR;
+         while (*p && G_IS_DIR_SEPARATOR (*p))
+           p++;
+       }
+    }
+  while (p);
+
+  g_free (fn);
+
+  return 0;
+}
+
+/**
  * g_file_test:
  * @filename: a filename to test in the GLib file name encoding
  * @test: bitfield of #GFileTest flags
index 7c23cad..a43dd8a 100644 (file)
@@ -107,6 +107,9 @@ gchar *g_build_path     (const gchar *separator,
 gchar *g_build_filename (const gchar *first_element,
                         ...) G_GNUC_NULL_TERMINATED;
 
+int    g_makepath       (const gchar *pathname,
+                        int          mode);
+
 G_END_DECLS
 
 #endif /* __G_FILEUTILS_H__ */
index b029230..6dbcc38 100644 (file)
@@ -260,6 +260,7 @@ g_file_open_tmp PRIVATE
 g_file_test PRIVATE
 g_file_read_link
 g_mkstemp PRIVATE
+g_makepath
 #ifdef G_OS_WIN32
 g_file_get_contents_utf8
 g_file_open_tmp_utf8
index 00f14cc..0250408 100644 (file)
@@ -38,6 +38,7 @@
 #include <errno.h>
 
 #include "glib.h"
+#include "gstdio.h"
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -318,6 +319,119 @@ find_first_that(gpointer key,
 }
 
 
+static gboolean
+test_g_makepath_1 (const gchar *base)
+{
+  char *p0 = g_build_filename (base, "fum", NULL);
+  char *p1 = g_build_filename (p0, "tem", NULL);
+  char *p2 = g_build_filename (p1, "zap", NULL);
+  FILE *f;
+
+  g_remove (p2);
+  g_remove (p1);
+  g_remove (p0);
+
+  if (g_file_test (p0, G_FILE_TEST_EXISTS))
+    {
+      g_print ("failed, %s exists, cannot test g_makepath\n", p0);
+      return FALSE;
+    }
+
+  if (g_file_test (p1, G_FILE_TEST_EXISTS))
+    {
+      g_print ("failed, %s exists, cannot test g_makepath\n", p1);
+      return FALSE;
+    }
+
+  if (g_file_test (p2, G_FILE_TEST_EXISTS))
+    {
+      g_print ("failed, %s exists, cannot test g_makepath\n", p2);
+      return FALSE;
+    }
+
+  if (g_makepath (p2, 0666) == -1)
+    {
+      g_print ("failed, g_makepath(%s) failed: %s\n", p2, g_strerror (errno));
+      return FALSE;
+    }
+
+  if (!g_file_test (p2, G_FILE_TEST_IS_DIR))
+    {
+      g_print ("failed, g_makepath(%s) succeeded, but %s is not a directory\n", p2, p2);
+      return FALSE;
+    }
+
+  if (!g_file_test (p1, G_FILE_TEST_IS_DIR))
+    {
+      g_print ("failed, g_makepath(%s) succeeded, but %s is not a directory\n", p2, p1);
+      return FALSE;
+    }
+
+  if (!g_file_test (p0, G_FILE_TEST_IS_DIR))
+    {
+      g_print ("failed, g_makepath(%s) succeeded, but %s is not a directory\n", p2, p0);
+      return FALSE;
+    }
+
+  g_rmdir (p2);
+  if (g_file_test (p2, G_FILE_TEST_EXISTS))
+    {
+      g_print ("failed, did g_rmdir(%s), but %s is still there\n", p2, p2);
+      return FALSE;
+    }
+
+  g_rmdir (p1);
+  if (g_file_test (p1, G_FILE_TEST_EXISTS))
+    {
+      g_print ("failed, did g_rmdir(%s), but %s is still there\n", p1, p1);
+      return FALSE;
+    }
+
+  f = g_fopen (p1, "w");
+  if (f == NULL)
+    {
+      g_print ("failed, couldn't create file %s\n", p1);
+      return FALSE;
+    }
+  fclose (f);
+  
+  if (g_makepath (p1, 0666) == 0)
+    {
+      g_print ("failed, g_makepath(%s) succeeded, even if %s is a file\n", p1, p1);
+      return FALSE;
+    }
+
+  if (g_makepath (p2, 0666) == 0)
+    {
+      g_print ("failed, g_makepath(%s) succeeded, even if %s is a file\n", p2, p1);
+      return FALSE;
+    }
+
+  g_remove (p2);
+  g_remove (p1);
+  g_remove (p0);
+
+  return TRUE;
+}
+
+static gboolean
+test_g_makepath (void)
+{
+  g_print ("checking g_makepath()...");
+  if (!test_g_makepath_1 ("hum"))
+    return FALSE;
+  g_remove ("hum");
+  if (!test_g_makepath_1 ("hii///haa/hee"))
+    return FALSE;
+  g_remove ("hii/haa/hee");
+  g_remove ("hii/haa");
+  g_remove ("hii");
+  if (!test_g_makepath_1 (g_get_current_dir ()))
+    return FALSE;
+
+  return TRUE;
+}
+
 int
 main (int   argc,
       char *argv[])
@@ -482,7 +596,6 @@ main (int   argc,
   string = g_path_get_basename ("/foo/file");
   g_assert (strcmp (string, "file") == 0);
   g_free (string);
-  g_print ("ok\n");
 #endif
 
   g_print ("checking g_path_get_dirname()...");
@@ -526,6 +639,9 @@ main (int   argc,
   if (n_skip_root_checks)
     g_print ("ok\n");
 
+  if (test_g_makepath ())
+    g_print ("ok\n");
+
   g_print ("checking doubly linked lists...");
 
   list = NULL;