Squash  0.7.0
plugin.c
1 /* Copyright (c) 2013-2015 The Squash Authors
2  *
3  * Permission is hereby granted, free of charge, to any person
4  * obtaining a copy of this software and associated documentation
5  * files (the "Software"), to deal in the Software without
6  * restriction, including without limitation the rights to use, copy,
7  * modify, merge, publish, distribute, sublicense, and/or sell copies
8  * of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  * Evan Nemerson <evan@nemerson.com>
25  */
26 
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31 
32 #if !defined(_WIN32)
33 #include <dlfcn.h>
34 #else
35 #include <windows.h>
36 #endif
37 
38 #include "internal.h"
39 
68 void
69 squash_plugin_add_codec (SquashPlugin* plugin, SquashCodec* codec) {
70  SquashContext* context;
71 
72  assert (plugin != NULL);
73  assert (codec != NULL);
74 
75  context = plugin->context;
76 
77  /* Insert a new entry into plugin->codecs */
78  SQUASH_TREE_INSERT(&(plugin->codecs), _SquashCodec, tree, codec);
79 
80  squash_context_add_codec (context, codec);
81 }
82 
83 SQUASH_MTX_DEFINE(plugin_init)
84 
85 
101 squash_plugin_init (SquashPlugin* plugin) {
102  if (plugin->plugin == NULL) {
103 #if !defined(_WIN32)
104  void* handle;
105 #else
106  HMODULE handle;
107 #endif
108  char* plugin_file_name;
109  size_t plugin_dir_length;
110  size_t plugin_name_length;
111  size_t plugin_file_name_max_length;
112  size_t squash_version_api_length = strlen (SQUASH_VERSION_API);
113 
114  plugin_dir_length = strlen (plugin->directory);
115  plugin_name_length = strlen (plugin->name);
116  plugin_file_name_max_length = plugin_dir_length + squash_version_api_length + plugin_name_length + 19 + strlen (SQUASH_SHARED_LIBRARY_SUFFIX);
117  plugin_file_name = (char*) malloc (plugin_file_name_max_length + 1);
118 
119  snprintf (plugin_file_name, plugin_file_name_max_length + 1,
120  "%s/libsquash%s-plugin-%s%s", plugin->directory, SQUASH_VERSION_API, plugin->name, SQUASH_SHARED_LIBRARY_SUFFIX);
121 
122 #if !defined(_WIN32)
123  handle = dlopen (plugin_file_name, RTLD_LAZY);
124 #else
125  handle = LoadLibrary (TEXT(plugin_file_name));
126 #endif
127 
128  free (plugin_file_name);
129 
130  if (handle != NULL) {
131  SQUASH_MTX_LOCK(plugin_init);
132  if (plugin->plugin == NULL) {
133  plugin->plugin = handle;
134  handle = NULL;
135  }
136  SQUASH_MTX_UNLOCK(plugin_init);
137  } else {
139  }
140 
141  if (handle != NULL) {
142 #if !defined(_WIN32)
143  dlclose (handle);
144 #else
145  FreeLibrary (handle);
146 #endif
147  } else {
148  SquashStatus (*init_func) (SquashPlugin*);
149 #if !defined(_WIN32)
150  *(void **) (&init_func) = dlsym (plugin->plugin, "squash_plugin_init_plugin");
151 #else
152  *(void **) (&init_func) = GetProcAddress (handle, "squash_plugin_init_plugin");
153 #endif
154  if (init_func != NULL) {
155  init_func (plugin);
156  }
157  }
158  }
159 
160  return (plugin->plugin != NULL) ? SQUASH_OK : squash_error (SQUASH_UNABLE_TO_LOAD);
161 }
162 
169 const char*
170 squash_plugin_get_name (SquashPlugin* plugin) {
171  assert (plugin != NULL);
172 
173  return plugin->name;
174 }
175 
183 SquashLicense*
184 squash_plugin_get_licenses (SquashPlugin* plugin) {
185  assert (plugin != NULL);
186 
187  return plugin->license;
188 }
189 
197 SquashCodec*
198 squash_plugin_get_codec (SquashPlugin* plugin, const char* codec) {
199  SquashCodec key = { 0, };
200  SquashCodec* codec_real;
201 
202  assert (plugin != NULL);
203  assert (codec != NULL);
204 
205  key.name = (char*) codec;
206 
207  codec_real = SQUASH_TREE_FIND (&(plugin->codecs), _SquashCodec, tree, &key);
208  return (squash_codec_init (codec_real) == SQUASH_OK) ? codec_real : NULL;
209 }
210 
221 int
222 squash_plugin_compare (SquashPlugin* a, SquashPlugin* b) {
223  assert (a != NULL);
224  assert (b != NULL);
225 
226  return strcmp (a->name, b->name);
227 }
228 
229 SQUASH_MTX_DEFINE(codec_init)
230 
231 
241 squash_plugin_init_codec (SquashPlugin* plugin, SquashCodec* codec, SquashCodecImpl* impl) {
242  SquashStatus res = SQUASH_OK;
243 
244  assert (plugin != NULL);
245 
246  if (plugin->plugin == NULL) {
247  res = squash_plugin_init (plugin);
248  if (res != SQUASH_OK) {
249  return res;
250  }
251  }
252 
253  if (codec->initialized == 0) {
254  SquashStatus (*init_codec_func) (SquashCodec*, SquashCodecImpl*);
255 
256 #if !defined(_WIN32)
257  *(void **) (&init_codec_func) = dlsym (plugin->plugin, "squash_plugin_init_codec");
258 #else
259  *(void **) (&init_codec_func) = GetProcAddress (plugin->plugin, "squash_plugin_init_codec");
260 #endif
261 
262  if (init_codec_func == NULL) {
264  }
265 
266  SQUASH_MTX_LOCK(codec_init);
267  res = init_codec_func (codec, impl);
268  codec->initialized = (res == SQUASH_OK);
269 
270  assert ((codec->impl.info & SQUASH_CODEC_INFO_AUTO_MASK) == 0);
271  if (codec->impl.process_stream != NULL)
272  codec->impl.info |= SQUASH_CODEC_INFO_NATIVE_STREAMING;
273  if (codec->impl.get_uncompressed_size != NULL)
274  codec->impl.info |= SQUASH_CODEC_INFO_KNOWS_UNCOMPRESSED_SIZE;
275  SQUASH_MTX_UNLOCK(codec_init);
276  }
277 
278  return res;
279 }
280 
297 void
298 squash_plugin_foreach_codec (SquashPlugin* plugin, SquashCodecForeachFunc func, void* data) {
299  SQUASH_TREE_FORWARD_APPLY(&(plugin->codecs), _SquashCodec, tree, func, data);
300 }
301 
310 SquashPlugin*
311 squash_plugin_new (char* name, char* directory, SquashContext* context) {
312  SquashPlugin* plugin = (SquashPlugin*) malloc (sizeof (SquashPlugin));
313 
314  plugin->name = name;
315  plugin->license = NULL;
316  plugin->context = context;
317  plugin->directory = directory;
318  plugin->plugin = NULL;
319  SQUASH_TREE_ENTRY_INIT(plugin->tree);
320  SQUASH_TREE_INIT(&(plugin->codecs), squash_codec_compare);
321 
322  return plugin;
323 }
324 
Mask of flags which are automatically set based on which callbacks are provided.
Definition: codec.h:41
#define SQUASH_VERSION_API
Definition: version.h:37
SquashStatus squash_codec_init(SquashCodec *codec)
Initialize a codec.
Definition: codec.c:347
void squash_plugin_foreach_codec(SquashPlugin *plugin, SquashCodecForeachFunc func, void *data)
Execute a callback for every codec in the plugin.
Definition: plugin.c:298
SquashLicense * squash_plugin_get_licenses(SquashPlugin *plugin)
Get the licenses of the plugin.
Definition: plugin.c:184
A compression/decompression codec.
SquashStatus
Status codes.
Definition: status.h:36
SquashStatus squash_error(SquashStatus status)
Emit an error.
Definition: status.c:173
void(* SquashCodecForeachFunc)(SquashCodec *codec, void *data)
Squashlback to be invoked on each SquashCodec in a set.
Definition: codec.h:97
SquashStatus squash_plugin_init(SquashPlugin *plugin)
load a SquashPlugin
Definition: plugin.c:101
SquashCodec * squash_plugin_get_codec(SquashPlugin *plugin, const char *codec)
Get a codec from a plugin by name.
Definition: plugin.c:198
Unable to load the requested resource.
Definition: status.h:42
Operation completed successfully.
Definition: status.h:37
const char * squash_plugin_get_name(SquashPlugin *plugin)
Get the name of a plugin.
Definition: plugin.c:170
The compressed data encodes the length of the uncompressed data without having to decompress it...
Definition: codec.h:43
The codec natively supports a streaming interface.
Definition: codec.h:44