]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-file-helpers.c
20c7bc4eabd1b8c66927ceafc401500b708a11de
[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 #if WITH_GNOME
66                 dot_dir = g_build_filename (gnome_user_dir_get (),
67                                             "evince",
68                                             NULL);
69 #else
70                 dot_dir = g_build_filename (g_get_user_config_dir (),
71                                             "evince",
72                                             NULL);
73 #endif
74
75                 exists = ensure_dir_exists (dot_dir);
76                 if (!exists)
77                         exit (1);
78         }
79
80         return dot_dir;
81 }
82
83 const gchar *
84 ev_tmp_dir (void)
85 {
86         if (tmp_dir == NULL) {
87                 gboolean exists;
88                 gchar   *dirname;
89
90                 dirname = g_strdup_printf ("evince-%u", getpid ());
91                 tmp_dir = g_build_filename (g_get_tmp_dir (),
92                                             dirname,
93                                             NULL);
94                 g_free (dirname);
95
96                 exists = ensure_dir_exists (tmp_dir);
97                 g_assert (exists);
98         }
99
100         return tmp_dir;
101 }
102
103 void
104 ev_file_helpers_init (void)
105 {
106 }
107
108 void
109 ev_file_helpers_shutdown (void)
110 {       
111         if (tmp_dir != NULL)    
112                 g_rmdir (tmp_dir);
113
114         g_free (tmp_dir);
115         g_free (dot_dir);
116
117         dot_dir = NULL;
118         tmp_dir = NULL;
119 }
120
121 GFile *
122 ev_tmp_file_get (const gchar *prefix)
123 {
124         gchar *path;
125         GFile *file;
126
127         path = ev_tmp_filename (prefix);
128         file = g_file_new_for_path (path);
129         
130         g_free (path);
131         
132         return file;
133 }
134
135 gchar * 
136 ev_tmp_filename (const gchar *prefix)
137 {
138         gchar *basename;
139         gchar *filename = NULL;
140
141         do {
142                 if (filename != NULL)
143                         g_free (filename);
144                         
145                 basename = g_strdup_printf ("%s-%d",
146                                             prefix ? prefix : "document",
147                                             count ++);
148                 
149                 filename = g_build_filename (ev_tmp_dir (),
150                                              basename, NULL);
151                 
152                 g_free (basename);
153         } while (g_file_test (filename, G_FILE_TEST_EXISTS));
154                         
155         return filename;
156 }
157
158 /* Remove a local temp file created by evince */
159 void
160 ev_tmp_filename_unlink (const gchar *filename)
161 {
162         const gchar *tempdir;
163         
164         if (!filename)
165                 return;
166
167         tempdir = g_get_tmp_dir ();
168         if (g_ascii_strncasecmp (filename, tempdir, strlen (tempdir)) == 0) {
169                 g_unlink (filename);
170         }
171 }
172
173 void
174 ev_tmp_file_unlink (GFile *file)
175 {
176         gboolean res;
177
178         if (!file)
179                 return;
180         
181         res = g_file_delete (file, NULL, NULL);
182         if (!res) {
183                 char *uri;
184                 
185                 uri = g_file_get_uri (file);
186                 g_warning ("Unable to delete temp file %s\n", uri);
187                 g_free (uri);
188         }
189 }
190
191 void
192 ev_tmp_uri_unlink (const gchar *uri)
193 {
194         GFile *file;
195         
196         if (!uri)
197                 return;
198         
199         file = g_file_new_for_uri (uri);
200         if (!g_file_is_native (file)) {
201                 g_warning ("Attempting to delete non native uri: %s\n", uri);
202                 g_object_unref (file);
203                 return;
204         }
205         
206         ev_tmp_file_unlink (file);
207         g_object_unref (file);
208 }
209
210 gboolean
211 ev_xfer_uri_simple (const char *from,
212                     const char *to,
213                     GError     **error)
214 {
215         GFile *source_file;
216         GFile *target_file;
217         GError *ioerror;
218         gboolean result;
219         
220         if (!from)
221                 return FALSE;
222         
223         source_file = g_file_new_for_uri (from);
224         target_file = g_file_new_for_uri (to);
225         
226         result = g_file_copy (source_file, target_file,
227                               G_FILE_COPY_OVERWRITE,
228                               NULL, NULL, NULL, &ioerror);
229
230         g_object_unref (target_file);
231         g_object_unref (source_file);
232     
233         if (!result) {
234                 g_propagate_error (error, ioerror);
235         }
236         return result;
237
238 }
239
240 /* Compressed files support */
241 #define BZIPCOMMAND "bzip2"
242 #define GZIPCOMMAND "gzip"
243 #define N_ARGS      4
244 #define BUFFER_SIZE 1024
245
246 static gchar *
247 compression_run (const gchar       *uri,
248                  EvCompressionType  type,
249                  gboolean           compress, 
250                  GError           **error)
251 {
252         gchar *argv[N_ARGS];
253         gchar *uri_dst = NULL;
254         gchar *filename, *filename_dst;
255         gchar *cmd;
256         gint   fd, pout;
257
258         if (type == EV_COMPRESSION_NONE)
259                 return NULL;
260
261         cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND);
262         if (!cmd)
263                 return NULL;
264
265         filename = g_filename_from_uri (uri, NULL, NULL);
266         if (!filename) {
267                 g_free (cmd);
268                 return NULL;
269         }
270         
271         filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
272         fd = g_mkstemp (filename_dst);
273         if (fd < 0) {
274                 g_free (cmd);
275                 g_free (filename);
276                 g_free (filename_dst);
277                 return NULL;
278         }
279
280         argv[0] = cmd;
281         argv[1] = compress ? "-c" : "-cd";
282         argv[2] = filename;
283         argv[3] = NULL;
284
285         if (g_spawn_async_with_pipes (NULL, argv, NULL,
286                                       G_SPAWN_STDERR_TO_DEV_NULL,
287                                       NULL, NULL, NULL,
288                                       NULL, &pout, NULL, error)) {
289                 GIOChannel *in, *out;
290                 gchar buf[BUFFER_SIZE];
291                 GIOStatus read_st, write_st;
292                 gsize bytes_read, bytes_written;
293
294                 in = g_io_channel_unix_new (pout);
295                 g_io_channel_set_encoding (in, NULL, NULL);
296                 out = g_io_channel_unix_new (fd);
297                 g_io_channel_set_encoding (out, NULL, NULL);
298
299                 do {
300                         read_st = g_io_channel_read_chars (in, buf,
301                                                            BUFFER_SIZE,
302                                                            &bytes_read,
303                                                            error);
304                         if (read_st == G_IO_STATUS_NORMAL) {
305                                 write_st = g_io_channel_write_chars (out, buf,
306                                                                      bytes_read,
307                                                                      &bytes_written,
308                                                                      error);
309                                 if (write_st == G_IO_STATUS_ERROR)
310                                         break;
311                         } else if (read_st == G_IO_STATUS_ERROR) {
312                                 break;
313                         }
314                 } while (bytes_read > 0);
315
316                 g_io_channel_unref (in);
317                 g_io_channel_unref (out);
318         }
319
320         close (fd);
321
322         if (*error == NULL) {
323                 uri_dst = g_filename_to_uri (filename_dst, NULL, NULL);
324         }
325
326         g_free (cmd);
327         g_free (filename);
328         g_free (filename_dst);
329
330         return uri_dst;
331 }
332
333 gchar *
334 ev_file_uncompress (const gchar       *uri,
335                     EvCompressionType  type,
336                     GError           **error)
337 {
338         g_return_val_if_fail (uri != NULL, NULL);
339
340         return compression_run (uri, type, FALSE, error);
341 }
342
343 gchar *
344 ev_file_compress (const gchar       *uri,
345                   EvCompressionType  type,
346                   GError           **error)
347 {
348         g_return_val_if_fail (uri != NULL, NULL);
349
350         return compression_run (uri, type, TRUE, error);
351 }