mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2024-12-28 08:56:01 +01:00
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:
parent
d1c38a703c
commit
e550ab66ee
8 changed files with 123 additions and 41 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue