Commit e550ab66 authored by Sebastian Ramacher's avatar Sebastian Ramacher

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's avatarSebastian Ramacher <sebastian+dev@ramacher.at>
parent d1c38a70
......@@ -17,14 +17,23 @@
#include <glib.h>
#include <gio/gio.h>
/** 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
static const char*
guess_type_magic(const char* path) {
const char* mime_type = NULL;
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
/* 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;
}
......
......@@ -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
......@@ -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);
......
......@@ -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);
/**
......
......@@ -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
......@@ -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;
......
......@@ -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) {
......
......@@ -6,7 +6,9 @@
#include <stdbool.h>
#include <girara/types.h>
#include <gtk/gtk.h>
#ifdef GDK_WINDOWING_X11
#include <gtk/gtkx.h>
#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;
};
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment