[libgsystem] Decouple gsystem-local-alloc from libgsystem.h



commit 43a525fd40faf7dfd261bf3d7469f642a68fad68
Author: Colin Walters <walters verbum org>
Date:   Wed Jan 23 15:18:07 2013 -0500

    Decouple gsystem-local-alloc from libgsystem.h
    
    I'd like some of the code here to possibly make its way into GLib.  In
    order to accomplish that, we can't use the local allocation macros =/

 gsystem-file-utils.c |  121 ++++++++++++++++++++++++-------------
 gsystem-shutil.c     |  163 ++++++++++++++++++++++++++++++-------------------
 libgsystem.h         |    1 -
 3 files changed, 179 insertions(+), 106 deletions(-)
---
diff --git a/gsystem-file-utils.c b/gsystem-file-utils.c
index f33bf41..140d53a 100644
--- a/gsystem-file-utils.c
+++ b/gsystem-file-utils.c
@@ -100,13 +100,13 @@ gs_file_read_noatime (GFile         *file,
                       GCancellable  *cancellable,
                       GError       **error)
 {
-  gs_free char *path = NULL;
+  const char *path = NULL;
   int fd;
 
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     return NULL;
 
-  path = g_file_get_path (file);
+  path = gs_file_get_path_cached (file);
   if (path == NULL)
     return NULL;
 
@@ -290,6 +290,71 @@ gen_tmp_name (const char *prefix,
 }
 
 static gboolean
+linkcopy_internal_attempt (GFile          *src,
+                          GFile          *dest,
+                          GFile          *dest_parent,
+                          GFileCopyFlags  flags,
+                          gboolean        sync_data,
+                          gboolean        enable_guestfs_fuse_workaround,
+                          gboolean       *out_try_again,
+                          GCancellable   *cancellable,
+                          GError        **error)
+{
+  gboolean ret = FALSE;
+  gboolean ret_try_again = FALSE;
+  int res;
+  char *tmp_name = NULL;
+  GFile *tmp_dest = NULL;
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    goto out;
+
+  tmp_name = gen_tmp_name (NULL, NULL);
+  tmp_dest = g_file_get_child (dest_parent, tmp_name);
+
+  res = link (gs_file_get_path_cached (src), gs_file_get_path_cached (tmp_dest));
+  if (res == -1)
+    {
+      if (errno == EEXIST)
+        {
+          /* Nothing, fall through */
+          ret_try_again = TRUE;
+          ret = TRUE;
+          goto out;
+        }
+      else if (errno == EXDEV || errno == EMLINK || errno == EPERM
+               || (enable_guestfs_fuse_workaround && errno == ENOENT))
+        {
+          if (!g_file_copy (src, tmp_dest, flags,
+                            cancellable, NULL, NULL, error))
+            goto out;
+        }
+      else
+        {
+          _set_error_from_errno (error);
+          goto out;
+        }
+    }
+      
+  if (sync_data)
+    {
+      /* Now, we need to fdatasync */
+      if (!gs_file_sync_data (tmp_dest, cancellable, error))
+        goto out;
+    }
+
+  if (!gs_file_rename (tmp_dest, dest, cancellable, error))
+    goto out;
+
+  ret = TRUE;
+  *out_try_again = FALSE;
+ out:
+  g_clear_pointer (&tmp_name, g_free);
+  g_clear_object (&tmp_dest);
+  return ret;
+}
+
+static gboolean
 linkcopy_internal (GFile          *src,
                    GFile          *dest,
                    GFileCopyFlags  flags,
@@ -303,7 +368,7 @@ linkcopy_internal (GFile          *src,
   gboolean enable_guestfs_fuse_workaround;
   struct stat src_stat;
   struct stat dest_stat;
-  gs_unref_object GFile *dest_parent = NULL;
+  GFile *dest_parent = NULL;
 
   flags |= G_FILE_COPY_NOFOLLOW_SYMLINKS;
 
@@ -347,50 +412,22 @@ linkcopy_internal (GFile          *src,
   /* 128 attempts seems reasonable... */
   for (i = 0; i < 128; i++)
     {
-      int res;
-      gs_free char *tmp_name = NULL;
-      gs_unref_object GFile *tmp_dest = NULL;
+      gboolean tryagain;
 
-      if (g_cancellable_set_error_if_cancelled (cancellable, error))
+      if (!linkcopy_internal_attempt (src, dest, dest_parent,
+                                      flags, sync_data,
+                                      enable_guestfs_fuse_workaround,
+                                      &tryagain,
+                                      cancellable, error))
         goto out;
 
-      tmp_name = gen_tmp_name (NULL, NULL);
-      tmp_dest = g_file_get_child (dest_parent, tmp_name);
-
-      res = link (gs_file_get_path_cached (src), gs_file_get_path_cached (tmp_dest));
-      if (res == -1)
-        {
-          if (errno == EEXIST)
-            continue;
-          else if (errno == EXDEV || errno == EMLINK || errno == EPERM
-                   || (enable_guestfs_fuse_workaround && errno == ENOENT))
-            {
-              if (!g_file_copy (src, tmp_dest, flags,
-                                cancellable, NULL, NULL, error))
-                goto out;
-            }
-          else
-            {
-              _set_error_from_errno (error);
-              goto out;
-            }
-        }
-      
-      if (sync_data)
-        {
-          /* Now, we need to fdatasync */
-          if (!gs_file_sync_data (tmp_dest, cancellable, error))
-            goto out;
-        }
-
-      if (!gs_file_rename (tmp_dest, dest, cancellable, error))
-        goto out;
-
-      break;
+      if (!tryagain)
+        break;
     }
 
   ret = TRUE;
  out:
+  g_clear_object (&dest_parent);
   return ret;
 
 }
@@ -654,14 +691,13 @@ gs_file_ensure_directory (GFile         *dir,
 {
   gboolean ret = FALSE;
   GError *temp_error = NULL;
+  GFile *parent = NULL;
 
   if (!g_file_make_directory (dir, cancellable, &temp_error))
     {
       if (with_parents &&
           g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
         {
-          gs_unref_object GFile *parent = NULL;
-
           g_clear_error (&temp_error);
 
           parent = g_file_get_parent (dir);
@@ -684,6 +720,7 @@ gs_file_ensure_directory (GFile         *dir,
 
   ret = TRUE;
  out:
+  g_clear_object (&parent);
   return ret;
 }
 
diff --git a/gsystem-shutil.c b/gsystem-shutil.c
index 380acc4..dc62741 100644
--- a/gsystem-shutil.c
+++ b/gsystem-shutil.c
@@ -34,11 +34,91 @@ cp_internal (GFile         *src,
              GFile         *dest,
              gboolean       use_hardlinks,
              GCancellable  *cancellable,
+             GError       **error);
+
+static gboolean
+cp_internal_one_item (GFile         *src,
+                      GFile         *dest,
+                      GFileInfo     *file_info,
+                      gboolean       use_hardlinks,
+                      GCancellable  *cancellable,
+                      GError       **error)
+{
+  gboolean ret = FALSE;
+  const char *name = g_file_info_get_name (file_info);
+  GFile *src_child = g_file_get_child (src, name);
+  GFile *dest_child = g_file_get_child (dest, name);
+
+  if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
+    {
+      if (!gs_file_ensure_directory (dest_child, FALSE, cancellable, error))
+        goto out;
+
+      /* Can't do this even though we'd like to; it fails with an error about
+       * setting standard::type not being supported =/
+       *
+       if (!g_file_set_attributes_from_info (dest_child, file_info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+       cancellable, error))
+       goto out;
+      */
+      if (chmod (gs_file_get_path_cached (dest_child),
+                 g_file_info_get_attribute_uint32 (file_info, "unix::mode")) == -1)
+        {
+          int errsv = errno;
+          g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+                               g_strerror (errsv));
+          goto out;
+        }
+
+      if (!cp_internal (src_child, dest_child, use_hardlinks, cancellable, error))
+        goto out;
+    }
+  else
+    {
+      gboolean did_link = FALSE;
+      (void) unlink (gs_file_get_path_cached (dest_child));
+      if (use_hardlinks)
+        {
+          if (link (gs_file_get_path_cached (src_child), gs_file_get_path_cached (dest_child)) == -1)
+            {
+              if (!(errno == EMLINK || errno == EXDEV))
+                {
+                  int errsv = errno;
+                  g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+                                       g_strerror (errsv));
+                  goto out;
+                }
+              use_hardlinks = FALSE;
+            }
+          else
+            did_link = TRUE;
+        }
+      if (!did_link)
+        {
+          if (!g_file_copy (src_child, dest_child,
+                            G_FILE_COPY_OVERWRITE | G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS,
+                            cancellable, NULL, NULL, error))
+            goto out;
+        }
+    }
+
+  ret = TRUE;
+ out:
+  g_clear_object (&src_child);
+  g_clear_object (&dest_child);
+  return ret;
+}
+
+static gboolean
+cp_internal (GFile         *src,
+             GFile         *dest,
+             gboolean       use_hardlinks,
+             GCancellable  *cancellable,
              GError       **error)
 {
   gboolean ret = FALSE;
-  gs_unref_object GFileEnumerator *enumerator = NULL;
-  gs_unref_object GFileInfo *file_info = NULL;
+  GFileEnumerator *enumerator = NULL;
+  GFileInfo *file_info = NULL;
   GError *temp_error = NULL;
 
   enumerator = g_file_enumerate_children (src, "standard::type,standard::name,unix::mode",
@@ -52,62 +132,9 @@ cp_internal (GFile         *src,
 
   while ((file_info = g_file_enumerator_next_file (enumerator, cancellable, &temp_error)) != NULL)
     {
-      const char *name = g_file_info_get_name (file_info);
-      gs_unref_object GFile *src_child = g_file_get_child (src, name);
-      gs_unref_object GFile *dest_child = g_file_get_child (dest, name);
-
-      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
-        {
-          if (!gs_file_ensure_directory (dest_child, FALSE, cancellable, error))
-            goto out;
-
-          /* Can't do this even though we'd like to; it fails with an error about
-           * setting standard::type not being supported =/
-           *
-           if (!g_file_set_attributes_from_info (dest_child, file_info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-           cancellable, error))
-           goto out;
-          */
-          if (chmod (gs_file_get_path_cached (dest_child),
-                     g_file_info_get_attribute_uint32 (file_info, "unix::mode")) == -1)
-            {
-              int errsv = errno;
-              g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
-                                   g_strerror (errsv));
-              goto out;
-            }
-
-          if (!cp_internal (src_child, dest_child, use_hardlinks, cancellable, error))
-            goto out;
-        }
-      else
-        {
-          gboolean did_link = FALSE;
-          (void) unlink (gs_file_get_path_cached (dest_child));
-          if (use_hardlinks)
-            {
-              if (link (gs_file_get_path_cached (src_child), gs_file_get_path_cached (dest_child)) == -1)
-                {
-                  if (!(errno == EMLINK || errno == EXDEV))
-                    {
-                      int errsv = errno;
-                      g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv),
-                                           g_strerror (errsv));
-                      goto out;
-                    }
-                  use_hardlinks = FALSE;
-                }
-              else
-                did_link = TRUE;
-            }
-          if (!did_link)
-            {
-              if (!g_file_copy (src_child, dest_child,
-                                G_FILE_COPY_OVERWRITE | G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS,
-                                cancellable, NULL, NULL, error))
-                goto out;
-            }
-        }
+      if (!cp_internal_one_item (src, dest, file_info, use_hardlinks,
+                                 cancellable, error))
+        goto out;
       g_clear_object (&file_info);
     }
   if (temp_error)
@@ -118,6 +145,8 @@ cp_internal (GFile         *src,
 
   ret = TRUE;
  out:
+  g_clear_object (&enumerator);
+  g_clear_object (&file_info);
   return ret;
 }
 
@@ -180,8 +209,8 @@ gs_shutil_rm_rf (GFile        *path,
                  GError      **error)
 {
   gboolean ret = FALSE;
-  gs_unref_object GFileEnumerator *dir_enum = NULL;
-  gs_unref_object GFileInfo *file_info = NULL;
+  GFileEnumerator *dir_enum = NULL;
+  GFileInfo *file_info = NULL;
   GError *temp_error = NULL;
 
   dir_enum = g_file_enumerate_children (path, "standard::type,standard::name", 
@@ -209,7 +238,7 @@ gs_shutil_rm_rf (GFile        *path,
 
   while ((file_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL)
     {
-      gs_unref_object GFile *subpath = NULL;
+      GFile *subpath = NULL;
       GFileType type;
       const char *name;
 
@@ -221,12 +250,18 @@ gs_shutil_rm_rf (GFile        *path,
       if (type == G_FILE_TYPE_DIRECTORY)
         {
           if (!gs_shutil_rm_rf (subpath, cancellable, error))
-            goto out;
+            {
+              g_object_unref (subpath);
+              goto out;
+            }
         }
       else
         {
           if (!gs_file_unlink (subpath, cancellable, error))
-            goto out;
+            {
+              g_object_unref (subpath);
+              goto out;
+            }
         }
       g_clear_object (&file_info);
     }
@@ -241,6 +276,8 @@ gs_shutil_rm_rf (GFile        *path,
 
   ret = TRUE;
  out:
+  g_clear_object (&dir_enum);
+  g_clear_object (&file_info);
   return ret;
 }
 
diff --git a/libgsystem.h b/libgsystem.h
index 1102b63..8c45633 100644
--- a/libgsystem.h
+++ b/libgsystem.h
@@ -25,7 +25,6 @@
 
 G_BEGIN_DECLS
 
-#include <gsystem-local-alloc.h>
 #include <gsystem-file-utils.h>
 #include <gsystem-shutil.h>
 #include <gsystem-subprocess.h>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]