How to write a plugin

Tagsistant uses dlopen() suite of functions to include external components. Mainly, Tagsistant uses external plugins to implement auto-tagging. Each plugin registers a MIME-type and is then called during a stack walking procedure to give it the opportunity of managing data.

The plugin can then return a code meaning “I’ve done!” or “Some other plugin can add more action for this file” or “I’ve no chance to do anything on that!”.

Let’s see how is structured a plugin using the HTML plugin as a reference.

#include "tagsistant.h"
#define DEFAULT_TAG "document"

/* declaring mime type */
char mime_type[] = "text/html";

First of all, import tagsistant.h to have all the symbols available. Then define a preprocessor macro DEFAULT_TAG with the tag the files will be tagged as, and a string called mime_type which describes the exact MIME-type, like in text/html.

/* exported init function */
int plugin_init()
{
	return 1;
}

/* exported finalize function */
void plugin_free()
{
}

The plugin_init() function is used by tagsistant while loading the plugin to execute some code that needs to be initialized, like calling a library entry point or creating some dynamic structures in memory.

Easy to guess, plugin_free() is the opposite. It’s called on program exit to unregister other code, free memory and clean up.

/* exported processor function */
int processor(const tagsistant_querytree *qtree)
{
	dbg(LOG_INFO, "Taggings %s as %s", filename, DEFAULT_TAG);
	tagsistant_sql_tag_object(qtree->dbi, DEFAULT_TAG, qtree->inode);
	tagsistant_sql_tag_object(qtree->dbi, "another_tag", qtree->inode);
	return TP_STOP;
}

processor() function is the hook Tagsistant registers to later call the plugin during stack walking. It just receives the path of the file as first argument. As you can see, many symbols are available to plugins. You can use dbg(level, format, …) macro to send lines to syslog or stderr. To tag files, you must use the Tagsistant function tag_file(filename, tagname) which accepts the file name as first argument (char *) and the tag as second argument (also char *).

Pay attention in returning a meaningful value. The available values can be found in tagsistant.h, and are:

#define TP_ERROR 0  /* an error occurred while processing with this plugin */
#define TP_OK    1  /* ok, but further tagging can be done by other plugins */
#define TP_STOP	 2  /* this plugin is authoritative for mimetype, stop chaining */
#define TP_NULL	 3  /* no tagging has been done, but that is not an error */

Defining a preprocessor symbol called DEFAULT_TAG is not mandatory, since all the occurrences will be inside processor() function, but will make plugin understanding a lot easier, by locating on its top the tag that the plugin creates.