Remove alleged support for last-millennium Unixes
[platform/upstream/glib.git] / glib / gfileutils.c
index 47de1b5..88a647d 100644 (file)
  *     library function.
  * @G_FILE_ERROR_PIPE: Broken pipe; there is no process reading from the
  *     other end of a pipe. Every library function that returns this
- *     error code also generates a `SIGPIPE' signal; this signal
+ *     error code also generates a 'SIGPIPE' signal; this signal
  *     terminates the program if not handled or blocked. Thus, your
  *     program will never actually see this code unless it has handled
- *     or blocked `SIGPIPE'.
+ *     or blocked 'SIGPIPE'.
  * @G_FILE_ERROR_AGAIN: Resource temporarily unavailable; the call might
  *     work if you try again later.
  * @G_FILE_ERROR_INTR: Interrupted function call; an asynchronous signal
@@ -484,150 +484,125 @@ g_file_error_from_errno (gint err_no)
 #ifdef EEXIST
     case EEXIST:
       return G_FILE_ERROR_EXIST;
-      break;
 #endif
 
 #ifdef EISDIR
     case EISDIR:
       return G_FILE_ERROR_ISDIR;
-      break;
 #endif
 
 #ifdef EACCES
     case EACCES:
       return G_FILE_ERROR_ACCES;
-      break;
 #endif
 
 #ifdef ENAMETOOLONG
     case ENAMETOOLONG:
       return G_FILE_ERROR_NAMETOOLONG;
-      break;
 #endif
 
 #ifdef ENOENT
     case ENOENT:
       return G_FILE_ERROR_NOENT;
-      break;
 #endif
 
 #ifdef ENOTDIR
     case ENOTDIR:
       return G_FILE_ERROR_NOTDIR;
-      break;
 #endif
 
 #ifdef ENXIO
     case ENXIO:
       return G_FILE_ERROR_NXIO;
-      break;
 #endif
 
 #ifdef ENODEV
     case ENODEV:
       return G_FILE_ERROR_NODEV;
-      break;
 #endif
 
 #ifdef EROFS
     case EROFS:
       return G_FILE_ERROR_ROFS;
-      break;
 #endif
 
 #ifdef ETXTBSY
     case ETXTBSY:
       return G_FILE_ERROR_TXTBSY;
-      break;
 #endif
 
 #ifdef EFAULT
     case EFAULT:
       return G_FILE_ERROR_FAULT;
-      break;
 #endif
 
 #ifdef ELOOP
     case ELOOP:
       return G_FILE_ERROR_LOOP;
-      break;
 #endif
 
 #ifdef ENOSPC
     case ENOSPC:
       return G_FILE_ERROR_NOSPC;
-      break;
 #endif
 
 #ifdef ENOMEM
     case ENOMEM:
       return G_FILE_ERROR_NOMEM;
-      break;
 #endif
 
 #ifdef EMFILE
     case EMFILE:
       return G_FILE_ERROR_MFILE;
-      break;
 #endif
 
 #ifdef ENFILE
     case ENFILE:
       return G_FILE_ERROR_NFILE;
-      break;
 #endif
 
 #ifdef EBADF
     case EBADF:
       return G_FILE_ERROR_BADF;
-      break;
 #endif
 
 #ifdef EINVAL
     case EINVAL:
       return G_FILE_ERROR_INVAL;
-      break;
 #endif
 
 #ifdef EPIPE
     case EPIPE:
       return G_FILE_ERROR_PIPE;
-      break;
 #endif
 
 #ifdef EAGAIN
     case EAGAIN:
       return G_FILE_ERROR_AGAIN;
-      break;
 #endif
 
 #ifdef EINTR
     case EINTR:
       return G_FILE_ERROR_INTR;
-      break;
 #endif
 
 #ifdef EIO
     case EIO:
       return G_FILE_ERROR_IO;
-      break;
 #endif
 
 #ifdef EPERM
     case EPERM:
       return G_FILE_ERROR_PERM;
-      break;
 #endif
 
 #ifdef ENOSYS
     case ENOSYS:
       return G_FILE_ERROR_NOSYS;
-      break;
 #endif
 
     default:
       return G_FILE_ERROR_FAILED;
-      break;
     }
 }
 
