]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-file-helpers.c
Move ev_dot_dir() from libdocument to shell, since it shouldn't be public
[evince.git] / libdocument / ev-file-helpers.c
1 /*
2  *  Copyright (C) 2002 Jorn Baayen
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2, or (at your option)
7  *  any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  *  $Id$
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <glib.h>
30 #include <glib/gstdio.h>
31 #include <errno.h>
32
33 #if WITH_GNOME
34 #include <libgnome/gnome-init.h>
35 #endif
36
37 #include "ev-file-helpers.h"
38
39 static gchar *tmp_dir = NULL;
40 static gint   count = 0;
41
42 gboolean
43 ev_dir_ensure_exists (const gchar *dir,
44                       int          mode)
45 {
46         if (g_mkdir_with_parents (dir, mode) == 0)
47                 return TRUE;
48
49         if (errno == EEXIST)
50                 return g_file_test (dir, G_FILE_TEST_IS_DIR);
51         
52         g_warning ("Failed to create directory %s: %s", dir, g_strerror (errno));
53         return FALSE;
54 }
55
56 const gchar *
57 ev_tmp_dir (void)
58 {
59         if (tmp_dir == NULL) {
60                 gboolean exists;
61                 gchar   *dirname, *prgname;
62
63                 prgname = g_get_prgname ();
64                 dirname = g_strdup_printf ("%s-%u", prgname ? prgname : "unknown", getpid ());
65                 tmp_dir = g_build_filename (g_get_tmp_dir (),
66                                             dirname,
67                                             NULL);
68                 g_free (dirname);
69
70                 exists = ev_dir_ensure_exists (tmp_dir, 0700);
71                 g_assert (exists);
72         }
73
74         return tmp_dir;
75 }
76
77 void
78 ev_file_helpers_init (void)
79 {
80 }
81
82 void
83 ev_file_helpers_shutdown (void)
84 {       
85         if (tmp_dir != NULL)    
86                 g_rmdir (tmp_dir);
87
88         g_free (tmp_dir);
89         tmp_dir = NULL;
90 }
91
92 GFile *
93 ev_tmp_file_get (const gchar *prefix)
94 {
95         gchar *path;
96         GFile *file;
97
98         path = ev_tmp_filename (prefix);
99         file = g_file_new_for_path (path);
100         
101         g_free (path);
102         
103         return file;
104 }
105
106 gchar * 
107 ev_tmp_filename (const gchar *prefix)
108 {
109         gchar *basename;
110         gchar *filename = NULL;
111
112         do {
113                 if (filename != NULL)
114                         g_free (filename);
115                         
116                 basename = g_strdup_printf ("%s-%d",
117                                             prefix ? prefix : "document",
118                                             count ++);
119                 
120                 filename = g_build_filename (ev_tmp_dir (),
121                                              basename, NULL);
122                 
123                 g_free (basename);
124         } while (g_file_test (filename, G_FILE_TEST_EXISTS));
125                         
126         return filename;
127 }
128
129 /* Remove a local temp file created by evince */
130 void
131 ev_tmp_filename_unlink (const gchar *filename)
132 {
133         const gchar *tempdir;
134         
135         if (!filename)
136                 return;
137
138         tempdir = g_get_tmp_dir ();
139         if (g_ascii_strncasecmp (filename, tempdir, strlen (tempdir)) == 0) {
140                 g_unlink (filename);
141         }
142 }
143
144 void
145 ev_tmp_file_unlink (GFile *file)
146 {
147         gboolean res;
148         GError  *error = NULL;
149
150         if (!file)
151                 return;
152         
153         res = g_file_delete (file, NULL, &error);
154         if (!res) {
155                 char *uri;
156                 
157                 uri = g_file_get_uri (file);
158                 g_warning ("Unable to delete temp file %s: %s\n", uri, error->message);
159                 g_free (uri);
160                 g_error_free (error);
161         }
162 }
163
164 void
165 ev_tmp_uri_unlink (const gchar *uri)
166 {
167         GFile *file;
168         
169         if (!uri)
170                 return;
171         
172         file = g_file_new_for_uri (uri);
173         if (!g_file_is_native (file)) {
174                 g_warning ("Attempting to delete non native uri: %s\n", uri);
175                 g_object_unref (file);
176                 return;
177         }
178         
179         ev_tmp_file_unlink (file);
180         g_object_unref (file);
181 }
182
183 gboolean
184 ev_xfer_uri_simple (const char *from,
185                     const char *to,
186                     GError     **error)
187 {
188         GFile *source_file;
189         GFile *target_file;
190         GError *ioerror = NULL;
191         gboolean result;
192         
193         if (!from)
194                 return FALSE;
195         
196         source_file = g_file_new_for_uri (from);
197         target_file = g_file_new_for_uri (to);
198         
199         result = g_file_copy (source_file, target_file,
200 #if GLIB_CHECK_VERSION(2,19,0)
201                               G_FILE_COPY_TARGET_DEFAULT_PERMS |
202 #endif
203                               G_FILE_COPY_OVERWRITE,
204                               NULL, NULL, NULL, &ioerror);
205
206         g_object_unref (target_file);
207         g_object_unref (source_file);
208     
209         if (!result) {
210                 g_propagate_error (error, ioerror);
211         }
212         return result;
213
214 }
215
216 static gchar *
217 get_mime_type_from_uri (const gchar *uri, GError **error)
218 {
219         GFile     *file;
220         GFileInfo *file_info;
221         gchar     *mime_type;
222
223         file = g_file_new_for_uri (uri);
224         file_info = g_file_query_info (file,
225                                        G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
226                                        0, NULL, error);
227         g_object_unref (file);
228
229         if (file_info == NULL)
230                 return NULL;
231
232         mime_type = g_content_type_get_mime_type (
233                         g_file_info_get_content_type (file_info));
234         g_object_unref (file_info);
235
236         return mime_type;
237 }
238
239 static gchar *
240 get_mime_type_from_data (const gchar *uri, GError **error)
241 {
242         GFile            *file;
243         GFileInputStream *input_stream;
244         gssize            size_read;
245         guchar            buffer[1024];
246
247         file = g_file_new_for_uri (uri);
248         
249         input_stream = g_file_read (file, NULL, error);
250         if (!input_stream) {
251                 g_object_unref (file);
252                 return NULL;
253         }
254
255         size_read = g_input_stream_read (G_INPUT_STREAM (input_stream),
256                                          buffer, 1024, NULL, NULL);
257         g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, error);
258
259         g_object_unref (file);
260
261         if (size_read == -1)
262                 return NULL;
263
264         return g_content_type_guess (NULL, /* no filename */
265                                      buffer, 1024,
266                                      NULL);
267 }
268
269 gchar *
270 ev_file_get_mime_type (const gchar *uri,
271                        gboolean     fast,
272                        GError     **error)
273 {
274         return fast ? get_mime_type_from_uri (uri, error) : get_mime_type_from_data (uri, error);
275 }
276
277 /* Compressed files support */
278 #define BZIPCOMMAND "bzip2"
279 #define GZIPCOMMAND "gzip"
280 #define N_ARGS      4
281 #define BUFFER_SIZE 1024
282
283 static gchar *
284 compression_run (const gchar       *uri,
285                  EvCompressionType  type,
286                  gboolean           compress, 
287                  GError           **error)
288 {
289         gchar *argv[N_ARGS];
290         gchar *uri_dst = NULL;
291         gchar *filename, *filename_dst;
292         gchar *cmd;
293         gint   fd, pout;
294
295         if (type == EV_COMPRESSION_NONE)
296                 return NULL;
297
298         cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND);
299         if (!cmd)
300                 return NULL;
301
302         filename = g_filename_from_uri (uri, NULL, NULL);
303         if (!filename) {
304                 g_free (cmd);
305                 return NULL;
306         }
307         
308         filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
309         fd = g_mkstemp (filename_dst);
310         if (fd < 0) {
311                 g_free (cmd);
312                 g_free (filename);
313                 g_free (filename_dst);
314                 return NULL;
315         }
316
317         argv[0] = cmd;
318         argv[1] = compress ? "-c" : "-cd";
319         argv[2] = filename;
320         argv[3] = NULL;
321
322         if (g_spawn_async_with_pipes (NULL, argv, NULL,
323                                       G_SPAWN_STDERR_TO_DEV_NULL,
324                                       NULL, NULL, NULL,
325                                       NULL, &pout, NULL, error)) {
326                 GIOChannel *in, *out;
327                 gchar buf[BUFFER_SIZE];
328                 GIOStatus read_st, write_st;
329                 gsize bytes_read, bytes_written;
330
331                 in = g_io_channel_unix_new (pout);
332                 g_io_channel_set_encoding (in, NULL, NULL);
333                 out = g_io_channel_unix_new (fd);
334                 g_io_channel_set_encoding (out, NULL, NULL);
335
336                 do {
337                         read_st = g_io_channel_read_chars (in, buf,
338                                                            BUFFER_SIZE,
339                                                            &bytes_read,
340                                                            error);
341                         if (read_st == G_IO_STATUS_NORMAL) {
342                                 write_st = g_io_channel_write_chars (out, buf,
343                                                                      bytes_read,
344                                                                      &bytes_written,
345                                                                      error);
346                                 if (write_st == G_IO_STATUS_ERROR)
347                                         break;
348                         } else if (read_st == G_IO_STATUS_ERROR) {
349                                 break;
350                         }
351                 } while (bytes_read > 0);
352
353                 g_io_channel_unref (in);
354                 g_io_channel_unref (out);
355         }
356
357         close (fd);
358
359         if (*error == NULL) {
360                 uri_dst = g_filename_to_uri (filename_dst, NULL, NULL);
361         }
362
363         g_free (cmd);
364         g_free (filename);
365         g_free (filename_dst);
366
367         return uri_dst;
368 }
369
370 gchar *
371 ev_file_uncompress (const gchar       *uri,
372                     EvCompressionType  type,
373                     GError           **error)
374 {
375         g_return_val_if_fail (uri != NULL, NULL);
376
377         return compression_run (uri, type, FALSE, error);
378 }
379
380 gchar *
381 ev_file_compress (const gchar       *uri,
382                   EvCompressionType  type,
383                   GError           **error)
384 {
385         g_return_val_if_fail (uri != NULL, NULL);
386
387         return compression_run (uri, type, TRUE, error);
388 }