[Telepathy-commits] [telepathy-mission-control/master] Take g_file_set_contents code from GLib

Alberto Mardegan alberto.mardegan at nokia.com
Mon Mar 16 02:44:33 PDT 2009


We'll need to sync the temporary file.
---
 src/mcd-misc.c |  244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/mcd-misc.h |    4 +
 2 files changed, 248 insertions(+), 0 deletions(-)

diff --git a/src/mcd-misc.c b/src/mcd-misc.c
index 356e1f5..153160e 100644
--- a/src/mcd-misc.c
+++ b/src/mcd-misc.c
@@ -24,6 +24,13 @@
  */
 
 #include "mcd-misc.h"
+#include <errno.h>
+#define __USE_POSIX
+#include <glib/gstdio.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
 #include <telepathy-glib/errors.h>
 #include <telepathy-glib/util.h>
 #include <libmcclient/mc-errors.h>
@@ -229,3 +236,240 @@ mcd_object_ready (gpointer object, GQuark quark, const GError *error)
     g_object_set_qdata ((GObject *)object, quark, NULL);
 }
 
+
+static gint
+create_temp_file (gchar *tmpl, 
+		  int    permissions)
+{
+  char *XXXXXX;
+  int count, fd;
+  static const char letters[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+  static const int NLETTERS = sizeof (letters) - 1;
+  glong value;
+  GTimeVal tv;
+  static int counter = 0;
+
+  /* find the last occurrence of "XXXXXX" */
+  XXXXXX = g_strrstr (tmpl, "XXXXXX");
+
+  if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  /* Get some more or less random data.  */
+  g_get_current_time (&tv);
+  value = (tv.tv_usec ^ tv.tv_sec) + counter++;
+
+  for (count = 0; count < 100; value += 7777, ++count)
+    {
+      glong v = value;
+
+      /* Fill in the random bits.  */
+      XXXXXX[0] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[1] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[2] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[3] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[4] = letters[v % NLETTERS];
+      v /= NLETTERS;
+      XXXXXX[5] = letters[v % NLETTERS];
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+      /* tmpl is in UTF-8 on Windows, thus use g_open() */
+      fd = g_open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, permissions);
+
+      if (fd >= 0)
+	return fd;
+      else if (errno != EEXIST)
+	/* Any other error will apply also to other names we might
+	 *  try, and there are 2^32 or so of them, so give up now.
+	 */
+	return -1;
+    }
+
+  /* We got out of the loop because we ran out of combinations to try.  */
+  errno = EEXIST;
+  return -1;
+}
+
+static gboolean
+rename_file (const char *old_name,
+	     const char *new_name,
+	     GError **err)
+{
+  errno = 0;
+  if (g_rename (old_name, new_name) == -1)
+    {
+      int save_errno = errno;
+      gchar *display_old_name = g_filename_display_name (old_name);
+      gchar *display_new_name = g_filename_display_name (new_name);
+
+      g_set_error (err,
+		   G_FILE_ERROR,
+		   g_file_error_from_errno (save_errno),
+		   "Failed to rename file '%s' to '%s': g_rename() failed: %s",
+		   display_old_name,
+		   display_new_name,
+		   g_strerror (save_errno));
+
+      g_free (display_old_name);
+      g_free (display_new_name);
+      
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+static gchar *
+write_to_temp_file (const gchar *contents,
+		    gssize length,
+		    const gchar *template,
+		    GError **err)
+{
+  gchar *tmp_name;
+  gchar *display_name;
+  gchar *retval;
+  FILE *file;
+  gint fd;
+  int save_errno;
+
+  retval = NULL;
+  
+  tmp_name = g_strdup_printf ("%s.XXXXXX", template);
+
+  errno = 0;
+  fd = create_temp_file (tmp_name, 0666);
+  save_errno = errno;
+
+  display_name = g_filename_display_name (tmp_name);
+      
+  if (fd == -1)
+    {
+      g_set_error (err,
+		   G_FILE_ERROR,
+		   g_file_error_from_errno (save_errno),
+		   "Failed to create file '%s': %s",
+		   display_name, g_strerror (save_errno));
+      
+      goto out;
+    }
+
+  errno = 0;
+  file = fdopen (fd, "wb");
+  if (!file)
+    {
+      save_errno = errno;
+      g_set_error (err,
+		   G_FILE_ERROR,
+		   g_file_error_from_errno (save_errno),
+		   "Failed to open file '%s' for writing: fdopen() failed: %s",
+		   display_name,
+		   g_strerror (save_errno));
+
+      close (fd);
+      g_unlink (tmp_name);
+      
+      goto out;
+    }
+
+  if (length > 0)
+    {
+      gsize n_written;
+      
+      errno = 0;
+
+      n_written = fwrite (contents, 1, length, file);
+
+      if (n_written < length)
+	{
+	  save_errno = errno;
+      
+ 	  g_set_error (err,
+		       G_FILE_ERROR,
+		       g_file_error_from_errno (save_errno),
+		       "Failed to write file '%s': fwrite() failed: %s",
+		       display_name,
+		       g_strerror (save_errno));
+
+	  fclose (file);
+	  g_unlink (tmp_name);
+	  
+	  goto out;
+	}
+    }
+   
+  errno = 0;
+  if (fclose (file) == EOF)
+    { 
+      save_errno = 0;
+      
+      g_set_error (err,
+		   G_FILE_ERROR,
+		   g_file_error_from_errno (save_errno),
+		   "Failed to close file '%s': fclose() failed: %s",
+		   display_name, 
+		   g_strerror (save_errno));
+
+      g_unlink (tmp_name);
+      
+      goto out;
+    }
+
+  retval = g_strdup (tmp_name);
+  
+ out:
+  g_free (tmp_name);
+  g_free (display_name);
+  
+  return retval;
+}
+
+gboolean
+_mcd_file_set_contents (const gchar *filename, const gchar *contents,
+                        gssize length, GError **error)
+{
+    gchar *tmp_filename;
+    gboolean retval;
+    GError *rename_error = NULL;
+
+    g_return_val_if_fail (filename != NULL, FALSE);
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+    g_return_val_if_fail (contents != NULL || length == 0, FALSE);
+    g_return_val_if_fail (length >= -1, FALSE);
+
+    if (length == -1)
+        length = strlen (contents);
+
+    tmp_filename = write_to_temp_file (contents, length, filename, error);
+
+    if (!tmp_filename)
+    {
+        retval = FALSE;
+        goto out;
+    }
+
+    if (!rename_file (tmp_filename, filename, &rename_error))
+    {
+        g_unlink (tmp_filename);
+        g_propagate_error (error, rename_error);
+        retval = FALSE;
+        goto out;
+    }
+
+    retval = TRUE;
+
+out:
+    g_free (tmp_filename);
+    return retval;
+}
+
diff --git a/src/mcd-misc.h b/src/mcd-misc.h
index 4f261f4..281bad5 100644
--- a/src/mcd-misc.h
+++ b/src/mcd-misc.h
@@ -57,5 +57,9 @@ void mcd_object_ready (gpointer object, GQuark quark, const GError *error);
 G_GNUC_INTERNAL
 GType _mcd_type_dbus_ao (void);
 
+G_GNUC_INTERNAL
+gboolean _mcd_file_set_contents (const gchar *filename, const gchar *contents,
+                                 gssize length, GError **error);
+
 G_END_DECLS
 #endif /* MCD_MISC_H */
-- 
1.5.6.5




More information about the telepathy-commits mailing list