blob: c2af07211c5cd7423b59396516836afe1be6e7d1 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% M M OOO DDDD U U L EEEEE %
7% MM MM O O D D U U L E %
8% M M M O O D D U U L EEE %
9% M M O O D D U U L E %
10% M M OOO DDDD UUU LLLLL EEEEE %
11% %
12% %
13% MagickCore Module Methods %
14% %
15% Software Design %
16% Bob Friesenhahn %
17% March 2000 %
18% %
19% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/coder.h"
46#include "MagickCore/client.h"
47#include "MagickCore/configure.h"
48#include "MagickCore/exception.h"
49#include "MagickCore/exception-private.h"
50#include "MagickCore/log.h"
51#include "MagickCore/hashmap.h"
52#include "MagickCore/magic.h"
53#include "MagickCore/magick.h"
54#include "MagickCore/memory_.h"
55#include "MagickCore/module.h"
cristy5ff4eaf2011-09-03 01:38:02 +000056#include "MagickCore/module-private.h"
cristyd2d11ec2012-03-28 13:53:49 +000057#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000058#include "MagickCore/policy.h"
59#include "MagickCore/semaphore.h"
60#include "MagickCore/splay-tree.h"
61#include "MagickCore/static.h"
62#include "MagickCore/string_.h"
cristy7832dc22011-09-05 01:21:53 +000063#include "MagickCore/string-private.h"
cristy4c08aed2011-07-01 19:47:50 +000064#include "MagickCore/token.h"
65#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000066#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000067#if defined(MAGICKCORE_MODULES_SUPPORT)
68#if defined(MAGICKCORE_LTDL_DELEGATE)
69#include "ltdl.h"
70typedef lt_dlhandle ModuleHandle;
71#else
72typedef void *ModuleHandle;
73#endif
74
75/*
76 Define declarations.
77*/
78#if defined(MAGICKCORE_LTDL_DELEGATE)
79# define ModuleGlobExpression "*.la"
80#else
81# if defined(_DEBUG)
82# define ModuleGlobExpression "IM_MOD_DB_*.dll"
83# else
84# define ModuleGlobExpression "IM_MOD_RL_*.dll"
85# endif
86#endif
87
88/*
89 Global declarations.
90*/
91static SemaphoreInfo
92 *module_semaphore = (SemaphoreInfo *) NULL;
93
94static SplayTreeInfo
95 *module_list = (SplayTreeInfo *) NULL;
cristy3ed852e2009-09-05 21:47:34 +000096
97/*
98 Forward declarations.
99*/
100static const ModuleInfo
101 *RegisterModule(const ModuleInfo *,ExceptionInfo *);
102
103static MagickBooleanType
104 GetMagickModulePath(const char *,MagickModuleType,char *,ExceptionInfo *),
cristy904e5912014-03-15 19:53:14 +0000105 IsModuleTreeInstantiated(ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000106 UnregisterModule(const ModuleInfo *,ExceptionInfo *);
107
108static void
109 TagToCoderModuleName(const char *,char *),
110 TagToFilterModuleName(const char *,char *),
111 TagToModuleName(const char *,const char *,char *);
112
113/*
114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115% %
116% %
117% %
118% A c q u i r e M o d u l e I n f o %
119% %
120% %
121% %
122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123%
124% AcquireModuleInfo() allocates the ModuleInfo structure.
125%
126% The format of the AcquireModuleInfo method is:
127%
128% ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
129%
130% A description of each parameter follows:
131%
132% o path: the path associated with the tag.
133%
134% o tag: a character string that represents the image format we are
135% looking for.
136%
137*/
138MagickExport ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
139{
140 ModuleInfo
141 *module_info;
142
cristy73bd4a52010-10-05 11:24:23 +0000143 module_info=(ModuleInfo *) AcquireMagickMemory(sizeof(*module_info));
cristy3ed852e2009-09-05 21:47:34 +0000144 if (module_info == (ModuleInfo *) NULL)
145 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
146 (void) ResetMagickMemory(module_info,0,sizeof(*module_info));
147 if (path != (const char *) NULL)
148 module_info->path=ConstantString(path);
149 if (tag != (const char *) NULL)
150 module_info->tag=ConstantString(tag);
151 module_info->timestamp=time(0);
152 module_info->signature=MagickSignature;
153 return(module_info);
154}
155
156/*
157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158% %
159% %
160% %
161% D e s t r o y M o d u l e L i s t %
162% %
163% %
164% %
165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166%
167% DestroyModuleList() unregisters any previously loaded modules and exits
168% the module loaded environment.
169%
170% The format of the DestroyModuleList module is:
171%
172% void DestroyModuleList(void)
173%
174*/
175MagickExport void DestroyModuleList(void)
176{
177 /*
178 Destroy magick modules.
179 */
cristyf84a1932010-01-03 18:00:18 +0000180 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000181#if defined(MAGICKCORE_MODULES_SUPPORT)
182 if (module_list != (SplayTreeInfo *) NULL)
183 module_list=DestroySplayTree(module_list);
cristy1e09ca22009-12-27 18:04:58 +0000184#endif
cristyf84a1932010-01-03 18:00:18 +0000185 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000186}
187
188/*
189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190% %
191% %
192% %
193% G e t M o d u l e I n f o %
194% %
195% %
196% %
197%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198%
199% GetModuleInfo() returns a pointer to a ModuleInfo structure that matches the
200% specified tag. If tag is NULL, the head of the module list is returned. If
201% no modules are loaded, or the requested module is not found, NULL is
202% returned.
203%
204% The format of the GetModuleInfo module is:
205%
206% ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
207%
208% A description of each parameter follows:
209%
210% o tag: a character string that represents the image format we are
211% looking for.
212%
213% o exception: return any errors or warnings in this structure.
214%
215*/
216MagickExport ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
217{
cristy49d4d222014-03-16 00:37:58 +0000218 ModuleInfo
219 *module_info;
220
cristy904e5912014-03-15 19:53:14 +0000221 if (IsModuleTreeInstantiated(exception) == MagickFalse)
222 return((ModuleInfo *) NULL);
cristy49d4d222014-03-16 00:37:58 +0000223 LockSemaphoreInfo(module_semaphore);
224 ResetSplayTreeIterator(module_list);
cristy3ed852e2009-09-05 21:47:34 +0000225 if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0))
226 {
cristy3ed852e2009-09-05 21:47:34 +0000227#if defined(MAGICKCORE_MODULES_SUPPORT)
228 if (LocaleCompare(tag,"*") == 0)
229 (void) OpenModules(exception);
230#endif
cristy49d4d222014-03-16 00:37:58 +0000231 module_info=(ModuleInfo *) GetNextValueInSplayTree(module_list);
cristyf84a1932010-01-03 18:00:18 +0000232 UnlockSemaphoreInfo(module_semaphore);
cristy49d4d222014-03-16 00:37:58 +0000233 return(module_info);
cristy3ed852e2009-09-05 21:47:34 +0000234 }
cristy49d4d222014-03-16 00:37:58 +0000235 module_info=(ModuleInfo *) GetValueFromSplayTree(module_list,tag);
236 UnlockSemaphoreInfo(module_semaphore);
237 return(module_info);
cristy3ed852e2009-09-05 21:47:34 +0000238}
239
240/*
241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242% %
243% %
244% %
245% G e t M o d u l e I n f o L i s t %
246% %
247% %
248% %
249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250%
251% GetModuleInfoList() returns any modules that match the specified pattern.
252%
253% The format of the GetModuleInfoList function is:
254%
255% const ModuleInfo **GetModuleInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000256% size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000257%
258% A description of each parameter follows:
259%
260% o pattern: Specifies a pointer to a text string containing a pattern.
261%
262% o number_modules: This integer returns the number of modules in the list.
263%
264% o exception: return any errors or warnings in this structure.
265%
266*/
267
268#if defined(__cplusplus) || defined(c_plusplus)
269extern "C" {
270#endif
271
272static int ModuleInfoCompare(const void *x,const void *y)
273{
274 const ModuleInfo
275 **p,
276 **q;
277
278 p=(const ModuleInfo **) x,
279 q=(const ModuleInfo **) y;
280 if (LocaleCompare((*p)->path,(*q)->path) == 0)
281 return(LocaleCompare((*p)->tag,(*q)->tag));
282 return(LocaleCompare((*p)->path,(*q)->path));
283}
284
285#if defined(__cplusplus) || defined(c_plusplus)
286}
287#endif
288
289MagickExport const ModuleInfo **GetModuleInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000290 size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000291{
292 const ModuleInfo
293 **modules;
294
295 register const ModuleInfo
296 *p;
297
cristybb503372010-05-27 20:51:26 +0000298 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000299 i;
300
301 /*
302 Allocate module list.
303 */
304 assert(pattern != (char *) NULL);
305 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000306 assert(number_modules != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000307 *number_modules=0;
308 p=GetModuleInfo("*",exception);
309 if (p == (const ModuleInfo *) NULL)
310 return((const ModuleInfo **) NULL);
311 modules=(const ModuleInfo **) AcquireQuantumMemory((size_t)
312 GetNumberOfNodesInSplayTree(module_list)+1UL,sizeof(*modules));
313 if (modules == (const ModuleInfo **) NULL)
314 return((const ModuleInfo **) NULL);
315 /*
316 Generate module list.
317 */
cristyf84a1932010-01-03 18:00:18 +0000318 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000319 ResetSplayTreeIterator(module_list);
320 p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
321 for (i=0; p != (const ModuleInfo *) NULL; )
322 {
323 if ((p->stealth == MagickFalse) &&
324 (GlobExpression(p->tag,pattern,MagickFalse) != MagickFalse))
325 modules[i++]=p;
326 p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
327 }
cristyf84a1932010-01-03 18:00:18 +0000328 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000329 qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleInfoCompare);
330 modules[i]=(ModuleInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000331 *number_modules=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000332 return(modules);
333}
334
335/*
336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337% %
338% %
339% %
340% G e t M o d u l e L i s t %
341% %
342% %
343% %
344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345%
346% GetModuleList() returns any image format modules that match the specified
347% pattern.
348%
349% The format of the GetModuleList function is:
350%
cristya6de29a2010-06-30 14:34:26 +0000351% char **GetModuleList(const char *pattern,const MagickModuleType type,
352% size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000353%
354% A description of each parameter follows:
355%
356% o pattern: Specifies a pointer to a text string containing a pattern.
357%
cristya6de29a2010-06-30 14:34:26 +0000358% o type: choose from MagickImageCoderModule or MagickImageFilterModule.
359%
cristy3ed852e2009-09-05 21:47:34 +0000360% o number_modules: This integer returns the number of modules in the
361% list.
362%
363% o exception: return any errors or warnings in this structure.
364%
365*/
366
367#if defined(__cplusplus) || defined(c_plusplus)
368extern "C" {
369#endif
370
371static int ModuleCompare(const void *x,const void *y)
372{
373 register const char
374 **p,
375 **q;
376
377 p=(const char **) x;
378 q=(const char **) y;
379 return(LocaleCompare(*p,*q));
380}
381
382#if defined(__cplusplus) || defined(c_plusplus)
383}
384#endif
385
386static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
387 struct dirent **result)
388{
389#if defined(MAGICKCORE_HAVE_READDIR_R)
390 return(readdir_r(directory,entry,result));
391#else
392 (void) entry;
393 errno=0;
394 *result=readdir(directory);
395 return(errno);
396#endif
397}
398
399MagickExport char **GetModuleList(const char *pattern,
cristya6de29a2010-06-30 14:34:26 +0000400 const MagickModuleType type,size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000401{
402 char
403 **modules,
404 filename[MaxTextExtent],
405 module_path[MaxTextExtent],
406 path[MaxTextExtent];
407
408 DIR
409 *directory;
410
411 MagickBooleanType
412 status;
413
cristybb503372010-05-27 20:51:26 +0000414 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000415 i;
416
417 size_t
cristyd1df72d2010-06-29 02:17:03 +0000418 max_entries;
cristy3ed852e2009-09-05 21:47:34 +0000419
420 struct dirent
421 *buffer,
422 *entry;
423
cristy3ed852e2009-09-05 21:47:34 +0000424 /*
cristya6de29a2010-06-30 14:34:26 +0000425 Locate all modules in the image coder or filter path.
cristy3ed852e2009-09-05 21:47:34 +0000426 */
cristya6de29a2010-06-30 14:34:26 +0000427 switch (type)
428 {
429 case MagickImageCoderModule:
430 default:
431 {
432 TagToCoderModuleName("magick",filename);
433 status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
434 exception);
435 break;
436 }
437 case MagickImageFilterModule:
438 {
439 TagToFilterModuleName("analyze",filename);
440 status=GetMagickModulePath(filename,MagickImageFilterModule,module_path,
441 exception);
442 break;
443 }
444 }
cristyd1df72d2010-06-29 02:17:03 +0000445 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000446 return((char **) NULL);
447 GetPathComponent(module_path,HeadPath,path);
448 max_entries=255;
449 modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
450 sizeof(*modules));
451 if (modules == (char **) NULL)
452 return((char **) NULL);
453 *modules=(char *) NULL;
454 directory=opendir(path);
455 if (directory == (DIR *) NULL)
456 {
457 modules=(char **) RelinquishMagickMemory(modules);
458 return((char **) NULL);
459 }
cristyaaaff842013-06-30 02:48:11 +0000460 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
cristy3ed852e2009-09-05 21:47:34 +0000461 if (buffer == (struct dirent *) NULL)
462 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
463 i=0;
464 while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
465 (entry != (struct dirent *) NULL))
466 {
467 status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
468 if (status == MagickFalse)
469 continue;
470 if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
471 continue;
cristybb503372010-05-27 20:51:26 +0000472 if (i >= (ssize_t) max_entries)
cristy3ed852e2009-09-05 21:47:34 +0000473 {
474 modules=(char **) NULL;
475 if (~max_entries > max_entries)
476 modules=(char **) ResizeQuantumMemory(modules,(size_t)
477 (max_entries << 1),sizeof(*modules));
478 max_entries<<=1;
479 if (modules == (char **) NULL)
480 break;
481 }
482 /*
483 Add new module name to list.
484 */
485 modules[i]=AcquireString((char *) NULL);
486 GetPathComponent(entry->d_name,BasePath,modules[i]);
cristy3ed852e2009-09-05 21:47:34 +0000487 if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
488 {
489 (void) CopyMagickString(modules[i],modules[i]+10,MaxTextExtent);
490 modules[i][strlen(modules[i])-1]='\0';
491 }
492 i++;
493 }
494 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
495 (void) closedir(directory);
496 if (modules == (char **) NULL)
497 {
498 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
cristyefe601c2013-01-05 17:51:12 +0000499 "MemoryAllocationFailed","`%s'",pattern);
cristy3ed852e2009-09-05 21:47:34 +0000500 return((char **) NULL);
501 }
502 qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
503 modules[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000504 *number_modules=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000505 return(modules);
506}
507
508/*
509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510% %
511% %
512% %
513% G e t M a g i c k M o d u l e P a t h %
514% %
515% %
516% %
517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518%
519% GetMagickModulePath() finds a module with the specified module type and
520% filename.
521%
522% The format of the GetMagickModulePath module is:
523%
524% MagickBooleanType GetMagickModulePath(const char *filename,
525% MagickModuleType module_type,char *path,ExceptionInfo *exception)
526%
527% A description of each parameter follows:
528%
529% o filename: the module file name.
530%
531% o module_type: the module type: MagickImageCoderModule or
532% MagickImageFilterModule.
533%
534% o path: the path associated with the filename.
535%
536% o exception: return any errors or warnings in this structure.
537%
538*/
539static MagickBooleanType GetMagickModulePath(const char *filename,
540 MagickModuleType module_type,char *path,ExceptionInfo *exception)
541{
542 char
543 *module_path;
544
545 assert(filename != (const char *) NULL);
546 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
547 assert(path != (char *) NULL);
548 assert(exception != (ExceptionInfo *) NULL);
549 (void) CopyMagickString(path,filename,MaxTextExtent);
550 module_path=(char *) NULL;
551 switch (module_type)
552 {
553 case MagickImageCoderModule:
554 default:
555 {
556 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
557 "Searching for coder module file \"%s\" ...",filename);
558 module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
559#if defined(MAGICKCORE_CODER_PATH)
560 if (module_path == (char *) NULL)
561 module_path=AcquireString(MAGICKCORE_CODER_PATH);
562#endif
563 break;
564 }
565 case MagickImageFilterModule:
566 {
567 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
568 "Searching for filter module file \"%s\" ...",filename);
569 module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
570#if defined(MAGICKCORE_FILTER_PATH)
571 if (module_path == (char *) NULL)
572 module_path=AcquireString(MAGICKCORE_FILTER_PATH);
573#endif
574 break;
575 }
576 }
577 if (module_path != (char *) NULL)
578 {
579 register char
580 *p,
581 *q;
582
583 for (p=module_path-1; p != (char *) NULL; )
584 {
585 (void) CopyMagickString(path,p+1,MaxTextExtent);
586 q=strchr(path,DirectoryListSeparator);
587 if (q != (char *) NULL)
588 *q='\0';
589 q=path+strlen(path)-1;
590 if ((q >= path) && (*q != *DirectorySeparator))
591 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
592 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
593 if (IsPathAccessible(path) != MagickFalse)
594 {
595 module_path=DestroyString(module_path);
596 return(MagickTrue);
597 }
598 p=strchr(p+1,DirectoryListSeparator);
599 }
600 module_path=DestroyString(module_path);
601 }
602#if defined(MAGICKCORE_INSTALLED_SUPPORT)
cristyd1df72d2010-06-29 02:17:03 +0000603 else
cristy3ed852e2009-09-05 21:47:34 +0000604#if defined(MAGICKCORE_CODER_PATH)
605 {
606 const char
607 *directory;
608
609 /*
610 Search hard coded paths.
611 */
612 switch (module_type)
613 {
614 case MagickImageCoderModule:
615 default:
616 {
617 directory=MAGICKCORE_CODER_PATH;
618 break;
619 }
620 case MagickImageFilterModule:
621 {
622 directory=MAGICKCORE_FILTER_PATH;
623 break;
624 }
625 }
cristyb51dff52011-05-19 16:55:47 +0000626 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",directory,filename);
cristy3ed852e2009-09-05 21:47:34 +0000627 if (IsPathAccessible(path) == MagickFalse)
628 {
629 ThrowFileException(exception,ConfigureWarning,
630 "UnableToOpenModuleFile",path);
631 return(MagickFalse);
632 }
633 return(MagickTrue);
634 }
635#else
cristy0157aea2010-04-24 21:12:18 +0000636#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000637 {
638 const char
639 *registery_key;
640
641 unsigned char
642 *key_value;
643
644 /*
645 Locate path via registry key.
646 */
647 switch (module_type)
648 {
649 case MagickImageCoderModule:
650 default:
651 {
652 registery_key="CoderModulesPath";
653 break;
654 }
655 case MagickImageFilterModule:
656 {
657 registery_key="FilterModulesPath";
658 break;
659 }
660 }
661 key_value=NTRegistryKeyLookup(registery_key);
662 if (key_value == (unsigned char *) NULL)
663 {
664 ThrowMagickException(exception,GetMagickModule(),ConfigureError,
cristyefe601c2013-01-05 17:51:12 +0000665 "RegistryKeyLookupFailed","`%s'",registery_key);
cristy3ed852e2009-09-05 21:47:34 +0000666 return(MagickFalse);
667 }
cristyb51dff52011-05-19 16:55:47 +0000668 (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",(char *) key_value,
cristy3ed852e2009-09-05 21:47:34 +0000669 DirectorySeparator,filename);
670 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
671 if (IsPathAccessible(path) == MagickFalse)
672 {
673 ThrowFileException(exception,ConfigureWarning,
674 "UnableToOpenModuleFile",path);
675 return(MagickFalse);
676 }
677 return(MagickTrue);
678 }
679#endif
680#endif
cristy0157aea2010-04-24 21:12:18 +0000681#if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
682# error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
cristy3ed852e2009-09-05 21:47:34 +0000683#endif
684#else
685 {
686 char
687 *home;
688
689 home=GetEnvironmentValue("MAGICK_HOME");
690 if (home != (char *) NULL)
691 {
692 /*
693 Search MAGICK_HOME.
694 */
695#if !defined(MAGICKCORE_POSIX_SUPPORT)
cristyb51dff52011-05-19 16:55:47 +0000696 (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",home,
cristy3ed852e2009-09-05 21:47:34 +0000697 DirectorySeparator,filename);
698#else
699 const char
700 *directory;
701
702 switch (module_type)
703 {
704 case MagickImageCoderModule:
705 default:
706 {
707 directory=MAGICKCORE_CODER_RELATIVE_PATH;
708 break;
709 }
710 case MagickImageFilterModule:
711 {
712 directory=MAGICKCORE_FILTER_RELATIVE_PATH;
713 break;
714 }
715 }
cristyb51dff52011-05-19 16:55:47 +0000716 (void) FormatLocaleString(path,MaxTextExtent,"%s/lib/%s/%s",home,
cristy3ed852e2009-09-05 21:47:34 +0000717 directory,filename);
718#endif
719 home=DestroyString(home);
720 if (IsPathAccessible(path) != MagickFalse)
721 return(MagickTrue);
722 }
723 }
724 if (*GetClientPath() != '\0')
725 {
726 /*
727 Search based on executable directory.
728 */
729#if !defined(MAGICKCORE_POSIX_SUPPORT)
cristyb51dff52011-05-19 16:55:47 +0000730 (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
cristy3ed852e2009-09-05 21:47:34 +0000731 DirectorySeparator,filename);
732#else
733 char
734 prefix[MaxTextExtent];
735
736 const char
737 *directory;
738
739 switch (module_type)
740 {
741 case MagickImageCoderModule:
742 default:
743 {
cristy905e5302011-11-09 18:08:43 +0000744 directory="coders";
cristy3ed852e2009-09-05 21:47:34 +0000745 break;
746 }
747 case MagickImageFilterModule:
748 {
749 directory="filters";
750 break;
751 }
752 }
753 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
754 ChopPathComponents(prefix,1);
cristyfee63262012-12-02 21:47:04 +0000755 (void) FormatLocaleString(path,MaxTextExtent,"%s/lib/%s/%s/%s",prefix,
756 MAGICKCORE_MODULES_RELATIVE_PATH,directory,filename);
cristy3ed852e2009-09-05 21:47:34 +0000757#endif
758 if (IsPathAccessible(path) != MagickFalse)
759 return(MagickTrue);
760 }
cristy0157aea2010-04-24 21:12:18 +0000761#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000762 {
763 /*
764 Search module path.
765 */
dirk7c6c80c2015-01-03 23:41:04 +0000766 if ((NTGetModulePath("CORE_RL_MagickCore_.dll",path) != MagickFalse) ||
767 (NTGetModulePath("CORE_DB_MagickCore_.dll",path) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +0000768 {
769 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
770 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
771 if (IsPathAccessible(path) != MagickFalse)
772 return(MagickTrue);
773 }
774 }
775#endif
776 {
777 char
778 *home;
779
780 home=GetEnvironmentValue("HOME");
781 if (home == (char *) NULL)
782 home=GetEnvironmentValue("USERPROFILE");
783 if (home != (char *) NULL)
784 {
785 /*
cristy9f3b4fc2014-02-08 14:56:20 +0000786 Search $HOME/.config/ImageMagick.
cristy3ed852e2009-09-05 21:47:34 +0000787 */
cristy9f3b4fc2014-02-08 14:56:20 +0000788 (void) FormatLocaleString(path,MaxTextExtent,
789 "%s%s.config%sImageMagick%s%s",home,DirectorySeparator,
cristy3ed852e2009-09-05 21:47:34 +0000790 DirectorySeparator,DirectorySeparator,filename);
791 home=DestroyString(home);
792 if (IsPathAccessible(path) != MagickFalse)
793 return(MagickTrue);
794 }
795 }
796 /*
797 Search current directory.
798 */
799 if (IsPathAccessible(path) != MagickFalse)
800 return(MagickTrue);
801 if (exception->severity < ConfigureError)
802 ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
803 path);
cristy3ed852e2009-09-05 21:47:34 +0000804#endif
805 return(MagickFalse);
806}
807
808/*
809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
810% %
811% %
812% %
cristy904e5912014-03-15 19:53:14 +0000813% I s M o d u l e T r e e I n s t a n t i a t e d %
cristy3ed852e2009-09-05 21:47:34 +0000814% %
815% %
816% %
817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
818%
cristy904e5912014-03-15 19:53:14 +0000819% IsModuleTreeInstantiated() determines if the module tree is instantiated.
820% If not, it instantiates the tree and returns it.
cristy3ed852e2009-09-05 21:47:34 +0000821%
cristy904e5912014-03-15 19:53:14 +0000822% The format of the IsModuleTreeInstantiated() method is:
cristy3ed852e2009-09-05 21:47:34 +0000823%
cristy904e5912014-03-15 19:53:14 +0000824% IsModuleTreeInstantiated(Exceptioninfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000825%
826% A description of each parameter follows.
827%
828% o exception: return any errors or warnings in this structure.
829%
830*/
831
832static void *DestroyModuleNode(void *module_info)
833{
834 ExceptionInfo
835 *exception;
836
837 register ModuleInfo
838 *p;
839
840 exception=AcquireExceptionInfo();
841 p=(ModuleInfo *) module_info;
842 if (UnregisterModule(p,exception) == MagickFalse)
843 CatchException(exception);
844 if (p->tag != (char *) NULL)
845 p->tag=DestroyString(p->tag);
846 if (p->path != (char *) NULL)
847 p->path=DestroyString(p->path);
848 exception=DestroyExceptionInfo(exception);
849 return(RelinquishMagickMemory(p));
850}
851
cristy904e5912014-03-15 19:53:14 +0000852static MagickBooleanType IsModuleTreeInstantiated(
cristy3ed852e2009-09-05 21:47:34 +0000853 ExceptionInfo *magick_unused(exception))
854{
cristy1460f262014-03-15 17:38:05 +0000855 if (module_list == (SplayTreeInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000856 {
cristy86e5ac92014-03-16 19:27:39 +0000857 if (module_semaphore == (SemaphoreInfo *) NULL)
858 ActivateSemaphoreInfo(&module_semaphore);
859 LockSemaphoreInfo(module_semaphore);
cristy1460f262014-03-15 17:38:05 +0000860 if (module_list == (SplayTreeInfo *) NULL)
cristy86e5ac92014-03-16 19:27:39 +0000861 {
862 MagickBooleanType
863 status;
864
865 ModuleInfo
866 *module_info;
867
868 module_list=NewSplayTree(CompareSplayTreeString,
869 (void *(*)(void *)) NULL,DestroyModuleNode);
870 if (module_list == (SplayTreeInfo *) NULL)
871 ThrowFatalException(ResourceLimitFatalError,
872 "MemoryAllocationFailed");
873 module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
874 module_info->stealth=MagickTrue;
875 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
876 if (status == MagickFalse)
877 ThrowFatalException(ResourceLimitFatalError,
878 "MemoryAllocationFailed");
879 if (lt_dlinit() != 0)
880 ThrowFatalException(ModuleFatalError,
881 "UnableToInitializeModuleLoader");
882 }
883 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000884 }
885 return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
886}
887
888/*
889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890% %
891% %
892% %
cristy3ed852e2009-09-05 21:47:34 +0000893% I n v o k e D y n a m i c I m a g e F i l t e r %
894% %
895% %
896% %
897%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
898%
899% InvokeDynamicImageFilter() invokes a dynamic image filter.
900%
901% The format of the InvokeDynamicImageFilter module is:
902%
903% MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
904% const int argc,const char **argv,ExceptionInfo *exception)
905%
906% A description of each parameter follows:
907%
908% o tag: a character string that represents the name of the particular
909% module.
910%
911% o image: the image.
912%
913% o argc: a pointer to an integer describing the number of elements in the
914% argument vector.
915%
916% o argv: a pointer to a text array containing the command line arguments.
917%
918% o exception: return any errors or warnings in this structure.
919%
920*/
921MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
922 Image **images,const int argc,const char **argv,ExceptionInfo *exception)
923{
924 char
925 name[MaxTextExtent],
926 path[MaxTextExtent];
927
928 ImageFilterHandler
929 *image_filter;
930
cristyd1df72d2010-06-29 02:17:03 +0000931 MagickBooleanType
932 status;
933
cristy3ed852e2009-09-05 21:47:34 +0000934 ModuleHandle
935 handle;
936
937 PolicyRights
938 rights;
939
cristy3ed852e2009-09-05 21:47:34 +0000940 /*
941 Find the module.
942 */
943 assert(images != (Image **) NULL);
944 assert((*images)->signature == MagickSignature);
945 if ((*images)->debug != MagickFalse)
946 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
947 (*images)->filename);
948#if !defined(MAGICKCORE_BUILD_MODULES)
949 {
950 MagickBooleanType
951 status;
952
953 status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
954 if (status != MagickFalse)
955 return(status);
956 }
957#endif
958 rights=ReadPolicyRights;
959 if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
960 {
cristya9197f62010-01-12 02:23:34 +0000961 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +0000962 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +0000963 "NotAuthorized","`%s'",tag);
cristy3ed852e2009-09-05 21:47:34 +0000964 return(MagickFalse);
965 }
966 TagToFilterModuleName(tag,name);
cristyd1df72d2010-06-29 02:17:03 +0000967 status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
968 if (status == MagickFalse)
969 {
970 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +0000971 "UnableToLoadModule","'%s': %s",name,path);
cristyd1df72d2010-06-29 02:17:03 +0000972 return(MagickFalse);
973 }
cristy3ed852e2009-09-05 21:47:34 +0000974 /*
975 Open the module.
976 */
977 handle=(ModuleHandle) lt_dlopen(path);
978 if (handle == (ModuleHandle) NULL)
979 {
980 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +0000981 "UnableToLoadModule","'%s': %s",name,lt_dlerror());
cristy3ed852e2009-09-05 21:47:34 +0000982 return(MagickFalse);
983 }
984 /*
985 Locate the module.
986 */
987#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
cristyb51dff52011-05-19 16:55:47 +0000988 (void) FormatLocaleString(name,MaxTextExtent,"%sImage",tag);
cristy3ed852e2009-09-05 21:47:34 +0000989#else
cristyb51dff52011-05-19 16:55:47 +0000990 (void) FormatLocaleString(name,MaxTextExtent,"%s%sImage",
cristy3ed852e2009-09-05 21:47:34 +0000991 MAGICKCORE_NAMESPACE_PREFIX,tag);
992#endif
993 /*
994 Execute the module.
995 */
cristyfe12d6c2010-05-07 01:38:41 +0000996 ClearMagickException(exception);
cristy3ed852e2009-09-05 21:47:34 +0000997 image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
998 if (image_filter == (ImageFilterHandler *) NULL)
999 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +00001000 "UnableToLoadModule","'%s': %s",name,lt_dlerror());
cristy3ed852e2009-09-05 21:47:34 +00001001 else
1002 {
cristybb503372010-05-27 20:51:26 +00001003 size_t
cristy3ed852e2009-09-05 21:47:34 +00001004 signature;
1005
1006 if ((*images)->debug != MagickFalse)
1007 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1008 "Invoking \"%s\" dynamic image filter",tag);
1009 signature=image_filter(images,argc,argv,exception);
1010 if ((*images)->debug != MagickFalse)
1011 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1012 tag);
1013 if (signature != MagickImageFilterSignature)
cristyfe12d6c2010-05-07 01:38:41 +00001014 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +00001015 "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
cristyf1d91242010-05-28 02:23:19 +00001016 (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
cristy3ed852e2009-09-05 21:47:34 +00001017 }
1018 /*
1019 Close the module.
1020 */
1021 if (lt_dlclose(handle) != 0)
cristyfe12d6c2010-05-07 01:38:41 +00001022 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
anthonye5b39652012-04-21 05:37:29 +00001023 "UnableToCloseModule","'%s': %s",name,lt_dlerror());
cristyfe12d6c2010-05-07 01:38:41 +00001024 return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001025}
1026
1027/*
1028%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029% %
1030% %
1031% %
1032% L i s t M o d u l e I n f o %
1033% %
1034% %
1035% %
1036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037%
1038% ListModuleInfo() lists the module info to a file.
1039%
1040% The format of the ListModuleInfo module is:
1041%
1042% MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1043%
1044% A description of each parameter follows.
1045%
1046% o file: An pointer to a FILE.
1047%
1048% o exception: return any errors or warnings in this structure.
1049%
1050*/
1051MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1052 ExceptionInfo *exception)
1053{
cristya6de29a2010-06-30 14:34:26 +00001054 char
1055 filename[MaxTextExtent],
1056 module_path[MaxTextExtent],
1057 **modules,
1058 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00001059
cristybb503372010-05-27 20:51:26 +00001060 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001061 i;
1062
cristybb503372010-05-27 20:51:26 +00001063 size_t
cristy3ed852e2009-09-05 21:47:34 +00001064 number_modules;
1065
1066 if (file == (const FILE *) NULL)
1067 file=stdout;
cristya6de29a2010-06-30 14:34:26 +00001068 /*
1069 List image coders.
1070 */
1071 modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1072 if (modules == (char **) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001073 return(MagickFalse);
cristya6de29a2010-06-30 14:34:26 +00001074 TagToCoderModuleName("magick",filename);
1075 (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
1076 exception);
1077 GetPathComponent(module_path,HeadPath,path);
cristyb51dff52011-05-19 16:55:47 +00001078 (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1079 (void) FormatLocaleFile(file,"Image Coder\n");
cristy1e604812011-05-19 18:07:50 +00001080 (void) FormatLocaleFile(file,
1081 "-------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +00001082 "------------------------------\n");
cristybb503372010-05-27 20:51:26 +00001083 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001084 {
cristyb51dff52011-05-19 16:55:47 +00001085 (void) FormatLocaleFile(file,"%s",modules[i]);
1086 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00001087 }
1088 (void) fflush(file);
cristya6de29a2010-06-30 14:34:26 +00001089 /*
1090 Relinquish resources.
1091 */
1092 for (i=0; i < (ssize_t) number_modules; i++)
1093 modules[i]=DestroyString(modules[i]);
1094 modules=(char **) RelinquishMagickMemory(modules);
1095 /*
1096 List image filters.
1097 */
1098 modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
1099 if (modules == (char **) NULL)
1100 return(MagickFalse);
1101 TagToFilterModuleName("analyze",filename);
1102 (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
1103 exception);
1104 GetPathComponent(module_path,HeadPath,path);
cristyb51dff52011-05-19 16:55:47 +00001105 (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1106 (void) FormatLocaleFile(file,"Image Filter\n");
cristy1e604812011-05-19 18:07:50 +00001107 (void) FormatLocaleFile(file,
1108 "-------------------------------------------------"
cristya6de29a2010-06-30 14:34:26 +00001109 "------------------------------\n");
1110 for (i=0; i < (ssize_t) number_modules; i++)
1111 {
cristyb51dff52011-05-19 16:55:47 +00001112 (void) FormatLocaleFile(file,"%s",modules[i]);
1113 (void) FormatLocaleFile(file,"\n");
cristya6de29a2010-06-30 14:34:26 +00001114 }
1115 (void) fflush(file);
1116 /*
1117 Relinquish resources.
1118 */
1119 for (i=0; i < (ssize_t) number_modules; i++)
1120 modules[i]=DestroyString(modules[i]);
1121 modules=(char **) RelinquishMagickMemory(modules);
cristy3ed852e2009-09-05 21:47:34 +00001122 return(MagickTrue);
1123}
1124
1125/*
1126%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1127% %
1128% %
1129% %
cristyf34a1452009-10-24 22:29:27 +00001130+ M o d u l e C o m p o n e n t G e n e s i s %
1131% %
1132% %
1133% %
1134%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1135%
1136% ModuleComponentGenesis() instantiates the module component.
1137%
1138% The format of the ModuleComponentGenesis method is:
1139%
1140% MagickBooleanType ModuleComponentGenesis(void)
1141%
1142*/
cristy5ff4eaf2011-09-03 01:38:02 +00001143MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +00001144{
1145 ExceptionInfo
1146 *exception;
1147
cristycee97112010-05-28 00:44:52 +00001148 MagickBooleanType
1149 status;
1150
cristy7c977062014-04-04 14:05:53 +00001151 if (module_semaphore == (SemaphoreInfo *) NULL)
1152 module_semaphore=AcquireSemaphoreInfo();
cristyf34a1452009-10-24 22:29:27 +00001153 exception=AcquireExceptionInfo();
cristy904e5912014-03-15 19:53:14 +00001154 status=IsModuleTreeInstantiated(exception);
cristyf34a1452009-10-24 22:29:27 +00001155 exception=DestroyExceptionInfo(exception);
cristycee97112010-05-28 00:44:52 +00001156 return(status);
cristyf34a1452009-10-24 22:29:27 +00001157}
1158
1159/*
1160%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1161% %
1162% %
1163% %
1164+ M o d u l e C o m p o n e n t T e r m i n u s %
1165% %
1166% %
1167% %
1168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1169%
1170% ModuleComponentTerminus() destroys the module component.
1171%
1172% The format of the ModuleComponentTerminus method is:
1173%
1174% ModuleComponentTerminus(void)
1175%
1176*/
cristy5ff4eaf2011-09-03 01:38:02 +00001177MagickPrivate void ModuleComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001178{
cristy18b17442009-10-25 18:36:48 +00001179 if (module_semaphore == (SemaphoreInfo *) NULL)
cristy04b11db2014-02-16 15:10:39 +00001180 ActivateSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001181 DestroyModuleList();
cristy3d162a92014-02-16 14:05:06 +00001182 RelinquishSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001183}
1184
1185/*
1186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187% %
1188% %
1189% %
cristy3ed852e2009-09-05 21:47:34 +00001190% O p e n M o d u l e %
1191% %
1192% %
1193% %
1194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195%
1196% OpenModule() loads a module, and invokes its registration module. It
1197% returns MagickTrue on success, and MagickFalse if there is an error.
1198%
1199% The format of the OpenModule module is:
1200%
1201% MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1202%
1203% A description of each parameter follows:
1204%
1205% o module: a character string that indicates the module to load.
1206%
1207% o exception: return any errors or warnings in this structure.
1208%
1209*/
cristy7832dc22011-09-05 01:21:53 +00001210MagickPrivate MagickBooleanType OpenModule(const char *module,
cristy3ed852e2009-09-05 21:47:34 +00001211 ExceptionInfo *exception)
1212{
1213 char
1214 filename[MaxTextExtent],
1215 module_name[MaxTextExtent],
1216 name[MaxTextExtent],
1217 path[MaxTextExtent];
1218
cristyd1df72d2010-06-29 02:17:03 +00001219 MagickBooleanType
1220 status;
1221
cristy3ed852e2009-09-05 21:47:34 +00001222 ModuleHandle
1223 handle;
1224
1225 ModuleInfo
1226 *module_info;
1227
1228 register const CoderInfo
1229 *p;
1230
1231 size_t
cristy3ed852e2009-09-05 21:47:34 +00001232 signature;
1233
1234 /*
1235 Assign module name from alias.
1236 */
1237 assert(module != (const char *) NULL);
1238 module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1239 if (module_info != (ModuleInfo *) NULL)
1240 return(MagickTrue);
1241 (void) CopyMagickString(module_name,module,MaxTextExtent);
1242 p=GetCoderInfo(module,exception);
1243 if (p != (CoderInfo *) NULL)
1244 (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1245 if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1246 return(MagickTrue); /* module already opened, return */
1247 /*
1248 Locate module.
1249 */
1250 handle=(ModuleHandle) NULL;
1251 TagToCoderModuleName(module_name,filename);
1252 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1253 "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1254 *path='\0';
cristyd1df72d2010-06-29 02:17:03 +00001255 status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1256 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001257 return(MagickFalse);
1258 /*
1259 Load module
1260 */
1261 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1262 "Opening module at path \"%s\"",path);
1263 handle=(ModuleHandle) lt_dlopen(path);
1264 if (handle == (ModuleHandle) NULL)
1265 {
1266 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +00001267 "UnableToLoadModule","'%s': %s",path,lt_dlerror());
cristy3ed852e2009-09-05 21:47:34 +00001268 return(MagickFalse);
1269 }
1270 /*
1271 Register module.
1272 */
1273 module_info=AcquireModuleInfo(path,module_name);
1274 module_info->handle=handle;
1275 if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1276 return(MagickFalse);
1277 /*
1278 Define RegisterFORMATImage method.
1279 */
1280 TagToModuleName(module_name,"Register%sImage",name);
cristybb503372010-05-27 20:51:26 +00001281 module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1282 if (module_info->register_module == (size_t (*)(void)) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001283 {
1284 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +00001285 "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
cristy3ed852e2009-09-05 21:47:34 +00001286 return(MagickFalse);
1287 }
1288 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1289 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1290 (void *) module_info->register_module);
1291 /*
1292 Define UnregisterFORMATImage method.
1293 */
1294 TagToModuleName(module_name,"Unregister%sImage",name);
1295 module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1296 if (module_info->unregister_module == (void (*)(void)) NULL)
1297 {
1298 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +00001299 "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
cristy3ed852e2009-09-05 21:47:34 +00001300 return(MagickFalse);
1301 }
1302 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1303 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1304 (void *) module_info->unregister_module);
1305 signature=module_info->register_module();
1306 if (signature != MagickImageCoderSignature)
1307 {
1308 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +00001309 "ImageCoderSignatureMismatch","'%s': %8lx != %8lx",module_name,
cristyf1d91242010-05-28 02:23:19 +00001310 (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
cristy3ed852e2009-09-05 21:47:34 +00001311 return(MagickFalse);
1312 }
1313 return(MagickTrue);
1314}
1315
1316/*
1317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1318% %
1319% %
1320% %
1321% O p e n M o d u l e s %
1322% %
1323% %
1324% %
1325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326%
1327% OpenModules() loads all available modules.
1328%
1329% The format of the OpenModules module is:
1330%
1331% MagickBooleanType OpenModules(ExceptionInfo *exception)
1332%
1333% A description of each parameter follows:
1334%
1335% o exception: return any errors or warnings in this structure.
1336%
1337*/
cristy7832dc22011-09-05 01:21:53 +00001338MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001339{
1340 char
1341 **modules;
1342
cristybb503372010-05-27 20:51:26 +00001343 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001344 i;
1345
cristybb503372010-05-27 20:51:26 +00001346 size_t
cristy3ed852e2009-09-05 21:47:34 +00001347 number_modules;
1348
1349 /*
1350 Load all modules.
1351 */
1352 (void) GetMagickInfo((char *) NULL,exception);
1353 number_modules=0;
cristya6de29a2010-06-30 14:34:26 +00001354 modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
cristy3ed852e2009-09-05 21:47:34 +00001355 if (modules == (char **) NULL)
1356 return(MagickFalse);
cristybb503372010-05-27 20:51:26 +00001357 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001358 (void) OpenModule(modules[i],exception);
1359 /*
1360 Relinquish resources.
1361 */
cristybb503372010-05-27 20:51:26 +00001362 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001363 modules[i]=DestroyString(modules[i]);
1364 modules=(char **) RelinquishMagickMemory(modules);
1365 return(MagickTrue);
1366}
1367
1368/*
1369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1370% %
1371% %
1372% %
1373% R e g i s t e r M o d u l e %
1374% %
1375% %
1376% %
1377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1378%
1379% RegisterModule() adds an entry to the module list. It returns a pointer to
1380% the registered entry on success.
1381%
1382% The format of the RegisterModule module is:
1383%
1384% ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1385% ExceptionInfo *exception)
1386%
1387% A description of each parameter follows:
1388%
1389% o info: a pointer to the registered entry is returned.
1390%
1391% o module_info: a pointer to the ModuleInfo structure to register.
1392%
1393% o exception: return any errors or warnings in this structure.
1394%
1395*/
1396static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1397 ExceptionInfo *exception)
1398{
1399 MagickBooleanType
1400 status;
1401
1402 assert(module_info != (ModuleInfo *) NULL);
1403 assert(module_info->signature == MagickSignature);
1404 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1405 if (module_list == (SplayTreeInfo *) NULL)
1406 return((const ModuleInfo *) NULL);
1407 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1408 if (status == MagickFalse)
1409 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
cristyefe601c2013-01-05 17:51:12 +00001410 "MemoryAllocationFailed","`%s'",module_info->tag);
cristy3ed852e2009-09-05 21:47:34 +00001411 return(module_info);
1412}
1413
1414/*
1415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1416% %
1417% %
1418% %
1419% T a g T o C o d e r M o d u l e N a m e %
1420% %
1421% %
1422% %
1423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424%
1425% TagToCoderModuleName() munges a module tag and obtains the filename of the
1426% corresponding module.
1427%
1428% The format of the TagToCoderModuleName module is:
1429%
1430% char *TagToCoderModuleName(const char *tag,char *name)
1431%
1432% A description of each parameter follows:
1433%
1434% o tag: a character string representing the module tag.
1435%
1436% o name: return the module name here.
1437%
1438*/
1439static void TagToCoderModuleName(const char *tag,char *name)
1440{
1441 assert(tag != (char *) NULL);
1442 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1443 assert(name != (char *) NULL);
1444#if defined(MAGICKCORE_LTDL_DELEGATE)
cristyb51dff52011-05-19 16:55:47 +00001445 (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
cristy3ed852e2009-09-05 21:47:34 +00001446 (void) LocaleLower(name);
1447#else
cristy0157aea2010-04-24 21:12:18 +00001448#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001449 if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1450 (void) CopyMagickString(name,tag,MaxTextExtent);
1451 else
1452 {
1453#if defined(_DEBUG)
cristyb51dff52011-05-19 16:55:47 +00001454 (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
cristy3ed852e2009-09-05 21:47:34 +00001455#else
cristyb51dff52011-05-19 16:55:47 +00001456 (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
cristy3ed852e2009-09-05 21:47:34 +00001457#endif
1458 }
1459#endif
1460#endif
1461}
1462
1463/*
1464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465% %
1466% %
1467% %
1468% T a g T o F i l t e r M o d u l e N a m e %
1469% %
1470% %
1471% %
1472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473%
1474% TagToFilterModuleName() munges a module tag and returns the filename of the
1475% corresponding filter module.
1476%
1477% The format of the TagToFilterModuleName module is:
1478%
1479% void TagToFilterModuleName(const char *tag,char name)
1480%
1481% A description of each parameter follows:
1482%
1483% o tag: a character string representing the module tag.
1484%
1485% o name: return the filter name here.
1486%
1487*/
1488static void TagToFilterModuleName(const char *tag,char *name)
1489{
1490 assert(tag != (char *) NULL);
1491 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1492 assert(name != (char *) NULL);
1493#if !defined(MAGICKCORE_LTDL_DELEGATE)
cristyb51dff52011-05-19 16:55:47 +00001494 (void) FormatLocaleString(name,MaxTextExtent,"%s.dll",tag);
cristy3ed852e2009-09-05 21:47:34 +00001495#else
cristyb51dff52011-05-19 16:55:47 +00001496 (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
cristy3ed852e2009-09-05 21:47:34 +00001497#endif
1498}
1499
1500/*
1501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502% %
1503% %
1504% %
1505% T a g T o M o d u l e N a m e %
1506% %
1507% %
1508% %
1509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1510%
1511% TagToModuleName() munges the module tag name and returns an upper-case tag
1512% name as the input string, and a user-provided format.
1513%
1514% The format of the TagToModuleName module is:
1515%
1516% TagToModuleName(const char *tag,const char *format,char *module)
1517%
1518% A description of each parameter follows:
1519%
1520% o tag: the module tag.
1521%
1522% o format: a sprintf-compatible format string containing %s where the
1523% upper-case tag name is to be inserted.
1524%
1525% o module: pointer to a destination buffer for the formatted result.
1526%
1527*/
1528static void TagToModuleName(const char *tag,const char *format,char *module)
1529{
1530 char
1531 name[MaxTextExtent];
1532
1533 assert(tag != (const char *) NULL);
1534 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1535 assert(format != (const char *) NULL);
1536 assert(module != (char *) NULL);
1537 (void) CopyMagickString(name,tag,MaxTextExtent);
1538 LocaleUpper(name);
1539#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
cristyb51dff52011-05-19 16:55:47 +00001540 (void) FormatLocaleString(module,MaxTextExtent,format,name);
cristy3ed852e2009-09-05 21:47:34 +00001541#else
1542 {
1543 char
1544 prefix_format[MaxTextExtent];
1545
cristyb51dff52011-05-19 16:55:47 +00001546 (void) FormatLocaleString(prefix_format,MaxTextExtent,"%s%s",
cristy3ed852e2009-09-05 21:47:34 +00001547 MAGICKCORE_NAMESPACE_PREFIX,format);
cristyb51dff52011-05-19 16:55:47 +00001548 (void) FormatLocaleString(module,MaxTextExtent,prefix_format,name);
cristy3ed852e2009-09-05 21:47:34 +00001549 }
1550#endif
1551}
1552
1553/*
1554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1555% %
1556% %
1557% %
1558% U n r e g i s t e r M o d u l e %
1559% %
1560% %
1561% %
1562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1563%
1564% UnregisterModule() unloads a module, and invokes its de-registration module.
1565% Returns MagickTrue on success, and MagickFalse if there is an error.
1566%
1567% The format of the UnregisterModule module is:
1568%
1569% MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1570% ExceptionInfo *exception)
1571%
1572% A description of each parameter follows:
1573%
1574% o module_info: the module info.
1575%
1576% o exception: return any errors or warnings in this structure.
1577%
1578*/
1579static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1580 ExceptionInfo *exception)
1581{
1582 /*
1583 Locate and execute UnregisterFORMATImage module.
1584 */
1585 assert(module_info != (const ModuleInfo *) NULL);
1586 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1587 assert(exception != (ExceptionInfo *) NULL);
1588 if (module_info->unregister_module == NULL)
1589 return(MagickTrue);
1590 module_info->unregister_module();
1591 if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1592 {
1593 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
anthonye5b39652012-04-21 05:37:29 +00001594 "UnableToCloseModule","'%s': %s",module_info->tag,lt_dlerror());
cristy3ed852e2009-09-05 21:47:34 +00001595 return(MagickFalse);
1596 }
1597 return(MagickTrue);
1598}
1599#else
dirk143157c2014-03-01 10:16:38 +00001600
1601#if !defined(MAGICKCORE_BUILD_MODULES)
1602extern size_t
1603 analyzeImage(Image **,const int,const char **,ExceptionInfo *);
1604#endif
1605
cristy3ed852e2009-09-05 21:47:34 +00001606MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1607 ExceptionInfo *magick_unused(exception))
1608{
1609 return(MagickTrue);
1610}
1611
1612MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1613 Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1614{
cristya6de29a2010-06-30 14:34:26 +00001615 PolicyRights
1616 rights;
1617
1618 assert(image != (Image **) NULL);
1619 assert((*image)->signature == MagickSignature);
1620 if ((*image)->debug != MagickFalse)
1621 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1622 rights=ReadPolicyRights;
1623 if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
1624 {
1625 errno=EPERM;
1626 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
cristyefe601c2013-01-05 17:51:12 +00001627 "NotAuthorized","`%s'",tag);
cristya6de29a2010-06-30 14:34:26 +00001628 return(MagickFalse);
1629 }
1630#if defined(MAGICKCORE_BUILD_MODULES)
1631 (void) tag;
1632 (void) argc;
1633 (void) argv;
1634 (void) exception;
1635#else
cristy3ed852e2009-09-05 21:47:34 +00001636 {
cristy3ed852e2009-09-05 21:47:34 +00001637 ImageFilterHandler
1638 *image_filter;
1639
1640 image_filter=(ImageFilterHandler *) NULL;
1641 if (LocaleCompare("analyze",tag) == 0)
cristya6de29a2010-06-30 14:34:26 +00001642 image_filter=(ImageFilterHandler *) analyzeImage;
1643 if (image_filter == (ImageFilterHandler *) NULL)
1644 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
cristyefe601c2013-01-05 17:51:12 +00001645 "UnableToLoadModule","`%s'",tag);
cristya6de29a2010-06-30 14:34:26 +00001646 else
cristy3ed852e2009-09-05 21:47:34 +00001647 {
cristybb503372010-05-27 20:51:26 +00001648 size_t
cristy3ed852e2009-09-05 21:47:34 +00001649 signature;
1650
cristya6de29a2010-06-30 14:34:26 +00001651 if ((*image)->debug != MagickFalse)
1652 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1653 "Invoking \"%s\" static image filter",tag);
cristy3ed852e2009-09-05 21:47:34 +00001654 signature=image_filter(image,argc,argv,exception);
cristya6de29a2010-06-30 14:34:26 +00001655 if ((*image)->debug != MagickFalse)
1656 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
1657 tag);
cristy3ed852e2009-09-05 21:47:34 +00001658 if (signature != MagickImageFilterSignature)
1659 {
1660 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
anthonye5b39652012-04-21 05:37:29 +00001661 "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
cristya6de29a2010-06-30 14:34:26 +00001662 (unsigned long) signature,(unsigned long)
cristy3ed852e2009-09-05 21:47:34 +00001663 MagickImageFilterSignature);
1664 return(MagickFalse);
1665 }
1666 }
1667 }
1668#endif
1669 return(MagickTrue);
1670}
1671#endif