[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r22813 - in Extractor: . doc src/include src/main
From: |
gnunet |
Subject: |
[GNUnet-SVN] r22813 - in Extractor: . doc src/include src/main |
Date: |
Sun, 22 Jul 2012 00:34:27 +0200 |
Author: grothoff
Date: 2012-07-22 00:34:27 +0200 (Sun, 22 Jul 2012)
New Revision: 22813
Added:
Extractor/src/main/extractor_datasource.c
Extractor/src/main/extractor_datasource.h
Extractor/src/main/extractor_ipc.h
Extractor/src/main/extractor_ipc_gnu.c
Extractor/src/main/extractor_ipc_w32.c
Modified:
Extractor/INSTALL
Extractor/doc/version.texi
Extractor/src/include/extractor.h
Extractor/src/main/Makefile.am
Extractor/src/main/extract.c
Extractor/src/main/extractor.c
Extractor/src/main/extractor_plugins.c
Extractor/src/main/extractor_plugins.h
Extractor/src/main/extractor_plugpath.c
Extractor/src/main/extractor_plugpath.h
Extractor/src/main/extractor_print.c
Log:
-towards a new LE core library with cleaner apis, does not currently compile
Modified: Extractor/INSTALL
===================================================================
--- Extractor/INSTALL 2012-07-21 13:55:13 UTC (rev 22812)
+++ Extractor/INSTALL 2012-07-21 22:34:27 UTC (rev 22813)
@@ -1,8 +1,8 @@
Installation Instructions
*************************
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
+Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
@@ -226,6 +226,11 @@
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+ HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved. Use GNU `make'
+instead.
+
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
Modified: Extractor/doc/version.texi
===================================================================
--- Extractor/doc/version.texi 2012-07-21 13:55:13 UTC (rev 22812)
+++ Extractor/doc/version.texi 2012-07-21 22:34:27 UTC (rev 22813)
@@ -1,4 +1,4 @@
address@hidden UPDATED 29 January 2012
address@hidden UPDATED-MONTH January 2012
address@hidden UPDATED 12 May 2012
address@hidden UPDATED-MONTH May 2012
@set EDITION 0.6.3
@set VERSION 0.6.3
Modified: Extractor/src/include/extractor.h
===================================================================
--- Extractor/src/include/extractor.h 2012-07-21 13:55:13 UTC (rev 22812)
+++ Extractor/src/include/extractor.h 2012-07-21 22:34:27 UTC (rev 22813)
@@ -1,6 +1,6 @@
/*
This file is part of libextractor.
- (C) 2002, 2003, 2004, 2005, 2006, 2009 Vidyut Samanta and Christian
Grothoff
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -32,7 +32,7 @@
* 0.2.6-1 => 0x00020601
* 4.5.2-0 => 0x04050200
*/
-#define EXTRACTOR_VERSION 0x00060301
+#define EXTRACTOR_VERSION 0x00060900
#include <stdio.h>
@@ -331,7 +331,7 @@
* translate using 'dgettext ("libextractor", rval)'
*/
const char *
-EXTRACTOR_metatype_to_string(enum EXTRACTOR_MetaType type);
+EXTRACTOR_metatype_to_string (enum EXTRACTOR_MetaType type);
/**
@@ -343,7 +343,7 @@
* translate using 'dgettext ("libextractor", rval)'
*/
const char *
-EXTRACTOR_metatype_to_description(enum EXTRACTOR_MetaType type);
+EXTRACTOR_metatype_to_description (enum EXTRACTOR_MetaType type);
/**
@@ -372,27 +372,85 @@
* @param data_len number of bytes in data
* @return 0 to continue extracting, 1 to abort
*/
-typedef int (*EXTRACTOR_MetaDataProcessor)(void *cls,
- const char *plugin_name,
- enum EXTRACTOR_MetaType type,
- enum EXTRACTOR_MetaFormat format,
- const char *data_mime_type,
- const char *data,
- size_t data_len);
+typedef int (*EXTRACTOR_MetaDataProcessor) (void *cls,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len);
-
+
/**
+ * Context provided for plugins that perform meta data extraction.
+ */
+struct EXTRACTOR_ExtractContext
+{
+
+ /**
+ * Closure argument to pass to all callbacks.
+ */
+ void *cls;
+
+ /**
+ * Configuration string for the plugin.
+ */
+ const char *config;
+
+ /**
+ * Obtain a pointer to up to 'size' bytes of data from the file to process.
+ *
+ * @param cls the 'cls' member of this struct
+ * @param data pointer to set to the file data, set to NULL on error
+ * @param size maximum number of bytes requested
+ * @return number of bytes now available in data (can be smaller than
'size'),
+ * -1 on error
+ */
+ ssize_t (*read) (void *cls,
+ unsigned char **data,
+ size_t size);
+
+
+ /**
+ * Seek in the file. Use 'SEEK_CUR' for whence and 'pos' of 0 to
+ * obtain the current position in the file.
+ *
+ * @param cls the 'cls' member of this struct
+ * @param pos position to seek (see 'man lseek')
+ * @param whence how to see (absolute to start, relative, absolute to end)
+ * @return new absolute position, UINT64_MAX on error (i.e. desired position
+ * does not exist)
+ */
+ uint64_t (*seek) (void *cls,
+ int64_t pos,
+ int whence);
+
+
+ /**
+ * Determine the overall size of the file.
+ *
+ * @param cls the 'cls' member of this struct
+ * @return overall file size, UINT64_MAX on error (i.e. IPC failure)
+ */
+ uint64_t (*get_size) (void *cls);
+
+ /**
+ * Function to call on extracted data.
+ */
+ EXTRACTOR_MetaDataProcessor proc;
+
+};
+
+
+/**
* Signature of the extract method that each plugin
* must provide.
*
- * @param data data to process
- * @param datasize number of bytes available in data
- * @param proc function to call for meta data found
- * @param proc_cls cls argument to proc
- * @param options options for this plugin; can be NULL
- * @return 0 if all calls to proc returned 0, otherwise 1
+ * @param ec extraction context provided to the plugin
*/
+typedef void (*EXTRACTOR_extract_method) (struct EXTRACTOR_ExtractContext *ec);
+
/**
* Linked list of extractor plugins. An application builds this list
* by telling libextractor to load various keyword-extraction
@@ -401,11 +459,7 @@
*/
struct EXTRACTOR_PluginList;
-typedef int (*EXTRACTOR_extract_method) (struct EXTRACTOR_PluginList *plugin,
- EXTRACTOR_MetaDataProcessor proc, void *proc_cls);
-
-
/**
* Load the default set of plugins. The default can be changed
* by setting the LIBEXTRACTOR_LIBRARIES environment variable;
@@ -428,7 +482,7 @@
* @return the default set of plugins, NULL if no plugins were found
*/
struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_add_defaults(enum EXTRACTOR_Options flags);
+EXTRACTOR_plugin_add_defaults (enum EXTRACTOR_Options flags);
/**
@@ -442,10 +496,11 @@
*/
struct EXTRACTOR_PluginList *
EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList * prev,
- const char * library,
+ const char *library,
const char *options,
enum EXTRACTOR_Options flags);
+
/**
* Load multiple libraries as specified by the user.
*
@@ -462,7 +517,7 @@
* or if config was empty (or NULL).
*/
struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList * prev,
+EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev,
const char *config,
enum EXTRACTOR_Options flags);
@@ -475,8 +530,8 @@
* @return the reduced list, unchanged if the plugin was not loaded
*/
struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_remove(struct EXTRACTOR_PluginList * prev,
- const char * library);
+EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *prev,
+ const char *library);
/**
@@ -485,7 +540,7 @@
* @param plugin the list of plugins
*/
void
-EXTRACTOR_plugin_remove_all(struct EXTRACTOR_PluginList *plugins);
+EXTRACTOR_plugin_remove_all (struct EXTRACTOR_PluginList *plugins);
/**
@@ -500,12 +555,12 @@
* @param proc_cls cls argument to proc
*/
void
-EXTRACTOR_extract(struct EXTRACTOR_PluginList *plugins,
- const char *filename,
- const void *data,
- size_t size,
- EXTRACTOR_MetaDataProcessor proc,
- void *proc_cls);
+EXTRACTOR_extract (struct EXTRACTOR_PluginList *plugins,
+ const char *filename,
+ const void *data,
+ size_t size,
+ EXTRACTOR_MetaDataProcessor proc,
+ void *proc_cls);
/**
@@ -525,13 +580,13 @@
* @return non-zero if printing failed, otherwise 0.
*/
int
-EXTRACTOR_meta_data_print(void * handle,
- const char *plugin_name,
- enum EXTRACTOR_MetaType type,
- enum EXTRACTOR_MetaFormat format,
- const char *data_mime_type,
- const char *data,
- size_t data_len);
+EXTRACTOR_meta_data_print (void * handle,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len);
#if 0 /* keep Emacsens' auto-indent happy */
Modified: Extractor/src/main/Makefile.am
===================================================================
--- Extractor/src/main/Makefile.am 2012-07-21 13:55:13 UTC (rev 22812)
+++ Extractor/src/main/Makefile.am 2012-07-21 22:34:27 UTC (rev 22813)
@@ -28,6 +28,11 @@
libextractor_la_LIBADD = \
$(LIBLTDL) $(zlib) $(bz2lib) $(LTLIBICONV)
+if WINDOWS
+EXTRACTOR_IPC=extractor_ipc_w32.c
+else
+EXTRACTOR_IPC=extractor_ipc_gnu.c
+endif
EXTRA_DIST = \
iconv.c fuzz_default.sh fuzz_thumbnail.sh
@@ -36,16 +41,15 @@
libextractor_la_SOURCES = \
extractor.c \
- extractor_plugpath.c \
- extractor_plugins.c \
+ $(EXTRACTOR_IPC) extractor_ipc.h \
+ extractor_plugpath.c extractor_plugpath.h \
+ extractor_plugins.c extractor_plugins.h \
extractor_metatypes.c \
extractor_print.c
extract_SOURCES = \
extract.c \
- getopt.c \
- getopt.h \
- getopt1.c
+ getopt.c getopt.h getopt1.c
LDADD = \
Modified: Extractor/src/main/extract.c
===================================================================
--- Extractor/src/main/extract.c 2012-07-21 13:55:13 UTC (rev 22812)
+++ Extractor/src/main/extract.c 2012-07-21 22:34:27 UTC (rev 22813)
@@ -4,7 +4,7 @@
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
+ by the Free Software Foundation; either version 3, or (at your
option) any later version.
libextractor is distributed in the hope that it will be useful, but
Modified: Extractor/src/main/extractor.c
===================================================================
--- Extractor/src/main/extractor.c 2012-07-21 13:55:13 UTC (rev 22812)
+++ Extractor/src/main/extractor.c 2012-07-21 22:34:27 UTC (rev 22813)
@@ -1,10 +1,10 @@
/*
This file is part of libextractor.
- (C) 2002, 2003, 2004, 2005, 2006, 2009 Vidyut Samanta and Christian
Grothoff
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
+ by the Free Software Foundation; either version 3, or (at your
option) any later version.
libextractor is distributed in the hope that it will be useful, but
@@ -23,30 +23,21 @@
#include "extractor.h"
#include <dirent.h>
#include <sys/types.h>
-#if !WINDOWS
-#include <sys/wait.h>
-#include <sys/shm.h>
-#endif
#include <signal.h>
#include <ltdl.h>
-#if HAVE_LIBBZ2
-#include <bzlib.h>
-#endif
-
-#if HAVE_ZLIB
-#include <zlib.h>
-#endif
-
+#include "extractor_datasource.h"
+#include "extractor_ipc.h"
#include "extractor_plugpath.h"
#include "extractor_plugins.h"
/**
- * How many bytes do we actually try to scan? (from the beginning
- * of the file). Limit to 32 MB.
+ * How long do we allow an individual meta data object to be?
+ * Used to guard against (broken) plugns causing us to use
+ * excessive amounts of memory.
*/
-#define MAX_READ 32 * 1024 * 1024
+#define MAX_META_DATA 32 * 1024 * 1024
/**
* Maximum length of a Mime-Type string.
@@ -129,87 +120,38 @@
*/
struct IpcHeader
{
+ /**
+ * Type of the meta data.
+ */
enum EXTRACTOR_MetaType meta_type;
+
+ /**
+ * Format of the meta data.
+ */
enum EXTRACTOR_MetaFormat meta_format;
+
+ /**
+ * Number of bytes of meta data (value)
+ */
size_t data_len;
+
+ /**
+ * Length of the mime type string describing the meta data value's mime type,
+ * including 0-terminator, 0 for mime type of "NULL".
+ */
size_t mime_len;
};
-#if !WINDOWS
-/**
- * Opens a shared memory object (for later mmapping).
- * This is POSIX variant of the the plugin_open_* function. Shm is always
memory-backed.
- * Closes a shm is already opened, closes it before opening a new one.
- *
- * @param plugin plugin context
- * @param shm_name name of the shm.
- * @return shm id (-1 on error). That is, the result of shm_open() syscall.
- */
-static int
-plugin_open_shm (struct EXTRACTOR_PluginList *plugin, const char *shm_name)
-{
- if (plugin->shm_id != -1)
- close (plugin->shm_id);
- plugin->shm_id = shm_open (shm_name, O_RDONLY, 0);
- return plugin->shm_id;
-}
/**
- * Opens a file (for later mmapping).
- * This is POSIX variant of the plugin_open_* function.
- * Closes a file is already opened, closes it before opening a new one.
- *
- * @param plugin plugin context
- * @param shm_name name of the file to open.
- * @return file id (-1 on error). That is, the result of open() syscall.
- */
-static int
-plugin_open_file (struct EXTRACTOR_PluginList *plugin, const char *shm_name)
-{
- if (plugin->shm_id != -1)
- close (plugin->shm_id);
- plugin->shm_id = open (shm_name, O_RDONLY, 0);
- return plugin->shm_id;
-}
-#else
-/**
- * Opens a shared memory object (for later mmapping).
- * This is W32 variant of the plugin_open_* function.
- * Opened shm might be memory-backed or file-backed (depending on how
- * it was created). shm_name is never a file name, unlike POSIX.
- * Closes a shm is already opened, closes it before opening a new one.
- *
- * @param plugin plugin context
- * @param shm_name name of the shared memory object.
- * @return memory-mapped file handle (NULL on error). That is, the result of
OpenFileMapping() syscall.
- */
-HANDLE
-plugin_open_shm (struct EXTRACTOR_PluginList *plugin, const char *shm_name)
-{
- if (plugin->map_handle != 0)
- CloseHandle (plugin->map_handle);
- plugin->map_handle = OpenFileMapping (FILE_MAP_READ, FALSE, shm_name);
- return plugin->map_handle;
-}
-/**
- * Another name for plugin_open_shm().
- */
-HANDLE
-plugin_open_file (struct EXTRACTOR_PluginList *plugin, const char *shm_name)
-{
- return plugin_open_shm (plugin, shm_name);
-}
-#endif
-
-/**
- * Writes @size bytes from @buf into @fd, returns only when
- * writing is not possible, or when all @size bytes were written
+ * Writes 'size' bytes from 'buf' to 'fd', returns only when
+ * writing is not possible, or when all 'size' bytes were written
* (never does partial writes).
*
* @param fd fd to write into
* @param buf buffer to read from
* @param size number of bytes to write
- * @return number of bytes written (that is - @size), or -1 on error
+ * @return number of bytes written (that is 'size'), or -1 on error
*/
static int
write_all (int fd,
@@ -230,6 +172,7 @@
return size;
}
+
/**
* Function called by a plugin in a child process. Transmits
* the meta data back to the parent process.
@@ -256,13 +199,12 @@
const char *data,
size_t data_len)
{
+ static const unsigned char meta_byte = MESSAGE_META;
int *cpipe_out = cls;
struct IpcHeader hdr;
size_t mime_len;
- unsigned char meta_byte = MESSAGE_META;
- unsigned char zero_byte = 0;
- if (data_mime_type == NULL)
+ if (NULL == data_mime_type)
mime_len = 0;
else
mime_len = strlen (data_mime_type) + 1;
@@ -272,86 +214,24 @@
hdr.meta_format = format;
hdr.data_len = data_len;
hdr.mime_len = mime_len;
- if ((1 != write_all (*cpipe_out, &meta_byte, 1)) ||
- (sizeof(hdr) != write_all (*cpipe_out, &hdr, sizeof(hdr))) ||
- (mime_len -1 != write_all (*cpipe_out, data_mime_type, mime_len - 1)) ||
- (1 != write_all (*cpipe_out, &zero_byte, 1)) ||
- (data_len != write_all (*cpipe_out, data, data_len)))
+ if ( (sizeof (meta_byte) !=
+ write_all (*cpipe_out,
+ &meta_byte, sizeof (meta_byte))) ||
+ (sizeof (hdr) !=
+ write_all (*cpipe_out,
+ &hdr, sizeof (hdr))) ||
+ (mime_len !=
+ write_all (*cpipe_out,
+ data_mime_type, mime_len)) ||
+ (data_len !=
+ write_all (*cpipe_out,
+ data, data_len)) )
return 1;
return 0;
}
-/**
- * Initializes an extracting session for a plugin.
- * opens the file/shm (only in OPMODE_FILE)
- * sets shm_ptr to NULL (unmaps it, if it was mapped)
- * sets position to 0
- * initializes file size to @fsize (may be -1)
- * sets seek request to 0
- *
- * @param plugin plugin context
- * @param operation_mode the mode of operation (OPMODE_*)
- * @param fsize size of the source file (may be -1)
- * @param shm_name name of the shm or file to open
- * @return 0 on success, non-0 on error.
- */
-static int
-init_state_method (struct EXTRACTOR_PluginList *plugin, uint8_t
operation_mode, int64_t fsize, const char *shm_name)
-{
- plugin->seek_request = 0;
-#if !WINDOWS
- if (plugin->shm_ptr != NULL)
- munmap (plugin->shm_ptr, plugin->map_size);
- plugin->shm_ptr = NULL;
- if (operation_mode == OPMODE_FILE)
- {
- if (-1 == plugin_open_file (plugin, shm_name))
- return 1;
- }
- else if (-1 == plugin_open_shm (plugin, shm_name))
- return 1;
-#else
- if (plugin->shm_ptr != NULL)
- UnmapViewOfFile (plugin->shm_ptr);
- plugin->shm_ptr = NULL;
- if (INVALID_HANDLE_VALUE == plugin_open_shm (plugin, shm_name))
- return 1;
-#endif
- plugin->fsize = fsize;
- plugin->shm_pos = 0;
- plugin->fpos = 0;
- return 0;
-}
/**
- * Deinitializes an extracting session for a plugin.
- * unmaps shm_ptr (if was mapped)
- * closes file/shm (if it was opened)
- * sets map size and shm_ptr to NULL.
- *
- * @param plugin plugin context
- */
-static void
-discard_state_method (struct EXTRACTOR_PluginList *plugin)
-{
-#if !WINDOWS
- if (plugin->shm_ptr != NULL && plugin->map_size > 0)
- munmap (plugin->shm_ptr, plugin->map_size);
- if (plugin->shm_id != -1)
- close (plugin->shm_id);
- plugin->shm_id = -1;
-#else
- if (plugin->shm_ptr != NULL)
- UnmapViewOfFile (plugin->shm_ptr);
- if (plugin->map_handle != 0)
- CloseHandle (plugin->map_handle);
- plugin->map_handle = 0;
-#endif
- plugin->map_size = 0;
- plugin->shm_ptr = NULL;
-}
-
-/**
* Main loop function for plugins.
* Reads a message from the plugin input pipe and acts on it.
* Can be called recursively (once) in OPMODE_DECOMPRESS.
@@ -368,9 +248,7 @@
unsigned char code;
char *shm_name = NULL;
size_t shm_name_len;
-
int extract_reply;
-
struct IpcHeader hdr;
int do_break;
#ifdef WINDOWS
@@ -584,6 +462,7 @@
return 0;
}
+
/**
* 'main' function of the child process. Loads the plugin,
* sets up its in and out pipes, then runs the request serving function.
@@ -593,7 +472,8 @@
* @param out stream to write to
*/
static void
-plugin_main (struct EXTRACTOR_PluginList *plugin, int in, int out)
+plugin_main (struct EXTRACTOR_PluginList *plugin,
+ int in, int out)
{
if (plugin == NULL)
{
@@ -601,7 +481,7 @@
close (out);
return;
}
- if (0 != plugin_load (plugin))
+ if (0 != EXTRACTOR_plugin_load_ (plugin))
{
close (in);
close (out);
@@ -626,660 +506,12 @@
close (out);
}
-#if !WINDOWS
/**
- * Start the process for the given plugin.
- */
-static void
-start_process (struct EXTRACTOR_PluginList *plugin)
-{
- int p1[2];
- int p2[2];
- pid_t pid;
- int status;
-
- switch (plugin->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- if (-1 != plugin->cpid && 0 != plugin->cpid)
- return;
- break;
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- if (0 != plugin->cpid)
- return;
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- return;
- break;
- case EXTRACTOR_OPTION_DISABLED:
- return;
- break;
- }
-
- plugin->cpid = -1;
- if (0 != pipe (p1))
- {
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
- if (0 != pipe (p2))
- {
- close (p1[0]);
- close (p1[1]);
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
- pid = fork ();
- plugin->cpid = pid;
- if (pid == -1)
- {
- close (p1[0]);
- close (p1[1]);
- close (p2[0]);
- close (p2[1]);
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
- if (pid == 0)
- {
- close (p1[1]);
- close (p2[0]);
- plugin_main (plugin, p1[0], p2[1]);
- _exit (0);
- }
- close (p1[0]);
- close (p2[1]);
- plugin->cpipe_in = fdopen (p1[1], "w");
- if (plugin->cpipe_in == NULL)
- {
- perror ("fdopen");
- (void) kill (plugin->cpid, SIGKILL);
- waitpid (plugin->cpid, &status, 0);
- close (p1[1]);
- close (p2[0]);
- plugin->cpid = -1;
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
- plugin->cpipe_out = p2[0];
-}
-
-/**
- * Stop the child process of this plugin.
- */
-static void
-stop_process (struct EXTRACTOR_PluginList *plugin)
-{
- int status;
-
-#if DEBUG
- if (plugin->cpid == -1)
- fprintf (stderr,
- "Plugin `%s' choked on this input\n",
- plugin->short_libname);
-#endif
- if ( (plugin->cpid == -1) ||
- (plugin->cpid == 0) )
- return;
- kill (plugin->cpid, SIGKILL);
- waitpid (plugin->cpid, &status, 0);
- plugin->cpid = -1;
- close (plugin->cpipe_out);
- fclose (plugin->cpipe_in);
- plugin->cpipe_out = -1;
- plugin->cpipe_in = NULL;
-
- if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
-
- plugin->seek_request = -1;
-}
-
-static int
-write_plugin_data (const struct EXTRACTOR_PluginList *plugin)
-{
- /* This function is only necessary on W32. On POSIX
- * systems plugin inherits its own data from the parent */
- return 0;
-}
-
-#define plugin_write(plug, buf, size) write_all (fileno (plug->cpipe_in), buf,
size)
-
-#else /* WINDOWS */
-
-#ifndef PIPE_BUF
-#define PIPE_BUF 512
-#endif
-
-/* Copyright Bob Byrnes <byrnes <at> curl.com>
- http://permalink.gmane.org/gmane.os.cygwin.patches/2121
-*/
-/* Create a pipe, and return handles to the read and write ends,
- just like CreatePipe, but ensure that the write end permits
- FILE_READ_ATTRIBUTES access, on later versions of win32 where
- this is supported. This access is needed by NtQueryInformationFile,
- which is used to implement select and nonblocking writes.
- Note that the return value is either NO_ERROR or GetLastError,
- unlike CreatePipe, which returns a bool for success or failure. */
-static int
-create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
- LPSECURITY_ATTRIBUTES sa_ptr, DWORD psize,
- DWORD dwReadMode, DWORD dwWriteMode)
-{
- /* Default to error. */
- *read_pipe_ptr = *write_pipe_ptr = INVALID_HANDLE_VALUE;
-
- HANDLE read_pipe = INVALID_HANDLE_VALUE, write_pipe = INVALID_HANDLE_VALUE;
-
- /* Ensure that there is enough pipe buffer space for atomic writes. */
- if (psize < PIPE_BUF)
- psize = PIPE_BUF;
-
- char pipename[MAX_PATH];
-
- /* Retry CreateNamedPipe as long as the pipe name is in use.
- * Retrying will probably never be necessary, but we want
- * to be as robust as possible. */
- while (1)
- {
- static volatile LONG pipe_unique_id;
-
- snprintf (pipename, sizeof pipename, "\\\\.\\pipe\\gnunet-%d-%ld",
- getpid (), InterlockedIncrement ((LONG *) & pipe_unique_id));
- /* Use CreateNamedPipe instead of CreatePipe, because the latter
- * returns a write handle that does not permit FILE_READ_ATTRIBUTES
- * access, on versions of win32 earlier than WinXP SP2.
- * CreatePipe also stupidly creates a full duplex pipe, which is
- * a waste, since only a single direction is actually used.
- * It's important to only allow a single instance, to ensure that
- * the pipe was not created earlier by some other process, even if
- * the pid has been reused. We avoid FILE_FLAG_FIRST_PIPE_INSTANCE
- * because that is only available for Win2k SP2 and WinXP. */
- read_pipe = CreateNamedPipeA (pipename, PIPE_ACCESS_INBOUND | dwReadMode,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, /* max instances */
- psize, /* output buffer size */
- psize, /* input buffer size */
- NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
-
- if (read_pipe != INVALID_HANDLE_VALUE)
- {
- break;
- }
-
- DWORD err = GetLastError ();
-
- switch (err)
- {
- case ERROR_PIPE_BUSY:
- /* The pipe is already open with compatible parameters.
- * Pick a new name and retry. */
- continue;
- case ERROR_ACCESS_DENIED:
- /* The pipe is already open with incompatible parameters.
- * Pick a new name and retry. */
- continue;
- case ERROR_CALL_NOT_IMPLEMENTED:
- /* We are on an older Win9x platform without named pipes.
- * Return an anonymous pipe as the best approximation. */
- if (CreatePipe (read_pipe_ptr, write_pipe_ptr, sa_ptr, psize))
- {
- return 0;
- }
- err = GetLastError ();
- return err;
- default:
- return err;
- }
- /* NOTREACHED */
- }
-
- /* Open the named pipe for writing.
- * Be sure to permit FILE_READ_ATTRIBUTES access. */
- write_pipe = CreateFileA (pipename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0,
/* share mode */
- sa_ptr, OPEN_EXISTING, dwWriteMode, /* flags and
attributes */
- 0); /* handle to template file */
-
- if (write_pipe == INVALID_HANDLE_VALUE)
- {
- /* Failure. */
- DWORD err = GetLastError ();
-
- CloseHandle (read_pipe);
- return err;
- }
-
- /* Success. */
- *read_pipe_ptr = read_pipe;
- *write_pipe_ptr = write_pipe;
- return 0;
-}
-
-/**
- * Writes @size bytes from @buf to @h, using @ov for
- * overlapped i/o. Deallocates @old_buf and sets it to NULL,
- * if necessary.
- * Writes asynchronously, but sequentially (only one writing
- * operation may be active at any given moment, but it will
- * be done in background). Thus it is intended to be used
- * for writing a few big chunks rather than a lot of small pieces.
- *
- * The extravagant interface is mainly because this function
- * does not use a separate struct to group together overlapped
- * structure, buffer pointer and the handle.
- *
- * @param h pipe handle
- * @param ov overlapped structure pointer
- * @param buf buffer to read from. Will be copied internally
- * @param size number of bytes to write
- * @param old_buf pointer where a copy of previous buffer is stored,
- * and where a copy of @buf will be stored.
- *
- * @return number of bytes written, -1 on error
- */
-static int
-write_to_pipe (HANDLE h, OVERLAPPED *ov, unsigned char *buf, size_t size,
unsigned char **old_buf)
-{
- DWORD written;
- BOOL bresult;
- DWORD err;
-
- if (WAIT_OBJECT_0 != WaitForSingleObject (ov->hEvent, INFINITE))
- return -1;
-
- ResetEvent (ov->hEvent);
-
- if (*old_buf != NULL)
- free (*old_buf);
-
- *old_buf = malloc (size);
- if (*old_buf == NULL)
- return -1;
- memcpy (*old_buf, buf, size);
- written = 0;
- ov->Offset = 0;
- ov->OffsetHigh = 0;
- ov->Pointer = 0;
- ov->Internal = 0;
- ov->InternalHigh = 0;
- bresult = WriteFile (h, *old_buf, size, &written, ov);
-
- if (bresult == TRUE)
- {
- SetEvent (ov->hEvent);
- free (*old_buf);
- *old_buf = NULL;
- return written;
- }
-
- err = GetLastError ();
- if (err == ERROR_IO_PENDING)
- return size;
- SetEvent (ov->hEvent);
- *old_buf = NULL;
- SetLastError (err);
- return -1;
-}
-
-#define plugin_write(plug, buf, size) write_to_pipe (plug->cpipe_in,
&plug->ov_write, buf, size, &plug->ov_write_buffer)
-
-/**
- * Communicates plugin data (library name, options) to the plugin
- * process. This is only necessary on W32, where this information
- * is not inherited by the plugin, because it is not forked.
- *
- * @param plugin plugin context
- *
- * @return 0 on success, -1 on failure
- */
-static int
-write_plugin_data (struct EXTRACTOR_PluginList *plugin)
-{
- size_t libname_len, shortname_len, opts_len;
- DWORD len;
- char *str;
- size_t total_len = 0;
- unsigned char *buf, *ptr;
-
- switch (plugin->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- break;
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- return 0;
- break;
- case EXTRACTOR_OPTION_DISABLED:
- return 0;
- break;
- }
-
- libname_len = strlen (plugin->libname) + 1;
- total_len += sizeof (size_t) + libname_len;
- shortname_len = strlen (plugin->short_libname) + 1;
- total_len += sizeof (size_t) + shortname_len;
- if (plugin->plugin_options != NULL)
- {
- opts_len = strlen (plugin->plugin_options) + 1;
- total_len += opts_len;
- }
- else
- {
- opts_len = 0;
- }
- total_len += sizeof (size_t);
-
- buf = malloc (total_len);
- if (buf == NULL)
- return -1;
- ptr = buf;
- memcpy (ptr, &libname_len, sizeof (size_t));
- ptr += sizeof (size_t);
- memcpy (ptr, plugin->libname, libname_len);
- ptr += libname_len;
- memcpy (ptr, &shortname_len, sizeof (size_t));
- ptr += sizeof (size_t);
- memcpy (ptr, plugin->short_libname, shortname_len);
- ptr += shortname_len;
- memcpy (ptr, &opts_len, sizeof (size_t));
- ptr += sizeof (size_t);
- if (opts_len > 0)
- {
- memcpy (ptr, plugin->plugin_options, opts_len);
- ptr += opts_len;
- }
- if (total_len != write_to_pipe (plugin->cpipe_in, &plugin->ov_write, buf,
total_len, &plugin->ov_write_buffer))
- {
- free (buf);
- return -1;
- }
- free (buf);
- return 0;
-}
-
-/**
- * Reads plugin data from the LE server process.
- * Also initializes allocation granularity (duh...).
- *
- * @param fd the pipe to read from
- *
- * @return newly allocated plugin context
- */
-static struct EXTRACTOR_PluginList *
-read_plugin_data (int fd)
-{
- struct EXTRACTOR_PluginList *ret;
- size_t i;
-
- ret = malloc (sizeof (struct EXTRACTOR_PluginList));
- if (ret == NULL)
- return NULL;
- read (fd, &i, sizeof (size_t));
- ret->libname = malloc (i);
- if (ret->libname == NULL)
- {
- free (ret);
- return NULL;
- }
- read (fd, ret->libname, i);
- ret->libname[i - 1] = '\0';
-
- read (fd, &i, sizeof (size_t));
- ret->short_libname = malloc (i);
- if (ret->short_libname == NULL)
- {
- free (ret->libname);
- free (ret);
- return NULL;
- }
- read (fd, ret->short_libname, i);
- ret->short_libname[i - 1] = '\0';
-
- read (fd, &i, sizeof (size_t));
- if (i == 0)
- {
- ret->plugin_options = NULL;
- }
- else
- {
- ret->plugin_options = malloc (i);
- if (ret->plugin_options == NULL)
- {
- free (ret->short_libname);
- free (ret->libname);
- free (ret);
- return NULL;
- }
- read (fd, ret->plugin_options, i);
- ret->plugin_options[i - 1] = '\0';
- }
-#if WINDOWS
- {
- SYSTEM_INFO si;
- GetSystemInfo (&si);
- ret->allocation_granularity = si.dwAllocationGranularity;
- }
-#else
- ret->allocation_granularity = sysconf (_SC_PAGE_SIZE);
-#endif
- return ret;
-}
-
-/**
- * Start the process for the given plugin.
- */
-static void
-start_process (struct EXTRACTOR_PluginList *plugin)
-{
- HANDLE p1[2];
- HANDLE p2[2];
- STARTUPINFO startup;
- PROCESS_INFORMATION proc;
- char cmd[MAX_PATH + 1];
- char arg1[10], arg2[10];
- HANDLE p10_os_inh = INVALID_HANDLE_VALUE, p21_os_inh = INVALID_HANDLE_VALUE;
- SECURITY_ATTRIBUTES sa;
-
- switch (plugin->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- if (plugin->hProcess != INVALID_HANDLE_VALUE && plugin->hProcess != 0)
- return;
- break;
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- if (plugin->hProcess != 0)
- return;
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- return;
- break;
- case EXTRACTOR_OPTION_DISABLED:
- return;
- break;
- }
-
- sa.nLength = sizeof (sa);
- sa.lpSecurityDescriptor = NULL;
- sa.bInheritHandle = FALSE;
-
- plugin->hProcess = NULL;
-
- if (0 != create_selectable_pipe (&p1[0], &p1[1], &sa, 1024,
FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED))
- {
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
- if (0 != create_selectable_pipe (&p2[0], &p2[1], &sa, 1024,
FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED))
- {
- CloseHandle (p1[0]);
- CloseHandle (p1[1]);
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
-
- memset (&startup, 0, sizeof (STARTUPINFO));
-
- if (!DuplicateHandle (GetCurrentProcess (), p1[0], GetCurrentProcess (),
- &p10_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS)
- || !DuplicateHandle (GetCurrentProcess (), p2[1], GetCurrentProcess (),
- &p21_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- if (p10_os_inh != INVALID_HANDLE_VALUE)
- CloseHandle (p10_os_inh);
- if (p21_os_inh != INVALID_HANDLE_VALUE)
- CloseHandle (p21_os_inh);
- CloseHandle (p1[0]);
- CloseHandle (p1[1]);
- CloseHandle (p2[0]);
- CloseHandle (p2[1]);
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
-
- /* TODO: write our own plugin-hosting executable? rundll32, for once, has
smaller than usual stack size.
- * Also, users might freak out seeing over 9000 rundll32 processes (seeing
over 9000 processes named
- * "libextractor_plugin_helper" is probably less confusing).
- */
- snprintf(cmd, MAX_PATH + 1, "rundll32.exe libextractor-3.dll,address@hidden
%lu %lu", p10_os_inh, p21_os_inh);
- cmd[MAX_PATH] = '\0';
- if (CreateProcessA (NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL,
- &startup, &proc))
- {
- plugin->hProcess = proc.hProcess;
- CloseHandle (proc.hThread);
- }
- else
- {
- CloseHandle (p1[0]);
- CloseHandle (p1[1]);
- CloseHandle (p2[0]);
- CloseHandle (p2[1]);
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
- return;
- }
- CloseHandle (p1[0]);
- CloseHandle (p2[1]);
- CloseHandle (p10_os_inh);
- CloseHandle (p21_os_inh);
-
- plugin->cpipe_in = p1[1];
- plugin->cpipe_out = p2[0];
-
- memset (&plugin->ov_read, 0, sizeof (OVERLAPPED));
- memset (&plugin->ov_write, 0, sizeof (OVERLAPPED));
-
- plugin->ov_write_buffer = NULL;
-
- plugin->ov_write.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL);
- plugin->ov_read.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL);
-}
-
-/**
- * Stop the child process of this plugin.
- */
-static void
-stop_process (struct EXTRACTOR_PluginList *plugin)
-{
- int status;
- HANDLE process;
-
-#if DEBUG
- if (plugin->hProcess == INVALID_HANDLE_VALUE)
- fprintf (stderr,
- "Plugin `%s' choked on this input\n",
- plugin->short_libname);
-#endif
- if (plugin->hProcess == INVALID_HANDLE_VALUE ||
- plugin->hProcess == NULL)
- return;
- TerminateProcess (plugin->hProcess, 0);
- CloseHandle (plugin->hProcess);
- plugin->hProcess = INVALID_HANDLE_VALUE;
- CloseHandle (plugin->cpipe_out);
- CloseHandle (plugin->cpipe_in);
- plugin->cpipe_out = INVALID_HANDLE_VALUE;
- plugin->cpipe_in = INVALID_HANDLE_VALUE;
- CloseHandle (plugin->ov_read.hEvent);
- CloseHandle (plugin->ov_write.hEvent);
- if (plugin->ov_write_buffer != NULL)
- {
- free (plugin->ov_write_buffer);
- plugin->ov_write_buffer = NULL;
- }
-
- if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
- plugin->flags = EXTRACTOR_OPTION_DISABLED;
-
- plugin->seek_request = -1;
-}
-
-#endif /* WINDOWS */
-
-/**
- * Remove a plugin from a list.
- *
- * @param prev the current list of plugins
- * @param library the name of the plugin to remove
- * @return the reduced list, unchanged if the plugin was not loaded
- */
-struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_remove(struct EXTRACTOR_PluginList * prev,
- const char * library)
-{
- struct EXTRACTOR_PluginList *pos;
- struct EXTRACTOR_PluginList *first;
-
- pos = prev;
- first = prev;
- while ((pos != NULL) && (0 != strcmp (pos->short_libname, library)))
- {
- prev = pos;
- pos = pos->next;
- }
- if (pos != NULL)
- {
- /* found, close library */
- if (first == pos)
- first = pos->next;
- else
- prev->next = pos->next;
- /* found */
- stop_process (pos);
- free (pos->short_libname);
- free (pos->libname);
- free (pos->plugin_options);
- if (NULL != pos->libraryHandle)
- lt_dlclose (pos->libraryHandle);
- free (pos);
- }
-#if DEBUG
- else
- fprintf(stderr,
- "Unloading plugin `%s' failed!\n",
- library);
-#endif
- return first;
-}
-
-
-/**
- * Remove all plugins from the given list (destroys the list).
- *
- * @param plugin the list of plugins
- */
-void
-EXTRACTOR_plugin_remove_all(struct EXTRACTOR_PluginList *plugins)
-{
- while (plugins != NULL)
- plugins = EXTRACTOR_plugin_remove (plugins, plugins->short_libname);
-}
-
-
-
-/**
* Open a file
*/
-static int file_open(const char *filename, int oflag, ...)
+static int
+file_open(const char *filename, int oflag, ...)
{
int mode;
const char *fn;
@@ -1305,940 +537,8 @@
return OPEN(fn, oflag, mode);
}
-#if WINDOWS
/**
- * Setup a shared memory segment.
- *
- * @param ptr set to the location of the map segment
- * @param map where to store the map handle
- * @param fn name of the mapping
- * @param fn_size size available in fn
- * @param size number of bytes to allocated for the mapping
- * @return 0 on success
- */
-static int
-make_shm_w32 (void **ptr, HANDLE *map, char *fn, size_t fn_size, size_t size)
-{
- const char *tpath = "Local\\";
- snprintf (fn, fn_size, "%slibextractor-shm-%u-%u", tpath, getpid(),
- (unsigned int) RANDOM());
- *map = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
size, fn);
- *ptr = MapViewOfFile (*map, FILE_MAP_WRITE, 0, 0, size);
- if (*ptr == NULL)
- {
- CloseHandle (*map);
- return 1;
- }
- return 0;
-}
-
-/**
- * Setup a file-backed shared memory segment.
- *
- * @param map where to store the map handle
- * @param file handle of the file to back the shm
- * @param fn name of the mapping
- * @param fn_size size available in fn
- * @param size number of bytes to allocated for the mapping
- * @return 0 on success
- */
-static int
-make_file_backed_shm_w32 (HANDLE *map, HANDLE file, char *fn, size_t fn_size)
-{
- const char *tpath = "Local\\";
- snprintf (fn, fn_size, "%slibextractor-shm-%u-%u", tpath, getpid(),
- (unsigned int) RANDOM());
- *map = CreateFileMapping (file, NULL, PAGE_READONLY, 0, 0, fn);
- if (*map == NULL)
- {
- DWORD err = GetLastError ();
- return 1;
- }
- return 0;
-}
-
-static void
-destroy_shm_w32 (void *ptr, HANDLE map)
-{
- UnmapViewOfFile (ptr);
- CloseHandle (map);
-}
-
-static void
-destroy_file_backed_shm_w32 (HANDLE map)
-{
- CloseHandle (map);
-}
-
-#else
-
-/**
- * Setup a shared memory segment.
- *
- * @param ptr set to the location of the shm segment
- * @param shmid where to store the shm ID
- * @param fn name of the shared segment
- * @param fn_size size available in fn
- * @param size number of bytes to allocated for the segment
- * @return 0 on success
- */
-static int
-make_shm_posix (void **ptr, int *shmid, char *fn, size_t fn_size, size_t size)
-{
- const char *tpath;
-#if SOMEBSD
- /* this works on FreeBSD, not sure about others... */
- tpath = getenv ("TMPDIR");
- if (tpath == NULL)
- tpath = "/tmp/";
-#else
- tpath = "/"; /* Linux */
-#endif
- snprintf (fn, fn_size, "%slibextractor-shm-%u-%u", tpath, getpid(),
- (unsigned int) RANDOM());
- *shmid = shm_open (fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
- *ptr = NULL;
- if (-1 == *shmid)
- return 1;
- if ((0 != ftruncate (*shmid, size)) ||
- (NULL == (*ptr = mmap (NULL, size, PROT_WRITE, MAP_SHARED, *shmid, 0)))
||
- (*ptr == (void*) -1) )
- {
- close (*shmid);
- *shmid = -1;
- shm_unlink (fn);
- return 1;
- }
- return 0;
-}
-
-static void
-destroy_shm_posix (void *ptr, int shm_id, size_t size, char *shm_name)
-{
- if (NULL != ptr)
- munmap (ptr, size);
- if (shm_id != -1)
- close (shm_id);
- shm_unlink (shm_name);
-}
-#endif
-
-#ifndef O_LARGEFILE
-#define O_LARGEFILE 0
-#endif
-
-/**
- * A poor attempt to abstract the data source (file or a memory buffer)
- * for the decompressor.
- */
-struct BufferedFileDataSource
-{
- /**
- * Descriptor of the file to read data from (may be -1)
- */
- int fd;
-
- /**
- * Pointer to the buffer to read from (may be NULL)
- */
- const unsigned char *data;
-
- /**
- * Size of the file (or the data buffer)
- */
- int64_t fsize;
-
- /**
- * Position within the file or the data buffer
- */
- int64_t fpos;
-
- /**
- * A buffer to read into. For fd != -1: when data != NULL,
- * data is used directly.
- */
- unsigned char *buffer;
-
- /**
- * Position within the buffer.
- */
- int64_t buffer_pos;
-
- /**
- * Number of bytes in the buffer (<= buffer_size)
- */
- int64_t buffer_bytes;
-
- /**
- * Allocated size of the buffer
- */
- int64_t buffer_size;
-};
-
-/**
- * Creates a bfds
- *
- * @param data data buffer to use as a source (NULL if fd != -1)
- * @param fd file descriptor to use as a source (-1 if data != NULL)
- * @param fsize size of the file (or the buffer)
- * @return newly allocated bfds
- */
-struct BufferedFileDataSource *
-bfds_new (const unsigned char *data, int fd, int64_t fsize);
-
-/**
- * Unallocates bfds
- *
- * @param bfds bfds to deallocate
- */
-void
-bfds_delete (struct BufferedFileDataSource *bfds);
-
-/**
- * Makes bfds seek to @pos and read a chunk of bytes there.
- * Changes bfds->fpos, bfds->buffer_bytes and bfds->buffer_pos.
- * Does almost nothing for memory-backed bfds.
- *
- * @param bfds bfds
- * @param pos position
- * @return 0 on success, -1 on error
- */
-int
-bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds, int64_t pos);
-
-/**
- * Makes bfds seek to @pos in @whence mode.
- * Will try to seek within the buffer, will move the buffer location if
- * the seek request falls outside of the buffer range.
- *
- * @param bfds bfds
- * @param pos position to seek to
- * @param whence one of the seek constants (SEEK_CUR, SEEK_SET, SEEK_END)
- * @return new absolute position
- */
-int64_t
-bfds_seek (struct BufferedFileDataSource *bfds, int64_t pos, int whence);
-
-/**
- * Fills @buf_ptr with a pointer to a chunk of data.
- * Same as read() but there's no need to allocate or de-allocate the
- * memory (since data IS already in memory).
- * Will seek if necessary. Will fail if @count exceeds buffer size.
- *
- * @param bfds bfds
- * @param buf_ptr location to store data pointer
- * @param count number of bytes to read
- * @return number of bytes (<= count) available at location pointed by buf_ptr
- */
-int64_t
-bfds_read (struct BufferedFileDataSource *bfds, unsigned char **buf_ptr,
int64_t count);
-
-struct BufferedFileDataSource *
-bfds_new (const unsigned char *data, int fd, int64_t fsize)
-{
- struct BufferedFileDataSource *result;
- result = malloc (sizeof (struct BufferedFileDataSource));
- if (result == NULL)
- return NULL;
- memset (result, 0, sizeof (struct BufferedFileDataSource));
- result->data = data;
- result->fsize = fsize;
- result->fd = fd;
- result->buffer_size = fsize;
- if (result->data == NULL)
- {
- if (result->buffer_size > MAX_READ)
- result->buffer_size = MAX_READ;
- result->buffer = malloc (result->buffer_size);
- if (result->buffer == NULL)
- {
- free (result);
- return NULL;
- }
- }
- bfds_pick_next_buffer_at (result, 0);
- return result;
-}
-
-void
-bfds_delete (struct BufferedFileDataSource *bfds)
-{
- if (bfds->buffer)
- free (bfds->buffer);
- free (bfds);
-}
-
-int
-bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds, int64_t pos)
-{
- int64_t position, rd;
- if (bfds->data != NULL)
- {
- bfds->buffer_bytes = bfds->fsize;
- return 0;
- }
-#if WINDOWS
- position = _lseeki64 (bfds->fd, pos, SEEK_SET);
-#elif HAVE_LSEEK64
- position = lseek64 (bfds->fd, pos, SEEK_SET);
-#else
- position = (int64_t) lseek (bfds->fd, pos, SEEK_SET);
-#endif
- if (position < 0)
- return -1;
- bfds->fpos = position;
- rd = read (bfds->fd, bfds->buffer, bfds->buffer_size);
- if (rd < 0)
- return -1;
- bfds->buffer_bytes = rd;
- return 0;
-}
-
-int64_t
-bfds_seek (struct BufferedFileDataSource *bfds, int64_t pos, int whence)
-{
- switch (whence)
- {
- case SEEK_CUR:
- if (bfds->data == NULL)
- {
- if (0 != bfds_pick_next_buffer_at (bfds, bfds->fpos + bfds->buffer_pos +
pos))
- return -1;
- bfds->buffer_pos = 0;
- return bfds->fpos;
- }
- bfds->buffer_pos += pos;
- return bfds->buffer_pos;
- break;
- case SEEK_SET:
- if (pos < 0)
- return -1;
- if (bfds->data == NULL)
- {
- if (0 != bfds_pick_next_buffer_at (bfds, pos))
- return -1;
- bfds->buffer_pos = 0;
- return bfds->fpos;
- }
- bfds->buffer_pos = pos;
- return bfds->buffer_pos;
- break;
- case SEEK_END:
- if (bfds->data == NULL)
- {
- if (0 != bfds_pick_next_buffer_at (bfds, bfds->fsize + pos))
- return -1;
- bfds->buffer_pos = 0;
- return bfds->fpos;
- }
- bfds->buffer_pos = bfds->fsize + pos;
- return bfds->buffer_pos;
- break;
- }
- return -1;
-}
-
-int64_t
-bfds_read (struct BufferedFileDataSource *bfds, unsigned char **buf_ptr,
int64_t count)
-{
- if (count > MAX_READ)
- return -1;
- if (count > bfds->buffer_bytes - bfds->buffer_pos)
- {
- if (bfds->fpos + bfds->buffer_pos != bfds_seek (bfds, bfds->fpos +
bfds->buffer_pos, SEEK_SET))
- return -1;
- if (bfds->data == NULL)
- {
- *buf_ptr = &bfds->buffer[bfds->buffer_pos];
- bfds->buffer_pos += count < bfds->buffer_bytes ? count :
bfds->buffer_bytes;
- return (count < bfds->buffer_bytes ? count : bfds->buffer_bytes);
- }
- else
- {
- int64_t ret = count < (bfds->buffer_bytes - bfds->buffer_pos) ? count :
(bfds->buffer_bytes - bfds->buffer_pos);
- *buf_ptr = (unsigned char*) &bfds->data[bfds->buffer_pos];
- bfds->buffer_pos += ret;
- return ret;
- }
- }
- else
- {
- if (bfds->data == NULL)
- *buf_ptr = &bfds->buffer[bfds->buffer_pos];
- else
- *buf_ptr = (unsigned char*) &bfds->data[bfds->buffer_pos];
- bfds->buffer_pos += count;
- return count;
- }
-}
-
-#if HAVE_ZLIB
-#define MIN_ZLIB_HEADER 12
-#endif
-#if HAVE_LIBBZ2
-#define MIN_BZ2_HEADER 4
-#endif
-#if !defined (MIN_COMPRESSED_HEADER) && HAVE_ZLIB
-#define MIN_COMPRESSED_HEADER MIN_ZLIB_HEADER
-#endif
-#if !defined (MIN_COMPRESSED_HEADER) && HAVE_LIBBZ2
-#define MIN_COMPRESSED_HEADER MIN_BZ2_HEADER
-#endif
-#if !defined (MIN_COMPRESSED_HEADER)
-#define MIN_COMPRESSED_HEADER -1
-#endif
-
-#define COMPRESSED_DATA_PROBE_SIZE 3
-
-enum ExtractorCompressionType
-{
- COMP_TYPE_UNDEFINED = -1,
- COMP_TYPE_INVALID = 0,
- COMP_TYPE_ZLIB = 1,
- COMP_TYPE_BZ2 = 2
-};
-
-/**
- * An object from which uncompressed data can be read
- */
-struct CompressedFileSource
-{
- /**
- * The type of compression used in the source
- */
- enum ExtractorCompressionType compression_type;
- /**
- * The source of data
- */
- struct BufferedFileDataSource *bfds;
- /**
- * Size of the source (same as bfds->fsize)
- */
- int64_t fsize;
- /**
- * Position within the source
- */
- int64_t fpos;
-
- /**
- * Total size of the uncompressed data. Remains -1 until
- * decompression is finished.
- */
- int64_t uncompressed_size;
-
- /*
- unsigned char *buffer;
- int64_t buffer_bytes;
- int64_t buffer_len;
- */
-
-#if WINDOWS
- /**
- * W32 handle of the shm into which data is uncompressed
- */
- HANDLE shm;
-#else
- /**
- * POSIX id of the shm into which data is uncompressed
- */
- int shm;
-#endif
- /**
- * Name of the shm
- */
- char shm_name[MAX_SHM_NAME + 1];
- /**
- * Pointer to the mapped region of the shm (covers the whole shm)
- */
- void *shm_ptr;
- /**
- * Position within shm
- */
- int64_t shm_pos;
- /**
- * Allocated size of the shm
- */
- int64_t shm_size;
- /**
- * Number of bytes in shm (<= shm_size)
- */
- size_t shm_buf_size;
-
-#if HAVE_ZLIB
- /**
- * ZLIB stream object
- */
- z_stream strm;
- /**
- * Length of gzip header (may be 0, in that case ZLIB parses the header)
- */
- int gzip_header_length;
-#endif
-#if HAVE_LIBBZ2
- /**
- * BZ2 stream object
- */
- bz_stream bstrm;
-#endif
-};
-
-void
-cfs_delete (struct CompressedFileSource *cfs)
-{
-#if WINDOWS
- destroy_shm_w32 (cfs->shm_ptr, cfs->shm);
-#else
- destroy_shm_posix (cfs->shm_ptr, cfs->shm, cfs->shm_size, cfs->shm_name);
-#endif
- free (cfs);
-}
-
-int
-cfs_reset_stream_zlib (struct CompressedFileSource *cfs)
-{
- if (cfs->gzip_header_length != bfds_seek (cfs->bfds,
cfs->gzip_header_length, SEEK_SET))
- return 0;
- cfs->strm.next_in = NULL;
- cfs->strm.avail_in = 0;
- cfs->strm.total_in = 0;
- cfs->strm.zalloc = NULL;
- cfs->strm.zfree = NULL;
- cfs->strm.opaque = NULL;
-
- /*
- * note: maybe plain inflateInit(&strm) is adequate,
- * it looks more backward-compatible also ;
- *
- * ZLIB_VERNUM isn't defined by zlib version 1.1.4 ;
- * there might be a better check.
- */
- if (Z_OK != inflateInit2 (&cfs->strm,
-#ifdef ZLIB_VERNUM
- 15 + 32
-#else
- -MAX_WBITS
-#endif
- ))
- {
- return -1;
- }
-
- cfs->fpos = cfs->gzip_header_length;
- cfs->shm_pos = 0;
- cfs->shm_buf_size = 0;
-
- return 1;
-}
-
-
-static int
-cfs_reset_stream_bz2 (struct CompressedFileSource *cfs)
-{
- return -1;
-}
-
-/**
- * Resets the compression stream to begin uncompressing
- * from the beginning. Used at initialization time, and when
- * seeking backward.
- *
- * @param cfs cfs to reset
- * @return 1 on success, -1 on error
- */
-int
-cfs_reset_stream (struct CompressedFileSource *cfs)
-{
- switch (cfs->compression_type)
- {
- case COMP_TYPE_ZLIB:
- return cfs_reset_stream_zlib (cfs);
- case COMP_TYPE_BZ2:
- return cfs_reset_stream_bz2 (cfs);
- default:
- return -1;
- }
-}
-
-
-static int
-cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
-{
- /* Process gzip header */
- unsigned int gzip_header_length = 10;
- unsigned char *pdata;
- unsigned char data[12];
-
- if (12 > bfds_read (cfs->bfds, &pdata, 12))
- return -1;
- memcpy (data, pdata, 12);
-
- if (data[3] & 0x4) /* FEXTRA set */
- gzip_header_length += 2 + (unsigned) (data[10] & 0xff) +
- (((unsigned) (data[11] & 0xff)) * 256);
-
- if (data[3] & 0x8) /* FNAME set */
- {
- int64_t buf_bytes;
- int len;
- unsigned char *buf, *cptr;
- if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
SEEK_SET))
- return -1;
- buf_bytes = bfds_read (cfs->bfds, &buf, 1024);
- if (buf_bytes <= 0)
- return -1;
- cptr = buf;
-
- len = 0;
- /* stored file name is here */
- while (len < buf_bytes)
- {
- if ('\0' == *cptr)
- break;
- cptr++;
- len++;
- }
-
- if (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_FILENAME,
- EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
- (const char *) buf,
- len))
- return 0; /* done */
-
- /* FIXME: check for correctness */
- //gzip_header_length = (cptr - data) + 1;
- gzip_header_length += len + 1;
- }
-
- if (data[3] & 0x16) /* FCOMMENT set */
- {
- int64_t buf_bytes;
- int len;
- unsigned char *buf, *cptr;
- if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
SEEK_SET))
- return -1;
- buf_bytes = bfds_read (cfs->bfds, &buf, 1024);
- if (buf_bytes <= 0)
- return -1;
- cptr = buf;
-
- len = 0;
- /* stored file name is here */
- while (len < buf_bytes)
- {
- if ('\0' == *cptr)
- break;
- cptr++;
- len++;
- }
-
- if (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_COMMENT,
- EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
- (const char *) buf,
- len))
- return 0; /* done */
-
- /* FIXME: check for correctness */
- //gzip_header_length = (cptr - data) + 1;
- gzip_header_length += len + 1;
- }
-
- if (data[3] & 0x2) /* FCHRC set */
- gzip_header_length += 2;
-
- memset (&cfs->strm, 0, sizeof (z_stream));
-
-#ifdef ZLIB_VERNUM
- gzip_header_length = 0;
-#endif
-
- cfs->gzip_header_length = gzip_header_length;
- return cfs_reset_stream_zlib (cfs);
-}
-
-static int
-cfs_deinit_decompressor_zlib (struct CompressedFileSource *cfs)
-{
- inflateEnd (&cfs->strm);
- return 1;
-}
-
-static int
-cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
-{
- return -1;
-}
-
-static int
-cfs_deinit_decompressor_bz2 (struct CompressedFileSource *cfs)
-{
- return -1;
-}
-
-/**
- * Initializes decompression object. Might report metadata about
- * compresse stream, if available. Resets the stream to the beginning.
- *
- * @param cfs cfs to initialize
- * @param proc callback for metadata
- * @param proc_cls callback cls
- * @return 1 on success, -1 on error
- */
-static int
-cfs_init_decompressor (struct CompressedFileSource *cfs,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
-{
- switch (cfs->compression_type)
- {
- case COMP_TYPE_ZLIB:
- return cfs_init_decompressor_zlib (cfs, proc, proc_cls);
- case COMP_TYPE_BZ2:
- return cfs_init_decompressor_bz2 (cfs, proc, proc_cls);
- default:
- return -1;
- }
-}
-
-/**
- * Deinitializes decompression object.
- *
- * @param cfs cfs to deinitialize
- * @return 1 on success, -1 on error
- */
-static int
-cfs_deinit_decompressor (struct CompressedFileSource *cfs)
-{
- switch (cfs->compression_type)
- {
- case COMP_TYPE_ZLIB:
- return cfs_deinit_decompressor_zlib (cfs);
- case COMP_TYPE_BZ2:
- return cfs_deinit_decompressor_bz2 (cfs);
- default:
- return -1;
- }
-}
-
-/**
- * Allocates and initializes new cfs object.
- *
- * @param bfds data source to use
- * @param fsize size of the source
- * @param compression_type type of compression used
- * @param proc metadata callback
- * @param proc_cls callback cls
- * @return newly allocated cfs on success, NULL on error
- */
-struct CompressedFileSource *
-cfs_new (struct BufferedFileDataSource *bfds, int64_t fsize, enum
ExtractorCompressionType compression_type, EXTRACTOR_MetaDataProcessor proc,
void *proc_cls)
-{
- int shm_result;
- struct CompressedFileSource *cfs;
- cfs = malloc (sizeof (struct CompressedFileSource));
- if (cfs == NULL)
- return NULL;
- memset (cfs, 0, sizeof (struct CompressedFileSource));
- cfs->compression_type = compression_type;
- cfs->bfds = bfds;
- cfs->fsize = fsize;
- cfs->uncompressed_size = -1;
- cfs->shm_size = MAX_READ;
-#if !WINDOWS
- shm_result = make_shm_posix ((void **) &cfs->shm_ptr, &cfs->shm,
cfs->shm_name, MAX_SHM_NAME, cfs->shm_size);
-#else
- shm_result = make_shm_w32 ((void **) &cfs->shm_ptr, &cfs->shm,
cfs->shm_name, MAX_SHM_NAME, cfs->shm_size);
-#endif
- if (shm_result != 0)
- {
- cfs_delete (cfs);
- return NULL;
- }
- return cfs;
-}
-
-/**
- * Data is read from the source and shoved into decompressor
- * in chunks this big.
- */
-#define COM_CHUNK_SIZE (10*1024)
-
-int
-cfs_read_zlib (struct CompressedFileSource *cfs, int64_t preserve)
-{
- int ret;
- int64_t rc = preserve;
- int64_t total = cfs->strm.total_out;
- if (preserve > 0)
- memmove (cfs->shm_ptr, &((unsigned char *)cfs->shm_ptr)[0], preserve);
-
- while (rc < cfs->shm_size && ret != Z_STREAM_END)
- {
- if (cfs->strm.avail_in == 0)
- {
- int64_t count = bfds_read (cfs->bfds, &cfs->strm.next_in,
COM_CHUNK_SIZE);
- if (count <= 0)
- return 0;
- cfs->strm.avail_in = (uInt) count;
- }
- cfs->strm.next_out = &((unsigned char *)cfs->shm_ptr)[rc];
- cfs->strm.avail_out = cfs->shm_size - rc;
- ret = inflate (&cfs->strm, Z_SYNC_FLUSH);
- if (ret != Z_OK && ret != Z_STREAM_END)
- return 0;
- rc = cfs->strm.total_out - total;
- }
- if (ret == Z_STREAM_END)
- cfs->uncompressed_size = cfs->strm.total_out;
- cfs->shm_pos = preserve;
- cfs->shm_buf_size = rc + preserve;
- return 1;
-}
-
-int
-cfs_read_bz2 (struct CompressedFileSource *cfs, int64_t preserve)
-{
- return -1;
-}
-
-/**
- * Re-fills shm with new uncompressed data, preserving the last
- * @preserve bytes of existing data as the first @preserve bytes
- * of the new data.
- * Does the actual decompression. Will set uncompressed_size on
- * the end of compressed stream.
- *
- * @param cfds cfs to read from
- * @param preserve number of bytes to preserve (0 to discard all old data)
- * @return number of bytes in shm. 0 if no more data can be uncompressed.
- */
-int64_t
-cfs_read (struct CompressedFileSource *cfs, int64_t preserve)
-{
- switch (cfs->compression_type)
- {
- case COMP_TYPE_ZLIB:
- return cfs_read_zlib (cfs, preserve);
- case COMP_TYPE_BZ2:
- return cfs_read_bz2 (cfs, preserve);
- default:
- return -1;
- }
-}
-
-int64_t
-cfs_seek_zlib (struct CompressedFileSource *cfs, int64_t position)
-{
- int64_t ret;
- if (position > cfs->strm.total_out - cfs->shm_buf_size && position <
cfs->strm.total_out)
- {
- ret = cfs_read (cfs, cfs->strm.total_out - position);
- if (ret < 0)
- return ret;
- return position;
- }
- while (position >= cfs->strm.total_out)
- {
- if (0 > (ret = cfs_read (cfs, 0)))
- return ret;
- if (ret == 0)
- return position;
- }
- if (position < cfs->strm.total_out && position > cfs->strm.total_out -
cfs->shm_buf_size)
- return cfs->strm.total_out - cfs->shm_buf_size;
- return -1;
-}
-
-int64_t
-cfs_seek_bz2 (struct CompressedFileSource *cfs, int64_t position)
-{
- return -1;
-}
-
-/**
- * Moves the buffer to @position in uncompressed steam. If position
- * requires seeking backwards beyond the boundaries of the buffer, resets the
- * stream and repeats decompression from the beginning to @position.
- *
- * @param cfds cfs to seek on
- * @param position new starting point for the buffer
- * @return new absolute buffer position, -1 on error or EOS
- */
-int64_t
-cfs_seek (struct CompressedFileSource *cfs, int64_t position)
-{
- switch (cfs->compression_type)
- {
- case COMP_TYPE_ZLIB:
- return cfs_seek_zlib (cfs, position);
- case COMP_TYPE_BZ2:
- return cfs_seek_bz2 (cfs, position);
- default:
- return -1;
- }
-}
-
-/**
- * Detect if we have compressed data on our hands.
- *
- * @param data pointer to a data buffer or NULL (in case fd is not -1)
- * @param fd a file to read data from, or -1 (if data is not NULL)
- * @param fsize size of data (if data is not NULL) or of file (if fd is not -1)
- * @return -1 to indicate an error, 0 to indicate uncompressed data, or a type
(> 0) of compression
- */
-static enum ExtractorCompressionType
-get_compression_type (const unsigned char *data, int fd, int64_t fsize)
-{
- void *read_data = NULL;
- size_t read_data_size = 0;
- ssize_t read_result;
- enum ExtractorCompressionType result = COMP_TYPE_INVALID;
-
- if ((MIN_COMPRESSED_HEADER < 0) || (fsize < MIN_COMPRESSED_HEADER))
- {
- return COMP_TYPE_INVALID;
- }
- if (data == NULL)
- {
- int64_t position;
- read_data_size = COMPRESSED_DATA_PROBE_SIZE;
- read_data = malloc (read_data_size);
- if (read_data == NULL)
- return -1;
-#if WINDOWS
- position = _lseeki64 (fd, 0, SEEK_CUR);
-#elif HAVE_LSEEK64
- position = lseek64 (fd, 0, SEEK_CUR);
-#else
- position = (int64_t) lseek (fd, 0, SEEK_CUR);
-#endif
- read_result = READ (fd, read_data, read_data_size);
-#if WINDOWS
- position = _lseeki64 (fd, position, SEEK_SET);
-#elif HAVE_LSEEK64
- position = lseek64 (fd, position, SEEK_SET);
-#else
- position = lseek (fd, (off_t) position, SEEK_SET);
-#endif
- if (read_result != read_data_size)
- {
- free (read_data);
- return COMP_TYPE_UNDEFINED;
- }
- data = (const void *) read_data;
- }
-#if HAVE_ZLIB
- if ((fsize >= MIN_ZLIB_HEADER) && (data[0] == 0x1f) && (data[1] == 0x8b) &&
(data[2] == 0x08))
- result = COMP_TYPE_ZLIB;
-#endif
-#if HAVE_LIBBZ2
- if ((fsize >= MIN_BZ2_HEADER) && (data[0] == 'B') && (data[1] == 'Z') &&
(data[2] == 'h'))
- result = COMP_TYPE_BZ2;
-#endif
- if (read_data != NULL)
- free (read_data);
- return result;
-}
-
-/**
* Initializes plugin state. Calls init_state_method()
* directly or indirectly.
*
@@ -2248,13 +548,16 @@
* @param fsize file size (may be -1)
*/
static void
-init_plugin_state (struct EXTRACTOR_PluginList *plugin, uint8_t
operation_mode, const char *shm_name, int64_t fsize)
+init_plugin_state (struct EXTRACTOR_PluginList *plugin,
+ uint8_t operation_mode,
+ const char *shm_name, int64_t fsize)
{
int write_result;
int init_state_size;
unsigned char *init_state;
int t;
size_t shm_name_len = strlen (shm_name) + 1;
+
init_state_size = 1 + sizeof (size_t) + shm_name_len + sizeof (uint8_t) +
sizeof (int64_t);
plugin->operation_mode = operation_mode;
switch (plugin->flags)
@@ -2297,6 +600,7 @@
}
}
+
/**
* Discards plugin state. Calls discard_state_method()
* directly or indirectly.
@@ -2308,6 +612,7 @@
{
int write_result;
unsigned char discard_state = MESSAGE_DISCARD_STATE;
+
switch (plugin->flags)
{
case EXTRACTOR_OPTION_DEFAULT_POLICY:
@@ -2335,8 +640,9 @@
}
}
+
/**
- * Forces plugin to move the buffer window to @pos.
+ * Forces plugin to move the buffer window to 'pos'.
*
* @param plugin plugin context
* @param pos position to move to
@@ -2347,7 +653,9 @@
* @return 0 on success, -1 on error
*/
static int
-pl_pick_next_buffer_at (struct EXTRACTOR_PluginList *plugin, int64_t pos,
uint8_t want_start)
+pl_pick_next_buffer_at (struct EXTRACTOR_PluginList *plugin,
+ int64_t pos,
+ uint8_t want_start)
{
if (plugin->operation_mode == OPMODE_MEMORY)
{
@@ -2485,6 +793,7 @@
return -1;
}
+
/**
* Moves current absolute buffer position to @pos in @whence mode.
* Will move logical position withouth shifting the buffer, if possible.
@@ -2495,7 +804,7 @@
* @param whence seek mode (SEEK_CUR, SEEK_SET, SEEK_END)
* @return new absolute position, -1 on error
*/
-int64_t
+static int64_t
pl_seek (struct EXTRACTOR_PluginList *plugin, int64_t pos, int whence)
{
switch (whence)
@@ -2549,17 +858,13 @@
return -1;
}
-int64_t
+
+static int64_t
pl_get_fsize (struct EXTRACTOR_PluginList *plugin)
{
return plugin->fsize;
}
-int64_t
-pl_get_pos (struct EXTRACTOR_PluginList *plugin)
-{
- return plugin->fpos + plugin->shm_pos;
-}
/**
* Fills @data with a pointer to the data buffer.
@@ -2572,9 +877,10 @@
* @param count number of bytes to read
* @return number of bytes (<= count) avalable in @data, -1 on error
*/
-int64_t
+static int64_t
pl_read (struct EXTRACTOR_PluginList *plugin, unsigned char **data, size_t
count)
{
+ *data = NULL;
if (count > MAX_READ)
return -1;
if (count > plugin->map_size - plugin->shm_pos)
@@ -2583,7 +889,7 @@
if (plugin->fpos + plugin->shm_pos != pl_seek (plugin, plugin->fpos +
plugin->shm_pos, SEEK_SET))
return -1;
*data = &plugin->shm_ptr[plugin->shm_pos];
- actual_count = (count < plugin->map_size - plugin->shm_pos ? count :
plugin->map_size - plugin->shm_pos);
+ actual_count = (count < plugin->map_size - plugin->shm_pos) ? count :
(plugin->map_size - plugin->shm_pos);
plugin->shm_pos += actual_count;
return actual_count;
}
@@ -2595,6 +901,7 @@
}
}
+
/**
* Transmits information about updated shm to plugin.
* For OPMODE_DECOMPRESS only.
@@ -2607,14 +914,18 @@
* @return 0 on success, 1 on error
*/
static int
-give_shm_to_plugin (struct EXTRACTOR_PluginList *plugin, int64_t position,
size_t map_size, int64_t fsize, uint8_t operation_mode)
+give_shm_to_plugin (struct EXTRACTOR_PluginList *plugin,
+ int64_t position,
+ size_t map_size, int64_t fsize,
+ uint8_t operation_mode)
{
int write_result;
int updated_shm_size = 1 + sizeof (int64_t) + sizeof (size_t) + sizeof
(int64_t);
unsigned char updated_shm[updated_shm_size];
int t = 0;
+
updated_shm[t] = MESSAGE_UPDATED_SHM;
- t += 1;
+ t++;
memcpy (&updated_shm[t], &position, sizeof (int64_t));
t += sizeof (int64_t);
memcpy (&updated_shm[t], &map_size, sizeof (size_t));
@@ -2622,36 +933,37 @@
memcpy (&updated_shm[t], &fsize, sizeof (int64_t));
t += sizeof (int64_t);
switch (plugin->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- if (operation_mode == OPMODE_DECOMPRESS)
{
- if (plugin->seek_request < 0)
- return 0;
- write_result = plugin_write (plugin, updated_shm, updated_shm_size);
- if (write_result < updated_shm_size)
- {
- stop_process (plugin);
- return 0;
- }
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ if (operation_mode == OPMODE_DECOMPRESS)
+ {
+ if (plugin->seek_request < 0)
+ return 0;
+ write_result = plugin_write (plugin, updated_shm, updated_shm_size);
+ if (write_result < updated_shm_size)
+ {
+ stop_process (plugin);
+ return 0;
+ }
+ }
+ return 1;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ if (operation_mode == OPMODE_DECOMPRESS)
+ {
+ plugin->fpos = position;
+ plugin->map_size = map_size;
+ plugin->fsize = fsize;
+ }
+ return 0;
+ case EXTRACTOR_OPTION_DISABLED:
+ return 0;
+ default:
+ return 1;
}
- return 1;
- case EXTRACTOR_OPTION_IN_PROCESS:
- if (operation_mode == OPMODE_DECOMPRESS)
- {
- plugin->fpos = position;
- plugin->map_size = map_size;
- plugin->fsize = fsize;
- }
- return 0;
- case EXTRACTOR_OPTION_DISABLED:
- return 0;
- default:
- return 1;
- }
}
+
/**
* Calls _extract_method of in-process plugin.
*
@@ -2661,79 +973,34 @@
* @param proc_cls callback cls
*/
static void
-ask_in_process_plugin (struct EXTRACTOR_PluginList *plugin, void *shm_ptr,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+ask_in_process_plugin (struct EXTRACTOR_PluginList *plugin,
+ void *shm_ptr,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
{
int extract_reply;
+
switch (plugin->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- return;
- case EXTRACTOR_OPTION_IN_PROCESS:
- if (plugin->seek_request >= 0)
{
- plugin->shm_ptr = shm_ptr;
- extract_reply = plugin->extract_method (plugin, proc, proc_cls);
- /* Don't leak errno from the extract method */
- errno = 0;
- if (extract_reply == 1)
- plugin->seek_request = -1;
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ return;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ if (plugin->seek_request >= 0)
+ {
+ plugin->shm_ptr = shm_ptr;
+ extract_reply = plugin->extract_method (plugin, proc, proc_cls);
+ /* Don't leak errno from the extract method */
+ errno = 0;
+ if (1 == extract_reply)
+ plugin->seek_request = -1;
+ }
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ return;
+ break;
}
- break;
- case EXTRACTOR_OPTION_DISABLED:
- return;
- break;
- }
}
-#if !WINDOWS
-/**
- * Receive @size bytes from plugin, store them in @buf
- *
- * @param plugin plugin context
- * @param buf buffer to fill
- * @param size number of bytes to read
- * @return number of bytes read, 0 on EOS, < 0 on error
- */
-int
-plugin_read (struct EXTRACTOR_PluginList *plugin, unsigned char *buf, size_t
size)
-{
- ssize_t read_result;
- size_t read_count = 0;
- while (read_count < size)
- {
- read_result = read (plugin->cpipe_out, &buf[read_count], size -
read_count);
- if (read_result <= 0)
- return read_result;
- read_count += read_result;
- }
- return read_count;
-}
-#else
-/**
- * Receive @size bytes from plugin, store them in @buf
- *
- * @param plugin plugin context
- * @param buf buffer to fill
- * @param size number of bytes to read
- * @return number of bytes read, 0 on EOS, < 0 on error
- */
-int
-plugin_read (struct EXTRACTOR_PluginList *plugin, unsigned char *buf, size_t
size)
-{
- DWORD bytes_read;
- BOOL bresult;
- size_t read_count = 0;
- while (read_count < size)
- {
- bresult = ReadFile (plugin->cpipe_out, &buf[read_count], size -
read_count, &bytes_read, NULL);
- if (!bresult)
- return -1;
- read_count += bytes_read;
- }
- return read_count;
-}
-#endif
/**
* Receive a reply from plugin (seek request, metadata and done message)
@@ -2744,268 +1011,105 @@
* @return 0 on success, -1 on error
*/
static int
-receive_reply (struct EXTRACTOR_PluginList *plugin,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+receive_reply (struct EXTRACTOR_PluginList *plugin,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
{
int read_result;
unsigned char code;
- int must_read = 1;
-
int64_t seek_position;
struct IpcHeader hdr;
char *mime_type;
char *data;
+ int must_read = 1;
while (must_read)
- {
- read_result = plugin_read (plugin, &code, 1);
- if (read_result < 1)
- return -1;
- switch (code)
{
- case MESSAGE_DONE: /* Done */
- plugin->seek_request = -1;
- must_read = 0;
- break;
- case MESSAGE_SEEK: /* Seek */
- read_result = plugin_read (plugin, (unsigned char *) &seek_position,
sizeof (int64_t));
- if (read_result < sizeof (int64_t))
- return -1;
- plugin->seek_request = seek_position;
- must_read = 0;
- break;
- case MESSAGE_META: /* Meta */
- read_result = plugin_read (plugin, (unsigned char *) &hdr, sizeof (hdr));
- if (read_result < sizeof (hdr)) /* FIXME: check hdr for sanity */
- return -1;
- mime_type = malloc (hdr.mime_len + 1);
- if (mime_type == NULL)
- return -1;
- read_result = plugin_read (plugin, (unsigned char *) mime_type,
hdr.mime_len);
- if (read_result < hdr.mime_len)
- return -1;
- mime_type[hdr.mime_len] = '\0';
- data = malloc (hdr.data_len);
- if (data == NULL)
- {
- free (mime_type);
- return -1;
- }
- read_result = plugin_read (plugin, (unsigned char *) data, hdr.data_len);
- if (read_result < hdr.data_len)
- {
- free (mime_type);
- free (data);
- return -1;
- }
- read_result = proc (proc_cls, plugin->short_libname, hdr.meta_type,
hdr.meta_format, mime_type, data, hdr.data_len);
- free (mime_type);
- free (data);
- if (read_result != 0)
- return 1;
- break;
- default:
- return -1;
+ read_result = plugin_read (plugin, &code, 1);
+ if (read_result < 1)
+ return -1;
+ switch (code)
+ {
+ case MESSAGE_DONE: /* Done */
+ plugin->seek_request = -1;
+ must_read = 0;
+ break;
+ case MESSAGE_SEEK: /* Seek */
+ read_result = plugin_read (plugin,
+ &seek_position, sizeof (int64_t));
+ if (read_result < sizeof (int64_t))
+ return -1;
+ plugin->seek_request = seek_position;
+ must_read = 0;
+ break;
+ case MESSAGE_META: /* Meta */
+ read_result = plugin_read (plugin,
+ &hdr, sizeof (hdr));
+ if (read_result < sizeof (hdr))
+ return -1;
+ /* FIXME: check hdr for sanity */
+ if (hdr.data_len > MAX_META_DATA)
+ return -1; /* not allowing more than MAX_META_DATA meta data */
+ if (0 == hdr.mime_len)
+ {
+ mime_type = NULL;
+ }
+ else
+ {
+ if (NULL == (mime_type = malloc (hdr.mime_len)))
+ return -1;
+ read_result = plugin_read (plugin,
+ mime_type,
+ hdr.mime_len);
+ if ( (read_result < hdr.mime_len) ||
+ ('\0' != mime_type[hdr.mime_len-1]) )
+ {
+ if (NULL != mime_type)
+ free (mime_type);
+ return -1;
+ }
+ }
+ if (0 == hdr.data_len)
+ {
+ data = NULL;
+ }
+ else
+ {
+ if (NULL == (data = malloc (hdr.data_len)))
+ {
+ if (NULL != mime_type)
+ free (mime_type);
+ return -1;
+ }
+ read_result = plugin_read (plugin,
+ data, hdr.data_len);
+ if (read_result < hdr.data_len)
+ {
+ if (NULL != mime_type)
+ free (mime_type);
+ free (data);
+ return -1;
+ }
+ }
+ read_result = proc (proc_cls,
+ plugin->short_libname,
+ hdr.meta_type, hdr.meta_format,
+ mime_type, data, hdr.data_len);
+ if (NULL != mime_type)
+ free (mime_type);
+ if (NULL != data)
+ free (data);
+ if (0 != read_result)
+ return 1;
+ break;
+ default:
+ return -1;
+ }
}
- }
return 0;
}
-#if !WINDOWS
-/**
- * Wait for one of the plugins to reply.
- * Selects on plugin output pipes, runs receive_reply()
- * on each activated pipe until it gets a seek request
- * or a done message. Called repeatedly by the user until all pipes are dry or
- * broken.
- *
- * @param plugins to select upon
- * @param proc metadata callback
- * @param proc_cls callback cls
- * @return number of dry/broken pipes since last call, -1 on error or if no
- * plugins reply in 10 seconds.
- */
-static int
-wait_for_reply (struct EXTRACTOR_PluginList *plugins,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
-{
- int ready;
- int result;
- struct timeval tv;
- fd_set to_check;
- int highest = 0;
- int read_result;
- struct EXTRACTOR_PluginList *ppos;
- FD_ZERO (&to_check);
-
- for (ppos = plugins; NULL != ppos; ppos = ppos->next)
- {
- switch (ppos->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- if (ppos->seek_request == -1)
- continue;
- FD_SET (ppos->cpipe_out, &to_check);
- if (highest < ppos->cpipe_out)
- highest = ppos->cpipe_out;
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- break;
- case EXTRACTOR_OPTION_DISABLED:
- break;
- }
- }
-
- tv.tv_sec = 10;
- tv.tv_usec = 0;
- ready = select (highest + 1, &to_check, NULL, NULL, &tv);
- if (ready <= 0)
- /* an error or timeout -> something's wrong or all plugins hung up */
- return -1;
-
- result = 0;
- for (ppos = plugins; NULL != ppos; ppos = ppos->next)
- {
- switch (ppos->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- if (ppos->seek_request == -1)
- continue;
- if (FD_ISSET (ppos->cpipe_out, &to_check))
- {
- read_result = receive_reply (ppos, proc, proc_cls);
- if (read_result < 0)
- {
- stop_process (ppos);
- }
- result += 1;
- }
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- break;
- case EXTRACTOR_OPTION_DISABLED:
- break;
- }
- }
- return result;
-}
-#else
/**
- * Wait for one of the plugins to reply.
- * Selects on plugin output pipes, runs receive_reply()
- * on each activated pipe until it gets a seek request
- * or a done message. Called repeatedly by the user until all pipes are dry or
- * broken.
- * This W32 version of wait_for_reply() can't select on more than 64 plugins
- * at once (returns -1 if there are more than 64 plugins).
- *
- * @param plugins to select upon
- * @param proc metadata callback
- * @param proc_cls callback cls
- * @return number of dry/broken pipes since last call, -1 on error or if no
- * plugins reply in 10 seconds.
- */
-static int
-wait_for_reply (struct EXTRACTOR_PluginList *plugins,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
-{
- int result;
- DWORD ms;
- DWORD first_ready;
- DWORD dwresult;
- DWORD bytes_read;
- BOOL bresult;
- int i;
- HANDLE events[MAXIMUM_WAIT_OBJECTS];
-
-
- struct EXTRACTOR_PluginList *ppos;
-
- i = 0;
- for (ppos = plugins; NULL != ppos; ppos = ppos->next)
- {
- if (i == MAXIMUM_WAIT_OBJECTS)
- return -1;
- if (ppos->seek_request == -1)
- continue;
- switch (ppos->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- if (WaitForSingleObject (ppos->ov_read.hEvent, 0) == WAIT_OBJECT_0)
- {
- ResetEvent (ppos->ov_read.hEvent);
- bresult = ReadFile (ppos->cpipe_out, &i, 0, &bytes_read,
&ppos->ov_read);
- if (bresult == TRUE)
- {
- SetEvent (ppos->ov_read.hEvent);
- }
- else
- {
- DWORD err = GetLastError ();
- if (err != ERROR_IO_PENDING)
- SetEvent (ppos->ov_read.hEvent);
- }
- }
- events[i] = ppos->ov_read.hEvent;
- i++;
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- break;
- case EXTRACTOR_OPTION_DISABLED:
- break;
- }
- }
-
- ms = 10000;
- first_ready = WaitForMultipleObjects (i, events, FALSE, ms);
- if (first_ready == WAIT_TIMEOUT || first_ready == WAIT_FAILED)
- /* an error or timeout -> something's wrong or all plugins hung up */
- return -1;
-
- i = 0;
- result = 0;
- for (ppos = plugins; NULL != ppos; ppos = ppos->next)
- {
- int read_result;
- switch (ppos->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- if (ppos->seek_request == -1)
- continue;
- if (i < first_ready)
- {
- i += 1;
- continue;
- }
- dwresult = WaitForSingleObject (ppos->ov_read.hEvent, 0);
- read_result = 0;
- if (dwresult == WAIT_OBJECT_0)
- {
- read_result = receive_reply (ppos, proc, proc_cls);
- result += 1;
- }
- if (dwresult == WAIT_FAILED || read_result < 0)
- {
- stop_process (ppos);
- if (dwresult == WAIT_FAILED)
- result += 1;
- }
- i++;
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- break;
- case EXTRACTOR_OPTION_DISABLED:
- break;
- }
- }
- return result;
-}
-
-#endif
-
-/**
* Checks the seek requests that plugins made, finds the one with
* smallest offset from the beginning of the stream, and satisfies it.
*
@@ -3016,53 +1120,59 @@
* @return new stream position, -1 on error
*/
static int64_t
-seek_to_new_position (struct EXTRACTOR_PluginList *plugins, struct
CompressedFileSource *cfs, int64_t current_position, int64_t map_size)
+seek_to_new_position (struct EXTRACTOR_PluginList *plugins,
+ struct CompressedFileSource *cfs,
+ int64_t current_position,
+ int64_t map_size)
{
int64_t min_pos = current_position + map_size;
int64_t min_plugin_pos = 0x7FFFFFFFFFFFFFF;
struct EXTRACTOR_PluginList *ppos;
+
for (ppos = plugins; NULL != ppos; ppos = ppos->next)
- {
- switch (ppos->flags)
{
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- case EXTRACTOR_OPTION_IN_PROCESS:
- if (ppos->seek_request >= 0 && ppos->seek_request <= min_pos)
- min_pos = ppos->seek_request;
- if (ppos->seek_request >= 0 && ppos->seek_request <= min_plugin_pos)
- min_plugin_pos = ppos->seek_request;
- break;
- case EXTRACTOR_OPTION_DISABLED:
- break;
+ switch (ppos->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ if (ppos->seek_request >= 0 && ppos->seek_request <= min_pos)
+ min_pos = ppos->seek_request;
+ if (ppos->seek_request >= 0 && ppos->seek_request <= min_plugin_pos)
+ min_plugin_pos = ppos->seek_request;
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ break;
+ }
}
- }
if (min_plugin_pos == 0x7FFFFFFFFFFFFFF)
return -1;
if (min_pos < current_position - map_size)
- {
- if (1 != cfs_reset_stream (cfs))
- return -1;
- return 0;
- }
+ {
+ if (1 != cfs_reset_stream (cfs))
+ return -1;
+ return 0;
+ }
return cfs_seek (cfs, min_pos);
}
+
static void
load_in_process_plugin (struct EXTRACTOR_PluginList *plugin)
{
switch (plugin->flags)
- {
- case EXTRACTOR_OPTION_DEFAULT_POLICY:
- case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
- case EXTRACTOR_OPTION_DISABLED:
- break;
- case EXTRACTOR_OPTION_IN_PROCESS:
- plugin_load (plugin);
- break;
- }
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ case EXTRACTOR_OPTION_DISABLED:
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ EXTRACTOR_plugin_load_ (plugin);
+ break;
+ }
}
+
/**
* Extract keywords using the given set of plugins.
*
@@ -3076,7 +1186,13 @@
* @param proc_cls cls argument to proc
*/
static void
-do_extract (struct EXTRACTOR_PluginList *plugins, const char *data, int fd,
const char *filename, struct CompressedFileSource *cfs, int64_t fsize,
EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+do_extract (struct EXTRACTOR_PluginList *plugins,
+ const char *data,
+ int fd,
+ const char *filename,
+ struct CompressedFileSource *cfs,
+ int64_t fsize,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
{
int operation_mode;
int plugin_count = 0;
@@ -3258,155 +1374,49 @@
*/
void
EXTRACTOR_extract (struct EXTRACTOR_PluginList *plugins,
- const char *filename,
- const void *data,
- size_t size,
- EXTRACTOR_MetaDataProcessor proc,
- void *proc_cls)
+ const char *filename,
+ const void *data,
+ size_t size,
+ EXTRACTOR_MetaDataProcessor proc,
+ void *proc_cls)
{
- int fd = -1;
- struct stat64 fstatbuf;
- int64_t fsize = 0;
- enum ExtractorCompressionType compression_type = -1;
- struct CompressedFileSource *cfs = NULL;
+ struct EXTRACTOR_Datasource *datasource;
- /* If data is not given, then we need to read it from the file. Try opening
it */
- if ((data == NULL) &&
- (filename != NULL) &&
- (0 == STAT64(filename, &fstatbuf)) &&
- (!S_ISDIR(fstatbuf.st_mode)) &&
- (-1 != (fd = file_open (filename,
- O_RDONLY | O_LARGEFILE))))
- {
- /* Empty files are of no interest */
- fsize = fstatbuf.st_size;
- if (fsize == 0)
- {
- close(fd);
- return;
- }
- }
-
- /* Data is not given, and we've failed to open the file with data -> exit */
- if ((fsize == 0) && (data == NULL))
+ if (NULL == filename)
+ datasource = EXTRACTOR_datasource_create_from_buffer_ (data, size);
+ else
+ datasource = EXTRACTOR_datasource_create_from_file_ (filename);
+ if (NULL == datasource)
return;
- /* fsize is now size of the data OR size of the file */
- if (data != NULL)
- fsize = size;
-
- errno = 0;
- /* Peek at first few bytes of the file (or of the data), and see if it's
compressed. */
- compression_type = get_compression_type (data, fd, fsize);
- if (compression_type < 0)
- {
- /* errno is set by get_compression_type () */
- if (fd != -1)
- close (fd);
- return;
- }
-
- struct BufferedFileDataSource *bfds;
- bfds = bfds_new (data, fd, fsize);
- if (bfds == NULL)
- return;
-
- if (compression_type > 0)
- {
- int icr = 0;
- /* Set up a decompressor.
- * Will also report compression-related metadata to the caller.
- */
- cfs = cfs_new (bfds, fsize, compression_type, proc, proc_cls);
- if (cfs == NULL)
- {
- if (fd != -1)
- close (fd);
- errno = EILSEQ;
- return;
- }
- icr = cfs_init_decompressor (cfs, proc, proc_cls);
- if (icr < 0)
- {
- if (fd != -1)
- close (fd);
- errno = EILSEQ;
- return;
- }
- else if (icr == 0)
- {
- if (fd != -1)
- close (fd);
- errno = 0;
- return;
- }
- }
-
- /* do_extract () might set errno itself, but from our point of view
everything is OK */
- errno = 0;
-
- do_extract (plugins, data, fd, filename, cfs, fsize, proc, proc_cls);
- if (cfs != NULL)
- {
- cfs_deinit_decompressor (cfs);
- cfs_delete (cfs);
- }
- bfds_delete (bfds);
- if (-1 != fd)
- close(fd);
+ do_extract (plugins, datasource, proc, proc_cls);
+ EXTRACTOR_datasource_destroy_ (datasource);
}
-#if WINDOWS
-void CALLBACK
-RundllEntryPoint (HWND hwnd,
- HINSTANCE hinst,
- LPSTR lpszCmdLine,
- int nCmdShow)
-{
- intptr_t in_h;
- intptr_t out_h;
- int in, out;
-
- sscanf(lpszCmdLine, "%lu %lu", &in_h, &out_h);
- in = _open_osfhandle (in_h, _O_RDONLY);
- out = _open_osfhandle (out_h, 0);
- setmode (in, _O_BINARY);
- setmode (out, _O_BINARY);
- plugin_main (read_plugin_data (in),
- in, out);
-}
-
-void CALLBACK
-RundllEntryPointA (HWND hwnd,
- HINSTANCE hinst,
- LPSTR lpszCmdLine,
- int nCmdShow)
-{
- return RundllEntryPoint(hwnd, hinst, lpszCmdLine, nCmdShow);
-}
-#endif
-
/**
* Initialize gettext and libltdl (and W32 if needed).
*/
-void __attribute__ ((constructor)) EXTRACTOR_ltdl_init() {
+void __attribute__ ((constructor))
+EXTRACTOR_ltdl_init ()
+{
int err;
#if ENABLE_NLS
- BINDTEXTDOMAIN(PACKAGE, LOCALEDIR);
- BINDTEXTDOMAIN("iso-639", ISOLOCALEDIR); /* used by wordextractor */
+ BINDTEXTDOMAIN (PACKAGE, LOCALEDIR);
+ BINDTEXTDOMAIN ("iso-639", ISOLOCALEDIR); /* used by wordextractor */
#endif
err = lt_dlinit ();
- if (err > 0) {
+ if (err > 0)
+ {
#if DEBUG
- fprintf(stderr,
- _("Initialization of plugin mechanism failed: %s!\n"),
- lt_dlerror());
+ fprintf (stderr,
+ _("Initialization of plugin mechanism failed: %s!\n"),
+ lt_dlerror ());
#endif
- return;
- }
+ return;
+ }
#if WINDOWS
- plibc_init("GNU", PACKAGE);
+ plibc_init ("GNU", PACKAGE);
#endif
}
@@ -3414,9 +1424,10 @@
/**
* Deinit.
*/
-void __attribute__ ((destructor)) EXTRACTOR_ltdl_fini() {
+void __attribute__ ((destructor))
+EXTRACTOR_ltdl_fini () {
#if WINDOWS
- plibc_shutdown();
+ plibc_shutdown ();
#endif
lt_dlexit ();
}
Added: Extractor/src/main/extractor_datasource.c
===================================================================
--- Extractor/src/main/extractor_datasource.c (rev 0)
+++ Extractor/src/main/extractor_datasource.c 2012-07-21 22:34:27 UTC (rev
22813)
@@ -0,0 +1,1041 @@
+/*
+ This file is part of libextractor.
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
+
+ libextractor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ libextractor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libextractor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+#include "platform.h"
+
+#if HAVE_LIBBZ2
+#include <bzlib.h>
+#endif
+
+#if HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
+/**
+ * Maximum size of an IO buffer.
+ */
+#define MAX_READ (4 * 1024 * 1024)
+
+
+#if HAVE_ZLIB
+#define MIN_ZLIB_HEADER 12
+#endif
+#if HAVE_LIBBZ2
+#define MIN_BZ2_HEADER 4
+#endif
+#if !defined (MIN_COMPRESSED_HEADER) && HAVE_ZLIB
+#define MIN_COMPRESSED_HEADER MIN_ZLIB_HEADER
+#endif
+#if !defined (MIN_COMPRESSED_HEADER) && HAVE_LIBBZ2
+#define MIN_COMPRESSED_HEADER MIN_BZ2_HEADER
+#endif
+#if !defined (MIN_COMPRESSED_HEADER)
+#define MIN_COMPRESSED_HEADER -1
+#endif
+
+#define COMPRESSED_DATA_PROBE_SIZE 3
+
+/**
+ * Enum with the various possible types of compression supported.
+ */
+enum ExtractorCompressionType
+{
+ /**
+ * We cannot tell from the data (header incomplete).
+ */
+ COMP_TYPE_UNDEFINED = -1,
+
+ /**
+ * Invalid header (likely uncompressed)
+ */
+ COMP_TYPE_INVALID = 0,
+
+ /**
+ * libz / gzip compression.
+ */
+ COMP_TYPE_ZLIB = 1,
+
+ /**
+ * bz2 compression
+ */
+ COMP_TYPE_BZ2 = 2
+};
+
+
+/**
+ * Abstraction of the data source (file or a memory buffer)
+ * for the decompressor.
+ */
+struct BufferedFileDataSource
+{
+ /**
+ * Pointer to the buffer to read from (may be NULL)
+ */
+ const void *data;
+
+ /**
+ * A buffer to read into. For fd != -1: when data != NULL,
+ * data is used directly.
+ */
+ void *buffer;
+
+ /**
+ * Size of the file (or the data buffer)
+ */
+ uint64_t fsize;
+
+ /**
+ * Position within the file or the data buffer
+ */
+ uint64_t fpos;
+
+ /**
+ * Position within the buffer.
+ */
+ uint64_t buffer_pos;
+
+ /**
+ * Number of bytes in the buffer (<= buffer_size)
+ */
+ uint64_t buffer_bytes;
+
+ /**
+ * Allocated size of the buffer
+ */
+ uint64_t buffer_size;
+
+ /**
+ * Descriptor of the file to read data from (may be -1)
+ */
+ int fd;
+
+};
+
+
+/**
+ * An object from which uncompressed data can be read
+ */
+struct CompressedFileSource
+{
+ /**
+ * The source of data
+ */
+ struct BufferedFileDataSource *bfds;
+
+ /**
+ * Size of the source (same as bfds->fsize)
+ */
+ int64_t fsize;
+
+ /**
+ * Position within the source
+ */
+ int64_t fpos;
+
+ /**
+ * Total size of the uncompressed data. Remains -1 until
+ * decompression is finished.
+ */
+ int64_t uncompressed_size;
+
+#if HAVE_LIBBZ2
+ /**
+ * BZ2 stream object
+ */
+ bz_stream bstrm;
+#endif
+
+#if HAVE_ZLIB
+ /**
+ * ZLIB stream object
+ */
+ z_stream strm;
+
+ /**
+ * Length of gzip header (may be 0, in that case ZLIB parses the header)
+ */
+ int gzip_header_length;
+#endif
+
+ /**
+ * The type of compression used in the source
+ */
+ enum ExtractorCompressionType compression_type;
+
+};
+
+
+/**
+ * Makes bfds seek to 'pos' and read a chunk of bytes there.
+ * Changes bfds->fpos, bfds->buffer_bytes and bfds->buffer_pos.
+ * Does almost nothing for memory-backed bfds.
+ *
+ * @param bfds bfds
+ * @param pos position
+ * @return 0 on success, -1 on error
+ */
+static int
+bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds,
+ uint64_t pos)
+{
+ int64_t position;
+ ssize_t rd;
+
+ if (pos > bfds->fsize)
+ return -1; /* invalid */
+ if (NULL == bfds->buffer)
+ {
+ bfds->buffer_bytes = bfds->fsize;
+ return 0;
+ }
+#if WINDOWS
+ position = _lseeki64 (bfds->fd, pos, SEEK_SET);
+#elif HAVE_LSEEK64
+ position = lseek64 (bfds->fd, pos, SEEK_SET);
+#else
+ position = (int64_t) lseek (bfds->fd, pos, SEEK_SET);
+#endif
+ if (position < 0)
+ return -1;
+ bfds->fpos = position;
+ rd = read (bfds->fd, bfds->buffer, bfds->buffer_size);
+ if (rd < 0)
+ return -1;
+ bfds->buffer_bytes = rd;
+ return 0;
+}
+
+
+/**
+ * Creates a bfds
+ *
+ * @param data data buffer to use as a source (NULL if fd != -1)
+ * @param fd file descriptor to use as a source (-1 if data != NULL)
+ * @param fsize size of the file (or the buffer)
+ * @return newly allocated bfds
+ */
+static struct BufferedFileDataSource *
+bfds_new (const void *data,
+ int fd,
+ int64_t fsize)
+{
+ struct BufferedFileDataSource *result;
+ size_t xtra;
+
+ if (fsize > MAX_READ)
+ xtra = MAX_READ;
+ else
+ xtra = (size_t) fsize;
+ if ( (-1 == fd) && (NULL == data) )
+ return NULL;
+ if ( (-1 != fd) && (NULL != data) )
+ fd = -1; /* don't need fd */
+ if (NULL != data)
+ xtra = 0;
+ if (NULL == (result = malloc (sizeof (struct BufferedFileDataSource) +
xtra)))
+ return NULL;
+ memset (result, 0, sizeof (struct BufferedFileDataSource));
+ result->data = (NULL != data) ? data : &result[1];
+ result->buffer = (NULL != data) ? NULL : &result[1];
+ result->buffer_size = (NULL != data) ? fsize : xtra;
+ result->fsize = fsize;
+ result->fd = fd;
+ bfds_pick_next_buffer_at (result, 0);
+ return result;
+}
+
+
+/**
+ * Unallocates bfds
+ *
+ * @param bfds bfds to deallocate
+ */
+static void
+bfds_delete (struct BufferedFileDataSource *bfds)
+{
+ if (NULL != bfds->buffer)
+ free (bfds->buffer);
+ free (bfds);
+}
+
+
+/**
+ * Makes bfds seek to 'pos' in 'whence' mode.
+ * Will try to seek within the buffer, will move the buffer location if
+ * the seek request falls outside of the buffer range.
+ *
+ * @param bfds bfds
+ * @param pos position to seek to
+ * @param whence one of the seek constants (SEEK_CUR, SEEK_SET, SEEK_END)
+ * @return new absolute position, -1 on error
+ */
+static int64_t
+bfds_seek (struct BufferedFileDataSource *bfds,
+ int64_t pos, int whence)
+{
+ switch (whence)
+ {
+ case SEEK_CUR:
+ if (NULL != bfds->buffer)
+ {
+ if (0 != bfds_pick_next_buffer_at (bfds,
+ bfds->fpos + bfds->buffer_pos +
pos))
+ return -1;
+ bfds->buffer_pos = 0;
+ return bfds->fpos;
+ }
+ bfds->buffer_pos += pos;
+ return bfds->buffer_pos;
+ case SEEK_SET:
+ if (pos < 0)
+ return -1;
+ if (NULL != bfds->buffer)
+ {
+ if (0 != bfds_pick_next_buffer_at (bfds, pos))
+ return -1;
+ bfds->buffer_pos = 0;
+ return bfds->fpos;
+ }
+ bfds->buffer_pos = pos;
+ return bfds->buffer_pos;
+ case SEEK_END:
+ if (NULL != bfds->buffer)
+ {
+ if (0 != bfds_pick_next_buffer_at (bfds, bfds->fsize + pos))
+ return -1;
+ bfds->buffer_pos = 0;
+ return bfds->fpos;
+ }
+ bfds->buffer_pos = bfds->fsize + pos;
+ return bfds->buffer_pos;
+ }
+ return -1;
+}
+
+
+/**
+ * Fills 'buf_ptr' with a chunk of data.
+ * Will seek if necessary. Will fail if 'count' exceeds buffer size.
+ *
+ * @param bfds bfds
+ * @param buf_ptr location to store data
+ * @param count number of bytes to read
+ * @return number of bytes (<= count) available at location pointed by buf_ptr
+ */
+static ssize_t
+bfds_read (struct BufferedFileDataSource *bfds,
+ void *buf_ptr,
+ size_t count)
+{
+ if (count > MAX_READ)
+ return -1;
+ if (count > bfds->buffer_bytes - bfds->buffer_pos)
+ {
+ if (bfds->fpos + bfds->buffer_pos != bfds_seek (bfds, bfds->fpos +
bfds->buffer_pos, SEEK_SET))
+ return -1;
+ if (NULL != bfds->buffer)
+ {
+ *buf_ptr = &bfds->buffer[bfds->buffer_pos];
+ bfds->buffer_pos += count < bfds->buffer_bytes ? count :
bfds->buffer_bytes;
+ return (count < bfds->buffer_bytes ? count : bfds->buffer_bytes);
+ }
+ else
+ {
+ int64_t ret = count < (bfds->buffer_bytes - bfds->buffer_pos) ? count
: (bfds->buffer_bytes - bfds->buffer_pos);
+ *buf_ptr = (unsigned char*) &bfds->data[bfds->buffer_pos];
+ bfds->buffer_pos += ret;
+ return ret;
+ }
+ }
+ else
+ {
+ if (NULL != bfds->buffer)
+ *buf_ptr = &bfds->buffer[bfds->buffer_pos];
+ else
+ *buf_ptr = (unsigned char*) &bfds->data[bfds->buffer_pos];
+ bfds->buffer_pos += count;
+ return count;
+ }
+}
+
+
+/**
+ * Release resources of a compressed data source.
+ *
+ * @param cfs compressed data source to free
+ */
+static void
+cfs_delete (struct CompressedFileSource *cfs)
+{
+ free (cfs);
+}
+
+
+/**
+ * Reset gz-compressed data stream to the beginning.
+ *
+ * @return 1 on success, 0 if we failed to seek,
+ * -1 on decompressor initialization failure
+ */
+static int
+cfs_reset_stream_zlib (struct CompressedFileSource *cfs)
+{
+ if (cfs->gzip_header_length !=
+ bfds_seek (cfs->bfds, cfs->gzip_header_length, SEEK_SET))
+ return 0;
+ cfs->strm.next_in = NULL;
+ cfs->strm.avail_in = 0;
+ cfs->strm.total_in = 0;
+ cfs->strm.zalloc = NULL;
+ cfs->strm.zfree = NULL;
+ cfs->strm.opaque = NULL;
+
+ /*
+ * note: maybe plain inflateInit(&strm) is adequate,
+ * it looks more backward-compatible also ;
+ *
+ * ZLIB_VERNUM isn't defined by zlib version 1.1.4 ;
+ * there might be a better check.
+ */
+ if (Z_OK != inflateInit2 (&cfs->strm,
+#ifdef ZLIB_VERNUM
+ 15 + 32
+#else
+ -MAX_WBITS
+#endif
+ ))
+ {
+ return -1;
+ }
+ cfs->fpos = cfs->gzip_header_length;
+ cfs->shm_pos = 0;
+ cfs->shm_buf_size = 0;
+ return 1;
+}
+
+
+/**
+ * Reset bz2-compressed data stream to the beginning.
+ *
+ * @return 1 on success, 0 if we failed to seek,
+ * -1 on decompressor initialization failure
+ */
+static int
+cfs_reset_stream_bz2 (struct CompressedFileSource *cfs)
+{
+ /* not implemented */
+ return -1;
+}
+
+
+/**
+ * Resets the compression stream to begin uncompressing
+ * from the beginning. Used at initialization time, and when
+ * seeking backward.
+ *
+ * @param cfs cfs to reset
+ * @return 1 on success, , 0 if we failed to seek,
+ * -1 on error
+ */
+static int
+cfs_reset_stream (struct CompressedFileSource *cfs)
+{
+ switch (cfs->compression_type)
+ {
+ case COMP_TYPE_ZLIB:
+ return cfs_reset_stream_zlib (cfs);
+ case COMP_TYPE_BZ2:
+ return cfs_reset_stream_bz2 (cfs);
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Initializes gz-decompression object. Might report metadata about
+ * compresse stream, if available. Resets the stream to the beginning.
+ *
+ * @param cfs cfs to initialize
+ * @param proc callback for metadata
+ * @param proc_cls callback cls
+ * @return 1 on success, -1 on error
+ */
+static int
+cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+{
+ /* Process gzip header */
+ unsigned int gzip_header_length = 10;
+ unsigned char data[12];
+ int64_t buf_bytes;
+ int len;
+ unsigned char *buf;
+ unsigned char *cptr;
+
+ if (sizeof (data) > bfds_read (cfs->bfds, data, sizeof (data)))
+ return -1;
+
+ if (0 != (data[3] & 0x4)) /* FEXTRA set */
+ gzip_header_length += 2 + (unsigned) (data[10] & 0xff) +
+ (((unsigned) (data[11] & 0xff)) * 256);
+
+ if (0 != (data[3] & 0x8)) /* FNAME set */
+ {
+ if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
SEEK_SET))
+ return -1;
+ buf_bytes = bfds_read (cfs->bfds, &buf, 1024);
+ if (buf_bytes <= 0)
+ return -1;
+ cptr = buf;
+
+ len = 0;
+ /* stored file name is here */
+ while (len < buf_bytes)
+ {
+ if ('\0' == *cptr)
+ break;
+ cptr++;
+ len++;
+ }
+
+ if (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_FILENAME,
+ EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
+ (const char *) buf,
+ len))
+ return 0; /* done */
+
+ /* FIXME: check for correctness */
+ //gzip_header_length = (cptr - data) + 1;
+ gzip_header_length += len + 1;
+ }
+
+ if (0 != (data[3] & 0x16)) /* FCOMMENT set */
+ {
+ int64_t buf_bytes;
+ int len;
+ unsigned char *buf;
+ unsigned char *cptr;
+
+ if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
SEEK_SET))
+ return -1;
+ buf_bytes = bfds_read (cfs->bfds, &buf, 1024);
+ if (buf_bytes <= 0)
+ return -1;
+ cptr = buf;
+
+ len = 0;
+ /* stored file name is here */
+ while (len < buf_bytes)
+ {
+ if ('\0' == *cptr)
+ break;
+ cptr++;
+ len++;
+ }
+
+ if (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_COMMENT,
+ EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
+ (const char *) buf,
+ len))
+ return 0; /* done */
+
+ /* FIXME: check for correctness */
+ //gzip_header_length = (cptr - data) + 1;
+ gzip_header_length += len + 1;
+ }
+
+ if (data[3] & 0x2) /* FCHRC set */
+ gzip_header_length += 2;
+
+ memset (&cfs->strm, 0, sizeof (z_stream));
+
+#ifdef ZLIB_VERNUM
+ gzip_header_length = 0;
+#endif
+
+ cfs->gzip_header_length = gzip_header_length;
+ return cfs_reset_stream_zlib (cfs);
+}
+
+
+/**
+ * Initializes bz2-decompression object. Might report metadata about
+ * compresse stream, if available. Resets the stream to the beginning.
+ *
+ * @param cfs cfs to initialize
+ * @param proc callback for metadata
+ * @param proc_cls callback cls
+ * @return 1 on success, -1 on error
+ */
+static int
+cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+{
+ return -1;
+}
+
+
+/**
+ * Initializes decompression object. Might report metadata about
+ * compresse stream, if available. Resets the stream to the beginning.
+ *
+ * @param cfs cfs to initialize
+ * @param proc callback for metadata
+ * @param proc_cls callback cls
+ * @return 1 on success, -1 on error
+ */
+static int
+cfs_init_decompressor (struct CompressedFileSource *cfs,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+{
+ switch (cfs->compression_type)
+ {
+ case COMP_TYPE_ZLIB:
+ return cfs_init_decompressor_zlib (cfs, proc, proc_cls);
+ case COMP_TYPE_BZ2:
+ return cfs_init_decompressor_bz2 (cfs, proc, proc_cls);
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Deinitializes gz-decompression object.
+ *
+ * @param cfs cfs to deinitialize
+ * @return 1 on success, -1 on error
+ */
+static int
+cfs_deinit_decompressor_zlib (struct CompressedFileSource *cfs)
+{
+ inflateEnd (&cfs->strm);
+ return 1;
+}
+
+
+/**
+ * Deinitializes bz2-decompression object.
+ *
+ * @param cfs cfs to deinitialize
+ * @return 1 on success, -1 on error
+ */
+static int
+cfs_deinit_decompressor_bz2 (struct CompressedFileSource *cfs)
+{
+ return -1;
+}
+
+
+/**
+ * Deinitializes decompression object.
+ *
+ * @param cfs cfs to deinitialize
+ * @return 1 on success, -1 on error
+ */
+static int
+cfs_deinit_decompressor (struct CompressedFileSource *cfs)
+{
+ switch (cfs->compression_type)
+ {
+ case COMP_TYPE_ZLIB:
+ return cfs_deinit_decompressor_zlib (cfs);
+ case COMP_TYPE_BZ2:
+ return cfs_deinit_decompressor_bz2 (cfs);
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Allocates and initializes new cfs object.
+ *
+ * @param bfds data source to use
+ * @param fsize size of the source
+ * @param compression_type type of compression used
+ * @param proc metadata callback
+ * @param proc_cls callback cls
+ * @return newly allocated cfs on success, NULL on error
+ */
+struct CompressedFileSource *
+cfs_new (struct BufferedFileDataSource *bfds,
+ int64_t fsize,
+ enum ExtractorCompressionType compression_type,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+{
+ int shm_result;
+ struct CompressedFileSource *cfs;
+
+ if (NULL == (cfs = malloc (sizeof (struct CompressedFileSource))))
+ return NULL;
+ memset (cfs, 0, sizeof (struct CompressedFileSource));
+ cfs->compression_type = compression_type;
+ cfs->bfds = bfds;
+ cfs->fsize = fsize;
+ cfs->uncompressed_size = -1;
+ return cfs;
+}
+
+
+/**
+ * Data is read from the source and shoved into decompressor
+ * in chunks this big.
+ */
+#define COM_CHUNK_SIZE (10*1024)
+
+
+/**
+ * Re-fills shm with new uncompressed data, preserving the last
+ * 'preserve' bytes of existing data as the first 'preserve' bytes
+ * of the new data.
+ * Does the actual decompression. Will set uncompressed_size on
+ * the end of compressed stream.
+ *
+ * @param cfds cfs to read from
+ * @param preserve number of bytes to preserve (0 to discard all old data)
+ * @return number of bytes in shm. 0 if no more data can be uncompressed, -1
on error
+ */
+static int
+cfs_read_zlib (struct CompressedFileSource *cfs, int64_t preserve)
+{
+ int ret;
+ int64_t rc = preserve;
+ int64_t total = cfs->strm.total_out;
+
+ if (preserve > 0)
+ memmove (cfs->shm_ptr, &((unsigned char *)cfs->shm_ptr)[0], preserve);
+
+ while (rc < cfs->shm_size && ret != Z_STREAM_END)
+ {
+ if (cfs->strm.avail_in == 0)
+ {
+ int64_t count = bfds_read (cfs->bfds, &cfs->strm.next_in,
COM_CHUNK_SIZE);
+ if (count <= 0)
+ return 0;
+ cfs->strm.avail_in = (uInt) count;
+ }
+ cfs->strm.next_out = &((unsigned char *)cfs->shm_ptr)[rc];
+ cfs->strm.avail_out = cfs->shm_size - rc;
+ ret = inflate (&cfs->strm, Z_SYNC_FLUSH);
+ if (ret != Z_OK && ret != Z_STREAM_END)
+ return 0;
+ rc = cfs->strm.total_out - total;
+ }
+ if (ret == Z_STREAM_END)
+ cfs->uncompressed_size = cfs->strm.total_out;
+ cfs->shm_pos = preserve;
+ cfs->shm_buf_size = rc + preserve;
+ return 1;
+}
+
+
+/**
+ * Re-fills shm with new uncompressed data, preserving the last
+ * 'preserve' bytes of existing data as the first 'preserve' bytes
+ * of the new data.
+ * Does the actual decompression. Will set uncompressed_size on
+ * the end of compressed stream.
+ *
+ * @param cfds cfs to read from
+ * @param preserve number of bytes to preserve (0 to discard all old data)
+ * @return number of bytes in shm. 0 if no more data can be uncompressed, -1
on error
+ */
+static int
+cfs_read_bz2 (struct CompressedFileSource *cfs, int64_t preserve)
+{
+ return -1;
+}
+
+
+/**
+ * Re-fills shm with new uncompressed data, preserving the last
+ * 'preserve' bytes of existing data as the first 'preserve' bytes
+ * of the new data.
+ * Does the actual decompression. Will set uncompressed_size on
+ * the end of compressed stream.
+ *
+ * @param cfds cfs to read from
+ * @param preserve number of bytes to preserve (0 to discard all old data)
+ * @return number of bytes in shm. 0 if no more data can be uncompressed, -1
on error
+ */
+static int64_t
+cfs_read (struct CompressedFileSource *cfs, int64_t preserve)
+{
+ switch (cfs->compression_type)
+ {
+ case COMP_TYPE_ZLIB:
+ return cfs_read_zlib (cfs, preserve);
+ case COMP_TYPE_BZ2:
+ return cfs_read_bz2 (cfs, preserve);
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Moves the buffer to 'position' in uncompressed steam. If position
+ * requires seeking backwards beyond the boundaries of the buffer, resets the
+ * stream and repeats decompression from the beginning to 'position'.
+ *
+ * @param cfds cfs to seek on
+ * @param position new starting point for the buffer
+ * @return new absolute buffer position, -1 on error or EOS
+ */
+static int64_t
+cfs_seek_zlib (struct CompressedFileSource *cfs, int64_t position)
+{
+ int64_t ret;
+
+ if (position > cfs->strm.total_out - cfs->shm_buf_size && position <
cfs->strm.total_out)
+ {
+ ret = cfs_read (cfs, cfs->strm.total_out - position);
+ if (ret < 0)
+ return ret;
+ return position;
+ }
+ while (position >= cfs->strm.total_out)
+ {
+ if (0 > (ret = cfs_read (cfs, 0)))
+ return ret;
+ if (ret == 0)
+ return position;
+ }
+ if (position < cfs->strm.total_out && position > cfs->strm.total_out -
cfs->shm_buf_size)
+ return cfs->strm.total_out - cfs->shm_buf_size;
+ return -1;
+}
+
+
+/**
+ * Moves the buffer to 'position' in uncompressed steam. If position
+ * requires seeking backwards beyond the boundaries of the buffer, resets the
+ * stream and repeats decompression from the beginning to 'position'.
+ *
+ * @param cfds cfs to seek on
+ * @param position new starting point for the buffer
+ * @return new absolute buffer position, -1 on error or EOS
+ */
+static int64_t
+cfs_seek_bz2 (struct CompressedFileSource *cfs, int64_t position)
+{
+ return -1;
+}
+
+
+/**
+ * Moves the buffer to 'position' in uncompressed steam. If position
+ * requires seeking backwards beyond the boundaries of the buffer, resets the
+ * stream and repeats decompression from the beginning to 'position'.
+ *
+ * @param cfds cfs to seek on
+ * @param position new starting point for the buffer
+ * @return new absolute buffer position, -1 on error or EOS
+ */
+static int64_t
+cfs_seek (struct CompressedFileSource *cfs, int64_t position)
+{
+ switch (cfs->compression_type)
+ {
+ case COMP_TYPE_ZLIB:
+ return cfs_seek_zlib (cfs, position);
+ case COMP_TYPE_BZ2:
+ return cfs_seek_bz2 (cfs, position);
+ default:
+ return -1;
+ }
+}
+
+
+/**
+ * Detect if we have compressed data on our hands.
+ *
+ * @param data pointer to a data buffer or NULL (in case fd is not -1)
+ * @param fd a file to read data from, or -1 (if data is not NULL)
+ * @param fsize size of data (if data is not NULL) or of file (if fd is not -1)
+ * @return -1 to indicate an error, 0 to indicate uncompressed data, or a type
(> 0) of compression
+ */
+static enum ExtractorCompressionType
+get_compression_type (const unsigned char *data,
+ int fd,
+ int64_t fsize)
+{
+ void *read_data = NULL;
+ size_t read_data_size = 0;
+ ssize_t read_result;
+ enum ExtractorCompressionType result = COMP_TYPE_INVALID;
+
+ if ((MIN_COMPRESSED_HEADER < 0) || (fsize < MIN_COMPRESSED_HEADER))
+ {
+ return COMP_TYPE_INVALID;
+ }
+ if (data == NULL)
+ {
+ int64_t position;
+ read_data_size = COMPRESSED_DATA_PROBE_SIZE;
+ read_data = malloc (read_data_size);
+ if (read_data == NULL)
+ return -1;
+#if WINDOWS
+ position = _lseeki64 (fd, 0, SEEK_CUR);
+#elif HAVE_LSEEK64
+ position = lseek64 (fd, 0, SEEK_CUR);
+#else
+ position = (int64_t) lseek (fd, 0, SEEK_CUR);
+#endif
+ read_result = READ (fd, read_data, read_data_size);
+#if WINDOWS
+ position = _lseeki64 (fd, position, SEEK_SET);
+#elif HAVE_LSEEK64
+ position = lseek64 (fd, position, SEEK_SET);
+#else
+ position = lseek (fd, (off_t) position, SEEK_SET);
+#endif
+ if (read_result != read_data_size)
+ {
+ free (read_data);
+ return COMP_TYPE_UNDEFINED;
+ }
+ data = (const void *) read_data;
+ }
+#if HAVE_ZLIB
+ if ((fsize >= MIN_ZLIB_HEADER) && (data[0] == 0x1f) && (data[1] == 0x8b) &&
(data[2] == 0x08))
+ result = COMP_TYPE_ZLIB;
+#endif
+#if HAVE_LIBBZ2
+ if ((fsize >= MIN_BZ2_HEADER) && (data[0] == 'B') && (data[1] == 'Z') &&
(data[2] == 'h'))
+ result = COMP_TYPE_BZ2;
+#endif
+ if (read_data != NULL)
+ free (read_data);
+ return result;
+}
+
+
+#if 0
+
+ enum ExtractorCompressionType compression_type = -1;
+ struct CompressedFileSource *cfs = NULL;
+ int fd = -1;
+ struct stat64 fstatbuf;
+ int64_t fsize = 0;
+
+ /* If data is not given, then we need to read it from the file. Try opening
it */
+ if ((data == NULL) &&
+ (filename != NULL) &&
+ (0 == STAT64(filename, &fstatbuf)) &&
+ (!S_ISDIR(fstatbuf.st_mode)) &&
+ (-1 != (fd = file_open (filename,
+ O_RDONLY | O_LARGEFILE))))
+ {
+ /* Empty files are of no interest */
+ fsize = fstatbuf.st_size;
+ if (fsize == 0)
+ {
+ close(fd);
+ return;
+ }
+ }
+
+ /* Data is not given, and we've failed to open the file with data -> exit */
+ if ((fsize == 0) && (data == NULL))
+ return;
+ /* fsize is now size of the data OR size of the file */
+ if (data != NULL)
+ fsize = size;
+
+ errno = 0;
+
+ /* Peek at first few bytes of the file (or of the data), and see if it's
compressed. */
+ compression_type = get_compression_type (data, fd, fsize);
+ if (compression_type < 0)
+ {
+ /* errno is set by get_compression_type () */
+ if (fd != -1)
+ close (fd);
+ return;
+ }
+
+ struct BufferedFileDataSource *bfds;
+ bfds = bfds_new (data, fd, fsize);
+ if (bfds == NULL)
+ return;
+
+ if (compression_type > 0)
+ {
+ int icr = 0;
+ /* Set up a decompressor.
+ * Will also report compression-related metadata to the caller.
+ */
+ cfs = cfs_new (bfds, fsize, compression_type, proc, proc_cls);
+ if (cfs == NULL)
+ {
+ if (fd != -1)
+ close (fd);
+ errno = EILSEQ;
+ return;
+ }
+ icr = cfs_init_decompressor (cfs, proc, proc_cls);
+ if (icr < 0)
+ {
+ if (fd != -1)
+ close (fd);
+ errno = EILSEQ;
+ return;
+ }
+ else if (icr == 0)
+ {
+ if (fd != -1)
+ close (fd);
+ errno = 0;
+ return;
+ }
+ }
+
+
+#endif
+
+
+
+/**
+ * Destroy a data source.
+ *
+ * @param datasource source to destroy
+ */
+void
+EXTRACTOR_datasource_destroy_ (struct EXTRACTOR_Datasource *datasource)
+{
+ if (cfs != NULL)
+ {
+ cfs_deinit_decompressor (cfs);
+ cfs_delete (cfs);
+ }
+ bfds_delete (bfds);
+ if (-1 != fd)
+ close(fd);
+}
+
+/* end of extractor_datasource.c */
Added: Extractor/src/main/extractor_datasource.h
===================================================================
--- Extractor/src/main/extractor_datasource.h (rev 0)
+++ Extractor/src/main/extractor_datasource.h 2012-07-21 22:34:27 UTC (rev
22813)
@@ -0,0 +1,101 @@
+/*
+ This file is part of libextractor.
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
+
+ libextractor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ libextractor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libextractor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+#ifndef EXTRACTOR_DATASOURCE_H
+#define EXTRACTOR_DATASOURCE_H
+
+/**
+ * Handle to a datasource we can use for the plugins.
+ */
+struct EXTRACTOR_Datasource;
+
+
+/**
+ * Create a datasource from a file on disk.
+ *
+ * @param filename name of the file on disk
+ * @return handle to the datasource
+ */
+struct EXTRACTOR_Datasource *
+EXTRACTOR_datasource_create_from_file_ (const char *filename);
+
+
+/**
+ * Create a datasource from a buffer in memory.
+ *
+ * @param buf data in memory
+ * @param size number of bytes in 'buf'
+ * @return handle to the datasource
+ */
+struct EXTRACTOR_Datasource *
+EXTRACTOR_datasource_create_from_buffer_ (const char *buf,
+ size_t size);
+
+
+/**
+ * Destroy a data source.
+ *
+ * @param datasource source to destroy
+ */
+void
+EXTRACTOR_datasource_destroy_ (struct EXTRACTOR_Datasource *datasource);
+
+
+/**
+ * Make 'size' bytes of data from the data source available at '*data'.
+ *
+ * @param cls must be a 'struct EXTRACTOR_Datasource'
+ * @param data where the data should be copied to
+ * @param size maximum number of bytes requested
+ * @return number of bytes now available in data (can be smaller than 'size'),
+ * -1 on error
+ */
+ssize_t
+EXTRACTOR_datasource_read_ (void *cls,
+ void *data,
+ size_t size);
+
+
+/**
+ * Seek in the datasource. Use 'SEEK_CUR' for whence and 'pos' of 0 to
+ * obtain the current position in the file.
+ *
+ * @param cls must be a 'struct EXTRACTOR_Datasource'
+ * @param pos position to seek (see 'man lseek')
+ * @param whence how to see (absolute to start, relative, absolute to end)
+ * @return new absolute position, UINT64_MAX on error (i.e. desired position
+ * does not exist)
+ */
+uint64_t
+EXTRACTOR_datasource_seek_ (void *cls,
+ uint64_t pos,
+ int whence);
+
+
+/**
+ * Determine the overall size of the data source (after compression).
+ *
+ * @param cls must be a 'struct EXTRACTOR_Datasource'
+ * @return overall file size, UINT64_MAX on error (i.e. IPC failure)
+ */
+uint64_t
+EXTRACTOR_datasource_get_size_ (void *cls);
+
+
+#endif
Added: Extractor/src/main/extractor_ipc.h
===================================================================
--- Extractor/src/main/extractor_ipc.h (rev 0)
+++ Extractor/src/main/extractor_ipc.h 2012-07-21 22:34:27 UTC (rev 22813)
@@ -0,0 +1,61 @@
+/*
+ This file is part of libextractor.
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
+
+ libextractor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ libextractor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libextractor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+#ifndef EXTRACTOR_IPC_H
+#define EXTRACTOR_IPC_H
+
+/**
+ * Definition of an IPC communication channel with
+ * some plugin.
+ */
+struct EXTRACTOR_Channel;
+
+
+/**
+ * Create a channel to communicate with a process wrapping
+ * the plugin of the given name. Starts the process as well.
+ *
+ * @param short_libname name of the plugin
+ * @return NULL on error, otherwise IPC channel
+ */
+struct EXTRACTOR_Channel *
+EXTRACTOR_IPC_channel_create_ (const char *short_libname);
+
+
+/**
+ * Destroy communication channel with a plugin/process. Also
+ * destroys the process.
+ *
+ * @param channel channel to communicate with the plugin
+ */
+void
+EXTRACTOR_IPC_channel_destroy_ (struct EXTRACTOR_Channel *channel);
+
+
+/**
+ * Map the given buffer
+ *
+ * @param channel channel to communicate with the plugin
+ */
+void
+EXTRACTOR_IPC_channel_xxx_ (struct EXTRACTOR_Channel *channel);
+
+
+
+#endif
Added: Extractor/src/main/extractor_ipc_gnu.c
===================================================================
--- Extractor/src/main/extractor_ipc_gnu.c (rev 0)
+++ Extractor/src/main/extractor_ipc_gnu.c 2012-07-21 22:34:27 UTC (rev
22813)
@@ -0,0 +1,490 @@
+/*
+ This file is part of libextractor.
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
+
+ libextractor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ libextractor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libextractor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+#include "platform.h"
+#include "plibc.h"
+#include "extractor.h"
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/shm.h>
+#include <signal.h>
+
+
+/**
+ * Definition of an IPC communication channel with
+ * some plugin.
+ */
+struct EXTRACTOR_Channel
+{
+ /**
+ * POSIX id of the shm into which data is uncompressed
+ */
+ int shm;
+
+ /**
+ * Name of the shm
+ */
+ char shm_name[MAX_SHM_NAME + 1];
+
+ /**
+ * Pointer to the mapped region of the shm (covers the whole shm)
+ */
+ void *shm_ptr;
+
+ /**
+ * Position within shm
+ */
+ int64_t shm_pos;
+
+ /**
+ * Allocated size of the shm
+ */
+ int64_t shm_size;
+
+ /**
+ * Number of bytes in shm (<= shm_size)
+ */
+ size_t shm_buf_size;
+
+
+};
+
+
+/**
+ * Opens a shared memory object (for later mmapping).
+ * This is POSIX variant of the the plugin_open_* function. Shm is always
memory-backed.
+ * Closes a shm is already opened, closes it before opening a new one.
+ *
+ * @param plugin plugin context
+ * @param shm_name name of the shm.
+ * @return shm id (-1 on error). That is, the result of shm_open() syscall.
+ */
+static int
+plugin_open_shm (struct EXTRACTOR_PluginList *plugin,
+ const char *shm_name)
+{
+ if (plugin->shm_id != -1)
+ close (plugin->shm_id);
+ plugin->shm_id = shm_open (shm_name, O_RDONLY, 0);
+ return plugin->shm_id;
+}
+
+
+/**
+ * Opens a file (for later mmapping).
+ * This is POSIX variant of the plugin_open_* function.
+ * Closes a file is already opened, closes it before opening a new one.
+ *
+ * @param plugin plugin context
+ * @param shm_name name of the file to open.
+ * @return file id (-1 on error). That is, the result of open() syscall.
+ */
+static int
+plugin_open_file (struct EXTRACTOR_PluginList *plugin,
+ const char *shm_name)
+{
+ if (plugin->shm_id != -1)
+ close (plugin->shm_id);
+ plugin->shm_id = open (shm_name, O_RDONLY, 0);
+ return plugin->shm_id;
+}
+
+
+/**
+ * Initializes an extracting session for a plugin.
+ * opens the file/shm (only in OPMODE_FILE)
+ * sets shm_ptr to NULL (unmaps it, if it was mapped)
+ * sets position to 0
+ * initializes file size to 'fsize' (may be -1)
+ * sets seek request to 0
+ *
+ * @param plugin plugin context
+ * @param operation_mode the mode of operation (OPMODE_*)
+ * @param fsize size of the source file (may be -1)
+ * @param shm_name name of the shm or file to open
+ * @return 0 on success, non-0 on error.
+ */
+static int
+init_state_method (struct EXTRACTOR_PluginList *plugin,
+ uint8_t operation_mode,
+ int64_t fsize,
+ const char *shm_name)
+{
+ plugin->seek_request = 0;
+ if (plugin->shm_ptr != NULL)
+ munmap (plugin->shm_ptr, plugin->map_size);
+ plugin->shm_ptr = NULL;
+ if (operation_mode == OPMODE_FILE)
+ {
+ if (-1 == plugin_open_file (plugin, shm_name))
+ return 1;
+ }
+ else if (-1 == plugin_open_shm (plugin, shm_name))
+ return 1;
+ plugin->fsize = fsize;
+ plugin->shm_pos = 0;
+ plugin->fpos = 0;
+ return 0;
+}
+
+
+/**
+ * Deinitializes an extracting session for a plugin.
+ * unmaps shm_ptr (if was mapped)
+ * closes file/shm (if it was opened)
+ * sets map size and shm_ptr to NULL.
+ *
+ * @param plugin plugin context
+ */
+static void
+discard_state_method (struct EXTRACTOR_PluginList *plugin)
+{
+ if (plugin->shm_ptr != NULL && plugin->map_size > 0)
+ munmap (plugin->shm_ptr, plugin->map_size);
+ if (plugin->shm_id != -1)
+ close (plugin->shm_id);
+ plugin->shm_id = -1;
+ plugin->map_size = 0;
+ plugin->shm_ptr = NULL;
+}
+
+
+
+/**
+ * Start the process for the given plugin.
+ */
+static void
+start_process (struct EXTRACTOR_PluginList *plugin)
+{
+ int p1[2];
+ int p2[2];
+ pid_t pid;
+ int status;
+
+ switch (plugin->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ if (-1 != plugin->cpid && 0 != plugin->cpid)
+ return;
+ break;
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ if (0 != plugin->cpid)
+ return;
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ return;
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ return;
+ break;
+ }
+
+ plugin->cpid = -1;
+ if (0 != pipe (p1))
+ {
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+ if (0 != pipe (p2))
+ {
+ close (p1[0]);
+ close (p1[1]);
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+ pid = fork ();
+ plugin->cpid = pid;
+ if (pid == -1)
+ {
+ close (p1[0]);
+ close (p1[1]);
+ close (p2[0]);
+ close (p2[1]);
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+ if (pid == 0)
+ {
+ close (p1[1]);
+ close (p2[0]);
+ plugin_main (plugin, p1[0], p2[1]);
+ _exit (0);
+ }
+ close (p1[0]);
+ close (p2[1]);
+ plugin->cpipe_in = fdopen (p1[1], "w");
+ if (plugin->cpipe_in == NULL)
+ {
+ perror ("fdopen");
+ (void) kill (plugin->cpid, SIGKILL);
+ waitpid (plugin->cpid, &status, 0);
+ close (p1[1]);
+ close (p2[0]);
+ plugin->cpid = -1;
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+ plugin->cpipe_out = p2[0];
+}
+
+
+/**
+ * Stop the child process of this plugin.
+ */
+static void
+stop_process (struct EXTRACTOR_PluginList *plugin)
+{
+ int status;
+
+#if DEBUG
+ if (plugin->cpid == -1)
+ fprintf (stderr,
+ "Plugin `%s' choked on this input\n",
+ plugin->short_libname);
+#endif
+ if ( (plugin->cpid == -1) ||
+ (plugin->cpid == 0) )
+ return;
+ kill (plugin->cpid, SIGKILL);
+ waitpid (plugin->cpid, &status, 0);
+ plugin->cpid = -1;
+ close (plugin->cpipe_out);
+ fclose (plugin->cpipe_in);
+ plugin->cpipe_out = -1;
+ plugin->cpipe_in = NULL;
+
+ if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+
+ plugin->seek_request = -1;
+}
+
+
+static int
+write_plugin_data (const struct EXTRACTOR_PluginList *plugin)
+{
+ /* This function is only necessary on W32. On POSIX
+ * systems plugin inherits its own data from the parent */
+ return 0;
+}
+
+
+/**
+ * Initializes an extracting session for a plugin.
+ * opens the file/shm (only in OPMODE_FILE)
+ * sets shm_ptr to NULL (unmaps it, if it was mapped)
+ * sets position to 0
+ * initializes file size to 'fsize' (may be -1)
+ * sets seek request to 0
+ *
+ * @param plugin plugin context
+ * @param operation_mode the mode of operation (OPMODE_*)
+ * @param fsize size of the source file (may be -1)
+ * @param shm_name name of the shm or file to open
+ * @return 0 on success, non-0 on error.
+ */
+static int
+init_state_method (struct EXTRACTOR_PluginList *plugin,
+ uint8_t operation_mode,
+ int64_t fsize,
+ const char *shm_name)
+{
+ plugin->seek_request = 0;
+ if (plugin->shm_ptr != NULL)
+ munmap (plugin->shm_ptr, plugin->map_size);
+ plugin->shm_ptr = NULL;
+ if (operation_mode == OPMODE_FILE)
+ {
+ if (-1 == plugin_open_file (plugin, shm_name))
+ return 1;
+ }
+ else if (-1 == plugin_open_shm (plugin, shm_name))
+ return 1;
+ plugin->fsize = fsize;
+ plugin->shm_pos = 0;
+ plugin->fpos = 0;
+ return 0;
+}
+
+
+/**
+ * Setup a shared memory segment.
+ *
+ * @param ptr set to the location of the shm segment
+ * @param shmid where to store the shm ID
+ * @param fn name of the shared segment
+ * @param fn_size size available in fn
+ * @param size number of bytes to allocated for the segment
+ * @return 0 on success
+ */
+static int
+make_shm_posix (void **ptr,
+ int *shmid,
+ char *fn,
+ size_t fn_size, size_t size)
+{
+ const char *tpath;
+#if SOMEBSD
+ /* this works on FreeBSD, not sure about others... */
+ tpath = getenv ("TMPDIR");
+ if (tpath == NULL)
+ tpath = "/tmp/";
+#else
+ tpath = "/"; /* Linux */
+#endif
+ snprintf (fn, fn_size, "%slibextractor-shm-%u-%u", tpath, getpid(),
+ (unsigned int) RANDOM());
+ *shmid = shm_open (fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ *ptr = NULL;
+ if (-1 == *shmid)
+ return 1;
+ if ((0 != ftruncate (*shmid, size)) ||
+ (NULL == (*ptr = mmap (NULL, size, PROT_WRITE, MAP_SHARED, *shmid, 0)))
||
+ (*ptr == (void*) -1) )
+ {
+ close (*shmid);
+ *shmid = -1;
+ shm_unlink (fn);
+ return 1;
+ }
+ return 0;
+}
+
+
+static void
+destroy_shm_posix (void *ptr, int shm_id, size_t size, char *shm_name)
+{
+ if (NULL != ptr)
+ munmap (ptr, size);
+ if (shm_id != -1)
+ close (shm_id);
+ shm_unlink (shm_name);
+}
+
+
+/**
+ * Receive 'size' bytes from plugin, store them in 'buf'
+ *
+ * @param plugin plugin context
+ * @param buf buffer to fill
+ * @param size number of bytes to read
+ * @return number of bytes read, 0 on EOS, < 0 on error
+ */
+static int
+plugin_read (struct EXTRACTOR_PluginList *plugin,
+ void *buf,
+ size_t size)
+{
+ char *rb = buf;
+ ssize_t read_result;
+ size_t read_count = 0;
+
+ while (read_count < size)
+ {
+ read_result = read (plugin->cpipe_out,
+ &rb[read_count], size - read_count);
+ if (read_result <= 0)
+ return read_result;
+ read_count += read_result;
+ }
+ return read_count;
+}
+
+
+/**
+ * Wait for one of the plugins to reply.
+ * Selects on plugin output pipes, runs receive_reply()
+ * on each activated pipe until it gets a seek request
+ * or a done message. Called repeatedly by the user until all pipes are dry or
+ * broken.
+ *
+ * @param plugins to select upon
+ * @param proc metadata callback
+ * @param proc_cls callback cls
+ * @return number of dry/broken pipes since last call, -1 on error or if no
+ * plugins reply in 10 seconds.
+ */
+static int
+wait_for_reply (struct EXTRACTOR_PluginList *plugins,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+{
+ int ready;
+ int result;
+ struct timeval tv;
+ fd_set to_check;
+ int highest = 0;
+ int read_result;
+ struct EXTRACTOR_PluginList *ppos;
+
+ FD_ZERO (&to_check);
+ for (ppos = plugins; NULL != ppos; ppos = ppos->next)
+ {
+ switch (ppos->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ if (ppos->seek_request == -1)
+ continue;
+ FD_SET (ppos->cpipe_out, &to_check);
+ if (highest < ppos->cpipe_out)
+ highest = ppos->cpipe_out;
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ break;
+ }
+ }
+
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ ready = select (highest + 1, &to_check, NULL, NULL, &tv);
+ if (ready <= 0)
+ /* an error or timeout -> something's wrong or all plugins hung up */
+ return -1;
+
+ result = 0;
+ for (ppos = plugins; NULL != ppos; ppos = ppos->next)
+ {
+ switch (ppos->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ if (ppos->seek_request == -1)
+ continue;
+ if (FD_ISSET (ppos->cpipe_out, &to_check))
+ {
+ read_result = receive_reply (ppos, proc, proc_cls);
+ if (read_result < 0)
+ {
+ stop_process (ppos);
+ }
+ result += 1;
+ }
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ break;
+ }
+ }
+ return result;
+}
Added: Extractor/src/main/extractor_ipc_w32.c
===================================================================
--- Extractor/src/main/extractor_ipc_w32.c (rev 0)
+++ Extractor/src/main/extractor_ipc_w32.c 2012-07-21 22:34:27 UTC (rev
22813)
@@ -0,0 +1,905 @@
+/*
+ This file is part of libextractor.
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
+
+ libextractor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ libextractor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libextractor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+
+/**
+ * Definition of an IPC communication channel with
+ * some plugin.
+ */
+struct EXTRACTOR_Channel
+{
+
+ /**
+ * W32 handle of the shm into which data is uncompressed
+ */
+ HANDLE shm;
+
+ /**
+ * Name of the shm
+ */
+ char shm_name[MAX_SHM_NAME + 1];
+
+ /**
+ * Pointer to the mapped region of the shm (covers the whole shm)
+ */
+ void *shm_ptr;
+
+ /**
+ * Position within shm
+ */
+ int64_t shm_pos;
+
+ /**
+ * Allocated size of the shm
+ */
+ int64_t shm_size;
+
+ /**
+ * Number of bytes in shm (<= shm_size)
+ */
+ size_t shm_buf_size;
+
+
+};
+
+
+
+/**
+ * Initializes an extracting session for a plugin.
+ * opens the file/shm (only in OPMODE_FILE)
+ * sets shm_ptr to NULL (unmaps it, if it was mapped)
+ * sets position to 0
+ * initializes file size to 'fsize' (may be -1)
+ * sets seek request to 0
+ *
+ * @param plugin plugin context
+ * @param operation_mode the mode of operation (OPMODE_*)
+ * @param fsize size of the source file (may be -1)
+ * @param shm_name name of the shm or file to open
+ * @return 0 on success, non-0 on error.
+ */
+static int
+init_state_method (struct EXTRACTOR_PluginList *plugin,
+ uint8_t operation_mode,
+ int64_t fsize,
+ const char *shm_name)
+{
+ plugin->seek_request = 0;
+ if (plugin->shm_ptr != NULL)
+ UnmapViewOfFile (plugin->shm_ptr);
+ plugin->shm_ptr = NULL;
+ if (INVALID_HANDLE_VALUE == plugin_open_shm (plugin, shm_name))
+ return 1;
+ plugin->fsize = fsize;
+ plugin->shm_pos = 0;
+ plugin->fpos = 0;
+ return 0;
+}
+
+/**
+ * Opens a shared memory object (for later mmapping).
+ * This is W32 variant of the plugin_open_* function.
+ * Opened shm might be memory-backed or file-backed (depending on how
+ * it was created). shm_name is never a file name, unlike POSIX.
+ * Closes a shm is already opened, closes it before opening a new one.
+ *
+ * @param plugin plugin context
+ * @param shm_name name of the shared memory object.
+ * @return memory-mapped file handle (NULL on error). That is, the result of
OpenFileMapping() syscall.
+ */
+static HANDLE
+plugin_open_shm (struct EXTRACTOR_PluginList *plugin,
+ const char *shm_name)
+{
+ if (plugin->map_handle != 0)
+ CloseHandle (plugin->map_handle);
+ plugin->map_handle = OpenFileMapping (FILE_MAP_READ, FALSE, shm_name);
+ return plugin->map_handle;
+}
+
+
+/**
+ * Another name for plugin_open_shm().
+ */
+static HANDLE
+plugin_open_file (struct EXTRACTOR_PluginList *plugin,
+ const char *shm_name)
+{
+ return plugin_open_shm (plugin, shm_name);
+}
+
+
+/**
+ * Initializes an extracting session for a plugin.
+ * opens the file/shm (only in OPMODE_FILE)
+ * sets shm_ptr to NULL (unmaps it, if it was mapped)
+ * sets position to 0
+ * initializes file size to 'fsize' (may be -1)
+ * sets seek request to 0
+ *
+ * @param plugin plugin context
+ * @param operation_mode the mode of operation (OPMODE_*)
+ * @param fsize size of the source file (may be -1)
+ * @param shm_name name of the shm or file to open
+ * @return 0 on success, non-0 on error.
+ */
+static int
+init_state_method (struct EXTRACTOR_PluginList *plugin,
+ uint8_t operation_mode,
+ int64_t fsize,
+ const char *shm_name)
+{
+ plugin->seek_request = 0;
+ if (plugin->shm_ptr != NULL)
+ UnmapViewOfFile (plugin->shm_ptr);
+ plugin->shm_ptr = NULL;
+ if (INVALID_HANDLE_VALUE == plugin_open_shm (plugin, shm_name))
+ return 1;
+ plugin->fsize = fsize;
+ plugin->shm_pos = 0;
+ plugin->fpos = 0;
+ return 0;
+}
+
+
+/**
+ * Deinitializes an extracting session for a plugin.
+ * unmaps shm_ptr (if was mapped)
+ * closes file/shm (if it was opened)
+ * sets map size and shm_ptr to NULL.
+ *
+ * @param plugin plugin context
+ */
+static void
+discard_state_method (struct EXTRACTOR_PluginList *plugin)
+{
+ if (plugin->shm_ptr != NULL)
+ UnmapViewOfFile (plugin->shm_ptr);
+ if (plugin->map_handle != 0)
+ CloseHandle (plugin->map_handle);
+ plugin->map_handle = 0;
+ plugin->map_size = 0;
+ plugin->shm_ptr = NULL;
+}
+
+
+#ifndef PIPE_BUF
+#define PIPE_BUF 512
+#endif
+
+/* Copyright Bob Byrnes <byrnes <at> curl.com>
+ http://permalink.gmane.org/gmane.os.cygwin.patches/2121
+*/
+/* Create a pipe, and return handles to the read and write ends,
+ just like CreatePipe, but ensure that the write end permits
+ FILE_READ_ATTRIBUTES access, on later versions of win32 where
+ this is supported. This access is needed by NtQueryInformationFile,
+ which is used to implement select and nonblocking writes.
+ Note that the return value is either NO_ERROR or GetLastError,
+ unlike CreatePipe, which returns a bool for success or failure. */
+static int
+create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr,
+ LPSECURITY_ATTRIBUTES sa_ptr, DWORD psize,
+ DWORD dwReadMode, DWORD dwWriteMode)
+{
+ /* Default to error. */
+ *read_pipe_ptr = *write_pipe_ptr = INVALID_HANDLE_VALUE;
+
+ HANDLE read_pipe = INVALID_HANDLE_VALUE, write_pipe = INVALID_HANDLE_VALUE;
+
+ /* Ensure that there is enough pipe buffer space for atomic writes. */
+ if (psize < PIPE_BUF)
+ psize = PIPE_BUF;
+
+ char pipename[MAX_PATH];
+
+ /* Retry CreateNamedPipe as long as the pipe name is in use.
+ * Retrying will probably never be necessary, but we want
+ * to be as robust as possible. */
+ while (1)
+ {
+ static volatile LONG pipe_unique_id;
+
+ snprintf (pipename, sizeof pipename, "\\\\.\\pipe\\gnunet-%d-%ld",
+ getpid (), InterlockedIncrement ((LONG *) & pipe_unique_id));
+ /* Use CreateNamedPipe instead of CreatePipe, because the latter
+ * returns a write handle that does not permit FILE_READ_ATTRIBUTES
+ * access, on versions of win32 earlier than WinXP SP2.
+ * CreatePipe also stupidly creates a full duplex pipe, which is
+ * a waste, since only a single direction is actually used.
+ * It's important to only allow a single instance, to ensure that
+ * the pipe was not created earlier by some other process, even if
+ * the pid has been reused. We avoid FILE_FLAG_FIRST_PIPE_INSTANCE
+ * because that is only available for Win2k SP2 and WinXP. */
+ read_pipe = CreateNamedPipeA (pipename, PIPE_ACCESS_INBOUND | dwReadMode,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, /* max instances */
+ psize, /* output buffer size */
+ psize, /* input buffer size */
+ NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
+
+ if (read_pipe != INVALID_HANDLE_VALUE)
+ {
+ break;
+ }
+
+ DWORD err = GetLastError ();
+
+ switch (err)
+ {
+ case ERROR_PIPE_BUSY:
+ /* The pipe is already open with compatible parameters.
+ * Pick a new name and retry. */
+ continue;
+ case ERROR_ACCESS_DENIED:
+ /* The pipe is already open with incompatible parameters.
+ * Pick a new name and retry. */
+ continue;
+ case ERROR_CALL_NOT_IMPLEMENTED:
+ /* We are on an older Win9x platform without named pipes.
+ * Return an anonymous pipe as the best approximation. */
+ if (CreatePipe (read_pipe_ptr, write_pipe_ptr, sa_ptr, psize))
+ {
+ return 0;
+ }
+ err = GetLastError ();
+ return err;
+ default:
+ return err;
+ }
+ /* NOTREACHED */
+ }
+
+ /* Open the named pipe for writing.
+ * Be sure to permit FILE_READ_ATTRIBUTES access. */
+ write_pipe = CreateFileA (pipename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0,
/* share mode */
+ sa_ptr, OPEN_EXISTING, dwWriteMode, /* flags and
attributes */
+ 0); /* handle to template file */
+
+ if (write_pipe == INVALID_HANDLE_VALUE)
+ {
+ /* Failure. */
+ DWORD err = GetLastError ();
+
+ CloseHandle (read_pipe);
+ return err;
+ }
+
+ /* Success. */
+ *read_pipe_ptr = read_pipe;
+ *write_pipe_ptr = write_pipe;
+ return 0;
+}
+
+
+/**
+ * Writes @size bytes from @buf to @h, using @ov for
+ * overlapped i/o. Deallocates @old_buf and sets it to NULL,
+ * if necessary.
+ * Writes asynchronously, but sequentially (only one writing
+ * operation may be active at any given moment, but it will
+ * be done in background). Thus it is intended to be used
+ * for writing a few big chunks rather than a lot of small pieces.
+ *
+ * The extravagant interface is mainly because this function
+ * does not use a separate struct to group together overlapped
+ * structure, buffer pointer and the handle.
+ *
+ * @param h pipe handle
+ * @param ov overlapped structure pointer
+ * @param buf buffer to read from. Will be copied internally
+ * @param size number of bytes to write
+ * @param old_buf pointer where a copy of previous buffer is stored,
+ * and where a copy of @buf will be stored.
+ *
+ * @return number of bytes written, -1 on error
+ */
+static int
+write_to_pipe (HANDLE h,
+ OVERLAPPED *ov,
+ unsigned char *buf, size_t size,
+ unsigned char **old_buf)
+{
+ DWORD written;
+ BOOL bresult;
+ DWORD err;
+
+ if (WAIT_OBJECT_0 != WaitForSingleObject (ov->hEvent, INFINITE))
+ return -1;
+
+ ResetEvent (ov->hEvent);
+
+ if (*old_buf != NULL)
+ free (*old_buf);
+
+ *old_buf = malloc (size);
+ if (*old_buf == NULL)
+ return -1;
+ memcpy (*old_buf, buf, size);
+ written = 0;
+ ov->Offset = 0;
+ ov->OffsetHigh = 0;
+ ov->Pointer = 0;
+ ov->Internal = 0;
+ ov->InternalHigh = 0;
+ bresult = WriteFile (h, *old_buf, size, &written, ov);
+
+ if (bresult == TRUE)
+ {
+ SetEvent (ov->hEvent);
+ free (*old_buf);
+ *old_buf = NULL;
+ return written;
+ }
+
+ err = GetLastError ();
+ if (err == ERROR_IO_PENDING)
+ return size;
+ SetEvent (ov->hEvent);
+ *old_buf = NULL;
+ SetLastError (err);
+ return -1;
+}
+
+
+#define plugin_write(plug, buf, size) write_to_pipe (plug->cpipe_in,
&plug->ov_write, buf, size, &plug->ov_write_buffer)
+
+
+/**
+ * Communicates plugin data (library name, options) to the plugin
+ * process. This is only necessary on W32, where this information
+ * is not inherited by the plugin, because it is not forked.
+ *
+ * @param plugin plugin context
+ *
+ * @return 0 on success, -1 on failure
+ */
+static int
+write_plugin_data (struct EXTRACTOR_PluginList *plugin)
+{
+ size_t libname_len, shortname_len, opts_len;
+ DWORD len;
+ char *str;
+ size_t total_len = 0;
+ unsigned char *buf, *ptr;
+
+ switch (plugin->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ break;
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ return 0;
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ return 0;
+ break;
+ }
+
+ libname_len = strlen (plugin->libname) + 1;
+ total_len += sizeof (size_t) + libname_len;
+ shortname_len = strlen (plugin->short_libname) + 1;
+ total_len += sizeof (size_t) + shortname_len;
+ if (plugin->plugin_options != NULL)
+ {
+ opts_len = strlen (plugin->plugin_options) + 1;
+ total_len += opts_len;
+ }
+ else
+ {
+ opts_len = 0;
+ }
+ total_len += sizeof (size_t);
+
+ buf = malloc (total_len);
+ if (buf == NULL)
+ return -1;
+ ptr = buf;
+ memcpy (ptr, &libname_len, sizeof (size_t));
+ ptr += sizeof (size_t);
+ memcpy (ptr, plugin->libname, libname_len);
+ ptr += libname_len;
+ memcpy (ptr, &shortname_len, sizeof (size_t));
+ ptr += sizeof (size_t);
+ memcpy (ptr, plugin->short_libname, shortname_len);
+ ptr += shortname_len;
+ memcpy (ptr, &opts_len, sizeof (size_t));
+ ptr += sizeof (size_t);
+ if (opts_len > 0)
+ {
+ memcpy (ptr, plugin->plugin_options, opts_len);
+ ptr += opts_len;
+ }
+ if (total_len != write_to_pipe (plugin->cpipe_in, &plugin->ov_write, buf,
total_len, &plugin->ov_write_buffer))
+ {
+ free (buf);
+ return -1;
+ }
+ free (buf);
+ return 0;
+}
+
+
+/**
+ * Reads plugin data from the LE server process.
+ * Also initializes allocation granularity (duh...).
+ *
+ * @param fd the pipe to read from
+ *
+ * @return newly allocated plugin context
+ */
+static struct EXTRACTOR_PluginList *
+read_plugin_data (int fd)
+{
+ struct EXTRACTOR_PluginList *ret;
+ size_t i;
+
+ ret = malloc (sizeof (struct EXTRACTOR_PluginList));
+ if (ret == NULL)
+ return NULL;
+ read (fd, &i, sizeof (size_t));
+ ret->libname = malloc (i);
+ if (ret->libname == NULL)
+ {
+ free (ret);
+ return NULL;
+ }
+ read (fd, ret->libname, i);
+ ret->libname[i - 1] = '\0';
+
+ read (fd, &i, sizeof (size_t));
+ ret->short_libname = malloc (i);
+ if (ret->short_libname == NULL)
+ {
+ free (ret->libname);
+ free (ret);
+ return NULL;
+ }
+ read (fd, ret->short_libname, i);
+ ret->short_libname[i - 1] = '\0';
+
+ read (fd, &i, sizeof (size_t));
+ if (i == 0)
+ {
+ ret->plugin_options = NULL;
+ }
+ else
+ {
+ ret->plugin_options = malloc (i);
+ if (ret->plugin_options == NULL)
+ {
+ free (ret->short_libname);
+ free (ret->libname);
+ free (ret);
+ return NULL;
+ }
+ read (fd, ret->plugin_options, i);
+ ret->plugin_options[i - 1] = '\0';
+ }
+ {
+ SYSTEM_INFO si;
+ GetSystemInfo (&si);
+ ret->allocation_granularity = si.dwAllocationGranularity;
+ }
+ return ret;
+}
+
+
+/**
+ * Start the process for the given plugin.
+ */
+static void
+start_process (struct EXTRACTOR_PluginList *plugin)
+{
+ HANDLE p1[2];
+ HANDLE p2[2];
+ STARTUPINFO startup;
+ PROCESS_INFORMATION proc;
+ char cmd[MAX_PATH + 1];
+ char arg1[10], arg2[10];
+ HANDLE p10_os_inh = INVALID_HANDLE_VALUE, p21_os_inh = INVALID_HANDLE_VALUE;
+ SECURITY_ATTRIBUTES sa;
+
+ switch (plugin->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ if (plugin->hProcess != INVALID_HANDLE_VALUE && plugin->hProcess != 0)
+ return;
+ break;
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ if (plugin->hProcess != 0)
+ return;
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ return;
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ return;
+ break;
+ }
+
+ sa.nLength = sizeof (sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = FALSE;
+
+ plugin->hProcess = NULL;
+
+ if (0 != create_selectable_pipe (&p1[0], &p1[1], &sa, 1024,
FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED))
+ {
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+ if (0 != create_selectable_pipe (&p2[0], &p2[1], &sa, 1024,
FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED))
+ {
+ CloseHandle (p1[0]);
+ CloseHandle (p1[1]);
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+
+ memset (&startup, 0, sizeof (STARTUPINFO));
+
+ if (!DuplicateHandle (GetCurrentProcess (), p1[0], GetCurrentProcess (),
+ &p10_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS)
+ || !DuplicateHandle (GetCurrentProcess (), p2[1], GetCurrentProcess (),
+ &p21_os_inh, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ if (p10_os_inh != INVALID_HANDLE_VALUE)
+ CloseHandle (p10_os_inh);
+ if (p21_os_inh != INVALID_HANDLE_VALUE)
+ CloseHandle (p21_os_inh);
+ CloseHandle (p1[0]);
+ CloseHandle (p1[1]);
+ CloseHandle (p2[0]);
+ CloseHandle (p2[1]);
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+
+ /* TODO: write our own plugin-hosting executable? rundll32, for once, has
smaller than usual stack size.
+ * Also, users might freak out seeing over 9000 rundll32 processes (seeing
over 9000 processes named
+ * "libextractor_plugin_helper" is probably less confusing).
+ */
+ snprintf(cmd, MAX_PATH + 1,
+ "rundll32.exe libextractor-3.dll,address@hidden %lu %lu",
+ p10_os_inh, p21_os_inh);
+ cmd[MAX_PATH] = '\0';
+ if (CreateProcessA (NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL,
+ &startup, &proc))
+ {
+ plugin->hProcess = proc.hProcess;
+ CloseHandle (proc.hThread);
+ }
+ else
+ {
+ CloseHandle (p1[0]);
+ CloseHandle (p1[1]);
+ CloseHandle (p2[0]);
+ CloseHandle (p2[1]);
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+ return;
+ }
+ CloseHandle (p1[0]);
+ CloseHandle (p2[1]);
+ CloseHandle (p10_os_inh);
+ CloseHandle (p21_os_inh);
+
+ plugin->cpipe_in = p1[1];
+ plugin->cpipe_out = p2[0];
+
+ memset (&plugin->ov_read, 0, sizeof (OVERLAPPED));
+ memset (&plugin->ov_write, 0, sizeof (OVERLAPPED));
+
+ plugin->ov_write_buffer = NULL;
+
+ plugin->ov_write.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL);
+ plugin->ov_read.hEvent = CreateEvent (NULL, TRUE, TRUE, NULL);
+}
+
+
+/**
+ * Stop the child process of this plugin.
+ */
+static void
+stop_process (struct EXTRACTOR_PluginList *plugin)
+{
+ int status;
+ HANDLE process;
+
+#if DEBUG
+ if (plugin->hProcess == INVALID_HANDLE_VALUE)
+ fprintf (stderr,
+ "Plugin `%s' choked on this input\n",
+ plugin->short_libname);
+#endif
+ if (plugin->hProcess == INVALID_HANDLE_VALUE ||
+ plugin->hProcess == NULL)
+ return;
+ TerminateProcess (plugin->hProcess, 0);
+ CloseHandle (plugin->hProcess);
+ plugin->hProcess = INVALID_HANDLE_VALUE;
+ CloseHandle (plugin->cpipe_out);
+ CloseHandle (plugin->cpipe_in);
+ plugin->cpipe_out = INVALID_HANDLE_VALUE;
+ plugin->cpipe_in = INVALID_HANDLE_VALUE;
+ CloseHandle (plugin->ov_read.hEvent);
+ CloseHandle (plugin->ov_write.hEvent);
+ if (plugin->ov_write_buffer != NULL)
+ {
+ free (plugin->ov_write_buffer);
+ plugin->ov_write_buffer = NULL;
+ }
+
+ if (plugin->flags != EXTRACTOR_OPTION_DEFAULT_POLICY)
+ plugin->flags = EXTRACTOR_OPTION_DISABLED;
+
+ plugin->seek_request = -1;
+}
+
+
+
+/**
+ * Setup a shared memory segment.
+ *
+ * @param ptr set to the location of the map segment
+ * @param map where to store the map handle
+ * @param fn name of the mapping
+ * @param fn_size size available in fn
+ * @param size number of bytes to allocated for the mapping
+ * @return 0 on success
+ */
+static int
+make_shm_w32 (void **ptr,
+ HANDLE *map,
+ char *fn,
+ size_t fn_size, size_t size)
+{
+ const char *tpath = "Local\\";
+
+ snprintf (fn, fn_size,
+ "%slibextractor-shm-%u-%u",
+ tpath, getpid(),
+ (unsigned int) RANDOM());
+ *map = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
size, fn);
+ *ptr = MapViewOfFile (*map, FILE_MAP_WRITE, 0, 0, size);
+ if (*ptr == NULL)
+ {
+ CloseHandle (*map);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Setup a file-backed shared memory segment.
+ *
+ * @param map where to store the map handle
+ * @param file handle of the file to back the shm
+ * @param fn name of the mapping
+ * @param fn_size size available in fn
+ * @param size number of bytes to allocated for the mapping
+ * @return 0 on success
+ */
+static int
+make_file_backed_shm_w32 (HANDLE *map, HANDLE file, char *fn, size_t fn_size)
+{
+ const char *tpath = "Local\\";
+ snprintf (fn, fn_size, "%slibextractor-shm-%u-%u", tpath, getpid(),
+ (unsigned int) RANDOM());
+ *map = CreateFileMapping (file, NULL, PAGE_READONLY, 0, 0, fn);
+ if (*map == NULL)
+ {
+ DWORD err = GetLastError ();
+ return 1;
+ }
+ return 0;
+}
+
+
+static void
+destroy_shm_w32 (void *ptr, HANDLE map)
+{
+ UnmapViewOfFile (ptr);
+ CloseHandle (map);
+}
+
+
+static void
+destroy_file_backed_shm_w32 (HANDLE map)
+{
+ CloseHandle (map);
+}
+
+
+
+#define plugin_write(plug, buf, size) write_all (fileno (plug->cpipe_in), buf,
size)
+
+
+void CALLBACK
+RundllEntryPoint (HWND hwnd,
+ HINSTANCE hinst,
+ LPSTR lpszCmdLine,
+ int nCmdShow)
+{
+ intptr_t in_h;
+ intptr_t out_h;
+ int in;
+ int out;
+
+ sscanf (lpszCmdLine, "%lu %lu", &in_h, &out_h);
+ in = _open_osfhandle (in_h, _O_RDONLY);
+ out = _open_osfhandle (out_h, 0);
+ setmode (in, _O_BINARY);
+ setmode (out, _O_BINARY);
+ plugin_main (read_plugin_data (in),
+ in, out);
+}
+
+
+void CALLBACK
+RundllEntryPointA (HWND hwnd,
+ HINSTANCE hinst,
+ LPSTR lpszCmdLine,
+ int nCmdShow)
+{
+ return RundllEntryPoint (hwnd, hinst, lpszCmdLine, nCmdShow);
+}
+
+
+
+/**
+ * Receive 'size' bytes from plugin, store them in 'buf'
+ *
+ * @param plugin plugin context
+ * @param buf buffer to fill
+ * @param size number of bytes to read
+ * @return number of bytes read, 0 on EOS, < 0 on error
+ */
+static int
+plugin_read (struct EXTRACTOR_PluginList *plugin,
+ void *buf, size_t size)
+{
+ char *rb = buf;
+ DWORD bytes_read;
+ size_t read_count = 0;
+
+ while (read_count < size)
+ {
+ if (! ReadFile (plugin->cpipe_out,
+ &rb[read_count], size - read_count,
+ &bytes_read, NULL))
+ return -1;
+ read_count += bytes_read;
+ }
+ return read_count;
+}
+
+
+/**
+ * Wait for one of the plugins to reply.
+ * Selects on plugin output pipes, runs receive_reply()
+ * on each activated pipe until it gets a seek request
+ * or a done message. Called repeatedly by the user until all pipes are dry or
+ * broken.
+ * This W32 version of wait_for_reply() can't select on more than 64 plugins
+ * at once (returns -1 if there are more than 64 plugins).
+ *
+ * @param plugins to select upon
+ * @param proc metadata callback
+ * @param proc_cls callback cls
+ * @return number of dry/broken pipes since last call, -1 on error or if no
+ * plugins reply in 10 seconds.
+ */
+static int
+wait_for_reply (struct EXTRACTOR_PluginList *plugins,
+ EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
+{
+ int result;
+ DWORD ms;
+ DWORD first_ready;
+ DWORD dwresult;
+ DWORD bytes_read;
+ BOOL bresult;
+ unsigned int i;
+ HANDLE events[MAXIMUM_WAIT_OBJECTS];
+ struct EXTRACTOR_PluginList *ppos;
+
+ i = 0;
+ for (ppos = plugins; NULL != ppos; ppos = ppos->next)
+ {
+ if (i == MAXIMUM_WAIT_OBJECTS)
+ return -1;
+ if (ppos->seek_request == -1)
+ continue;
+ switch (ppos->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ if (WaitForSingleObject (ppos->ov_read.hEvent, 0) == WAIT_OBJECT_0)
+ {
+ ResetEvent (ppos->ov_read.hEvent);
+ bresult = ReadFile (ppos->cpipe_out, &i, 0, &bytes_read,
&ppos->ov_read);
+ if (bresult == TRUE)
+ {
+ SetEvent (ppos->ov_read.hEvent);
+ }
+ else
+ {
+ DWORD err = GetLastError ();
+ if (err != ERROR_IO_PENDING)
+ SetEvent (ppos->ov_read.hEvent);
+ }
+ }
+ events[i] = ppos->ov_read.hEvent;
+ i++;
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ break;
+ }
+ }
+
+ ms = 10000;
+ first_ready = WaitForMultipleObjects (i, events, FALSE, ms);
+ if (first_ready == WAIT_TIMEOUT || first_ready == WAIT_FAILED)
+ /* an error or timeout -> something's wrong or all plugins hung up */
+ return -1;
+
+ i = 0;
+ result = 0;
+ for (ppos = plugins; NULL != ppos; ppos = ppos->next)
+ {
+ int read_result;
+ switch (ppos->flags)
+ {
+ case EXTRACTOR_OPTION_DEFAULT_POLICY:
+ case EXTRACTOR_OPTION_OUT_OF_PROCESS_NO_RESTART:
+ if (ppos->seek_request == -1)
+ continue;
+ if (i < first_ready)
+ {
+ i += 1;
+ continue;
+ }
+ dwresult = WaitForSingleObject (ppos->ov_read.hEvent, 0);
+ read_result = 0;
+ if (dwresult == WAIT_OBJECT_0)
+ {
+ read_result = receive_reply (ppos, proc, proc_cls);
+ result += 1;
+ }
+ if (dwresult == WAIT_FAILED || read_result < 0)
+ {
+ stop_process (ppos);
+ if (dwresult == WAIT_FAILED)
+ result += 1;
+ }
+ i++;
+ break;
+ case EXTRACTOR_OPTION_IN_PROCESS:
+ break;
+ case EXTRACTOR_OPTION_DISABLED:
+ break;
+ }
+ }
+ return result;
+}
+
+
Modified: Extractor/src/main/extractor_plugins.c
===================================================================
--- Extractor/src/main/extractor_plugins.c 2012-07-21 13:55:13 UTC (rev
22812)
+++ Extractor/src/main/extractor_plugins.c 2012-07-21 22:34:27 UTC (rev
22813)
@@ -1,6 +1,6 @@
/*
This file is part of libextractor.
- (C) 2002, 2003, 2004, 2005, 2006, 2009 Vidyut Samanta and Christian
Grothoff
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -17,38 +17,11 @@
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
-
#include "extractor_plugins.h"
#include "extractor_plugpath.h"
/**
- * Load the default set of plugins. The default can be changed
- * by setting the LIBEXTRACTOR_LIBRARIES environment variable.
- * If it is set to "env", then this function will return
- * EXTRACTOR_plugin_add_config (NULL, env, flags). Otherwise,
- * it will load all of the installed plugins and return them.
- *
- * @param flags options for all of the plugins loaded
- * @return the default set of plugins, NULL if no plugins were found
- */
-struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_add_defaults(enum EXTRACTOR_Options flags)
-{
- struct DefaultLoaderContext dlc;
- char *env;
-
- env = getenv ("LIBEXTRACTOR_LIBRARIES");
- if (env != NULL)
- return EXTRACTOR_plugin_add_config (NULL, env, flags);
- dlc.res = NULL;
- dlc.flags = flags;
- get_installation_paths (&load_plugins_from_dir,
- &dlc);
- return dlc.res;
-}
-
-/**
* Try to resolve a plugin function.
*
* @param lib_handle library to search for the symbol
@@ -58,10 +31,10 @@
* @return NULL on error, otherwise pointer to the symbol
*/
static void *
-get_symbol_with_prefix(void *lib_handle,
- const char *template,
- const char *prefix,
- const char **options)
+get_symbol_with_prefix (void *lib_handle,
+ const char *template,
+ const char *prefix,
+ const char **options)
{
char *name;
void *symbol;
@@ -70,19 +43,17 @@
char *dot;
const char *(*opt_fun)(void);
- if (NULL != options) *options = NULL;
- sym_name = strrchr (prefix, '_');
- if (sym_name == NULL)
+ if (NULL != options)
+ *options = NULL;
+ if (NULL == (sym_name = strrchr (prefix, '_')))
return NULL;
sym_name++;
- sym = strdup (sym_name);
- if (sym == NULL)
+ if (NULL == (sym = strdup (sym_name)))
return NULL;
dot = strchr (sym, '.');
- if (dot != NULL)
+ if (NULL != dot)
*dot = '\0';
- name = malloc(strlen(sym) + strlen(template) + 1);
- if (name == NULL)
+ if (NULL == (name = malloc(strlen(sym) + strlen(template) + 1)))
{
free (sym);
return NULL;
@@ -91,32 +62,32 @@
template,
sym);
/* try without '_' first */
- symbol = lt_dlsym(lib_handle, name + 1);
- if (symbol==NULL)
+ symbol = lt_dlsym (lib_handle, name + 1);
+ if (NULL == symbol)
{
/* now try with the '_' */
#if DEBUG
- char *first_error = strdup (lt_dlerror());
+ char *first_error = strdup (lt_dlerror ());
#endif
- symbol = lt_dlsym(lib_handle, name);
+ symbol = lt_dlsym (lib_handle, name);
#if DEBUG
if (NULL == symbol)
{
- fprintf(stderr,
- "Resolving symbol `%s' failed, "
- "so I tried `%s', but that failed also. Errors are: "
- "`%s' and `%s'.\n",
- name+1,
- name,
- first_error == NULL ? "out of memory" : first_error,
- lt_dlerror());
+ fprintf (stderr,
+ "Resolving symbol `%s' failed, "
+ "so I tried `%s', but that failed also. Errors are: "
+ "`%s' and `%s'.\n",
+ name+1,
+ name,
+ first_error == NULL ? "out of memory" : first_error,
+ lt_dlerror());
}
- if (first_error != NULL)
+ if (NULL != first_error)
free(first_error);
#endif
}
- if ( (symbol != NULL) &&
+ if ( (NULL != symbol) &&
(NULL != options) )
{
/* get special options */
@@ -124,15 +95,14 @@
"_EXTRACTOR_%s_options",
sym);
/* try without '_' first */
- opt_fun = lt_dlsym(lib_handle, name + 1);
- if (opt_fun == NULL)
- opt_fun = lt_dlsym(lib_handle, name);
- if (opt_fun != NULL)
+ opt_fun = lt_dlsym (lib_handle, name + 1);
+ if (NULL == opt_fun)
+ opt_fun = lt_dlsym (lib_handle, name);
+ if (NULL != opt_fun)
*options = opt_fun ();
}
free (sym);
- free(name);
-
+ free (name);
return symbol;
}
@@ -144,7 +114,7 @@
* @return 0 on success, -1 on error
*/
int
-plugin_load (struct EXTRACTOR_PluginList *plugin)
+EXTRACTOR_plugin_load_ (struct EXTRACTOR_PluginList *plugin)
{
#if WINDOWS
wchar_t wlibname[4097];
@@ -152,9 +122,11 @@
#endif
lt_dladvise advise;
- if (plugin->libname == NULL)
- plugin->libname = find_plugin (plugin->short_libname);
- if (plugin->libname == NULL)
+ if (EXTRACTOR_OPTION_DISABLED == plugin->flags)
+ return -1;
+ if (NULL == plugin->libname)
+ plugin->libname = EXTRACTOR_find_plugin_ (plugin->short_libname);
+ if (NULL == plugin->libname)
{
#if DEBUG
fprintf (stderr,
@@ -170,9 +142,11 @@
#if WINDOWS
wlibname[0] = L'\0';
llibname[0] = '\0';
- if (MultiByteToWideChar (CP_UTF8, 0, plugin->libname, -1, wlibname, 4097) <= 0
- || WideCharToMultiByte (CP_ACP, 0, wlibname, -1, llibname, 4097, NULL,
NULL) < 0)
- {
+ if ( (MultiByteToWideChar (CP_UTF8, 0, plugin->libname, -1,
+ wlibname, sizeof (wlibname)) <= 0) ||
+ (WideCharToMultiByte (CP_ACP, 0, wlibname, -1,
+ llibname, sizeof (llibname), NULL, NULL) < 0) )
+ {
#if DEBUG
fprintf (stderr,
"Loading `%s' plugin failed: %s\n",
@@ -185,13 +159,13 @@
#endif
}
plugin->libraryHandle = lt_dlopenadvise (llibname,
- advise);
+ advise);
#else
plugin->libraryHandle = lt_dlopenadvise (plugin->libname,
- advise);
+ advise);
#endif
- lt_dladvise_destroy(&advise);
- if (plugin->libraryHandle == NULL)
+ lt_dladvise_destroy (&advise);
+ if (NULL == plugin->libraryHandle)
{
#if DEBUG
fprintf (stderr,
@@ -205,10 +179,10 @@
return -1;
}
plugin->extract_method = get_symbol_with_prefix (plugin->libraryHandle,
-
"_EXTRACTOR_%s_extract_method",
- plugin->libname,
- &plugin->specials);
- if (plugin->extract_method == NULL)
+
"_EXTRACTOR_%s_extract_method",
+ plugin->libname,
+ &plugin->specials);
+ if (NULL == plugin->extract_method)
{
#if DEBUG
fprintf (stderr,
@@ -226,46 +200,39 @@
}
-
-
/**
* Add a library for keyword extraction.
*
* @param prev the previous list of libraries, may be NULL
* @param library the name of the library
+ * @param options options to pass to the plugin
* @param flags options to use
* @return the new list of libraries, equal to prev iff an error occured
*/
struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList * prev,
+EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *prev,
const char *library,
const char *options,
enum EXTRACTOR_Options flags)
{
struct EXTRACTOR_PluginList *result;
- struct EXTRACTOR_PluginList *i;
+ struct EXTRACTOR_PluginList *pos;
char *libname;
- for (i = prev; i != NULL; i = i->next)
- {
- if (strcmp (i->short_libname, library) == 0)
- return prev;
- }
-
- libname = find_plugin (library);
- if (libname == NULL)
+ for (pos = prev; NULL != pos; pos = pos->next)
+ if (0 == strcmp (pos->short_libname, library))
+ return prev; /* no change, library already loaded */
+ if (NULL == (libname = find_plugin (library)))
{
fprintf (stderr,
"Could not load `%s'\n",
library);
return prev;
}
- result = calloc (1, sizeof (struct EXTRACTOR_PluginList));
- if (result == NULL)
+ if (NULL == (result = malloc (sizeof (struct EXTRACTOR_PluginList))))
return prev;
result->next = prev;
- result->short_libname = strdup (library);
- if (result->short_libname == NULL)
+ if (NULL == (result->short_libname = strdup (library)))
{
free (result);
return NULL;
@@ -310,7 +277,7 @@
* or if config was empty (or NULL).
*/
struct EXTRACTOR_PluginList *
-EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList * prev,
+EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev,
const char *config,
enum EXTRACTOR_Options flags)
{
@@ -320,37 +287,49 @@
ssize_t lastconf;
size_t len;
- if (config == NULL)
+ if (NULL == config)
return prev;
- len = strlen(config);
- cpy = strdup(config);
- if (cpy == NULL)
+ if (NULL == (cpy = strdup (config)))
return prev;
+ len = strlen (config);
pos = 0;
last = 0;
lastconf = 0;
while (pos < len)
{
- while ((cpy[pos] != ':') && (cpy[pos] != '\0') &&
- (cpy[pos] != '('))
+ while ( (':' != cpy[pos]) &&
+ ('\0' != cpy[pos]) &&
+ ('(' != cpy[pos]) )
pos++;
- if( cpy[pos] == '(' ) {
- cpy[pos++] = '\0'; /* replace '(' by termination */
- lastconf = pos; /* start config from here, after (. */
- while ((cpy[pos] != '\0') && (cpy[pos] != ')'))
- pos++; /* config until ) or EOS. */
- if( cpy[pos] == ')' ) {
- cpy[pos++] = '\0'; /* write end of config here. */
- while ((cpy[pos] != ':') && (cpy[pos] != '\0'))
- pos++; /* forward until real end of string found. */
- cpy[pos++] = '\0';
- } else {
- cpy[pos++] = '\0'; /* end of string. */
+ switch (cpy[pos])
+ {
+ case '(':
+ cpy[pos++] = '\0'; /* replace '(' by termination */
+ lastconf = pos; /* start config from here, after (. */
+ while ( ('\0' != cpy[pos]) &&
+ (')' != cpy[pos]))
+ pos++; /* config until ) or EOS. */
+ if (')' == cpy[pos])
+ {
+ cpy[pos++] = '\0'; /* write end of config here. */
+ while ( (':' != cpy[pos]) &&
+ ('\0' != cpy[pos]) )
+ pos++; /* forward until real end of string found. */
+ cpy[pos++] = '\0';
+ }
+ else
+ {
+ cpy[pos++] = '\0'; /* end of string. */
+ }
+ break;
+ case ':':
+ case '\0':
+ lastconf = -1; /* NULL config when no (). */
+ cpy[pos++] = '\0'; /* replace ':' by termination */
+ break;
+ default:
+ abort ();
}
- } else {
- lastconf = -1; /* NULL config when no (). */
- cpy[pos++] = '\0'; /* replace ':' by termination */
- }
if (cpy[last] == '-')
{
last++;
@@ -361,7 +340,7 @@
{
prev = EXTRACTOR_plugin_add (prev,
&cpy[last],
- (lastconf != -1) ? &cpy[lastconf] : NULL,
+ (-1 != lastconf) ? &cpy[lastconf] : NULL,
flags);
}
last = pos;
@@ -369,3 +348,67 @@
free (cpy);
return prev;
}
+
+
+/**
+ * Remove a plugin from a list.
+ *
+ * @param prev the current list of plugins
+ * @param library the name of the plugin to remove
+ * @return the reduced list, unchanged if the plugin was not loaded
+ */
+struct EXTRACTOR_PluginList *
+EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList * prev,
+ const char * library)
+{
+ struct EXTRACTOR_PluginList *pos;
+ struct EXTRACTOR_PluginList *first;
+
+ pos = prev;
+ first = prev;
+ while ( (NULL != pos) &&
+ (0 != strcmp (pos->short_libname, library)) )
+ {
+ prev = pos;
+ pos = pos->next;
+ }
+ if (NULL == pos)
+ {
+#if DEBUG
+ fprintf(stderr,
+ "Unloading plugin `%s' failed!\n",
+ library);
+#endif
+ return first;
+ }
+ /* found, close library */
+ if (first == pos)
+ first = pos->next;
+ else
+ prev->next = pos->next;
+ /* found */
+ stop_process (pos);
+ free (pos->short_libname);
+ free (pos->libname);
+ free (pos->plugin_options);
+ if (NULL != pos->libraryHandle)
+ lt_dlclose (pos->libraryHandle);
+ free (pos);
+ return first;
+}
+
+
+/**
+ * Remove all plugins from the given list (destroys the list).
+ *
+ * @param plugin the list of plugins
+ */
+void
+EXTRACTOR_plugin_remove_all (struct EXTRACTOR_PluginList *plugins)
+{
+ while (NULL != plugins)
+ plugins = EXTRACTOR_plugin_remove (plugins, plugins->short_libname);
+}
+
+
+/* end of extractor_plugins.c */
Modified: Extractor/src/main/extractor_plugins.h
===================================================================
--- Extractor/src/main/extractor_plugins.h 2012-07-21 13:55:13 UTC (rev
22812)
+++ Extractor/src/main/extractor_plugins.h 2012-07-21 22:34:27 UTC (rev
22813)
@@ -1,6 +1,6 @@
/*
This file is part of libextractor.
- (C) 2002, 2003, 2004, 2005, 2006, 2009 Vidyut Samanta and Christian
Grothoff
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -18,14 +18,12 @@
Boston, MA 02111-1307, USA.
*/
-#if !defined (EXTRACTOR_PLUGINS_H)
+#ifndef EXTRACTOR_PLUGINS_H
#define EXTRACTOR_PLUGINS_H
#include "platform.h"
#include "plibc.h"
#include "extractor.h"
-//#include <dirent.h>
-//#include <sys/types.h>
#ifndef WINDOWS
#include <sys/wait.h>
#include <sys/shm.h>
@@ -57,7 +55,7 @@
char *libname;
/**
- * Name of the library (i.e., 'libextractor_foo.so')
+ * Short name of the plugin (i.e., 'foo')
*/
char *short_libname;
@@ -69,7 +67,7 @@
/**
* Options for the plugin.
*/
- char * plugin_options;
+ char *plugin_options;
/**
* Special options for the plugin
@@ -211,6 +209,7 @@
int waiting_for_update;
};
+
/**
* Load a plugin.
*
@@ -218,18 +217,6 @@
* @return 0 on success, -1 on error
*/
int
-plugin_load (struct EXTRACTOR_PluginList *plugin);
+EXTRACTOR_plugin_load_ (struct EXTRACTOR_PluginList *plugin);
-int64_t
-pl_read (struct EXTRACTOR_PluginList *plugin, unsigned char **data, size_t
count);
-
-int64_t
-pl_seek (struct EXTRACTOR_PluginList *plugin, int64_t pos, int whence);
-
-int64_t
-pl_get_fsize (struct EXTRACTOR_PluginList *plugin);
-
-int64_t
-pl_get_pos (struct EXTRACTOR_PluginList *plugin);
-
#endif /* EXTRACTOR_PLUGINS_H */
Modified: Extractor/src/main/extractor_plugpath.c
===================================================================
--- Extractor/src/main/extractor_plugpath.c 2012-07-21 13:55:13 UTC (rev
22812)
+++ Extractor/src/main/extractor_plugpath.c 2012-07-21 22:34:27 UTC (rev
22813)
@@ -1,6 +1,6 @@
/*
This file is part of libextractor.
- (C) 2002, 2003, 2004, 2005, 2006, 2009 Vidyut Samanta and Christian
Grothoff
+ (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian
Grothoff
libextractor is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -33,25 +33,36 @@
#include "extractor_plugpath.h"
/**
- * Remove a trailing '/bin' from in (if present).
+ * Remove a trailing '/bin/' from 'in' (if present).
+ *
+ * @param in input string, modified
+ * @return NULL if 'in' is NULL, otherwise 'in' with '/bin/' removed
*/
static char *
-cut_bin(char * in) {
+cut_bin (char * in)
+{
size_t p;
- if (in == NULL)
+ if (NULL == in)
return NULL;
- p = strlen(in);
- if (p > 4) {
- if ( (in[p-1] == '/') ||
- (in[p-1] == '\\') )
- in[--p] = '\0';
- if (0 == strcmp(&in[p-3],
- "bin")) {
- in[p-3] = '\0';
- p -= 3;
+ p = strlen (in);
+ if (p < 4)
+ return in;
+ if ( ('/' == in[p-1]) ||
+ ('\\' == in[p-1]) )
+ in[--p] = '\0';
+ if (0 == strcmp (&in[p-4],
+ "/bin"))
+ {
+ in[p-4] = '\0';
+ p -= 4;
}
- }
+ else if (0 == strcmp (&in[p-4],
+ "\bin"))
+ {
+ in[p-4] = '\0';
+ p -= 4;
+ }
return in;
}
@@ -64,208 +75,269 @@
* and the binary linking against it sits elsewhere.
*/
static char *
-get_path_from_proc_exe() {
+get_path_from_proc_exe ()
+{
char fn[64];
char line[1024];
char dir[1024];
- char * lnk;
- char * ret;
- char * lestr;
+ char *lnk;
+ char *ret;
+ char *lestr;
ssize_t size;
- FILE * f;
+ FILE *f;
- snprintf(fn,
- sizeof (fn),
- "/proc/%u/maps",
- getpid());
- f = FOPEN(fn, "r");
- if (f != NULL) {
- while (NULL != fgets(line, 1024, f)) {
- if ( (1 == sscanf(line,
- "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s",
- dir)) &&
- (NULL != (lestr = strstr(dir,
- "libextractor")) ) ) {
- lestr[0] = '\0';
- fclose(f);
- return strdup(dir);
- }
+ snprintf (fn,
+ sizeof (fn),
+ "/proc/%u/maps",
+ getpid ());
+ if (NULL != (f = FOPEN (fn, "r")))
+ {
+ while (NULL != fgets (line, 1024, f))
+ {
+ if ( (1 == sscanf (line,
+ "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s",
+ dir)) &&
+ (NULL != (lestr = strstr (dir,
+ "libextractor")) ) )
+ {
+ lestr[0] = '\0';
+ fclose (f);
+ return strdup (dir);
+ }
+ }
+ fclose (f);
}
- fclose(f);
- }
- snprintf(fn,
- sizeof (fn),
- "/proc/%u/exe",
- getpid());
- lnk = malloc(1029); /* 1024 + 5 for "lib/" catenation */
- if (lnk == NULL)
+ snprintf (fn,
+ sizeof (fn),
+ "/proc/%u/exe",
+ getpid ());
+ if (NULL == (lnk = malloc (1029))) /* 1024 + 6 for "/lib/" catenation */
return NULL;
- size = readlink(fn, lnk, 1023);
- if ( (size <= 0) || (size >= 1024) ) {
- free(lnk);
- return NULL;
- }
+ size = readlink (fn, lnk, 1023);
+ if ( (size <= 0) || (size >= 1024) )
+ {
+ free (lnk);
+ return NULL;
+ }
lnk[size] = '\0';
- while ( (lnk[size] != '/') &&
+ while ( ('/' != lnk[size]) &&
(size > 0) )
size--;
if ( (size < 4) ||
- (lnk[size-4] != '/') ) {
- /* not installed in "/bin/" -- binary path probably useless */
- free(lnk);
- return NULL;
- }
+ ('/' != lnk[size-4]) )
+ {
+ /* not installed in "/bin/" -- binary path probably useless */
+ free (lnk);
+ return NULL;
+ }
lnk[size] = '\0';
- lnk = cut_bin(lnk);
- ret = realloc(lnk, strlen(lnk) + 5);
- if (ret == NULL)
+ lnk = cut_bin (lnk);
+ if (NULL == (ret = realloc (lnk, strlen(lnk) + 6)))
{
free (lnk);
return NULL;
}
- strcat(ret, "lib/"); /* guess "lib/" as the library dir */
+ strcat (ret, "/lib/"); /* guess "lib/" as the library dir */
return ret;
}
#endif
+
#if WINDOWS
/**
* Try to determine path with win32-specific function
*/
static char *
-get_path_from_module_filename() {
- char * path;
- char * ret;
- char * idx;
+get_path_from_module_filename ()
+{
+ char *path;
+ char *ret;
+ char *idx;
- path = malloc(4103); /* 4096+nil+6 for "/lib/" catenation */
- if (path == NULL)
+ if (NULL == (path = malloc (4103))) /* 4096+nil+6 for "/lib/" catenation */
return NULL;
- GetModuleFileName(NULL, path, 4096);
- idx = path + strlen(path);
+ GetModuleFileName (NULL, path, 4096);
+ idx = path + strlen (path);
while ( (idx > path) &&
- (*idx != '\\') &&
- (*idx != '/') )
+ ('\\' != *idx) &&
+ ('/' != *idx) )
idx--;
*idx = '\0';
- path = cut_bin(path);
- ret = realloc(path, strlen(path) + 6);
- if (ret == NULL)
+ path = cut_bin (path);
+ if (NULL == (ret = realloc (path, strlen(path) + 6)))
{
free (path);
return NULL;
}
- strcat(ret, "/lib/"); /* guess "lib/" as the library dir */
+ strcat (ret, "/lib/"); /* guess "lib/" as the library dir */
return ret;
}
#endif
+
#if DARWIN
-static char * get_path_from_dyld_image() {
- const char * path;
- char * p, * s;
- int i;
+/**
+ * Signature of the '_NSGetExecutablePath" function.
+ *
+ * @param buf where to write the path
+ * @param number of bytes available in 'buf'
+ * @return 0 on success, otherwise desired number of bytes is stored in
'bufsize'
+ */
+typedef int (*MyNSGetExecutablePathProto) (char *buf,
+ size_t *bufsize);
+
+
+/**
+ * Try to obtain the path of our executable using '_NSGetExecutablePath'.
+ *
+ * @return NULL on error
+ */
+static char *
+get_path_from_NSGetExecutablePath ()
+{
+ static char zero;
+ char *path;
+ size_t len;
+ MyNSGetExecutablePathProto func;
+
+ path = NULL;
+ if (NULL == (func =
+ (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT,
+ "_NSGetExecutablePath")))
+ return NULL;
+ path = &zero;
+ len = 0;
+ /* get the path len, including the trailing \0 */
+ (void) func (path, &len);
+ if (0 == len)
+ return NULL;
+ path = GNUNET_malloc (len);
+ if (0 != func (path, &len))
+ {
+ GNUNET_free (path);
+ return NULL;
+ }
+ len = strlen (path);
+ while ((path[len] != '/') && (len > 0))
+ len--;
+ path[len] = '\0';
+ return path;
+}
+
+
+/**
+ * Try to obtain the path of our executable using '_dyld_image' API.
+ *
+ * @return NULL on error
+ */
+static char *
+get_path_from_dyld_image ()
+{
+ const char *path;
+ char *s;
+ unsigned int i;
int c;
- p = NULL;
- c = _dyld_image_count();
- for (i = 0; i < c; i++) {
- if (_dyld_get_image_header(i) == &_mh_dylib_header) {
- path = _dyld_get_image_name(i);
- if (path != NULL && strlen(path) > 0) {
- p = strdup(path);
- if (p == NULL)
- return NULL;
- s = p + strlen(p);
- while ( (s > p) && (*s != '/') )
- s--;
- s++;
- *s = '\0';
- }
- break;
+ c = _dyld_image_count ();
+ for (i = 0; i < c; i++)
+ {
+ if (_dyld_get_image_header (i) != &_mh_dylib_header)
+ continue;
+ path = _dyld_get_image_name (i);
+ if ( (NULL == path) || (0 == strlen (path)) )
+ continue;
+ if (NULL == (p = strdup (path)))
+ return NULL;
+ s = p + strlen (p);
+ while ( (s > p) && ('/' != *s) )
+ s--;
+ s++;
+ *s = '\0';
+ return p;
}
- }
- return p;
+ return NULL;
}
#endif
+
/**
- * This may also fail -- for example, if extract
- * is not also installed.
+ * Return the actual path to a file found in the current
+ * PATH environment variable.
+ *
+ * @return path to binary, NULL if not found
*/
static char *
get_path_from_PATH() {
struct stat sbuf;
- char * path;
- char * pos;
- char * end;
- char * buf;
- char * ret;
- const char * p;
+ char *path;
+ char *pos;
+ char *end;
+ char *buf;
+ char *ret;
+ const char *p;
- p = getenv("PATH");
- if (p == NULL)
+ if (NULL == (p = getenv ("PATH")))
return NULL;
- path = strdup(p); /* because we write on it */
- if (path == NULL)
+ if (NULL == (path = strdup (p))) /* because we write on it */
return NULL;
- buf = malloc(strlen(path) + 20);
- if (buf == NULL)
+ if (NULL == (buf = malloc (strlen(path) + 20)))
{
free (path);
return NULL;
}
pos = path;
-
- while (NULL != (end = strchr(pos, ':'))) {
- *end = '\0';
- sprintf(buf, "%s/%s", pos, "extract");
- if (0 == stat(buf, &sbuf)) {
- pos = strdup(pos);
- free(buf);
- free(path);
- if (pos == NULL)
+ while (NULL != (end = strchr(pos, ':')))
+ {
+ *end = '\0';
+ sprintf(buf, "%s/%s", pos, "extract");
+ if (0 == stat(buf, &sbuf))
+ {
+ pos = strdup(pos);
+ free (buf);
+ free (path);
+ if (NULL == pos)
+ return NULL;
+ pos = cut_bin (pos);
+ if (NULL == (ret = realloc (pos, strlen(pos) + 5)))
+ {
+ free (pos);
+ return NULL;
+ }
+ strcat (ret, "lib/");
+ return ret;
+ }
+ pos = end + 1;
+ }
+ sprintf(buf, "%s/%s", pos, "extract");
+ if (0 == stat (buf, &sbuf))
+ {
+ pos = strdup (pos);
+ free (buf);
+ free (path);
+ if (NULL == pos)
return NULL;
- pos = cut_bin(pos);
- ret = realloc(pos, strlen(pos) + 5);
- if (ret == NULL)
+ pos = cut_bin (pos);
+ ret = realloc (pos, strlen(pos) + 5);
+ if (NULL == ret)
{
free (pos);
return NULL;
}
- strcat(ret, "lib/");
+ strcat (ret, "lib/");
return ret;
}
- pos = end + 1;
- }
- sprintf(buf, "%s/%s", pos, "extract");
- if (0 == stat(buf, &sbuf)) {
- pos = strdup(pos);
- free(buf);
- free(path);
- if (pos == NULL)
- return NULL;
- pos = cut_bin(pos);
- ret = realloc(pos, strlen(pos) + 5);
- if (ret == NULL)
- {
- free (pos);
- return NULL;
- }
- strcat(ret, "lib/");
- return ret;
- }
free(buf);
free(path);
return NULL;
}
+
/**
* Create a filename by appending 'fname' to 'path'.
*
* @param path the base path
* @param fname the filename to append
- * @return '$path/$fname'
+ * @return '$path/$fname', NULL on error
*/
static char *
append_to_dir (const char *path,
@@ -274,16 +346,15 @@
char *ret;
size_t slen;
- slen = strlen (path);
- if (slen == 0)
+ if (0 == (slen = strlen (path)))
return NULL;
- if (fname[0] == DIR_SEPARATOR)
+ if (DIR_SEPARATOR == fname[0])
fname++;
ret = malloc (slen + strlen(fname) + 2);
- if (ret == NULL)
+ if (NULL == ret)
return NULL;
#ifdef MINGW
- if (path[slen-1] == '\\')
+ if ('\\' == path[slen-1])
sprintf (ret,
"%s%s",
path,
@@ -294,16 +365,16 @@
path,
fname);
#else
- if (path[slen-1] == '/')
+ if ('/' == path[slen-1])
sprintf (ret,
- "%s%s",
- path,
- fname);
+ "%s%s",
+ path,
+ fname);
else
sprintf (ret,
- "%s/%s",
- path,
- fname);
+ "%s/%s",
+ path,
+ fname);
#endif
return ret;
}
@@ -317,49 +388,47 @@
* @param pp_cls cls argument for pp.
*/
void
-get_installation_paths (PathProcessor pp,
- void *pp_cls)
+EXTRACTOR_get_installation_paths_ (EXTRACTOR_PathProcessor pp,
+ void *pp_cls)
{
const char *p;
- char * path;
- char * prefix;
- char * d;
+ char *path;
+ char *prefix;
+ char *d;
prefix = NULL;
- p = getenv("LIBEXTRACTOR_PREFIX");
- if (p != NULL)
+ if (NULL != (p = getenv ("LIBEXTRACTOR_PREFIX")))
{
- d = strdup (p);
- if (d == NULL)
+ if (NULL == (d = strdup (p)))
return;
- prefix = strtok (d, PATH_SEPARATOR_STR);
- while (NULL != prefix)
- {
- pp (pp_cls, prefix);
- prefix = strtok (NULL, PATH_SEPARATOR_STR);
- }
+ for (prefix = strtok (d, PATH_SEPARATOR_STR);
+ NULL != prefix;
+ prefix = strtok (NULL, PATH_SEPARATOR_STR))
+ pp (pp_cls, prefix);
free (d);
return;
}
#if LINUX
- if (prefix == NULL)
- prefix = get_path_from_proc_exe();
+ if (NULL == prefix)
+ prefix = get_path_from_proc_exe ();
#endif
#if WINDOWS
- if (prefix == NULL)
- prefix = get_path_from_module_filename();
+ if (NULL == prefix)
+ prefix = get_path_from_module_filename ();
#endif
#if DARWIN
- if (prefix == NULL)
- prefix = get_path_from_dyld_image();
+ if (NULL == prefix)
+ prefix = get_path_from_NSGetExecutablePath ();
+ if (NULL == prefix)
+ prefix = get_path_from_dyld_image ();
#endif
- if (prefix == NULL)
- prefix = get_path_from_PATH();
+ if (NULL == prefix)
+ prefix = get_path_from_PATH ();
pp (pp_cls, PLUGININSTDIR);
- if (prefix == NULL)
+ if (NULL == prefix)
return;
path = append_to_dir (prefix, PLUGINDIR);
- if (path != NULL)
+ if (NULL != path)
{
if (0 != strcmp (path,
PLUGININSTDIR))
@@ -370,9 +439,19 @@
}
+/**
+ * Closure for 'find_plugin_in_path'.
+ */
struct SearchContext
{
+ /**
+ * Name of the plugin we are looking for.
+ */
const char *short_name;
+
+ /**
+ * Location for storing the path to the plugin upon success.
+ */
char *path;
};
@@ -395,30 +474,28 @@
char *sym;
char *dot;
- if (sc->path != NULL)
+ if (NULL != sc->path)
return;
- dir = OPENDIR (path);
- if (NULL == dir)
+ if (NULL == (dir = OPENDIR (path)))
return;
while (NULL != (ent = READDIR (dir)))
{
- if (ent->d_name[0] == '.')
+ if ('.' == ent->d_name[0])
continue;
if ( (NULL != (la = strstr (ent->d_name, ".la"))) &&
- (la[3] == '\0') )
+ ('\0' == la[3]) )
continue; /* only load '.so' and '.dll' */
- sym_name = strrchr (ent->d_name, '_');
- if (sym_name == NULL)
+ if (NULL == (sym_name = strrchr (ent->d_name, '_')))
continue;
sym_name++;
sym = strdup (sym_name);
- if (sym == NULL)
+ if (NULL == sym)
{
CLOSEDIR (dir);
return;
}
dot = strchr (sym, '.');
- if (dot != NULL)
+ if (NULL != dot)
*dot = '\0';
if (0 == strcmp (sym, sc->short_name))
{
@@ -428,13 +505,6 @@
}
free (sym);
}
-#if DEBUG
- if (sc->path == NULL)
- fprintf (stderr,
- "Failed to find plugin `%s' in `%s'\n",
- sc->short_name,
- path);
-#endif
CLOSEDIR (dir);
}
@@ -444,7 +514,7 @@
* the full path of the respective plugin.
*/
char *
-find_plugin (const char *short_name)
+EXTRACTOR_find_plugin_ (const char *short_name)
{
struct SearchContext sc;
@@ -456,13 +526,30 @@
}
+/**
+ * Closure for 'load_plugins_from_dir'.
+ */
+struct DefaultLoaderContext
+{
+ /**
+ * Accumulated result list.
+ */
+ struct EXTRACTOR_PluginList *res;
+
+ /**
+ * Flags to use for all plugins.
+ */
+ enum EXTRACTOR_Options flags;
+};
+
+
/**
* Load all plugins from the given directory.
*
* @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend
* @param path path to a directory with plugins
*/
-void
+static void
load_plugins_from_dir (void *cls,
const char *path)
{
@@ -514,3 +601,32 @@
closedir (dir);
}
+
+/**
+ * Load the default set of plugins. The default can be changed
+ * by setting the LIBEXTRACTOR_LIBRARIES environment variable.
+ * If it is set to "env", then this function will return
+ * EXTRACTOR_plugin_add_config (NULL, env, flags). Otherwise,
+ * it will load all of the installed plugins and return them.
+ *
+ * @param flags options for all of the plugins loaded
+ * @return the default set of plugins, NULL if no plugins were found
+ */
+struct EXTRACTOR_PluginList *
+EXTRACTOR_plugin_add_defaults (enum EXTRACTOR_Options flags)
+{
+ struct DefaultLoaderContext dlc;
+ char *env;
+
+ env = getenv ("LIBEXTRACTOR_LIBRARIES");
+ if (NULL != env)
+ return EXTRACTOR_plugin_add_config (NULL, env, flags);
+ dlc.res = NULL;
+ dlc.flags = flags;
+ get_installation_paths (&load_plugins_from_dir,
+ &dlc);
+ return dlc.res;
+}
+
+
+/* end of extractor_plugpath.c */
Modified: Extractor/src/main/extractor_plugpath.h
===================================================================
--- Extractor/src/main/extractor_plugpath.h 2012-07-21 13:55:13 UTC (rev
22812)
+++ Extractor/src/main/extractor_plugpath.h 2012-07-21 22:34:27 UTC (rev
22813)
@@ -1,21 +1,16 @@
-#if !defined(EXTRACTOR_PLUGPATH_H)
+#ifndef EXTRACTOR_PLUGPATH_H
#define EXTRACTOR_PLUGPATH_H
-struct DefaultLoaderContext
-{
- struct EXTRACTOR_PluginList *res;
- enum EXTRACTOR_Options flags;
-};
-
/**
* Function to call on paths.
*
* @param cls closure
* @param path a directory path
*/
-typedef void (*PathProcessor)(void *cls,
- const char *path);
+typedef void (*EXTRACTOR_PathProcessor)(void *cls,
+ const char *path);
+
/**
* Iterate over all paths where we expect to find GNU libextractor
* plugins.
@@ -24,24 +19,17 @@
* @param pp_cls cls argument for pp.
*/
void
-get_installation_paths (PathProcessor pp,
- void *pp_cls);
+EXTRACTOR_get_installation_paths_ (EXTRACTOR_PathProcessor pp,
+ void *pp_cls);
+
/**
* Given a short name of a library (i.e. "mime"), find
* the full path of the respective plugin.
*/
-char *
-find_plugin (const char *short_name);
+char *
+EXTRACTOR_find_plugin_ (const char *short_name);
-/**
- * Load all plugins from the given directory.
- *
- * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend
- * @param path path to a directory with plugins
- */
-void
-load_plugins_from_dir (void *cls,
- const char *path);
-#endif /* EXTRACTOR_PLUGPATH_H */
+#endif
+/* EXTRACTOR_PLUGPATH_H */
Modified: Extractor/src/main/extractor_print.c
===================================================================
--- Extractor/src/main/extractor_print.c 2012-07-21 13:55:13 UTC (rev
22812)
+++ Extractor/src/main/extractor_print.c 2012-07-21 22:34:27 UTC (rev
22813)
@@ -40,44 +40,43 @@
* @return non-zero if printing failed, otherwise 0.
*/
int
-EXTRACTOR_meta_data_print(void * handle,
- const char *plugin_name,
- enum EXTRACTOR_MetaType type,
- enum EXTRACTOR_MetaFormat format,
- const char *data_mime_type,
- const char *data,
- size_t data_len)
+EXTRACTOR_meta_data_print (void *handle,
+ const char *plugin_name,
+ enum EXTRACTOR_MetaType type,
+ enum EXTRACTOR_MetaFormat format,
+ const char *data_mime_type,
+ const char *data,
+ size_t data_len)
{
iconv_t cd;
char * buf;
int ret;
const char *mt;
- if (format != EXTRACTOR_METAFORMAT_UTF8)
+ if (EXTRACTOR_METAFORMAT_UTF8 != format)
return 0;
- cd = iconv_open(nl_langinfo(CODESET),
- "UTF-8");
- if (cd == (iconv_t) -1)
+ cd = iconv_open (nl_langinfo(CODESET),
+ "UTF-8");
+ if (((iconv_t) -1) == cd)
return 1;
buf = iconv_helper(cd, data);
- if (buf != NULL)
+ if (NULL == buf)
{
- mt = EXTRACTOR_metatype_to_string (type);
- ret = fprintf(handle,
- "%s - %s\n",
- (mt == NULL) ? _("unknown") : dgettext ("libextractor",
- mt),
- buf);
- free(buf);
+ ret = -1;
}
else
{
- ret = -1;
+ mt = EXTRACTOR_metatype_to_string (type);
+ ret = fprintf (handle,
+ "%s - %s\n",
+ (NULL == mt)
+ ? dgettext ("libextractor", gettext_noop ("unknown"))
+ : dgettext ("libextractor", mt),
+ buf);
+ free(buf);
}
iconv_close(cd);
- if (ret < 0)
- return 1;
- return 0;
+ return (ret < 0) ? 1 : 0;
}
/* end of extractor_print.c */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r22813 - in Extractor: . doc src/include src/main,
gnunet <=