X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=libdocument%2Fev-file-helpers.c;h=3da4a59832d5031bedac8c19a00c3ef62fc4686b;hb=776a6fe02961d8901d21e172633d3c8d1c85dc93;hp=80254b3e69d649398f7ec1c3cac826d22babb082;hpb=83a7a11ba109b8aee5cdc047dec8b93967ccfc0e;p=evince.git diff --git a/libdocument/ev-file-helpers.c b/libdocument/ev-file-helpers.c index 80254b3e..3da4a598 100644 --- a/libdocument/ev-file-helpers.c +++ b/libdocument/ev-file-helpers.c @@ -30,65 +30,40 @@ #include #include -#if WITH_GNOME -#include -#endif - #include "ev-file-helpers.h" -static gchar *dot_dir = NULL; static gchar *tmp_dir = NULL; static gint count = 0; -static gboolean -ensure_dir_exists (const char *dir) +gboolean +ev_dir_ensure_exists (const gchar *dir, + int mode) { - if (g_file_test (dir, G_FILE_TEST_IS_DIR)) - return TRUE; - - if (g_mkdir_with_parents (dir, 488) == 0) + if (g_mkdir_with_parents (dir, mode) == 0) return TRUE; if (errno == EEXIST) return g_file_test (dir, G_FILE_TEST_IS_DIR); - g_warning ("Failed to create directory %s: %s", dir, strerror (errno)); + g_warning ("Failed to create directory %s: %s", dir, g_strerror (errno)); return FALSE; } -const gchar * -ev_dot_dir (void) -{ - if (dot_dir == NULL) { - gboolean exists; - - dot_dir = g_build_filename (g_get_home_dir (), - ".gnome2", - "evince", - NULL); - - exists = ensure_dir_exists (dot_dir); - if (!exists) - exit (1); - } - - return dot_dir; -} - const gchar * ev_tmp_dir (void) { if (tmp_dir == NULL) { gboolean exists; - gchar *dirname; + gchar *dirname, *prgname; - dirname = g_strdup_printf ("evince-%u", getpid ()); + prgname = g_get_prgname (); + dirname = g_strdup_printf ("%s-%u", prgname ? prgname : "unknown", getpid ()); tmp_dir = g_build_filename (g_get_tmp_dir (), dirname, NULL); g_free (dirname); - exists = ensure_dir_exists (tmp_dir); + exists = ev_dir_ensure_exists (tmp_dir, 0700); g_assert (exists); } @@ -96,20 +71,17 @@ ev_tmp_dir (void) } void -ev_file_helpers_init (void) +_ev_file_helpers_init (void) { } void -ev_file_helpers_shutdown (void) +_ev_file_helpers_shutdown (void) { if (tmp_dir != NULL) g_rmdir (tmp_dir); g_free (tmp_dir); - g_free (dot_dir); - - dot_dir = NULL; tmp_dir = NULL; } @@ -150,6 +122,12 @@ ev_tmp_filename (const gchar *prefix) return filename; } +gchar * +ev_tmp_directory (const gchar *prefix) +{ + return ev_tmp_filename (prefix ? prefix : "directory"); +} + /* Remove a local temp file created by evince */ void ev_tmp_filename_unlink (const gchar *filename) @@ -169,17 +147,19 @@ void ev_tmp_file_unlink (GFile *file) { gboolean res; + GError *error = NULL; if (!file) return; - res = g_file_delete (file, NULL, NULL); + res = g_file_delete (file, NULL, &error); if (!res) { char *uri; uri = g_file_get_uri (file); - g_warning ("Unable to delete temp file %s\n", uri); + g_warning ("Unable to delete temp file %s: %s\n", uri, error->message); g_free (uri); + g_error_free (error); } } @@ -202,6 +182,16 @@ ev_tmp_uri_unlink (const gchar *uri) g_object_unref (file); } +/** + * ev_xfer_uri_simple: + * @from: the source URI + * @to: the target URI + * @error: a #GError location to store an error, or %NULL + * + * Performs a g_file_copy() from @from to @to. + * + * Returns: %TRUE on success, or %FALSE on error with @error filled in + */ gboolean ev_xfer_uri_simple (const char *from, const char *to, @@ -209,27 +199,117 @@ ev_xfer_uri_simple (const char *from, { GFile *source_file; GFile *target_file; - GError *ioerror; gboolean result; if (!from) - return FALSE; - + return TRUE; + + g_return_val_if_fail (to != NULL, TRUE); + source_file = g_file_new_for_uri (from); target_file = g_file_new_for_uri (to); result = g_file_copy (source_file, target_file, +#if GLIB_CHECK_VERSION(2,19,0) + G_FILE_COPY_TARGET_DEFAULT_PERMS | +#endif G_FILE_COPY_OVERWRITE, - NULL, NULL, NULL, &ioerror); + NULL, NULL, NULL, error); g_object_unref (target_file); g_object_unref (source_file); - if (!result) { - g_propagate_error (error, ioerror); - } return result; +} + +static gchar * +get_mime_type_from_uri (const gchar *uri, GError **error) +{ + GFile *file; + GFileInfo *file_info; + const gchar *content_type; + gchar *mime_type = NULL; + + file = g_file_new_for_uri (uri); + file_info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + 0, NULL, error); + g_object_unref (file); + if (file_info == NULL) + return NULL; + + content_type = g_file_info_get_content_type (file_info); + if (content_type) { + mime_type = g_content_type_get_mime_type (content_type); + } + + g_object_unref (file_info); + return mime_type; +} + +static gchar * +get_mime_type_from_data (const gchar *uri, GError **error) +{ + GFile *file; + GFileInputStream *input_stream; + gssize size_read; + guchar buffer[1024]; + gboolean retval; + gchar *content_type, *mime_type; + + file = g_file_new_for_uri (uri); + + input_stream = g_file_read (file, NULL, error); + if (!input_stream) { + g_object_unref (file); + return NULL; + } + + size_read = g_input_stream_read (G_INPUT_STREAM (input_stream), + buffer, sizeof (buffer), NULL, error); + if (size_read == -1) { + g_object_unref (input_stream); + g_object_unref (file); + return NULL; + } + + retval = g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, error); + + g_object_unref (input_stream); + g_object_unref (file); + if (!retval) + return NULL; + + content_type = g_content_type_guess (NULL, /* no filename */ + buffer, size_read, + NULL); + if (!content_type) + return NULL; + + mime_type = g_content_type_get_mime_type (content_type); + g_free (content_type); + return mime_type; +} + +/** + * ev_file_get_mime_type: + * @uri: the URI + * @fast: whether to use fast MIME type detection + * @error: a #GError location to store an error, or %NULL + * + * Note: on unknown MIME types, this may return NULL without @error + * being filled in. + * + * Returns: a newly allocated string with the MIME type of the file at + * @uri, or %NULL on error or if the MIME type could not be determined + */ +gchar * +ev_file_get_mime_type (const gchar *uri, + gboolean fast, + GError **error) +{ + return fast ? get_mime_type_from_uri (uri, error) : get_mime_type_from_data (uri, error); } /* Compressed files support */ @@ -249,15 +329,22 @@ compression_run (const gchar *uri, gchar *filename, *filename_dst; gchar *cmd; gint fd, pout; + GError *err = NULL; if (type == EV_COMPRESSION_NONE) return NULL; cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND); - if (!cmd) + if (!cmd) { + /* FIXME: better error codes! */ + /* FIXME: i18n later */ + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, + "Failed to find the \"%s\" command in the search path.", + type == EV_COMPRESSION_BZIP2 ? BZIPCOMMAND : GZIPCOMMAND); return NULL; + } - filename = g_filename_from_uri (uri, NULL, NULL); + filename = g_filename_from_uri (uri, NULL, error); if (!filename) { g_free (cmd); return NULL; @@ -266,9 +353,16 @@ compression_run (const gchar *uri, filename_dst = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL); fd = g_mkstemp (filename_dst); if (fd < 0) { + int errsv = errno; + g_free (cmd); g_free (filename); g_free (filename_dst); + + g_set_error (error, G_IO_ERROR, + g_io_error_from_errno (errsv), + "Error creating a temporary file: %s", + g_strerror (errsv)); return NULL; } @@ -280,7 +374,7 @@ compression_run (const gchar *uri, if (g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, - NULL, &pout, NULL, error)) { + NULL, &pout, NULL, &err)) { GIOChannel *in, *out; gchar buf[BUFFER_SIZE]; GIOStatus read_st, write_st; @@ -314,8 +408,10 @@ compression_run (const gchar *uri, close (fd); - if (*error == NULL) { - uri_dst = g_filename_to_uri (filename_dst, NULL, NULL); + if (err) { + g_propagate_error (error, err); + } else { + uri_dst = g_filename_to_uri (filename_dst, NULL, error); } g_free (cmd); @@ -325,6 +421,24 @@ compression_run (const gchar *uri, return uri_dst; } +/** + * ev_file_uncompress: + * @uri: a file URI + * @type: the compression type + * @error: a #GError location to store an error, or %NULL + * + * Uncompresses the file at @uri. + * + * If @type is %EV_COMPRESSION_NONE, it does nothing and returns %NULL. + * + * Otherwise, it returns the filename of a + * temporary file containing the decompressed data from the file at @uri. + * On error it returns %NULL and fills in @error. + * + * It is the caller's responsibility to unlink the temp file after use. + * + * Returns: a newly allocated string URI, or %NULL on error + */ gchar * ev_file_uncompress (const gchar *uri, EvCompressionType type, @@ -335,6 +449,25 @@ ev_file_uncompress (const gchar *uri, return compression_run (uri, type, FALSE, error); } +/** + * ev_file_compress: + * @uri: a file URI + * @type: the compression type + * @error: a #GError location to store an error, or %NULL + * + * Compresses the file at @uri. + + * If @type is %EV_COMPRESSION_NONE, it does nothing and returns %NULL. + * + * Otherwise, it returns the filename of a + * temporary file containing the compressed data from the file at @uri. + * + * On error it returns %NULL and fills in @error. + * + * It is the caller's responsibility to unlink the temp file after use. + * + * Returns: a newly allocated string URI, or %NULL on error + */ gchar * ev_file_compress (const gchar *uri, EvCompressionType type,