2 * Copyright (C) 2002 Jorn Baayen
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)
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.
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.
26 #include <sys/types.h>
30 #include <glib/gstdio.h>
33 #include "ev-file-helpers.h"
35 static gchar *tmp_dir = NULL;
36 static gint count = 0;
39 ev_dir_ensure_exists (const gchar *dir,
42 if (g_mkdir_with_parents (dir, mode) == 0)
46 return g_file_test (dir, G_FILE_TEST_IS_DIR);
48 g_warning ("Failed to create directory %s: %s", dir, g_strerror (errno));
55 if (tmp_dir == NULL) {
57 gchar *dirname, *prgname;
59 prgname = g_get_prgname ();
60 dirname = g_strdup_printf ("%s-%u", prgname ? prgname : "unknown", getpid ());
61 tmp_dir = g_build_filename (g_get_tmp_dir (),
66 exists = ev_dir_ensure_exists (tmp_dir, 0700);
74 _ev_file_helpers_init (void)
79 _ev_file_helpers_shutdown (void)
89 ev_tmp_file_get (const gchar *prefix)
94 path = ev_tmp_filename (prefix);
95 file = g_file_new_for_path (path);
103 ev_tmp_filename (const gchar *prefix)
106 gchar *filename = NULL;
109 if (filename != NULL)
112 basename = g_strdup_printf ("%s-%d",
113 prefix ? prefix : "document",
116 filename = g_build_filename (ev_tmp_dir (),
120 } while (g_file_test (filename, G_FILE_TEST_EXISTS));
125 /* Remove a local temp file created by evince */
127 ev_tmp_filename_unlink (const gchar *filename)
129 const gchar *tempdir;
134 tempdir = g_get_tmp_dir ();
135 if (g_ascii_strncasecmp (filename, tempdir, strlen (tempdir)) == 0) {
141 ev_tmp_file_unlink (GFile *file)
144 GError *error = NULL;
149 res = g_file_delete (file, NULL, &error);
153 uri = g_file_get_uri (file);
154 g_warning ("Unable to delete temp file %s: %s\n", uri, error->message);
156 g_error_free (error);
161 ev_tmp_uri_unlink (const gchar *uri)
168 file = g_file_new_for_uri (uri);
169 if (!g_file_is_native (file)) {
170 g_warning ("Attempting to delete non native uri: %s\n", uri);
171 g_object_unref (file);
175 ev_tmp_file_unlink (file);
176 g_object_unref (file);
180 ev_xfer_uri_simple (const char *from,
186 GError *ioerror = NULL;
192 source_file = g_file_new_for_uri (from);
193 target_file = g_file_new_for_uri (to);
195 result = g_file_copy (source_file, target_file,
196 #if GLIB_CHECK_VERSION(2,19,0)
197 G_FILE_COPY_TARGET_DEFAULT_PERMS |
199 G_FILE_COPY_OVERWRITE,
200 NULL, NULL, NULL, &ioerror);
202 g_object_unref (target_file);
203 g_object_unref (source_file);
206 g_propagate_error (error, ioerror);
213 get_mime_type_from_uri (const gchar *uri, GError **error)
216 GFileInfo *file_info;
217 const gchar *content_type;
219 file = g_file_new_for_uri (uri);
220 file_info = g_file_query_info (file,
221 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
223 g_object_unref (file);
225 if (file_info == NULL)
228 content_type = g_file_info_get_content_type (file_info);
229 g_object_unref (file_info);
234 return g_content_type_get_mime_type (content_type);
238 get_mime_type_from_data (const gchar *uri, GError **error)
241 GFileInputStream *input_stream;
245 gchar *content_type, *mime_type;
247 file = g_file_new_for_uri (uri);
249 input_stream = g_file_read (file, NULL, error);
251 g_object_unref (file);
255 size_read = g_input_stream_read (G_INPUT_STREAM (input_stream),
256 buffer, sizeof (buffer), NULL, error);
257 if (size_read == -1) {
258 g_object_unref (input_stream);
259 g_object_unref (file);
263 retval = g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, error);
265 g_object_unref (input_stream);
266 g_object_unref (file);
270 content_type = g_content_type_guess (NULL, /* no filename */
276 mime_type = g_content_type_get_mime_type (content_type);
277 g_free (content_type);
282 * ev_file_get_mime_type:
284 * @fast: whether to use fast MIME type detection
285 * @error: a #GError location to store an error, or %NULL
287 * Note: on unknown MIME types, this may return NULL without @error
290 * Returns: a newly allocated string with the MIME type of the file at
291 * @uri, or %NULL on error or if the MIME type could not be determined
294 ev_file_get_mime_type (const gchar *uri,
298 return fast ? get_mime_type_from_uri (uri, error) : get_mime_type_from_data (uri, error);
301 /* Compressed files support */
302 #define BZIPCOMMAND "bzip2"
303 #define GZIPCOMMAND "gzip"
305 #define BUFFER_SIZE 1024
308 compression_run (const gchar *uri,
309 EvCompressionType type,
314 gchar *uri_dst = NULL;
315 gchar *filename, *filename_dst;
320 if (type == EV_COMPRESSION_NONE)
323 cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND);
325 /* FIXME: better error codes! */
326 /* FIXME: i18n later */
327 g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
328 "Failed to find the \"%s\" command in the search path.",
329 type == EV_COMPRESSION_BZIP2 ? BZIPCOMMAND : GZIPCOMMAND);
333 filename = g_filename_from_uri (uri, NULL, error);
339 filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
340 fd = g_mkstemp (filename_dst);
346 g_free (filename_dst);
348 g_set_error (error, G_IO_ERROR,
349 g_io_error_from_errno (errsv),
350 "Error creating a temporary file: %s",
356 argv[1] = compress ? "-c" : "-cd";
360 if (g_spawn_async_with_pipes (NULL, argv, NULL,
361 G_SPAWN_STDERR_TO_DEV_NULL,
363 NULL, &pout, NULL, &err)) {
364 GIOChannel *in, *out;
365 gchar buf[BUFFER_SIZE];
366 GIOStatus read_st, write_st;
367 gsize bytes_read, bytes_written;
369 in = g_io_channel_unix_new (pout);
370 g_io_channel_set_encoding (in, NULL, NULL);
371 out = g_io_channel_unix_new (fd);
372 g_io_channel_set_encoding (out, NULL, NULL);
375 read_st = g_io_channel_read_chars (in, buf,
379 if (read_st == G_IO_STATUS_NORMAL) {
380 write_st = g_io_channel_write_chars (out, buf,
384 if (write_st == G_IO_STATUS_ERROR)
386 } else if (read_st == G_IO_STATUS_ERROR) {
389 } while (bytes_read > 0);
391 g_io_channel_unref (in);
392 g_io_channel_unref (out);
398 g_propagate_error (error, err);
400 uri_dst = g_filename_to_uri (filename_dst, NULL, error);
405 g_free (filename_dst);
411 * ev_file_uncompress:
413 * @type: the compression type
414 * @error: a #GError location to store an error, or %NULL
416 * Uncompresses the file at @uri.
418 * If @type is %EV_COMPRESSION_NONE, it does nothing and returns %NULL.
420 * Otherwise, it returns the filename of a
421 * temporary file containing the decompressed data from the file at @uri.
422 * On error it returns %NULL and fills in @error.
424 * It is the caller's responsibility to unlink the temp file after use.
426 * Returns: a newly allocated string URI, or %NULL on error
429 ev_file_uncompress (const gchar *uri,
430 EvCompressionType type,
433 g_return_val_if_fail (uri != NULL, NULL);
435 return compression_run (uri, type, FALSE, error);
441 * @type: the compression type
442 * @error: a #GError location to store an error, or %NULL
444 * Compresses the file at @uri.
446 * If @type is %EV_COMPRESSION_NONE, it does nothing and returns %NULL.
448 * Otherwise, it returns the filename of a
449 * temporary file containing the compressed data from the file at @uri.
451 * On error it returns %NULL and fills in @error.
453 * It is the caller's responsibility to unlink the temp file after use.
455 * Returns: a newly allocated string URI, or %NULL on error
458 ev_file_compress (const gchar *uri,
459 EvCompressionType type,
462 g_return_val_if_fail (uri != NULL, NULL);
464 return compression_run (uri, type, TRUE, error);