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 <sebastian+dev@ramacher.at>
This commit is contained in:
Sebastian Ramacher 2016-01-20 13:45:46 +01:00
parent d1c38a703c
commit e550ab66ee
8 changed files with 123 additions and 41 deletions

View file

@ -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
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;
}

View file

@ -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

View file

@ -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);

View file

@ -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);
/**

View file

@ -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

View file

@ -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;

View file

@ -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) {

View file

@ -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;
};
/**