@@ -668,7 +643,7 @@ get_contents_stdio (const gchar  *display_filename,
               g_set_error (error,
                            G_FILE_ERROR,
                            G_FILE_ERROR_NOMEM,
-                           g_dngettext (GETTEXT_PACKAGE, "Could not allocate %ld byte to read file \"%s\"", "Could not allocate %lu bytes to read file \"%s\"", (gulong)total_allocated),
+                           g_dngettext (GETTEXT_PACKAGE, "Could not allocate %lu byte to read file \"%s\"", "Could not allocate %lu bytes to read file \"%s\"", (gulong)total_allocated),
                            (gulong) total_allocated,
                           display_filename);
 
@@ -756,7 +731,7 @@ get_contents_regfile (const gchar  *display_filename,
       g_set_error (error,
                    G_FILE_ERROR,
                    G_FILE_ERROR_NOMEM,
-                           g_dngettext (GETTEXT_PACKAGE, "Could not allocate %ld byte to read file \"%s\"", "Could not allocate %lu bytes to read file \"%s\"", (gulong)alloc_size),
+                           g_dngettext (GETTEXT_PACKAGE, "Could not allocate %lu byte to read file \"%s\"", "Could not allocate %lu bytes to read file \"%s\"", (gulong)alloc_size),
                    (gulong) alloc_size, 
                   display_filename);
 
@@ -1004,6 +979,49 @@ rename_file (const char  *old_name,
   return TRUE;
 }
 
+static char *
+format_error_message (const gchar  *filename,
+                      const gchar  *format_string) G_GNUC_FORMAT(2);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+static char *
+format_error_message (const gchar  *filename,
+                      const gchar  *format_string)
+{
+  gint saved_errno = errno;
+  gchar *display_name;
+  gchar *msg;
+
+  display_name = g_filename_display_name (filename);
+  msg = g_strdup_printf (format_string, display_name, g_strerror (saved_errno));
+  g_free (display_name);
+
+  return msg;
+}
+
+#pragma GCC diagnostic pop
+
+/* format string must have two '%s':
+ *
+ *   - the place for the filename
+ *   - the place for the strerror
+ */
+static void
+set_file_error (GError      **error,
+                const gchar  *filename,
+                const gchar  *format_string)
+                      
+{
+  int saved_errno = errno;
+  char *msg = format_error_message (filename, format_string);
+
+  g_set_error_literal (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
+                       msg);
+  g_free (msg);
+}
+
 static gchar *
 write_to_temp_file (const gchar  *contents,
                    gssize        length,
@@ -1011,93 +1029,53 @@ write_to_temp_file (const gchar  *contents,
                    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", dest_file);
 
   errno = 0;
   fd = g_mkstemp_full (tmp_name, O_RDWR | O_BINARY, 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));
-      
+      set_file_error (err, tmp_name, _("Failed to create file '%s': %s"));
       goto out;
     }
 
-  errno = 0;
-  file = fdopen (fd, "wb");
-  if (!file)
+#ifdef HAVE_FALLOCATE
+  if (length > 0)
     {
-      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;
+      /* We do this on a 'best effort' basis... It may not be supported
+       * on the underlying filesystem.
+       */
+      (void) fallocate (fd, 0, 0, length);
     }
-
-  if (length > 0)
+#endif
+  while (length > 0)
     {
-      gsize n_written;
-      
-      errno = 0;
+      gssize s;
 
-      n_written = fwrite (contents, 1, length, file);
+      s = write (fd, contents, length);
 
-      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));
+      if (s < 0)
+        {
+          if (errno == EINTR)
+            continue;
 
-         fclose (file);
-         g_unlink (tmp_name);
-         
-         goto out;
-       }
-    }
+          set_file_error (err, tmp_name, _("Failed to write file '%s': write() failed: %s"));
+          close (fd);
+          g_unlink (tmp_name);
 
-  errno = 0;
-  if (fflush (file) != 0)
-    { 
-      save_errno = errno;
-      
-      g_set_error (err,
-                  G_FILE_ERROR,
-                  g_file_error_from_errno (save_errno),
-                  _("Failed to write file '%s': fflush() failed: %s"),
-                  display_name, 
-                  g_strerror (save_errno));
+          goto out;
+        }
 
-      fclose (file);
-      g_unlink (tmp_name);
-      
-      goto out;
+      g_assert (s <= length);
+
+      contents += s;
+      length -= s;
     }
 
 #ifdef BTRFS_SUPER_MAGIC
@@ -1113,7 +1091,7 @@ write_to_temp_file (const gchar  *contents,
       goto no_fsync;
   }
 #endif
-  
+
 #ifdef HAVE_FSYNC
   {
     struct stat statbuf;
@@ -1125,23 +1103,13 @@ write_to_temp_file (const gchar  *contents,
      * the new and the old file on some filesystems. (I.E. those that don't
      * guarantee the data is written to the disk before the metadata.)
      */
-    if (g_lstat (dest_file, &statbuf) == 0 &&
-       statbuf.st_size > 0 &&
-       fsync (fileno (file)) != 0)
+    if (g_lstat (dest_file, &statbuf) == 0 && statbuf.st_size > 0 && fsync (fd) != 0)
       {
-       save_errno = errno;
-
-       g_set_error (err,
-                    G_FILE_ERROR,
-                    g_file_error_from_errno (save_errno),
-                    _("Failed to write file '%s': fsync() failed: %s"),
-                    display_name,
-                    g_strerror (save_errno));
+        set_file_error (err, tmp_name, _("Failed to write file '%s': fsync() failed: %s"));
+        close (fd);
+        g_unlink (tmp_name);
 
-        fclose (file);
-       g_unlink (tmp_name);
-
-       goto out;
+        goto out;
       }
   }
 #endif
@@ -1149,30 +1117,20 @@ write_to_temp_file (const gchar  *contents,
 #ifdef BTRFS_SUPER_MAGIC
  no_fsync:
 #endif
-  
-  errno = 0;
-  if (fclose (file) == EOF)
-    { 
-      save_errno = errno;
-      
-      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));
 
+  errno = 0;
+  if (!g_close (fd, err))
+    {
       g_unlink (tmp_name);
-      
+
       goto out;
     }
 
   retval = g_strdup (tmp_name);
-  
+
  out:
   g_free (tmp_name);
-  g_free (display_name);
-  
+
   return retval;
 }
 
@@ -2519,10 +2477,7 @@ g_get_current_dir (void)
   if (max_len == 0)
     max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
 
-  /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
-   * and, if that wasn't bad enough, hangs in doing so.
-   */
-#if (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
+#if !defined(HAVE_GETCWD)
   buffer = g_new (gchar, max_len + 1);
   *buffer = 0;
   dir = getwd (buffer);