Merge remote-tracking branch 'gvdb/master'
[platform/upstream/glib.git] / glib / gfileutils.c
index 13f8627..da6cacd 100644 (file)
@@ -19,8 +19,7 @@
  */
 
 #include "config.h"
-
-#include "glib.h"
+#include "glibconfig.h"
 
 #include <sys/stat.h>
 #ifdef HAVE_UNISTD_H
 #define O_BINARY 0
 #endif
 
+#include "gfileutils.h"
+
 #include "gstdio.h"
 #include "glibintl.h"
 
-#include "galias.h"
-
-static gint create_temp_file (gchar *tmpl, 
-                             int    permissions);
+#ifdef HAVE_LINUX_MAGIC_H /* for btrfs check */
+#include <linux/magic.h>
+#include <sys/vfs.h>
+#endif
 
 /**
  * g_mkdir_with_parents:
@@ -207,19 +208,26 @@ g_file_test (const gchar *filename,
     return TRUE;
       
   if (test & G_FILE_TEST_IS_REGULAR)
-    return (attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0;
+    {
+      if ((attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0)
+       return TRUE;
+    }
 
   if (test & G_FILE_TEST_IS_DIR)
-    return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+    {
+      if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+       return TRUE;
+    }
 
-  if (test & G_FILE_TEST_IS_EXECUTABLE)
+  /* "while" so that we can exit this "loop" with a simple "break" */
+  while (test & G_FILE_TEST_IS_EXECUTABLE)
     {
       const gchar *lastdot = strrchr (filename, '.');
       const gchar *pathext = NULL, *p;
       int extlen;
 
       if (lastdot == NULL)
-       return FALSE;
+        break;
 
       if (_stricmp (lastdot, ".exe") == 0 ||
          _stricmp (lastdot, ".cmd") == 0 ||
@@ -231,7 +239,7 @@ g_file_test (const gchar *filename,
 
       pathext = g_getenv ("PATHEXT");
       if (pathext == NULL)
-       return FALSE;
+        break;
 
       pathext = g_utf8_casefold (pathext, -1);
 
@@ -259,7 +267,7 @@ g_file_test (const gchar *filename,
 
       g_free ((gchar *) pathext);
       g_free ((gchar *) lastdot);
-      return FALSE;
+      break;
     }
 
   return FALSE;
@@ -883,7 +891,7 @@ write_to_temp_file (const gchar  *contents,
   tmp_name = g_strdup_printf ("%s.XXXXXX", dest_file);
 
   errno = 0;
-  fd = create_temp_file (tmp_name, 0666);
+  fd = g_mkstemp_full (tmp_name, O_RDWR | O_BINARY, 0666);
   save_errno = errno;
 
   display_name = g_filename_display_name (tmp_name);
@@ -959,6 +967,20 @@ write_to_temp_file (const gchar  *contents,
       
       goto out;
     }
+
+#ifdef BTRFS_SUPER_MAGIC
+  {
+    struct statfs buf;
+
+    /* On Linux, on btrfs, skip the fsync since rename-over-existing is
+     * guaranteed to be atomic and this is the only case in which we
+     * would fsync() anyway.
+     */
+
+    if (fstatfs (fd, &buf) == 0 && buf.f_type == BTRFS_SUPER_MAGIC)
+      goto no_fsync;
+  }
+#endif
   
 #ifdef HAVE_FSYNC
   {
@@ -990,6 +1012,7 @@ write_to_temp_file (const gchar  *contents,
       }
   }
 #endif
+ no_fsync:
   
   errno = 0;
   if (fclose (file) == EOF)
@@ -1053,6 +1076,9 @@ write_to_temp_file (const gchar  *contents,
  * it returns %FALSE and sets @error. The error domain is #G_FILE_ERROR.
  * Possible error codes are those in the #GFileError enumeration.
  *
+ * Note that the name for the temporary file is constructed by appending up
+ * to 7 characters to @filename.
+ *
  * Return value: %TRUE on success, %FALSE if an error occurred
  *
  * Since: 2.8
@@ -1144,13 +1170,39 @@ g_file_set_contents (const gchar  *filename,
   return retval;
 }
 
+/**
+ * g_mkstemp_full:
+ * @tmpl: template filename
+ * @flags: flags to pass to an open() call in addition to O_EXCL and
+ *         O_CREAT, which are passed automatically
+ * @mode: permissios to create the temporary file with
+ *
+ * Opens a temporary file. See the mkstemp() documentation
+ * on most UNIX-like systems.
+ *
+ * The parameter is a string that should follow the rules for
+ * mkstemp() templates, i.e. contain the string "XXXXXX".
+ * g_mkstemp_full() is slightly more flexible than mkstemp()
+ * in that the sequence does not have to occur at the very end of the
+ * template and you can pass a @mode and additional @flags. The X
+ * string will be modified to form the name of a file that didn't exist.
+ * The string should be in the GLib file name encoding. Most importantly,
+ * on Windows it should be in UTF-8.
+ *
+ * Return value: A file handle (as from open()) to the file
+ *     opened for reading and writing. The file handle should be
+ *     closed with close(). In case of errors, -1 is returned.
+ *
+ * Since: 2.22
+ */
 /*
- * create_temp_file based on the mkstemp implementation from the GNU C library.
+ * g_mkstemp_full based on the mkstemp implementation from the GNU C library.
  * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
  */
-static gint
-create_temp_file (gchar *tmpl, 
-                 int    permissions)
+gint
+g_mkstemp_full (gchar *tmpl, 
+                int    flags,
+               int    mode)
 {
   char *XXXXXX;
   int count, fd;
@@ -1161,6 +1213,9 @@ create_temp_file (gchar *tmpl,
   GTimeVal tv;
   static int counter = 0;
 
+  g_return_val_if_fail (tmpl != NULL, -1);
+
+
   /* find the last occurrence of "XXXXXX" */
   XXXXXX = g_strrstr (tmpl, "XXXXXX");
 
@@ -1192,7 +1247,7 @@ create_temp_file (gchar *tmpl,
       XXXXXX[5] = letters[v % NLETTERS];
 
       /* tmpl is in UTF-8 on Windows, thus use g_open() */
-      fd = g_open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, permissions);
+      fd = g_open (tmpl, flags | O_CREAT | O_EXCL, mode);
 
       if (fd >= 0)
        return fd;
@@ -1232,7 +1287,7 @@ create_temp_file (gchar *tmpl,
 gint
 g_mkstemp (gchar *tmpl)
 {
-  return create_temp_file (tmpl, 0600);
+  return g_mkstemp_full (tmpl, O_RDWR | O_BINARY, 0600);
 }
 
 /**
@@ -1392,8 +1447,7 @@ g_build_path_va (const gchar  *separator,
 
       if (separator_len)
        {
-         while (start &&
-                strncmp (start, separator, separator_len) == 0)
+         while (strncmp (start, separator, separator_len) == 0)
            start += separator_len;
        }
 
@@ -1710,9 +1764,12 @@ g_build_filename (const gchar *first_element,
   return str;
 }
 
-#define KILOBYTE_FACTOR 1024.0
-#define MEGABYTE_FACTOR (1024.0 * 1024.0)
-#define GIGABYTE_FACTOR (1024.0 * 1024.0 * 1024.0)
+#define KILOBYTE_FACTOR (G_GOFFSET_CONSTANT (1024))
+#define MEGABYTE_FACTOR (KILOBYTE_FACTOR * KILOBYTE_FACTOR)
+#define GIGABYTE_FACTOR (MEGABYTE_FACTOR * KILOBYTE_FACTOR)
+#define TERABYTE_FACTOR (GIGABYTE_FACTOR * KILOBYTE_FACTOR)
+#define PETABYTE_FACTOR (TERABYTE_FACTOR * KILOBYTE_FACTOR)
+#define EXABYTE_FACTOR  (PETABYTE_FACTOR * KILOBYTE_FACTOR)
 
 /**
  * g_format_size_for_display:
@@ -1743,19 +1800,34 @@ g_format_size_for_display (goffset size)
       
       if (size < (goffset) MEGABYTE_FACTOR)
        {
-         displayed_size = (gdouble) size / KILOBYTE_FACTOR;
+         displayed_size = (gdouble) size / (gdouble) KILOBYTE_FACTOR;
          return g_strdup_printf (_("%.1f KB"), displayed_size);
        }
       else if (size < (goffset) GIGABYTE_FACTOR)
        {
-         displayed_size = (gdouble) size / MEGABYTE_FACTOR;
+         displayed_size = (gdouble) size / (gdouble) MEGABYTE_FACTOR;
          return g_strdup_printf (_("%.1f MB"), displayed_size);
        }
-      else
+      else if (size < (goffset) TERABYTE_FACTOR)
        {
-         displayed_size = (gdouble) size / GIGABYTE_FACTOR;
+         displayed_size = (gdouble) size / (gdouble) GIGABYTE_FACTOR;
          return g_strdup_printf (_("%.1f GB"), displayed_size);
        }
+      else if (size < (goffset) PETABYTE_FACTOR)
+       {
+         displayed_size = (gdouble) size / (gdouble) TERABYTE_FACTOR;
+         return g_strdup_printf (_("%.1f TB"), displayed_size);
+       }
+      else if (size < (goffset) EXABYTE_FACTOR)
+       {
+         displayed_size = (gdouble) size / (gdouble) PETABYTE_FACTOR;
+         return g_strdup_printf (_("%.1f PB"), displayed_size);
+       }
+      else
+        {
+         displayed_size = (gdouble) size / (gdouble) EXABYTE_FACTOR;
+         return g_strdup_printf (_("%.1f EB"), displayed_size);
+        }
     }
 }
 
@@ -1965,6 +2037,3 @@ g_file_open_tmp (const gchar  *tmpl,
 }
 
 #endif
-
-#define __G_FILEUTILS_C__
-#include "galiasdef.c"