]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-file-helpers.c
6a8c2568eef5fb4b7da5ff0261eeff04dcd47f8c
[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 *dot_dir = NULL;
40 static gchar *tmp_dir = NULL;
41 static gint   count = 0;
42
43 static gboolean
44 ensure_dir_exists (const char *dir)
45 {
46         if (g_file_test (dir, G_FILE_TEST_IS_DIR))
47                 return TRUE;
48         
49         if (g_mkdir_with_parents (dir, 488) == 0)
50                 return TRUE;
51
52         if (errno == EEXIST)
53                 return g_file_test (dir, G_FILE_TEST_IS_DIR);
54         
55         g_warning ("Failed to create directory %s: %s", dir, strerror (errno));
56         return FALSE;
57 }
58
59 const gchar *
60 ev_dot_dir (void)
61 {
62         if (dot_dir == NULL) {
63                 gboolean exists;
64
65                 dot_dir = g_build_filename (g_get_home_dir (),
66                                             ".gnome2",
67                                             "evince",
68                                             NULL);
69
70                 exists = ensure_dir_exists (dot_dir);
71                 if (!exists)
72                         exit (1);
73         }
74
75         return dot_dir;
76 }
77
78 const gchar *
79 ev_tmp_dir (void)
80 {
81         if (tmp_dir == NULL) {
82                 gboolean exists;
83                 gchar   *dirname;
84
85                 dirname = g_strdup_printf ("evince-%u", getpid ());
86                 tmp_dir = g_build_filename (g_get_tmp_dir (),
87                                             dirname,
88                                             NULL);
89                 g_free (dirname);
90
91                 exists = ensure_dir_exists (tmp_dir);
92                 g_assert (exists);
93         }
94
95         return tmp_dir;
96 }
97
98 void
99 ev_file_helpers_init (void)
100 {
101 }
102
103 void
104 ev_file_helpers_shutdown (void)
105 {       
106         if (tmp_dir != NULL)    
107                 g_rmdir (tmp_dir);
108
109         g_free (tmp_dir);
110         g_free (dot_dir);
111
112         dot_dir = NULL;
113         tmp_dir = NULL;
114 }
115
116 GFile *
117 ev_tmp_file_get (const gchar *prefix)
118 {
119         gchar *path;
120         GFile *file;
121
122         path = ev_tmp_filename (prefix);
123         file = g_file_new_for_path (path);
124         
125         g_free (path);
126         
127         return file;
128 }
129
130 gchar * 
131 ev_tmp_filename (const gchar *prefix)
132 {
133         gchar *basename;
134         gchar *filename = NULL;
135
136         do {
137                 if (filename != NULL)
138                         g_free (filename);
139                         
140                 basename = g_strdup_printf ("%s-%d",
141                                             prefix ? prefix : "document",
142                                             count ++);
143                 
144                 filename = g_build_filename (ev_tmp_dir (),
145                                              basename, NULL);
146                 
147                 g_free (basename);
148         } while (g_file_test (filename, G_FILE_TEST_EXISTS));
149                         
150         return filename;
151 }
152
153 /* Remove a local temp file created by evince */
154 void
155 ev_tmp_filename_unlink (const gchar *filename)
156 {
157         const gchar *tempdir;
158         
159         if (!filename)
160                 return;
161
162         tempdir = g_get_tmp_dir ();
163         if (g_ascii_strncasecmp (filename, tempdir, strlen (tempdir)) == 0) {
164                 g_unlink (filename);
165         }
166 }
167
168 void
169 ev_tmp_file_unlink (GFile *file)
170 {
171         gboolean res;
172         GError  *error = NULL;
173
174         if (!file)
175                 return;
176         
177         res = g_file_delete (file, NULL, &error);
178         if (!res) {
179                 char *uri;
180                 
181                 uri = g_file_get_uri (file);
182                 g_warning ("Unable to delete temp file %s: %s\n", uri, error->message);
183                 g_free (uri);
184                 g_error_free (error);
185         }
186 }
187
188 void
189 ev_tmp_uri_unlink (const gchar *uri)
190 {
191         GFile *file;
192         
193         if (!uri)
194                 return;
195         
196         file = g_file_new_for_uri (uri);
197         if (!g_file_is_native (file)) {
198                 g_warning ("Attempting to delete non native uri: %s\n", uri);
199                 g_object_unref (file);
200                 return;
201         }
202         
203         ev_tmp_file_unlink (file);
204         g_object_unref (file);
205 }
206
207 gboolean
208 ev_xfer_uri_simple (const char *from,
209                     const char *to,
210                     GError     **error)
211 {
212         GFile *source_file;
213         GFile *target_file;
214         GError *ioerror = NULL;
215         gboolean result;
216         
217         if (!from)
218                 return FALSE;
219         
220         source_file = g_file_new_for_uri (from);
221         target_file = g_file_new_for_uri (to);
222         
223         result = g_file_copy (source_file, target_file,
224                               G_FILE_COPY_OVERWRITE,
225                               NULL, NULL, NULL, &ioerror);
226
227         g_object_unref (target_file);
228         g_object_unref (source_file);
229     
230         if (!result) {
231                 g_propagate_error (error, ioerror);
232         }
233         return result;
234
235 }
236
237 static gchar *
238 get_mime_type_from_uri (const gchar *uri, GError **error)
239 {
240         GFile     *file;
241         GFileInfo *file_info;
242         gchar     *mime_type;
243
244         file = g_file_new_for_uri (uri);
245         file_info = g_file_query_info (file,
246                                        G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
247                                        0, NULL, error);
248         g_object_unref (file);
249
250         if (file_info == NULL)
251                 return NULL;
252
253         mime_type = g_strdup (g_file_info_get_content_type (file_info));
254         g_object_unref (file_info);
255
256         return mime_type;
257 }
258
259 static gchar *
260 get_mime_type_from_data (const gchar *uri, GError **error)
261 {
262         GFile            *file;
263         GFileInputStream *input_stream;
264         gssize            size_read;
265         guchar            buffer[1024];
266
267         file = g_file_new_for_uri (uri);
268         
269         input_stream = g_file_read (file, NULL, error);
270         if (!input_stream) {
271                 g_object_unref (file);
272                 return NULL;
273         }
274
275         size_read = g_input_stream_read (G_INPUT_STREAM (input_stream),
276                                          buffer, 1024, NULL, NULL);
277         g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, error);
278
279         g_object_unref (file);
280
281         if (size_read == -1)
282                 return NULL;
283
284         return g_content_type_guess (NULL, /* no filename */
285                                      buffer, 1024,
286                                      NULL);
287 }
288
289 gchar *
290 ev_file_get_mime_type (const gchar *uri,
291                        gboolean     fast,
292                        GError     **error)
293 {
294         return fast ? get_mime_type_from_uri (uri, error) : get_mime_type_from_data (uri, error);
295 }
296
297 /* Compressed files support */
298 #define BZIPCOMMAND "bzip2"
299 #define GZIPCOMMAND "gzip"
300 #define N_ARGS      4
301 #define BUFFER_SIZE 1024
302
303 static gchar *
304 compression_run (const gchar       *uri,
305                  EvCompressionType  type,
306                  gboolean           compress, 
307                  GError           **error)
308 {
309         gchar *argv[N_ARGS];
310         gchar *uri_dst = NULL;
311         gchar *filename, *filename_dst;
312         gchar *cmd;
313         gint   fd, pout;
314
315         if (type == EV_COMPRESSION_NONE)
316                 return NULL;
317
318         cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND);
319         if (!cmd)
320                 return NULL;
321
322         filename = g_filename_from_uri (uri, NULL, NULL);
323         if (!filename) {
324                 g_free (cmd);
325                 return NULL;
326         }
327         
328         filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
329         fd = g_mkstemp (filename_dst);
330         if (fd < 0) {
331                 g_free (cmd);
332                 g_free (filename);
333                 g_free (filename_dst);
334                 return NULL;
335         }
336
337         argv[0] = cmd;
338         argv[1] = compress ? "-c" : "-cd";
339         argv[2] = filename;
340         argv[3] = NULL;
341
342         if (g_spawn_async_with_pipes (NULL, argv, NULL,
343                                       G_SPAWN_STDERR_TO_DEV_NULL,
344                                       NULL, NULL, NULL,
345                                       NULL, &pout, NULL, error)) {
346                 GIOChannel *in, *out;
347                 gchar buf[BUFFER_SIZE];
348                 GIOStatus read_st, write_st;
349                 gsize bytes_read, bytes_written;
350
351                 in = g_io_channel_unix_new (pout);
352                 g_io_channel_set_encoding (in, NULL, NULL);
353                 out = g_io_channel_unix_new (fd);
354                 g_io_channel_set_encoding (out, NULL, NULL);
355
356                 do {
357                         read_st = g_io_channel_read_chars (in, buf,
358                                                            BUFFER_SIZE,
359                                                            &bytes_read,
360                                                            error);
361                         if (read_st == G_IO_STATUS_NORMAL) {
362                                 write_st = g_io_channel_write_chars (out, buf,
363                                                                      bytes_read,
364                                                                      &bytes_written,
365                                                                      error);
366                                 if (write_st == G_IO_STATUS_ERROR)
367                                         break;
368                         } else if (read_st == G_IO_STATUS_ERROR) {
369                                 break;
370                         }
371                 } while (bytes_read > 0);
372
373                 g_io_channel_unref (in);
374                 g_io_channel_unref (out);
375         }
376
377         close (fd);
378
379         if (*error == NULL) {
380                 uri_dst = g_filename_to_uri (filename_dst, NULL, NULL);
381         }
382
383         g_free (cmd);
384         g_free (filename);
385         g_free (filename_dst);
386
387         return uri_dst;
388 }
389
390 gchar *
391 ev_file_uncompress (const gchar       *uri,
392                     EvCompressionType  type,
393                     GError           **error)
394 {
395         g_return_val_if_fail (uri != NULL, NULL);
396
397         return compression_run (uri, type, FALSE, error);
398 }
399
400 gchar *
401 ev_file_compress (const gchar       *uri,
402                   EvCompressionType  type,
403                   GError           **error)
404 {
405         g_return_val_if_fail (uri != NULL, NULL);
406
407         return compression_run (uri, type, TRUE, error);
408 }