]> www.fi.muni.cz Git - evince.git/commitdiff
libdocument: Clean up temp file handling
authorChristian Persch <chpe@gnome.org>
Sun, 25 Oct 2009 15:04:20 +0000 (16:04 +0100)
committerChristian Persch <chpe@gnome.org>
Sun, 25 Oct 2009 18:38:22 +0000 (19:38 +0100)
t push origin HEAD:master
Make sure we can cope with not being able to create our temp directory.
Bug #595372.

backend/comics/comics-document.c
libdocument/ev-attachment.c
libdocument/ev-file-helpers.c
libdocument/ev-file-helpers.h
libdocument/ev-image.c
libview/ev-jobs.c
shell/ev-application.c
shell/ev-sidebar-attachments.c
shell/ev-window.c

index fbe6ba01c99c047ba52a70958fe02b976868d8e2..b53d513d0de6685a950e56e33ba7261445df5c8f 100644 (file)
@@ -205,32 +205,20 @@ comics_generate_command_lines (ComicsDocument *comics_document,
        comics_document->regex_arg = command_usage_def[type].regex_arg;
        comics_document->offset = command_usage_def[type].offset;
        if (command_usage_def[type].decompress_tmp) {
-               comics_document->dir = ev_tmp_directory (NULL); 
-               comics_document->decompress_tmp = 
+               comics_document->dir = ev_mkdtemp ("comics.XXXXXX", error);
+                if (comics_document->dir == NULL)
+                        return FALSE;
+
+               /* unrar-free can't create directories, but ev_mkdtemp already created the dir */
+
+               comics_document->decompress_tmp =
                        g_strdup_printf (command_usage_def[type].decompress_tmp, 
                                         comics_document->selected_command, 
                                         quoted_file, 
                                         comics_document->dir);
                g_free (quoted_file);
-               /* unrar-free can't create directories so we do it on its 
-                * behalf */
-               if (type == GNAUNRAR) {
-                       if (g_mkdir_with_parents (comics_document->dir, 0700) != 
-                           0) {
-                               int errsv = errno;
-                               g_set_error (error,
-                                            EV_DOCUMENT_ERROR,
-                                            EV_DOCUMENT_ERROR_INVALID,
-                                            _("Failed to create a temporary "
-                                            "directory."));
-                               g_warning ("Failed to create directory %s: %s", 
-                                          comics_document->dir, 
-                                          g_strerror (errsv));
-                               
-                               return FALSE;
-                       }
-               }
-               if (!comics_decompress_temp_dir (comics_document->decompress_tmp, 
+
+               if (!comics_decompress_temp_dir (comics_document->decompress_tmp,
                    comics_document->selected_command, error))
                        return FALSE;
                else
@@ -713,7 +701,6 @@ comics_document_finalize (GObject *object)
                        g_warning (_("There was an error deleting “%s”."),
                                   comics_document->dir);
                g_free (comics_document->dir);
-               g_remove (ev_tmp_dir ());
        }
        
        if (comics_document->page_names) {
index c1d13333bc882b63154c9b830c52a051314d55ec..c4dd38d7addb4937a074ec070d96034e3838864f 100644 (file)
@@ -101,7 +101,7 @@ ev_attachment_finalize (GObject *object)
                attachment->priv->tmp_file = NULL;
        }
 
-       (* G_OBJECT_CLASS (ev_attachment_parent_class)->finalize) (object);
+       G_OBJECT_CLASS (ev_attachment_parent_class)->finalize (object);
 }
 
 static void
@@ -411,18 +411,19 @@ ev_attachment_open (EvAttachment *attachment,
                return FALSE;
        }
 
-       if (attachment->priv->tmp_file &&
-           g_file_query_exists (attachment->priv->tmp_file, NULL)) {
+       if (attachment->priv->tmp_file) {
                retval = ev_attachment_launch_app (attachment, screen,
                                                   timestamp, error);
        } else {
-               GFile *tmpdir;
+                char *template;
                GFile *file;
-               
-               tmpdir = g_file_new_for_path (ev_tmp_dir ());
-               file = g_file_get_child (tmpdir, attachment->priv->name);
 
-               if (ev_attachment_save (attachment, file, error)) {
+                /* FIXMEchpe: convert to filename encoding first! */
+                template = g_strdup_printf ("%s.XXXXXX", ev_attachment_get_name (attachment));
+                file = ev_mkstemp_file (template, error);
+                g_free (template);
+
+               if (file != NULL && ev_attachment_save (attachment, file, error)) {
                        if (attachment->priv->tmp_file)
                                g_object_unref (attachment->priv->tmp_file);
                        attachment->priv->tmp_file = g_object_ref (file);
@@ -432,7 +433,6 @@ ev_attachment_open (EvAttachment *attachment,
                }
 
                g_object_unref (file);
-               g_object_unref (tmpdir);
        }
 
        return retval;
index 3da4a59832d5031bedac8c19a00c3ef62fc4686b..4816db0e51edaca16ee4d0e6ef36c65ba69557b3 100644 (file)
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 2002 Jorn Baayen
+ *  Copyright © 2009 Christian Persch
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *  $Id$
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <config.h>
 
 #include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
+
 #include <glib.h>
 #include <glib/gstdio.h>
-#include <errno.h>
+#include <glib/gi18n-lib.h>
 
 #include "ev-file-helpers.h"
 
 static gchar *tmp_dir = NULL;
-static gint   count = 0;
 
+/**
+ * ev_dir_ensure_exists:
+ * @dir: the directory name
+ * @mode: permissions to use when creating the directory
+ * @error: a location to store a #GError
+ *
+ * Create @dir recursively with permissions @mode.
+ *
+ * Returns: %TRUE on success, or %FALSE on error with @error filled in
+ */
 gboolean
 ev_dir_ensure_exists (const gchar *dir,
-                      int          mode)
+                      int          mode,
+                      GError     **error)
 {
+        int errsv;
+        char *display_name;
+
+        g_return_val_if_fail (dir != NULL, FALSE);
+
+        errno = 0;
        if (g_mkdir_with_parents (dir, mode) == 0)
                return TRUE;
 
-       if (errno == EEXIST)
-               return g_file_test (dir, G_FILE_TEST_IS_DIR);
-       
-       g_warning ("Failed to create directory %s: %s", dir, g_strerror (errno));
+        errsv = errno;
+       if (errsv == EEXIST && g_file_test (dir, G_FILE_TEST_IS_DIR))
+                return TRUE;
+
+        display_name = g_filename_display_name (dir);
+        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+                     "Failed to create directory '%s': %s",
+                     display_name, g_strerror (errsv));
+        g_free (display_name);
+
        return FALSE;
 }
 
-const gchar *
-ev_tmp_dir (void)
+/*
+ * _ev_tmp_dir:
+ * @error: a location to store a #GError
+ *
+ * Returns the tmp directory.
+ *
+ * Returns: the tmp directory, or %NULL with @error filled in if the
+ *   directory could not be created
+ */
+const char *
+_ev_tmp_dir (GError **error)
 {
-       if (tmp_dir == NULL) {
-               gboolean exists;
-               gchar   *dirname, *prgname;
+
+        if (tmp_dir == NULL) {
+                gchar *dirname, *prgname;
 
                 prgname = g_get_prgname ();
-               dirname = g_strdup_printf ("%s-%u", prgname ? prgname : "unknown", getpid ());
-               tmp_dir = g_build_filename (g_get_tmp_dir (),
-                                           dirname,
-                                           NULL);
-               g_free (dirname);
-
-               exists = ev_dir_ensure_exists (tmp_dir, 0700);
-               g_assert (exists);
-       }
+                dirname = g_strdup_printf ("%s-%u", prgname ? prgname : "unknown", getpid ());
+                tmp_dir = g_build_filename (g_get_tmp_dir (), dirname, NULL);
+                g_free (dirname);
+        }
+
+        if (!ev_dir_ensure_exists (tmp_dir, 0700, error))
+                return NULL;
 
        return tmp_dir;
 }
@@ -85,47 +113,121 @@ _ev_file_helpers_shutdown (void)
        tmp_dir = NULL;
 }
 
-GFile *
-ev_tmp_file_get (const gchar *prefix)
+/**
+ * ev_mkstemp:
+ * @template: a template string; must contain 'XXXXXX', but not necessarily as a suffix
+ * @file_name: a location to store the filename of the temp file
+ * @error: a location to store a #GError
+ *
+ * Creates a temp file in the evince temp directory.
+ *
+ * Returns: a file descriptor to the newly created temp file name, or %-1
+ *   on error with @error filled in
+ */
+int
+ev_mkstemp (const char  *template,
+            char       **file_name,
+            GError     **error)
 {
-       gchar *path;
-       GFile *file;
+        const char *tmp;
+        char *name;
+        int fd;
 
-       path = ev_tmp_filename (prefix);
-       file = g_file_new_for_path (path);
-       
-       g_free (path);
-       
-       return file;
+        if ((tmp = _ev_tmp_dir (error)) == NULL)
+              return -1;
+
+        name = g_build_filename (tmp, template, NULL);
+        fd = g_mkstemp (name);
+
+        if (fd == -1) {
+               int errsv = errno;
+
+                g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+                             _("Failed to create a temporary file: %s"),
+                             g_strerror (errsv));
+
+                g_free (name);
+                return -1;
+        }
+
+        if (file_name)
+                *file_name = name;
+
+        return fd;
 }
 
-gchar * 
-ev_tmp_filename (const gchar *prefix)
+static void
+close_fd_cb (gpointer fdptr)
 {
-       gchar *basename;
-       gchar *filename = NULL;
-
-       do {
-               if (filename != NULL)
-                       g_free (filename);
-                       
-               basename = g_strdup_printf ("%s-%d",
-                                           prefix ? prefix : "document",
-                                           count ++);
-               
-               filename = g_build_filename (ev_tmp_dir (),
-                                            basename, NULL);
-               
-               g_free (basename);
-       } while (g_file_test (filename, G_FILE_TEST_EXISTS));
-                       
-       return filename;
+        int fd = GPOINTER_TO_INT (fdptr);
+
+        close (fd);
+}
+
+/**
+ * ev_mkstemp_file:
+ * @template: a template string; must contain 'XXXXXX', but not necessarily as a suffix
+ * @error: a location to store a #GError
+ *
+ * Creates a temp #GFile in the evince temp directory. See ev_mkstemp() for more information.
+ *
+ * Returns: a newly allocated #GFile for the newly created temp file name, or %NULL
+ *   on error with @error filled in
+ */
+GFile *
+ev_mkstemp_file (const char        *template,
+                 GError           **error)
+{
+        char *file_name;
+        int fd;
+        GFile *file;
+
+        fd = ev_mkstemp (template, &file_name, error);
+        if (fd == -1)
+                return NULL;
+
+        file = g_file_new_for_path (file_name);
+        g_free (file_name);
+
+        g_object_set_data_full (G_OBJECT (file), "ev-mkstemp-fd",
+                                GINT_TO_POINTER (fd), (GDestroyNotify) close_fd_cb);
+
+        return file;
 }
 
-gchar * 
-ev_tmp_directory (const gchar *prefix) 
+/**
+ * ev_mkdtemp:
+ * @template: a template string; must end in 'XXXXXX'
+ * @error: a location to store a #GError
+ *
+ * Creates a temp directory in the evince temp directory.
+ *
+ * Returns: a newly allocated string with the temp directory name, or %NULL
+ *   on error with @error filled in
+ */
+gchar *
+ev_mkdtemp (const char        *template,
+            GError           **error)
 {
-       return ev_tmp_filename (prefix ? prefix : "directory");
+        const char *tmp;
+        char *name;
+
+        if ((tmp = _ev_tmp_dir (error)) == NULL)
+              return NULL;
+
+        name = g_build_filename (tmp, template, NULL);
+        if (mkdtemp (name) == NULL) {
+               int errsv = errno;
+
+                g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+                             _("Failed to create a temporary directory: %s"),
+                             g_strerror (errsv));
+
+                g_free (name);
+                return NULL;
+        }
+
+        return name;
 }
 
 /* Remove a local temp file created by evince */
