]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-file-helpers.c
Save document compressed when saving a copy of a compressed document.
[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 #include <libgnomevfs/gnome-vfs-uri.h>
33 #include <libgnomevfs/gnome-vfs-utils.h>
34 #include <libgnomevfs/gnome-vfs-ops.h>
35 #include <libgnomevfs/gnome-vfs-xfer.h>
36 #include <libgnome/gnome-init.h>
37
38 #include "ev-file-helpers.h"
39
40 static gchar *dot_dir = NULL;
41 static gchar *tmp_dir = NULL;
42 static gint   count = 0;
43
44 static gboolean
45 ensure_dir_exists (const char *dir)
46 {
47         if (g_file_test (dir, G_FILE_TEST_IS_DIR))
48                 return TRUE;
49         
50         if (g_mkdir (dir, 488) == 0)
51                 return TRUE;
52
53         if (errno == EEXIST)
54                 return g_file_test (dir, G_FILE_TEST_IS_DIR);
55         
56         g_warning ("Failed to create directory %s: %s", dir, strerror (errno));
57         return FALSE;
58 }
59
60 const gchar *
61 ev_dot_dir (void)
62 {
63         if (dot_dir == NULL) {
64                 gboolean exists;
65
66                 dot_dir = g_build_filename (gnome_user_dir_get (),
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 gchar * 
117 ev_tmp_filename (const gchar *prefix)
118 {
119         gchar *basename;
120         gchar *filename = NULL;
121
122         do {
123                 if (filename != NULL)
124                         g_free (filename);
125                         
126                 basename = g_strdup_printf ("%s-%d",
127                                             prefix ? prefix : "document",
128                                             count ++);
129                 
130                 filename = g_build_filename (ev_tmp_dir (),
131                                              basename, NULL);
132                 
133                 g_free (basename);
134         } while (g_file_test (filename, G_FILE_TEST_EXISTS));
135                         
136         return filename;
137 }
138
139 gboolean
140 ev_xfer_uri_simple (const char *from,
141                     const char *to,
142                     GError     **error)
143 {
144         GnomeVFSResult result;
145         GnomeVFSURI *source_uri;
146         GnomeVFSURI *target_uri;
147         
148         if (!from)
149                 return FALSE;
150         
151         source_uri = gnome_vfs_uri_new (from);
152         target_uri = gnome_vfs_uri_new (to);
153
154         result = gnome_vfs_xfer_uri (source_uri, target_uri, 
155                                      GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
156                                      GNOME_VFS_XFER_ERROR_MODE_ABORT,
157                                      GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
158                                      NULL,
159                                      NULL);
160         gnome_vfs_uri_unref (target_uri);
161         gnome_vfs_uri_unref (source_uri);
162     
163         if (result != GNOME_VFS_OK)
164                 g_set_error (error,
165                              G_FILE_ERROR,
166                              G_FILE_ERROR_FAILED,
167                              gnome_vfs_result_to_string (result));
168         return (result == GNOME_VFS_OK);
169
170 }
171
172 /* Compressed files support */
173 #define BZIPCOMMAND "bzip2"
174 #define GZIPCOMMAND "gzip"
175 #define N_ARGS      4
176 #define BUFFER_SIZE 1024
177
178 static gchar *
179 compression_run (const gchar       *uri,
180                  EvCompressionType  type,
181                  gboolean           compress, 
182                  GError           **error)
183 {
184         gchar *argv[N_ARGS];
185         gchar *uri_dst = NULL;
186         gchar *filename, *filename_dst;
187         gchar *cmd;
188         gint   fd, pout;
189
190         if (type == EV_COMPRESSION_NONE)
191                 return NULL;
192
193         cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND);
194         if (!cmd)
195                 return NULL;
196
197         filename = g_filename_from_uri (uri, NULL, NULL);
198         if (!filename) {
199                 g_free (cmd);
200                 return NULL;
201         }
202         
203         filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
204         fd = g_mkstemp (filename_dst);
205         if (fd < 0) {
206                 g_free (cmd);
207                 g_free (filename);
208                 g_free (filename_dst);
209                 return NULL;
210         }
211
212         argv[0] = cmd;
213         argv[1] = compress ? "-c" : "-cd";
214         argv[2] = filename;
215         argv[3] = NULL;
216
217         if (g_spawn_async_with_pipes (NULL, argv, NULL,
218                                       G_SPAWN_STDERR_TO_DEV_NULL,
219                                       NULL, NULL, NULL,
220                                       NULL, &pout, NULL, error)) {
221                 GIOChannel *in, *out;
222                 gchar buf[BUFFER_SIZE];
223                 GIOStatus read_st, write_st;
224                 gsize bytes_read, bytes_written;
225
226                 in = g_io_channel_unix_new (pout);
227                 g_io_channel_set_encoding (in, NULL, NULL);
228                 out = g_io_channel_unix_new (fd);
229                 g_io_channel_set_encoding (out, NULL, NULL);
230
231                 do {
232                         read_st = g_io_channel_read_chars (in, buf,
233                                                            BUFFER_SIZE,
234                                                            &bytes_read,
235                                                            error);
236                         if (read_st == G_IO_STATUS_NORMAL) {
237                                 write_st = g_io_channel_write_chars (out, buf,
238                                                                      bytes_read,
239                                                                      &bytes_written,
240                                                                      error);
241                                 if (write_st == G_IO_STATUS_ERROR)
242                                         break;
243                         } else if (read_st == G_IO_STATUS_ERROR) {
244                                 break;
245                         }
246                 } while (bytes_read > 0);
247
248                 g_io_channel_unref (in);
249                 g_io_channel_unref (out);
250         }
251
252         close (fd);
253
254         if (*error == NULL) {
255                 uri_dst = g_filename_to_uri (filename_dst, NULL, NULL);
256         }
257
258         g_free (cmd);
259         g_free (filename);
260         g_free (filename_dst);
261
262         return uri_dst;
263 }
264
265 gchar *
266 ev_file_uncompress (const gchar       *uri,
267                     EvCompressionType  type,
268                     GError           **error)
269 {
270         g_return_val_if_fail (uri != NULL, NULL);
271
272         return compression_run (uri, type, FALSE, error);
273 }
274
275 gchar *
276 ev_file_compress (const gchar       *uri,
277                   EvCompressionType  type,
278                   GError           **error)
279 {
280         g_return_val_if_fail (uri != NULL, NULL);
281
282         return compression_run (uri, type, TRUE, error);
283 }