[ostree] gioutils: Many new utility functions



commit e3dc0c91dfeb9fc956ca6b0e5b932d865946b210
Author: Colin Walters <walters verbum org>
Date:   Sat Jun 29 11:43:31 2013 -0400

    gioutils: Many new utility functions
    
    Reading symbolic links becomes a much more common thing now.

 src/libotutil/ot-gio-utils.c |  207 ++++++++++++++++++++++++++++++++++++++++++
 src/libotutil/ot-gio-utils.h |   37 ++++++++
 2 files changed, 244 insertions(+), 0 deletions(-)
---
diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c
index d37beeb..49d1a51 100644
--- a/src/libotutil/ot-gio-utils.c
+++ b/src/libotutil/ot-gio-utils.c
@@ -132,3 +132,210 @@ ot_gfile_get_child_build_path (GFile      *parent,
 
   return g_file_resolve_relative_path (parent, path);
 }
+
+GFile *
+ot_gfile_resolve_path_printf (GFile       *path,
+                              const char  *format,
+                              ...)
+{
+  va_list args;
+  gs_free char *relpath = NULL;
+
+  va_start (args, format);
+  relpath = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  return g_file_resolve_relative_path (path, relpath);
+}
+
+
+gboolean
+ot_gfile_get_symlink_target_from_info (GFile             *path,
+                                       GFileInfo         *file_info,
+                                       GFile            **out_target,
+                                       GCancellable      *cancellable,
+                                       GError           **error)
+{
+  gboolean ret = FALSE;
+  const char *target;
+  gs_unref_object GFile *path_parent = NULL;
+  gs_unref_object GFile *ret_target = NULL;
+
+  if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_SYMBOLIC_LINK)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Not a symbolic link");
+      goto out;
+    }
+
+  path_parent = g_file_get_parent (path);
+  target = g_file_info_get_symlink_target (file_info);
+  g_assert (target);
+  ret_target = g_file_resolve_relative_path (path_parent, target);
+
+  ret = TRUE;
+ out:
+  ot_transfer_out_value (out_target, &ret_target);
+  return ret;
+}
+
+gboolean
+ot_gfile_query_info_allow_noent (GFile                *path,
+                                 const char           *queryopts,
+                                 GFileQueryInfoFlags   flags,
+                                 GFileInfo           **out_info,
+                                 GCancellable         *cancellable,
+                                 GError              **error)
+{
+  gboolean ret = FALSE;
+  gs_unref_object GFileInfo *ret_file_info = NULL;
+  GError *temp_error = NULL;
+
+  ret_file_info = g_file_query_info (path, queryopts, flags,
+                                     cancellable, &temp_error);
+  if (!ret_file_info)
+    {
+      if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+        {
+          g_clear_error (&temp_error);
+        }
+      else
+        {
+          g_propagate_error (error, temp_error);
+          goto out;
+        }
+    }
+
+  ret = TRUE;
+  ot_transfer_out_value (out_info, &ret_file_info);
+ out:
+  return ret;
+}
+
+gboolean
+ot_gfile_query_symlink_target_allow_noent (GFile          *path,
+                                           GFile         **out_target,
+                                           GCancellable   *cancellable,
+                                           GError        **error)
+{
+  gboolean ret = FALSE;
+  gs_unref_object GFileInfo *file_info = NULL;
+  gs_unref_object GFile *ret_target = NULL;
+
+  if (!ot_gfile_query_info_allow_noent (path, OSTREE_GIO_FAST_QUERYINFO,
+                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                        &file_info,
+                                        cancellable, error))
+    goto out;
+
+  if (file_info != NULL)
+    {
+      if (!ot_gfile_get_symlink_target_from_info (path, file_info, &ret_target,
+                                                  cancellable, error))
+        goto out;
+    }
+  
+  ret = TRUE;
+  ot_transfer_out_value (out_target, &ret_target);
+ out:
+  return ret;
+}
+
+gboolean
+ot_gfile_load_contents_utf8_allow_noent (GFile          *path,
+                                         char          **out_contents,
+                                         GCancellable   *cancellable,
+                                         GError        **error)
+{
+  gboolean ret = TRUE;
+  GError *temp_error = NULL;
+  gs_free char *ret_contents = NULL;
+
+  ret_contents = gs_file_load_contents_utf8 (path, cancellable, &temp_error);
+  if (!ret_contents)
+    {
+      if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+        {
+          g_clear_error (&temp_error);
+        }
+      else
+        {
+          g_propagate_error (error, temp_error);
+          goto out;
+        }
+    }
+
+  ret = TRUE;
+  ot_transfer_out_value (out_contents, &ret_contents);
+ out:
+  return ret;
+}
+
+/**
+ * ot_gfile_ensure_unlinked:
+ *
+ * Like gs_file_unlink(), but return successfully if the file doesn't
+ * exist.
+ */
+gboolean
+ot_gfile_ensure_unlinked (GFile         *path,
+                          GCancellable  *cancellable,
+                          GError       **error)
+{
+  gboolean ret = FALSE;
+  GError *temp_error = NULL;
+
+  if (!gs_file_unlink (path, cancellable, &temp_error))
+    {
+      if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+        {
+          g_clear_error (&temp_error);
+        }
+      else
+        {
+          g_propagate_error (error, temp_error);
+          goto out;
+        }
+    }
+  
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+/**
+ * ot_gfile_atomic_symlink_swap:
+ * @path: Replace the contents of this symbolic link
+ * @target: New symbolic link target
+ * @cancellable:
+ * @error
+ *
+ * Create a new temporary symbolic link, then use the Unix rename()
+ * function to atomically replace @path with the new symbolic link.
+ * Do not use this function inside directories such as /tmp as it uses
+ * a predicatable file name.
+ */
+gboolean
+ot_gfile_atomic_symlink_swap (GFile          *path,
+                              const char     *target,
+                              GCancellable   *cancellable,
+                              GError        **error)
+{
+  gboolean ret = FALSE;
+  gs_unref_object GFile *parent = g_file_get_parent (path);
+  gs_free char *tmpname = g_strconcat (gs_file_get_basename_cached (path), ".tmp", NULL);
+  gs_unref_object GFile *tmppath = g_file_get_child (parent, tmpname);
+
+  if (!ot_gfile_ensure_unlinked (tmppath, cancellable, error))
+    goto out;
+  
+  if (!g_file_make_symbolic_link (tmppath, target, cancellable, error))
+    goto out;
+
+  if (!gs_file_rename (tmppath, path, cancellable, error))
+    goto out;
+
+  ret = TRUE;
+ out:
+  return ret;
+}
diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h
index 802602d..5ebf04a 100644
--- a/src/libotutil/ot-gio-utils.h
+++ b/src/libotutil/ot-gio-utils.h
@@ -42,6 +42,43 @@ GFile *ot_gfile_get_child_strconcat (GFile *parent, const char *first, ...) G_GN
 
 GFile *ot_gfile_get_child_build_path (GFile *parent, const char *first, ...) G_GNUC_NULL_TERMINATED;
 
+GFile * ot_gfile_resolve_path_printf (GFile       *path,
+                                      const char  *format,
+                                      ...) G_GNUC_PRINTF(2, 3);
+
+
+gboolean ot_gfile_get_symlink_target_from_info (GFile             *path,
+                                                GFileInfo         *file_info,
+                                                GFile            **out_target,
+                                                GCancellable      *cancellable,
+                                                GError           **error);
+
+gboolean ot_gfile_query_info_allow_noent (GFile                *path,
+                                          const char           *queryopts,
+                                          GFileQueryInfoFlags   flags,
+                                          GFileInfo           **out_info,
+                                          GCancellable         *cancellable,
+                                          GError              **error);
+  
+gboolean ot_gfile_query_symlink_target_allow_noent (GFile          *path,
+                                                    GFile         **out_target,
+                                                    GCancellable   *cancellable,
+                                                    GError        **error);
+
+gboolean ot_gfile_load_contents_utf8_allow_noent (GFile          *path,
+                                                  char          **out_contents,
+                                                  GCancellable   *cancellable,
+                                                  GError        **error);
+
+gboolean ot_gfile_ensure_unlinked (GFile         *path,
+                                   GCancellable  *cancellable,
+                                   GError       **error);
+
+gboolean ot_gfile_atomic_symlink_swap (GFile          *path,
+                                       const char     *target,
+                                       GCancellable   *cancellable,
+                                       GError        **error);
+
 G_END_DECLS
 
 #endif


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