@@ -138,7 +240,7 @@ ev_tmp_filename_unlink (const gchar *filename)
                return;
 
        tempdir = g_get_tmp_dir ();
-       if (g_ascii_strncasecmp (filename, tempdir, strlen (tempdir)) == 0) {
+       if (g_str_has_prefix (filename, tempdir) == 0) {
                g_unlink (filename);
        }
 }
@@ -326,7 +428,7 @@ compression_run (const gchar       *uri,
 {
        gchar *argv[N_ARGS];
        gchar *uri_dst = NULL;
-       gchar *filename, *filename_dst;
+       gchar *filename, *filename_dst = NULL;
        gchar *cmd;
        gint   fd, pout;
        GError *err = NULL;
@@ -349,20 +451,12 @@ compression_run (const gchar       *uri,
                g_free (cmd);
                return NULL;
        }
-       
-       filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
-       fd = g_mkstemp (filename_dst);
-       if (fd < 0) {
-               int errsv = errno;
 
+        fd = ev_mkstemp ("comp.XXXXXX", &filename_dst, error);
+       if (fd == -1) {
                g_free (cmd);
                g_free (filename);
-               g_free (filename_dst);
 
-               g_set_error (error, G_IO_ERROR,
-                            g_io_error_from_errno (errsv),
-                            "Error creating a temporary file: %s",
-                            g_strerror (errsv));
                return NULL;
        }
 
index 47a5417149f915b25abde991052a30fe3a448e89..99df4ed48e22054b4d6804ae930ad0813dc5774a 100644 (file)
@@ -36,18 +36,23 @@ typedef enum {
        EV_COMPRESSION_GZIP
 } EvCompressionType;
 
-const gchar *ev_tmp_dir               (void);
+const char *_ev_tmp_dir               (GError **error);
 
 void        _ev_file_helpers_init     (void);
 
 void        _ev_file_helpers_shutdown (void);
 
 gboolean     ev_dir_ensure_exists     (const gchar       *dir,
-                                       int                mode);
-
-GFile       *ev_tmp_file_get          (const gchar       *prefix);
-gchar       *ev_tmp_filename          (const char        *prefix);
-gchar       *ev_tmp_directory         (const char        *prefix);
+                                       int                mode,
+                                       GError           **error);
+
+int          ev_mkstemp               (const char        *template,
+                                       char             **file_name,
+                                       GError           **error);
+GFile       *ev_mkstemp_file          (const char        *template,
+                                       GError           **error);
+gchar       *ev_mkdtemp               (const char        *template,
+                                       GError           **error);
 void         ev_tmp_filename_unlink   (const gchar       *filename);
 void         ev_tmp_file_unlink       (GFile             *file);
 void         ev_tmp_uri_unlink        (const gchar       *uri);
index 4fa22253def1468b6e5fa9eef101a57d006e8eb7..572b1195263fa1b014b4f32d1696e2818621a3ec 100644 (file)
  */
 
 #include <config.h>
+
 #include <glib/gstdio.h>
+#include <unistd.h>
+
 #include "ev-document-misc.h"
 #include "ev-file-helpers.h"
 #include "ev-image.h"
@@ -132,7 +135,8 @@ ev_image_save_tmp (EvImage   *image,
                   GdkPixbuf *pixbuf)
 {
        GError *error = NULL;
-       gchar  *filename;
+       gchar  *filename = NULL;
+        int fd;
        
        g_return_val_if_fail (EV_IS_IMAGE (image), NULL);
        g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
@@ -140,19 +144,28 @@ ev_image_save_tmp (EvImage   *image,
        if (image->priv->tmp_uri)
                return image->priv->tmp_uri;
 
-       filename = ev_tmp_filename ("image");
+        if ((fd = ev_mkstemp ("image.XXXXXX", &filename, &error)) == -1)
+                goto had_error;
+
        gdk_pixbuf_save (pixbuf, filename,
                         "png", &error,
                         "compression", "3", NULL);
+        close (fd);
+
        if (!error) {
-               image->priv->tmp_uri = g_filename_to_uri (filename, NULL, NULL);
+               image->priv->tmp_uri = g_filename_to_uri (filename, NULL, &error);
+                if (image->priv->tmp_uri == NULL)
+                        goto had_error;
+
                g_free (filename);
                
                return image->priv->tmp_uri;
        }
 
+    had_error:
+
        /* Erro saving image */
-       g_warning ("%s", error->message);
+       g_warning ("Error saving image: %s", error->message);
        g_error_free (error);
        g_free (filename);
 
@@ -166,6 +179,3 @@ ev_image_get_tmp_uri (EvImage *image)
 
        return image->priv->tmp_uri;
 }
-
-
-
index c0aa0b482d5347aa4a63a361ec98c4088caf06fc..a0866d508b0ec31d7ef8aed7312b3ae56677ad7f 100644 (file)
@@ -936,31 +936,17 @@ ev_job_save_run (EvJob *job)
 {
        EvJobSave *job_save = EV_JOB_SAVE (job);
        gint       fd;
-       gchar     *filename;
-       gchar     *tmp_filename;
+       gchar     *tmp_filename = NULL;
        gchar     *local_uri;
        GError    *error = NULL;
        
        ev_debug_message (DEBUG_JOBS, "uri: %s, document_uri: %s", job_save->uri, job_save->document_uri);
        ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
-       
-       filename = ev_tmp_filename ("saveacopy");
-       tmp_filename = g_strdup_printf ("%s.XXXXXX", filename);
-       g_free (filename);
-
-       fd = g_mkstemp (tmp_filename);
-       if (fd == -1) {
-               gchar *display_name;
-               gint   save_errno = errno;
 
-               display_name = g_filename_display_name (tmp_filename);
-               ev_job_failed (job,
-                              G_FILE_ERROR,
-                              g_file_error_from_errno (save_errno),
-                              _("Failed to create file “%s”: %s"),
-                              display_name, g_strerror (save_errno));
-               g_free (display_name);
-               g_free (tmp_filename);
+        fd = ev_mkstemp ("saveacopy.XXXXXX", &tmp_filename, &error);
+        if (fd == -1) {
+                ev_job_failed_from_error (job, error);
+                g_error_free (error);
 
                return FALSE;
        }
@@ -968,8 +954,11 @@ ev_job_save_run (EvJob *job)
        ev_document_doc_mutex_lock ();
 
        /* Save document to temp filename */
-       local_uri = g_filename_to_uri (tmp_filename, NULL, NULL);
-       ev_document_save (job->document, local_uri, &error);
+       local_uri = g_filename_to_uri (tmp_filename, NULL, &error);
+        if (local_uri != NULL) {
+                ev_document_save (job->document, local_uri, &error);
+        }
+
        close (fd);
 
        ev_document_doc_mutex_unlock ();
@@ -1000,7 +989,7 @@ ev_job_save_run (EvJob *job)
 
                uri_comp = ev_file_compress (local_uri, ctype, &error);
                g_free (local_uri);
-               ev_tmp_filename_unlink (tmp_filename);
+               g_unlink (tmp_filename);
 
                if (!uri_comp || error) {
                        local_uri = NULL;
@@ -1010,7 +999,7 @@ ev_job_save_run (EvJob *job)
        }
 
        g_free (tmp_filename);
-       
+
        if (error) {
                g_free (local_uri);
                ev_job_failed_from_error (job, error);
index bbd5ec6ee815746ff13b65fb28a98471ff7e42a4..2c6b5097296abb0790cdd89805b1c5cc6244248d 100644 (file)
@@ -885,7 +885,7 @@ ev_application_init (EvApplication *ev_application)
                                                     NULL);
 
         /* FIXME: why make this fatal? */
-        if (!ev_dir_ensure_exists (ev_application->dot_dir, 0700))
+        if (!ev_dir_ensure_exists (ev_application->dot_dir, 0700, NULL))
                 exit (1);
 
 #ifdef G_OS_WIN32
index d89617b1d6471ffc126b558e83376abeab009727..74e89c4163d1756e3789ec263d9213c44aa69eaf 100644 (file)
@@ -410,7 +410,7 @@ ev_sidebar_attachments_drag_data_get (GtkWidget        *widget,
                GtkTreePath  *path;
                GtkTreeIter   iter;
                GFile        *file;
-               gchar        *filename;
+               gchar        *filename, *template, *name;
                GError       *error = NULL;
                
                path = (GtkTreePath *) l->data;
@@ -421,13 +421,12 @@ ev_sidebar_attachments_drag_data_get (GtkWidget        *widget,
                                    COLUMN_ATTACHMENT, &attachment,
                                    -1);
 
-               filename = g_build_filename (ev_tmp_dir (),
-                                            ev_attachment_get_name (attachment),
-                                            NULL);
-               file = g_file_new_for_path (filename);
-               g_free (filename);
+                /* FIXMEchpe: convert to filename encoding first! */
+                template = g_strdup_printf ("%s.XXXXXX", ev_attachment_get_name (attachment));
+                file = ev_mkstemp_file (template, &error);
+                g_free (template);
                
-               if (ev_attachment_save (attachment, file, &error)) {
+               if (file != NULL && ev_attachment_save (attachment, file, &error)) {
                        gchar *uri;
 
                        uri = g_file_get_uri (file);
index c55c9f80650f7e479cf832abdd2d21e9f8dcdb62..042b4f93ba81988b881d3a85e37dc19287c6feec 100644 (file)
@@ -1708,19 +1708,30 @@ ev_window_load_file_remote (EvWindow *ev_window,
        GFile *target_file;
        
        if (!ev_window->priv->local_uri) {
-               gchar *tmp_name;
-               gchar *base_name;
+               char *base_name, *template;
+                GFile *tmp_file;
+                GError *err = NULL;
 
                /* We'd like to keep extension of source uri since
-                * it helps to resolve some mime types, say cbz */
-               tmp_name = ev_tmp_filename (NULL);
+                * it helps to resolve some mime types, say cbz.
+                 */
                base_name = g_file_get_basename (source_file);
-               ev_window->priv->local_uri = g_strconcat ("file:", tmp_name, "-",
-                                                         base_name, NULL);
+                template = g_build_filename ("document.XXXXXX-%s", base_name, NULL);
+                g_free (base_name);
+
+                tmp_file = ev_mkstemp_file (template, &err);
+                if (tmp_file == NULL) {
+                        ev_window_error_message (ev_window, err,
+                                                 "%s", _("Failed to load remote file."));
+                        g_error_free (err);
+                        return;
+                }
+
+               ev_window->priv->local_uri = g_file_get_uri (tmp_file);
+               g_object_unref (tmp_file);
+
                ev_job_load_set_uri (EV_JOB_LOAD (ev_window->priv->load_job),
                                     ev_window->priv->local_uri);
-               g_free (base_name);
-               g_free (tmp_name);
        }
 
        ev_window_reset_progress_cancellable (ev_window);
@@ -4648,13 +4659,13 @@ ev_window_drag_data_received (GtkWidget        *widget,
 static void
 ev_window_finalize (GObject *object)
 {
+       G_OBJECT_CLASS (ev_window_parent_class)->finalize (object);
+
        if (ev_window_n_copies == 0) {
                ev_application_shutdown (EV_APP);
        } else {
                ev_window_n_copies--;
        }
-
-       G_OBJECT_CLASS (ev_window_parent_class)->finalize (object);
 }
 
 static void
@@ -5629,7 +5640,9 @@ image_save_dialog_response_cb (GtkWidget *fc,
        if (is_native) {
                filename = g_file_get_path (target_file);
        } else {
-               filename = ev_tmp_filename ("saveimage");
+                /* Create a temporary local file to save to */
+                if (ev_mkstemp ("saveimage.XXXXXX", &filename, &error) == -1)
+                        goto has_error;
        }
 
        ev_document_doc_mutex_lock ();
@@ -5642,6 +5655,7 @@ image_save_dialog_response_cb (GtkWidget *fc,
        g_free (file_format);
        g_object_unref (pixbuf);
        
+    has_error:
        if (error) {
                ev_window_error_message (ev_window, error, 
                                         "%s", _("The image could not be saved."));
@@ -5774,7 +5788,7 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
        
        for (l = ev_window->priv->attach_list; l && l->data; l = g_list_next (l)) {
                EvAttachment *attachment;
-               GFile        *save_to;
+               GFile        *save_to = NULL;
                GError       *error = NULL;
                
                attachment = (EvAttachment *) l->data;
@@ -5782,15 +5796,17 @@ attachment_save_dialog_response_cb (GtkWidget *fc,
                if (is_native) {
                        if (is_dir) {
                                save_to = g_file_get_child (target_file,
+                                    /* FIXMEchpe: file name encoding! */
                                                            ev_attachment_get_name (attachment));
                        } else {
                                save_to = g_object_ref (target_file);
                        }
                } else {
-                       save_to = ev_tmp_file_get ("saveattachment");
+                       save_to = ev_mkstemp_file ("saveattachment.XXXXXX", &error);
                }
 
-               ev_attachment_save (attachment, save_to, &error);
+                if (save_to)
+                        ev_attachment_save (attachment, save_to, &error);
                
                if (error) {
                        ev_window_error_message (ev_window, error,