From e550ab66ee1b89b1d9439e8dc6d204f1200dcdf3 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Wed, 20 Jan 2016 13:45:46 +0100 Subject: [PATCH] Reduce amount of leaked memory by libmagic libmagic always leaks 48 bytes. Now we leak those bytes only once instead of every content type detection. Signed-off-by: Sebastian Ramacher --- zathura/content-type.c | 82 ++++++++++++++++++++++++++++++++---------- zathura/content-type.h | 19 +++++++++- zathura/document.c | 10 +++--- zathura/document.h | 6 ++-- zathura/types.h | 25 +++++++------ zathura/utils.c | 6 ++-- zathura/zathura.c | 9 ++++- zathura/zathura.h | 7 ++++ 8 files changed, 123 insertions(+), 41 deletions(-) diff --git a/zathura/content-type.c b/zathura/content-type.c index 5edcf10..9352da1 100644 --- a/zathura/content-type.c +++ b/zathura/content-type.c @@ -17,14 +17,23 @@ #include #include -/** Read a most GT_MAX_READ bytes before falling back to file. */ -static const size_t GT_MAX_READ = 1 << 16; +struct zathura_content_type_context_s +{ +#ifdef WITH_MAGIC + magic_t magic; +#endif +}; + +zathura_content_type_context_t* +zathura_content_type_new(void) +{ + zathura_content_type_context_t* context = + g_try_malloc0(sizeof(zathura_content_type_context_t)); + if (context == NULL) { + return NULL; + } #ifdef WITH_MAGIC -static const char* -guess_type_magic(const char* path) { - const char* mime_type = NULL; - /* creat magic cookie */ const int flags = MAGIC_MIME_TYPE | @@ -36,31 +45,63 @@ guess_type_magic(const char* path) { magic_t magic = magic_open(flags); if (magic == NULL) { girara_debug("failed creating the magic cookie"); - goto cleanup; + return context; } /* ... and load mime database */ if (magic_load(magic, NULL) < 0) { girara_debug("failed loading the magic database: %s", magic_error(magic)); - goto cleanup; + magic_close(magic); + return context; } + context->magic = magic; +#endif + + return context; +} + +void +zathura_content_type_free(zathura_content_type_context_t* context) +{ + if (context == NULL) { + return; + } + +#ifdef WITH_MAGIC + if (context->magic != NULL) { + magic_close(context->magic); + } +#endif + + g_free(context); +} + + +/** Read a most GT_MAX_READ bytes before falling back to file. */ +static const size_t GT_MAX_READ = 1 << 16; + +#ifdef WITH_MAGIC +static const char* +guess_type_magic(zathura_content_type_context_t* context, const char* path) +{ + if (context == NULL || context->magic == NULL) { + return NULL; + } + + const char* mime_type = NULL; + /* get the mime type */ - mime_type = magic_file(magic, path); + mime_type = magic_file(context->magic, path); if (mime_type == NULL) { - girara_debug("failed guessing filetype: %s", magic_error(magic)); - goto cleanup; + girara_debug("failed guessing filetype: %s", magic_error(context->magic)); + return NULL; } /* dup so we own the memory */ mime_type = g_strdup(mime_type); girara_debug("magic detected filetype: %s", mime_type); -cleanup: - if (magic != NULL) { - magic_close(magic); - } - return mime_type; } @@ -71,7 +112,9 @@ guess_type_file(const char* UNUSED(path)) } #else static const char* -guess_type_magic(const char* UNUSED(path)) { +guess_type_magic(zathura_content_type_context_t* UNUSED(context), + const char* UNUSED(path)) +{ return NULL; } @@ -161,10 +204,11 @@ guess_type_glib(const char* path) } const char* -guess_content_type(const char* path) +zathura_content_type_guess(zathura_content_type_context_t* context, + const char* path) { /* try libmagic first */ - const char* content_type = guess_type_magic(path); + const char* content_type = guess_type_magic(context, path); if (content_type != NULL) { return content_type; } diff --git a/zathura/content-type.h b/zathura/content-type.h index fca53d1..c02d937 100644 --- a/zathura/content-type.h +++ b/zathura/content-type.h @@ -3,6 +3,22 @@ #ifndef ZATHURA_CONTENT_TYPE_H #define ZATHURA_CONTENT_TYPE_H +#include "types.h" + +/** + * Create new context for MIME type detection. + * + * @return new context + */ +zathura_content_type_context_t* zathura_content_type_new(void); + +/** + * Free MIME type detection context. + * + * @param context The context. + */ +void zathura_content_type_free(zathura_content_type_context_t* context); + /** * "Guess" the content type of a file. Various methods are tried depending on * the available libraries. @@ -10,6 +26,7 @@ * @param path file name * @return content type of path */ -const char* guess_content_type(const char* path); +const char* zathura_content_type_guess(zathura_content_type_context_t* context, + const char* path); #endif diff --git a/zathura/document.c b/zathura/document.c index fb03f65..f4563b7 100644 --- a/zathura/document.c +++ b/zathura/document.c @@ -61,10 +61,10 @@ check_set_error(zathura_error_t* error, zathura_error_t code) { } zathura_document_t* -zathura_document_open(zathura_plugin_manager_t* plugin_manager, const char* - path, const char *uri, const char* password, zathura_error_t* error) +zathura_document_open(zathura_t* zathura, const char* path, const char* uri, + const char* password, zathura_error_t* error) { - if (path == NULL) { + if (zathura == NULL || path == NULL) { return NULL; } @@ -87,14 +87,14 @@ zathura_document_open(zathura_plugin_manager_t* plugin_manager, const char* goto error_free; } - content_type = guess_content_type(real_path); + content_type = zathura_content_type_guess(zathura->content_type_context, real_path); if (content_type == NULL) { girara_error("Could not determine file type."); check_set_error(error, ZATHURA_ERROR_UNKNOWN); goto error_free; } - plugin = zathura_plugin_manager_get_plugin(plugin_manager, content_type); + plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type); if (plugin == NULL) { girara_error("Unknown file type: '%s'", content_type); diff --git a/zathura/document.h b/zathura/document.h index 6880d07..8992dab 100644 --- a/zathura/document.h +++ b/zathura/document.h @@ -11,14 +11,14 @@ /** * Open the document * - * @param plugin_manager The plugin manager + * @param plugin_manager The zathura instance * @param path Path to the document * @param password Password of the document or NULL * @param error Optional error parameter * @return The document object and NULL if an error occurs */ -zathura_document_t* zathura_document_open(zathura_plugin_manager_t* - plugin_manager, const char* path, const char *uri, const char* password, zathura_error_t* +zathura_document_t* zathura_document_open(zathura_t* zathura, + const char* path, const char *uri, const char* password, zathura_error_t* error); /** diff --git a/zathura/types.h b/zathura/types.h index 380e4f7..7f8a65e 100644 --- a/zathura/types.h +++ b/zathura/types.h @@ -148,7 +148,7 @@ typedef struct zathura_image_s typedef enum zathura_link_type_e { ZATHURA_LINK_INVALID, /**< Invalid type */ - ZATHURA_LINK_NONE, /**< No action */ + ZATHURA_LINK_NONE, /**< No action */ ZATHURA_LINK_GOTO_DEST, /**< Links to a page */ ZATHURA_LINK_GOTO_REMOTE, /**< Links to a page */ ZATHURA_LINK_URI, /**< Links to an external source */ @@ -158,15 +158,15 @@ typedef enum zathura_link_type_e typedef enum zathura_link_destination_type_e { - ZATHURA_LINK_DESTINATION_UNKNOWN, - ZATHURA_LINK_DESTINATION_XYZ, - ZATHURA_LINK_DESTINATION_FIT, - ZATHURA_LINK_DESTINATION_FITH, - ZATHURA_LINK_DESTINATION_FITV, - ZATHURA_LINK_DESTINATION_FITR, - ZATHURA_LINK_DESTINATION_FITB, - ZATHURA_LINK_DESTINATION_FITBH, - ZATHURA_LINK_DESTINATION_FITBV + ZATHURA_LINK_DESTINATION_UNKNOWN, + ZATHURA_LINK_DESTINATION_XYZ, + ZATHURA_LINK_DESTINATION_FIT, + ZATHURA_LINK_DESTINATION_FITH, + ZATHURA_LINK_DESTINATION_FITV, + ZATHURA_LINK_DESTINATION_FITR, + ZATHURA_LINK_DESTINATION_FITB, + ZATHURA_LINK_DESTINATION_FITBH, + ZATHURA_LINK_DESTINATION_FITBV } zathura_link_destination_type_t; typedef struct zathura_link_target_s @@ -255,4 +255,9 @@ zathura_document_information_entry_new(zathura_document_information_type_t */ void zathura_document_information_entry_free(zathura_document_information_entry_t* entry); +/** + * Context for MIME type detection + */ +typedef struct zathura_content_type_context_s zathura_content_type_context_t; + #endif // TYPES_H diff --git a/zathura/utils.c b/zathura/utils.c index 531196c..ea5bc2b 100644 --- a/zathura/utils.c +++ b/zathura/utils.c @@ -52,12 +52,14 @@ file_valid_extension(zathura_t* zathura, const char* path) return false; } - const gchar* content_type = guess_content_type(path); + const gchar* content_type = + zathura_content_type_guess(zathura->content_type_context, path); if (content_type == NULL) { return false; } - zathura_plugin_t* plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type); + zathura_plugin_t* plugin = + zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type); g_free((void*)content_type); return (plugin == NULL) ? false : true; diff --git a/zathura/zathura.c b/zathura/zathura.c index 87f4adc..163063b 100644 --- a/zathura/zathura.c +++ b/zathura/zathura.c @@ -43,6 +43,7 @@ #include "dbus-interface.h" #include "css-definitions.h" #include "synctex.h" +#include "content-type.h" typedef struct zathura_document_info_s { zathura_t* zathura; @@ -103,6 +104,9 @@ zathura_create(void) zathura->signals.sigterm = g_unix_signal_add(SIGTERM, zathura_signal_sigterm, zathura); #endif + /* MIME type detection */ + zathura->content_type_context = zathura_content_type_new(); + zathura->ui.session->global.data = zathura; return zathura; @@ -376,6 +380,9 @@ zathura_free(zathura_t* zathura) document_close(zathura, false); + /* MIME type detection */ + zathura_content_type_free(zathura->content_type_context); + #ifdef G_OS_UNIX if (zathura->signals.sigterm > 0) { g_source_remove(zathura->signals.sigterm); @@ -760,7 +767,7 @@ document_open(zathura_t* zathura, const char* path, const char* uri, const char* gchar* file_uri = NULL; zathura_error_t error = ZATHURA_ERROR_OK; - zathura_document_t* document = zathura_document_open(zathura->plugins.manager, path, uri, password, &error); + zathura_document_t* document = zathura_document_open(zathura, path, uri, password, &error); if (document == NULL) { if (error == ZATHURA_ERROR_INVALID_PASSWORD) { diff --git a/zathura/zathura.h b/zathura/zathura.h index e536b56..66b3744 100644 --- a/zathura/zathura.h +++ b/zathura/zathura.h @@ -6,7 +6,9 @@ #include #include #include +#ifdef GDK_WINDOWING_X11 #include +#endif #include "macros.h" #include "types.h" @@ -222,6 +224,11 @@ struct zathura_s double zoom; } toggle_presentation_mode; } shortcut; + + /** + * Context for MIME type detection + */ + zathura_content_type_context_t* content_type_context; }; /**