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));
126 ev_tmp_directory (const gchar *prefix)
128 return ev_tmp_filename (prefix ? prefix : "directory");
131 /* Remove a local temp file created by evince */
133 ev_tmp_filename_unlink (const gchar *filename)
135 const gchar *tempdir;
140 tempdir = g_get_tmp_dir ();
141 if (g_ascii_strncasecmp (filename, tempdir, strlen (tempdir)) == 0) {
147 ev_tmp_file_unlink (GFile *file)
150 GError *error = NULL;
155 res = g_file_delete (file, NULL, &error);
159 uri = g_file_get_uri (file);
160 g_warning ("Unable to delete temp file %s: %s\n", uri, error->message);
162 g_error_free (error);
167 ev_tmp_uri_unlink (const gchar *uri)
174 file = g_file_new_for_uri (uri);
175 if (!g_file_is_native (file)) {
176 g_warning ("Attempting to delete non native uri: %s\n", uri);
177 g_object_unref (file);
181 ev_tmp_file_unlink (file);
182 g_object_unref (file);
186 * ev_xfer_uri_simple:
187 * @from: the source URI
188 * @to: the target URI
189 * @error: a #GError location to store an error, or %NULL
191 * Performs a g_file_copy() from @from to @to.
193 * Returns: %TRUE on success, or %FALSE on error with @error filled in
196 ev_xfer_uri_simple (const char *from,
207 g_return_val_if_fail (to != NULL, TRUE);
209 source_file = g_file_new_for_uri (from);
210 target_file = g_file_new_for_uri (to);
212 result = g_file_copy (source_file, target_file,
213 #if GLIB_CHECK_VERSION(2,19,0)
214 G_FILE_COPY_TARGET_DEFAULT_PERMS |
216 G_FILE_COPY_OVERWRITE,
217 NULL, NULL, NULL, error);
219 g_object_unref (target_file);
220 g_object_unref (source_file);
226 get_mime_type_from_uri (const gchar *uri, GError **error)
229 GFileInfo *file_info;
230 const gchar *content_type;
231 gchar *mime_type = NULL;
233 file = g_file_new_for_uri (uri);
234 file_info = g_file_query_info (file,
235 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
237 g_object_unref (file);
239 if (file_info == NULL)
242 content_type = g_file_info_get_content_type (file_info);
244 mime_type = g_content_type_get_mime_type (content_type);
247 g_object_unref (file_info);
252 get_mime_type_from_data (const gchar *uri, GError **error)
255 GFileInputStream *input_stream;
259 gchar *content_type, *mime_type;
261 file = g_file_new_for_uri (uri);
263 input_stream = g_file_read (file, NULL, error);
265 g_object_unref (file);
269 size_read = g_input_stream_read (G_INPUT_STREAM (input_stream),
270 buffer, sizeof (buffer), NULL, error);
271 if (size_read == -1) {
272 g_object_unref (input_stream);
273 g_object_unref (file);
277 retval = g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, error);
279 g_object_unref (input_stream);
280 g_object_unref (file);
284 content_type = g_content_type_guess (NULL, /* no filename */
290 mime_type = g_content_type_get_mime_type (content_type);
291 g_free (content_type);
296 * ev_file_get_mime_type:
298 * @fast: whether to use fast MIME type detection
299 * @error: a #GError location to store an error, or %NULL
301 * Note: on unknown MIME types, this may return NULL without @error
304 * Returns: a newly allocated string with the MIME type of the file at
305 * @uri, or %NULL on error or if the MIME type could not be determined
308 ev_file_get_mime_type (const gchar *uri,
312 return fast ? get_mime_type_from_uri (uri, error) : get_mime_type_from_data (uri, error);
315 /* Compressed files support */
316 #define BZIPCOMMAND "bzip2"
317 #define GZIPCOMMAND "gzip"
319 #define BUFFER_SIZE 1024
322 compression_run (const gchar *uri,
323 EvCompressionType type,
328 gchar *uri_dst = NULL;
329 gchar *filename, *filename_dst;
334 if (type == EV_COMPRESSION_NONE)
337 cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND);
339 /* FIXME: better error codes! */
340 /* FIXME: i18n later */
341 g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
342 "Failed to find the \"%s\" command in the search path.",
343 type == EV_COMPRESSION_BZIP2 ? BZIPCOMMAND : GZIPCOMMAND);
347 filename = g_filename_from_uri (uri, NULL, error);
353 filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
354 fd = g_mkstemp (filename_dst);
360 g_free (filename_dst);
362 g_set_error (error, G_IO_ERROR,
363 g_io_error_from_errno (errsv),
364 "Error creating a temporary file: %s",
370 argv[1] = compress ? "-c" : "-cd";
374 if (g_spawn_async_with_pipes (NULL, argv, NULL,
375 G_SPAWN_STDERR_TO_DEV_NULL,
377 NULL, &pout, NULL, &err)) {
378 GIOChannel *in, *out;
379 gchar buf[BUFFER_SIZE];
380 GIOStatus read_st, write_st;
381 gsize bytes_read, bytes_written;
383 in = g_io_channel_unix_new (pout);
384 g_io_channel_set_encoding (in, NULL, NULL);
385 out = g_io_channel_unix_new (fd);
386 g_io_channel_set_encoding (out, NULL, NULL);
389 read_st = g_io_channel_read_chars (in, buf,
393 if (read_st == G_IO_STATUS_NORMAL) {
394 write_st = g_io_channel_write_chars (out, buf,
398 if (write_st == G_IO_STATUS_ERROR)
400 } else if (read_st == G_IO_STATUS_ERROR) {
403 } while (bytes_read > 0);
405 g_io_channel_unref (in);
406 g_io_channel_unref (out);
412 g_propagate_error (error, err);
414 uri_dst = g_filename_to_uri (filename_dst, NULL, error);
419 g_free (filename_dst);
425 * ev_file_uncompress:
427 * @type: the compression type
428 * @error: a #GError location to store an error, or %NULL
430 * Uncompresses the file at @uri.
432 * If @type is %EV_COMPRESSION_NONE, it does nothing and returns %NULL.
434 * Otherwise, it returns the filename of a
435 * temporary file containing the decompressed data from the file at @uri.
436 * On error it returns %NULL and fills in @error.
438 * It is the caller's responsibility to unlink the temp file after use.
440 * Returns: a newly allocated string URI, or %NULL on error
443 ev_file_uncompress (const gchar *uri,
444 EvCompressionType type,
447 g_return_val_if_fail (uri != NULL, NULL);
449 return compression_run (uri, type, FALSE, error);
455 * @type: the compression type
456 * @error: a #GError location to store an error, or %NULL
458 * Compresses the file at @uri.
460 * If @type is %EV_COMPRESSION_NONE, it does nothing and returns %NULL.
462 * Otherwise, it returns the filename of a
463 * temporary file containing the compressed data from the file at @uri.
465 * On error it returns %NULL and fills in @error.
467 * It is the caller's responsibility to unlink the temp file after use.
469 * Returns: a newly allocated string URI, or %NULL on error
472 ev_file_compress (const gchar *uri,
473 EvCompressionType type,
476 g_return_val_if_fail (uri != NULL, NULL);
478 return compression_run (uri, type, TRUE, error);