blob: 52ccb5a7fab318594a5570b5ce0c4413c386ecde [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% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 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*/
43#include "magick/studio.h"
44#include "magick/blob.h"
45#include "magick/coder.h"
46#include "magick/client.h"
47#include "magick/configure.h"
48#include "magick/exception.h"
49#include "magick/exception-private.h"
50#include "magick/log.h"
51#include "magick/hashmap.h"
52#include "magick/magic.h"
53#include "magick/magick.h"
54#include "magick/memory_.h"
55#include "magick/module.h"
56#include "magick/policy.h"
57#include "magick/semaphore.h"
58#include "magick/splay-tree.h"
59#include "magick/static.h"
60#include "magick/string_.h"
61#include "magick/token.h"
62#include "magick/utility.h"
63#if defined(MAGICKCORE_MODULES_SUPPORT)
64#if defined(MAGICKCORE_LTDL_DELEGATE)
65#include "ltdl.h"
66typedef lt_dlhandle ModuleHandle;
67#else
68typedef void *ModuleHandle;
69#endif
70
71/*
72 Define declarations.
73*/
74#if defined(MAGICKCORE_LTDL_DELEGATE)
75# define ModuleGlobExpression "*.la"
76#else
77# if defined(_DEBUG)
78# define ModuleGlobExpression "IM_MOD_DB_*.dll"
79# else
80# define ModuleGlobExpression "IM_MOD_RL_*.dll"
81# endif
82#endif
83
84/*
85 Global declarations.
86*/
87static SemaphoreInfo
88 *module_semaphore = (SemaphoreInfo *) NULL;
89
90static SplayTreeInfo
91 *module_list = (SplayTreeInfo *) NULL;
92
93static volatile MagickBooleanType
94 instantiate_module = MagickFalse;
95
96/*
97 Forward declarations.
98*/
99static const ModuleInfo
100 *RegisterModule(const ModuleInfo *,ExceptionInfo *);
101
102static MagickBooleanType
103 GetMagickModulePath(const char *,MagickModuleType,char *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000104 UnregisterModule(const ModuleInfo *,ExceptionInfo *);
105
106static void
107 TagToCoderModuleName(const char *,char *),
108 TagToFilterModuleName(const char *,char *),
109 TagToModuleName(const char *,const char *,char *);
110
111/*
112%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113% %
114% %
115% %
116% A c q u i r e M o d u l e I n f o %
117% %
118% %
119% %
120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121%
122% AcquireModuleInfo() allocates the ModuleInfo structure.
123%
124% The format of the AcquireModuleInfo method is:
125%
126% ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
127%
128% A description of each parameter follows:
129%
130% o path: the path associated with the tag.
131%
132% o tag: a character string that represents the image format we are
133% looking for.
134%
135*/
136MagickExport ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
137{
138 ModuleInfo
139 *module_info;
140
cristy90823212009-12-12 20:48:33 +0000141 module_info=(ModuleInfo *) AcquireAlignedMemory(1,sizeof(*module_info));
cristy3ed852e2009-09-05 21:47:34 +0000142 if (module_info == (ModuleInfo *) NULL)
143 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
144 (void) ResetMagickMemory(module_info,0,sizeof(*module_info));
145 if (path != (const char *) NULL)
146 module_info->path=ConstantString(path);
147 if (tag != (const char *) NULL)
148 module_info->tag=ConstantString(tag);
149 module_info->timestamp=time(0);
150 module_info->signature=MagickSignature;
151 return(module_info);
152}
153
154/*
155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156% %
157% %
158% %
159% D e s t r o y M o d u l e L i s t %
160% %
161% %
162% %
163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164%
165% DestroyModuleList() unregisters any previously loaded modules and exits
166% the module loaded environment.
167%
168% The format of the DestroyModuleList module is:
169%
170% void DestroyModuleList(void)
171%
172*/
173MagickExport void DestroyModuleList(void)
174{
175 /*
176 Destroy magick modules.
177 */
cristyf84a1932010-01-03 18:00:18 +0000178 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000179#if defined(MAGICKCORE_MODULES_SUPPORT)
180 if (module_list != (SplayTreeInfo *) NULL)
181 module_list=DestroySplayTree(module_list);
182 if (instantiate_module != MagickFalse)
cristy1e09ca22009-12-27 18:04:58 +0000183 {
184#if !defined(MAGICKCORE_JP2_DELEGATE)
185 (void) lt_dlexit(); /* Jasper has an errant atexit() handler */
cristy3ed852e2009-09-05 21:47:34 +0000186#endif
cristy1e09ca22009-12-27 18:04:58 +0000187 instantiate_module=MagickFalse;
188 }
189#endif
cristyf84a1932010-01-03 18:00:18 +0000190 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000191}
192
193/*
194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195% %
196% %
197% %
198% G e t M o d u l e I n f o %
199% %
200% %
201% %
202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203%
204% GetModuleInfo() returns a pointer to a ModuleInfo structure that matches the
205% specified tag. If tag is NULL, the head of the module list is returned. If
206% no modules are loaded, or the requested module is not found, NULL is
207% returned.
208%
209% The format of the GetModuleInfo module is:
210%
211% ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
212%
213% A description of each parameter follows:
214%
215% o tag: a character string that represents the image format we are
216% looking for.
217%
218% o exception: return any errors or warnings in this structure.
219%
220*/
221MagickExport ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
222{
223 if ((module_list == (SplayTreeInfo *) NULL) ||
224 (instantiate_module == MagickFalse))
225 if (InitializeModuleList(exception) == MagickFalse)
226 return((ModuleInfo *) NULL);
227 if ((module_list == (SplayTreeInfo *) NULL) ||
228 (GetNumberOfNodesInSplayTree(module_list) == 0))
229 return((ModuleInfo *) NULL);
230 if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0))
231 {
232 ModuleInfo
233 *p;
234
235#if defined(MAGICKCORE_MODULES_SUPPORT)
236 if (LocaleCompare(tag,"*") == 0)
237 (void) OpenModules(exception);
238#endif
cristyf84a1932010-01-03 18:00:18 +0000239 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000240 ResetSplayTreeIterator(module_list);
241 p=(ModuleInfo *) GetNextValueInSplayTree(module_list);
cristyf84a1932010-01-03 18:00:18 +0000242 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000243 return(p);
244 }
245 return((ModuleInfo *) GetValueFromSplayTree(module_list,tag));
246}
247
248/*
249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250% %
251% %
252% %
253% G e t M o d u l e I n f o L i s t %
254% %
255% %
256% %
257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258%
259% GetModuleInfoList() returns any modules that match the specified pattern.
260%
261% The format of the GetModuleInfoList function is:
262%
263% const ModuleInfo **GetModuleInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000264% size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000265%
266% A description of each parameter follows:
267%
268% o pattern: Specifies a pointer to a text string containing a pattern.
269%
270% o number_modules: This integer returns the number of modules in the list.
271%
272% o exception: return any errors or warnings in this structure.
273%
274*/
275
276#if defined(__cplusplus) || defined(c_plusplus)
277extern "C" {
278#endif
279
280static int ModuleInfoCompare(const void *x,const void *y)
281{
282 const ModuleInfo
283 **p,
284 **q;
285
286 p=(const ModuleInfo **) x,
287 q=(const ModuleInfo **) y;
288 if (LocaleCompare((*p)->path,(*q)->path) == 0)
289 return(LocaleCompare((*p)->tag,(*q)->tag));
290 return(LocaleCompare((*p)->path,(*q)->path));
291}
292
293#if defined(__cplusplus) || defined(c_plusplus)
294}
295#endif
296
297MagickExport const ModuleInfo **GetModuleInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000298 size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000299{
300 const ModuleInfo
301 **modules;
302
303 register const ModuleInfo
304 *p;
305
cristybb503372010-05-27 20:51:26 +0000306 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000307 i;
308
309 /*
310 Allocate module list.
311 */
312 assert(pattern != (char *) NULL);
313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000314 assert(number_modules != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000315 *number_modules=0;
316 p=GetModuleInfo("*",exception);
317 if (p == (const ModuleInfo *) NULL)
318 return((const ModuleInfo **) NULL);
319 modules=(const ModuleInfo **) AcquireQuantumMemory((size_t)
320 GetNumberOfNodesInSplayTree(module_list)+1UL,sizeof(*modules));
321 if (modules == (const ModuleInfo **) NULL)
322 return((const ModuleInfo **) NULL);
323 /*
324 Generate module list.
325 */
cristyf84a1932010-01-03 18:00:18 +0000326 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000327 ResetSplayTreeIterator(module_list);
328 p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
329 for (i=0; p != (const ModuleInfo *) NULL; )
330 {
331 if ((p->stealth == MagickFalse) &&
332 (GlobExpression(p->tag,pattern,MagickFalse) != MagickFalse))
333 modules[i++]=p;
334 p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
335 }
cristyf84a1932010-01-03 18:00:18 +0000336 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000337 qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleInfoCompare);
338 modules[i]=(ModuleInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000339 *number_modules=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000340 return(modules);
341}
342
343/*
344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345% %
346% %
347% %
348% G e t M o d u l e L i s t %
349% %
350% %
351% %
352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353%
354% GetModuleList() returns any image format modules that match the specified
355% pattern.
356%
357% The format of the GetModuleList function is:
358%
cristybb503372010-05-27 20:51:26 +0000359% char **GetModuleList(const char *pattern,size_t *number_modules,
cristy3ed852e2009-09-05 21:47:34 +0000360% ExceptionInfo *exception)
361%
362% A description of each parameter follows:
363%
364% o pattern: Specifies a pointer to a text string containing a pattern.
365%
366% o number_modules: This integer returns the number of modules in the
367% list.
368%
369% o exception: return any errors or warnings in this structure.
370%
371*/
372
373#if defined(__cplusplus) || defined(c_plusplus)
374extern "C" {
375#endif
376
377static int ModuleCompare(const void *x,const void *y)
378{
379 register const char
380 **p,
381 **q;
382
383 p=(const char **) x;
384 q=(const char **) y;
385 return(LocaleCompare(*p,*q));
386}
387
388#if defined(__cplusplus) || defined(c_plusplus)
389}
390#endif
391
392static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
393 struct dirent **result)
394{
395#if defined(MAGICKCORE_HAVE_READDIR_R)
396 return(readdir_r(directory,entry,result));
397#else
398 (void) entry;
399 errno=0;
400 *result=readdir(directory);
401 return(errno);
402#endif
403}
404
405MagickExport char **GetModuleList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000406 size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000407{
408 char
409 **modules,
410 filename[MaxTextExtent],
411 module_path[MaxTextExtent],
412 path[MaxTextExtent];
413
414 DIR
415 *directory;
416
417 MagickBooleanType
418 status;
419
cristybb503372010-05-27 20:51:26 +0000420 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000421 i;
422
423 size_t
424 length;
425
426 struct dirent
427 *buffer,
428 *entry;
429
cristybb503372010-05-27 20:51:26 +0000430 size_t
cristy3ed852e2009-09-05 21:47:34 +0000431 max_entries;
432
433 /*
434 Locate all modules in the coder path.
435 */
436 TagToCoderModuleName("magick",filename);
437 length=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
438 exception);
439 if (length == 0)
440 return((char **) NULL);
441 GetPathComponent(module_path,HeadPath,path);
442 max_entries=255;
443 modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
444 sizeof(*modules));
445 if (modules == (char **) NULL)
446 return((char **) NULL);
447 *modules=(char *) NULL;
448 directory=opendir(path);
449 if (directory == (DIR *) NULL)
450 {
451 modules=(char **) RelinquishMagickMemory(modules);
452 return((char **) NULL);
453 }
cristy90823212009-12-12 20:48:33 +0000454 buffer=(struct dirent *) AcquireAlignedMemory(1,sizeof(*buffer)+FILENAME_MAX+1);
cristy3ed852e2009-09-05 21:47:34 +0000455 if (buffer == (struct dirent *) NULL)
456 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
457 i=0;
458 while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
459 (entry != (struct dirent *) NULL))
460 {
461 status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
462 if (status == MagickFalse)
463 continue;
464 if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
465 continue;
cristybb503372010-05-27 20:51:26 +0000466 if (i >= (ssize_t) max_entries)
cristy3ed852e2009-09-05 21:47:34 +0000467 {
468 modules=(char **) NULL;
469 if (~max_entries > max_entries)
470 modules=(char **) ResizeQuantumMemory(modules,(size_t)
471 (max_entries << 1),sizeof(*modules));
472 max_entries<<=1;
473 if (modules == (char **) NULL)
474 break;
475 }
476 /*
477 Add new module name to list.
478 */
479 modules[i]=AcquireString((char *) NULL);
480 GetPathComponent(entry->d_name,BasePath,modules[i]);
481 LocaleUpper(modules[i]);
482 if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
483 {
484 (void) CopyMagickString(modules[i],modules[i]+10,MaxTextExtent);
485 modules[i][strlen(modules[i])-1]='\0';
486 }
487 i++;
488 }
489 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
490 (void) closedir(directory);
491 if (modules == (char **) NULL)
492 {
493 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
494 "MemoryAllocationFailed","`%s'",pattern);
495 return((char **) NULL);
496 }
497 qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
498 modules[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000499 *number_modules=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000500 return(modules);
501}
502
503/*
504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505% %
506% %
507% %
508% G e t M a g i c k M o d u l e P a t h %
509% %
510% %
511% %
512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513%
514% GetMagickModulePath() finds a module with the specified module type and
515% filename.
516%
517% The format of the GetMagickModulePath module is:
518%
519% MagickBooleanType GetMagickModulePath(const char *filename,
520% MagickModuleType module_type,char *path,ExceptionInfo *exception)
521%
522% A description of each parameter follows:
523%
524% o filename: the module file name.
525%
526% o module_type: the module type: MagickImageCoderModule or
527% MagickImageFilterModule.
528%
529% o path: the path associated with the filename.
530%
531% o exception: return any errors or warnings in this structure.
532%
533*/
534static MagickBooleanType GetMagickModulePath(const char *filename,
535 MagickModuleType module_type,char *path,ExceptionInfo *exception)
536{
537 char
538 *module_path;
539
540 assert(filename != (const char *) NULL);
541 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
542 assert(path != (char *) NULL);
543 assert(exception != (ExceptionInfo *) NULL);
544 (void) CopyMagickString(path,filename,MaxTextExtent);
545 module_path=(char *) NULL;
546 switch (module_type)
547 {
548 case MagickImageCoderModule:
549 default:
550 {
551 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
552 "Searching for coder module file \"%s\" ...",filename);
553 module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
554#if defined(MAGICKCORE_CODER_PATH)
555 if (module_path == (char *) NULL)
556 module_path=AcquireString(MAGICKCORE_CODER_PATH);
557#endif
558 break;
559 }
560 case MagickImageFilterModule:
561 {
562 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
563 "Searching for filter module file \"%s\" ...",filename);
564 module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
565#if defined(MAGICKCORE_FILTER_PATH)
566 if (module_path == (char *) NULL)
567 module_path=AcquireString(MAGICKCORE_FILTER_PATH);
568#endif
569 break;
570 }
571 }
572 if (module_path != (char *) NULL)
573 {
574 register char
575 *p,
576 *q;
577
578 for (p=module_path-1; p != (char *) NULL; )
579 {
580 (void) CopyMagickString(path,p+1,MaxTextExtent);
581 q=strchr(path,DirectoryListSeparator);
582 if (q != (char *) NULL)
583 *q='\0';
584 q=path+strlen(path)-1;
585 if ((q >= path) && (*q != *DirectorySeparator))
586 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
587 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
588 if (IsPathAccessible(path) != MagickFalse)
589 {
590 module_path=DestroyString(module_path);
591 return(MagickTrue);
592 }
593 p=strchr(p+1,DirectoryListSeparator);
594 }
595 module_path=DestroyString(module_path);
596 }
597#if defined(MAGICKCORE_INSTALLED_SUPPORT)
598 else
599#if defined(MAGICKCORE_CODER_PATH)
600 {
601 const char
602 *directory;
603
604 /*
605 Search hard coded paths.
606 */
607 switch (module_type)
608 {
609 case MagickImageCoderModule:
610 default:
611 {
612 directory=MAGICKCORE_CODER_PATH;
613 break;
614 }
615 case MagickImageFilterModule:
616 {
617 directory=MAGICKCORE_FILTER_PATH;
618 break;
619 }
620 }
621 (void) FormatMagickString(path,MaxTextExtent,"%s%s",directory,filename);
622 if (IsPathAccessible(path) == MagickFalse)
623 {
624 ThrowFileException(exception,ConfigureWarning,
625 "UnableToOpenModuleFile",path);
626 return(MagickFalse);
627 }
628 return(MagickTrue);
629 }
630#else
cristy0157aea2010-04-24 21:12:18 +0000631#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000632 {
633 const char
634 *registery_key;
635
636 unsigned char
637 *key_value;
638
639 /*
640 Locate path via registry key.
641 */
642 switch (module_type)
643 {
644 case MagickImageCoderModule:
645 default:
646 {
647 registery_key="CoderModulesPath";
648 break;
649 }
650 case MagickImageFilterModule:
651 {
652 registery_key="FilterModulesPath";
653 break;
654 }
655 }
656 key_value=NTRegistryKeyLookup(registery_key);
657 if (key_value == (unsigned char *) NULL)
658 {
659 ThrowMagickException(exception,GetMagickModule(),ConfigureError,
660 "RegistryKeyLookupFailed","`%s'",registery_key);
661 return(MagickFalse);
662 }
663 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",(char *) key_value,
664 DirectorySeparator,filename);
665 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
666 if (IsPathAccessible(path) == MagickFalse)
667 {
668 ThrowFileException(exception,ConfigureWarning,
669 "UnableToOpenModuleFile",path);
670 return(MagickFalse);
671 }
672 return(MagickTrue);
673 }
674#endif
675#endif
cristy0157aea2010-04-24 21:12:18 +0000676#if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
677# error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
cristy3ed852e2009-09-05 21:47:34 +0000678#endif
679#else
680 {
681 char
682 *home;
683
684 home=GetEnvironmentValue("MAGICK_HOME");
685 if (home != (char *) NULL)
686 {
687 /*
688 Search MAGICK_HOME.
689 */
690#if !defined(MAGICKCORE_POSIX_SUPPORT)
691 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",home,
692 DirectorySeparator,filename);
693#else
694 const char
695 *directory;
696
697 switch (module_type)
698 {
699 case MagickImageCoderModule:
700 default:
701 {
702 directory=MAGICKCORE_CODER_RELATIVE_PATH;
703 break;
704 }
705 case MagickImageFilterModule:
706 {
707 directory=MAGICKCORE_FILTER_RELATIVE_PATH;
708 break;
709 }
710 }
711 (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/%s",home,
712 directory,filename);
713#endif
714 home=DestroyString(home);
715 if (IsPathAccessible(path) != MagickFalse)
716 return(MagickTrue);
717 }
718 }
719 if (*GetClientPath() != '\0')
720 {
721 /*
722 Search based on executable directory.
723 */
724#if !defined(MAGICKCORE_POSIX_SUPPORT)
725 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
726 DirectorySeparator,filename);
727#else
728 char
729 prefix[MaxTextExtent];
730
731 const char
732 *directory;
733
734 switch (module_type)
735 {
736 case MagickImageCoderModule:
737 default:
738 {
739 directory="modules";
740 break;
741 }
742 case MagickImageFilterModule:
743 {
744 directory="filters";
745 break;
746 }
747 }
748 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
749 ChopPathComponents(prefix,1);
750 (void) FormatMagickString(path,MaxTextExtent,
751 "%s/lib/%s/modules-Q%d/%s/%s",prefix,MAGICKCORE_LIBRARY_RELATIVE_PATH,
752 MAGICKCORE_QUANTUM_DEPTH,directory,filename);
753#endif
754 if (IsPathAccessible(path) != MagickFalse)
755 return(MagickTrue);
756 }
cristy0157aea2010-04-24 21:12:18 +0000757#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000758 {
759 /*
760 Search module path.
761 */
762 if ((NTGetModulePath("CORE_RL_magick_.dll",path) != MagickFalse) ||
763 (NTGetModulePath("CORE_DB_magick_.dll",path) != MagickFalse) ||
764 (NTGetModulePath("Magick.dll",path) != MagickFalse))
765 {
766 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
767 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
768 if (IsPathAccessible(path) != MagickFalse)
769 return(MagickTrue);
770 }
771 }
772#endif
773 {
774 char
775 *home;
776
777 home=GetEnvironmentValue("HOME");
778 if (home == (char *) NULL)
779 home=GetEnvironmentValue("USERPROFILE");
780 if (home != (char *) NULL)
781 {
782 /*
783 Search $HOME/.magick.
784 */
785 (void) FormatMagickString(path,MaxTextExtent,"%s%s.magick%s%s",home,
786 DirectorySeparator,DirectorySeparator,filename);
787 home=DestroyString(home);
788 if (IsPathAccessible(path) != MagickFalse)
789 return(MagickTrue);
790 }
791 }
792 /*
793 Search current directory.
794 */
795 if (IsPathAccessible(path) != MagickFalse)
796 return(MagickTrue);
797 if (exception->severity < ConfigureError)
798 ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
799 path);
800 return(MagickFalse);
801#endif
802 return(MagickFalse);
803}
804
805/*
806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807% %
808% %
809% %
cristy498543d2009-10-11 03:14:50 +0000810% I n i t i a l i z e M o d u l e L i s t %
cristy3ed852e2009-09-05 21:47:34 +0000811% %
812% %
813% %
814%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815%
816% InitializeModuleList() initializes the module loader.
817%
818% The format of the InitializeModuleList() method is:
819%
820% InitializeModuleList(Exceptioninfo *exception)
821%
822% A description of each parameter follows.
823%
824% o exception: return any errors or warnings in this structure.
825%
826*/
827
828static void *DestroyModuleNode(void *module_info)
829{
830 ExceptionInfo
831 *exception;
832
833 register ModuleInfo
834 *p;
835
836 exception=AcquireExceptionInfo();
837 p=(ModuleInfo *) module_info;
838 if (UnregisterModule(p,exception) == MagickFalse)
839 CatchException(exception);
840 if (p->tag != (char *) NULL)
841 p->tag=DestroyString(p->tag);
842 if (p->path != (char *) NULL)
843 p->path=DestroyString(p->path);
844 exception=DestroyExceptionInfo(exception);
845 return(RelinquishMagickMemory(p));
846}
847
cristy498543d2009-10-11 03:14:50 +0000848MagickExport MagickBooleanType InitializeModuleList(
cristy3ed852e2009-09-05 21:47:34 +0000849 ExceptionInfo *magick_unused(exception))
850{
851 if ((module_list == (SplayTreeInfo *) NULL) &&
852 (instantiate_module == MagickFalse))
853 {
cristy4e1dff62009-10-25 20:36:03 +0000854 if (module_semaphore == (SemaphoreInfo *) NULL)
855 AcquireSemaphoreInfo(&module_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000856 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000857 if ((module_list == (SplayTreeInfo *) NULL) &&
858 (instantiate_module == MagickFalse))
859 {
860 MagickBooleanType
861 status;
862
863 ModuleInfo
864 *module_info;
865
866 module_list=NewSplayTree(CompareSplayTreeString,
867 (void *(*)(void *)) NULL,DestroyModuleNode);
868 if (module_list == (SplayTreeInfo *) NULL)
869 ThrowFatalException(ResourceLimitFatalError,
870 "MemoryAllocationFailed");
871 module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
872 module_info->stealth=MagickTrue;
873 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
874 if (status == MagickFalse)
875 ThrowFatalException(ResourceLimitFatalError,
876 "MemoryAllocationFailed");
877 if (lt_dlinit() != 0)
878 ThrowFatalException(ModuleFatalError,
879 "UnableToInitializeModuleLoader");
880 instantiate_module=MagickTrue;
881 }
cristyf84a1932010-01-03 18:00:18 +0000882 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000883 }
884 return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
885}
886
887/*
888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889% %
890% %
891% %
cristy3ed852e2009-09-05 21:47:34 +0000892% I n v o k e D y n a m i c I m a g e F i l t e r %
893% %
894% %
895% %
896%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
897%
898% InvokeDynamicImageFilter() invokes a dynamic image filter.
899%
900% The format of the InvokeDynamicImageFilter module is:
901%
902% MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
903% const int argc,const char **argv,ExceptionInfo *exception)
904%
905% A description of each parameter follows:
906%
907% o tag: a character string that represents the name of the particular
908% module.
909%
910% o image: the image.
911%
912% o argc: a pointer to an integer describing the number of elements in the
913% argument vector.
914%
915% o argv: a pointer to a text array containing the command line arguments.
916%
917% o exception: return any errors or warnings in this structure.
918%
919*/
920MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
921 Image **images,const int argc,const char **argv,ExceptionInfo *exception)
922{
923 char
924 name[MaxTextExtent],
925 path[MaxTextExtent];
926
927 ImageFilterHandler
928 *image_filter;
929
930 ModuleHandle
931 handle;
932
933 PolicyRights
934 rights;
935
936 size_t
937 length;
938
939 /*
940 Find the module.
941 */
942 assert(images != (Image **) NULL);
943 assert((*images)->signature == MagickSignature);
944 if ((*images)->debug != MagickFalse)
945 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
946 (*images)->filename);
947#if !defined(MAGICKCORE_BUILD_MODULES)
948 {
949 MagickBooleanType
950 status;
951
952 status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
953 if (status != MagickFalse)
954 return(status);
955 }
956#endif
957 rights=ReadPolicyRights;
958 if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
959 {
cristya9197f62010-01-12 02:23:34 +0000960 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +0000961 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
962 "NotAuthorized","`%s'",tag);
963 return(MagickFalse);
964 }
965 TagToFilterModuleName(tag,name);
966 length=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
967 if (length == 0)
968 return(MagickFalse);
969 /*
970 Open the module.
971 */
972 handle=(ModuleHandle) lt_dlopen(path);
973 if (handle == (ModuleHandle) NULL)
974 {
975 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
976 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
977 return(MagickFalse);
978 }
979 /*
980 Locate the module.
981 */
982#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
983 (void) FormatMagickString(name,MaxTextExtent,"%sImage",tag);
984#else
985 (void) FormatMagickString(name,MaxTextExtent,"%s%sImage",
986 MAGICKCORE_NAMESPACE_PREFIX,tag);
987#endif
988 /*
989 Execute the module.
990 */
cristyfe12d6c2010-05-07 01:38:41 +0000991 ClearMagickException(exception);
cristy3ed852e2009-09-05 21:47:34 +0000992 image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
993 if (image_filter == (ImageFilterHandler *) NULL)
994 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
995 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
996 else
997 {
cristybb503372010-05-27 20:51:26 +0000998 size_t
cristy3ed852e2009-09-05 21:47:34 +0000999 signature;
1000
1001 if ((*images)->debug != MagickFalse)
1002 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1003 "Invoking \"%s\" dynamic image filter",tag);
1004 signature=image_filter(images,argc,argv,exception);
1005 if ((*images)->debug != MagickFalse)
1006 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1007 tag);
1008 if (signature != MagickImageFilterSignature)
cristyfe12d6c2010-05-07 01:38:41 +00001009 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
cristyf1d91242010-05-28 02:23:19 +00001010 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,
1011 (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
cristy3ed852e2009-09-05 21:47:34 +00001012 }
1013 /*
1014 Close the module.
1015 */
1016 if (lt_dlclose(handle) != 0)
cristyfe12d6c2010-05-07 01:38:41 +00001017 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1018 "UnableToCloseModule","`%s': %s",name,lt_dlerror());
1019 return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001020}
1021
1022/*
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024% %
1025% %
1026% %
1027% L i s t M o d u l e I n f o %
1028% %
1029% %
1030% %
1031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032%
1033% ListModuleInfo() lists the module info to a file.
1034%
1035% The format of the ListModuleInfo module is:
1036%
1037% MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1038%
1039% A description of each parameter follows.
1040%
1041% o file: An pointer to a FILE.
1042%
1043% o exception: return any errors or warnings in this structure.
1044%
1045*/
1046MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1047 ExceptionInfo *exception)
1048{
1049 const ModuleInfo
1050 **module_info;
1051
cristybb503372010-05-27 20:51:26 +00001052 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001053 i;
1054
cristybb503372010-05-27 20:51:26 +00001055 size_t
cristy3ed852e2009-09-05 21:47:34 +00001056 number_modules;
1057
1058 if (file == (const FILE *) NULL)
1059 file=stdout;
1060 module_info=GetModuleInfoList("*",&number_modules,exception);
1061 if (module_info == (const ModuleInfo **) NULL)
1062 return(MagickFalse);
1063 if (module_info[0]->path != (char *) NULL)
1064 {
1065 char
1066 path[MaxTextExtent];
1067
1068 GetPathComponent(module_info[0]->path,HeadPath,path);
1069 (void) fprintf(file,"\nPath: %s\n\n",path);
1070 }
1071 (void) fprintf(file,"Module\n");
1072 (void) fprintf(file,"-------------------------------------------------"
1073 "------------------------------\n");
cristybb503372010-05-27 20:51:26 +00001074 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001075 {
1076 if (module_info[i]->stealth != MagickFalse)
1077 continue;
1078 (void) fprintf(file,"%s",module_info[i]->tag);
1079 (void) fprintf(file,"\n");
1080 }
1081 (void) fflush(file);
1082 module_info=(const ModuleInfo **)
1083 RelinquishMagickMemory((void *) module_info);
1084 return(MagickTrue);
1085}
1086
1087/*
1088%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1089% %
1090% %
1091% %
cristyf34a1452009-10-24 22:29:27 +00001092+ M o d u l e C o m p o n e n t G e n e s i s %
1093% %
1094% %
1095% %
1096%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1097%
1098% ModuleComponentGenesis() instantiates the module component.
1099%
1100% The format of the ModuleComponentGenesis method is:
1101%
1102% MagickBooleanType ModuleComponentGenesis(void)
1103%
1104*/
1105MagickExport MagickBooleanType ModuleComponentGenesis(void)
1106{
1107 ExceptionInfo
1108 *exception;
1109
cristycee97112010-05-28 00:44:52 +00001110 MagickBooleanType
1111 status;
1112
cristy165b6092009-10-26 13:52:10 +00001113 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001114 exception=AcquireExceptionInfo();
cristycee97112010-05-28 00:44:52 +00001115 status=InitializeModuleList(exception);
cristyf34a1452009-10-24 22:29:27 +00001116 exception=DestroyExceptionInfo(exception);
cristycee97112010-05-28 00:44:52 +00001117 return(status);
cristyf34a1452009-10-24 22:29:27 +00001118}
1119
1120/*
1121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1122% %
1123% %
1124% %
1125+ M o d u l e C o m p o n e n t T e r m i n u s %
1126% %
1127% %
1128% %
1129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130%
1131% ModuleComponentTerminus() destroys the module component.
1132%
1133% The format of the ModuleComponentTerminus method is:
1134%
1135% ModuleComponentTerminus(void)
1136%
1137*/
1138MagickExport void ModuleComponentTerminus(void)
1139{
cristy18b17442009-10-25 18:36:48 +00001140 if (module_semaphore == (SemaphoreInfo *) NULL)
1141 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001142 DestroyModuleList();
1143 DestroySemaphoreInfo(&module_semaphore);
1144}
1145
1146/*
1147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1148% %
1149% %
1150% %
cristy3ed852e2009-09-05 21:47:34 +00001151% O p e n M o d u l e %
1152% %
1153% %
1154% %
1155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156%
1157% OpenModule() loads a module, and invokes its registration module. It
1158% returns MagickTrue on success, and MagickFalse if there is an error.
1159%
1160% The format of the OpenModule module is:
1161%
1162% MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1163%
1164% A description of each parameter follows:
1165%
1166% o module: a character string that indicates the module to load.
1167%
1168% o exception: return any errors or warnings in this structure.
1169%
1170*/
1171MagickExport MagickBooleanType OpenModule(const char *module,
1172 ExceptionInfo *exception)
1173{
1174 char
1175 filename[MaxTextExtent],
1176 module_name[MaxTextExtent],
1177 name[MaxTextExtent],
1178 path[MaxTextExtent];
1179
1180 ModuleHandle
1181 handle;
1182
1183 ModuleInfo
1184 *module_info;
1185
1186 register const CoderInfo
1187 *p;
1188
1189 size_t
1190 length;
1191
cristybb503372010-05-27 20:51:26 +00001192 size_t
cristy3ed852e2009-09-05 21:47:34 +00001193 signature;
1194
1195 /*
1196 Assign module name from alias.
1197 */
1198 assert(module != (const char *) NULL);
1199 module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1200 if (module_info != (ModuleInfo *) NULL)
1201 return(MagickTrue);
1202 (void) CopyMagickString(module_name,module,MaxTextExtent);
1203 p=GetCoderInfo(module,exception);
1204 if (p != (CoderInfo *) NULL)
1205 (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1206 if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1207 return(MagickTrue); /* module already opened, return */
1208 /*
1209 Locate module.
1210 */
1211 handle=(ModuleHandle) NULL;
1212 TagToCoderModuleName(module_name,filename);
1213 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1214 "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1215 *path='\0';
1216 length=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1217 if (length == 0)
1218 return(MagickFalse);
1219 /*
1220 Load module
1221 */
1222 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1223 "Opening module at path \"%s\"",path);
1224 handle=(ModuleHandle) lt_dlopen(path);
1225 if (handle == (ModuleHandle) NULL)
1226 {
1227 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1228 "UnableToLoadModule","`%s': %s",path,lt_dlerror());
1229 return(MagickFalse);
1230 }
1231 /*
1232 Register module.
1233 */
1234 module_info=AcquireModuleInfo(path,module_name);
1235 module_info->handle=handle;
1236 if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1237 return(MagickFalse);
1238 /*
1239 Define RegisterFORMATImage method.
1240 */
1241 TagToModuleName(module_name,"Register%sImage",name);
cristybb503372010-05-27 20:51:26 +00001242 module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1243 if (module_info->register_module == (size_t (*)(void)) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001244 {
1245 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1246 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1247 return(MagickFalse);
1248 }
1249 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1250 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1251 (void *) module_info->register_module);
1252 /*
1253 Define UnregisterFORMATImage method.
1254 */
1255 TagToModuleName(module_name,"Unregister%sImage",name);
1256 module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1257 if (module_info->unregister_module == (void (*)(void)) NULL)
1258 {
1259 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1260 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1261 return(MagickFalse);
1262 }
1263 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1264 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1265 (void *) module_info->unregister_module);
1266 signature=module_info->register_module();
1267 if (signature != MagickImageCoderSignature)
1268 {
1269 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1270 "ImageCoderSignatureMismatch","`%s': %8lx != %8lx",module_name,
cristyf1d91242010-05-28 02:23:19 +00001271 (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
cristy3ed852e2009-09-05 21:47:34 +00001272 return(MagickFalse);
1273 }
1274 return(MagickTrue);
1275}
1276
1277/*
1278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1279% %
1280% %
1281% %
1282% O p e n M o d u l e s %
1283% %
1284% %
1285% %
1286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1287%
1288% OpenModules() loads all available modules.
1289%
1290% The format of the OpenModules module is:
1291%
1292% MagickBooleanType OpenModules(ExceptionInfo *exception)
1293%
1294% A description of each parameter follows:
1295%
1296% o exception: return any errors or warnings in this structure.
1297%
1298*/
1299MagickExport MagickBooleanType OpenModules(ExceptionInfo *exception)
1300{
1301 char
1302 **modules;
1303
cristybb503372010-05-27 20:51:26 +00001304 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001305 i;
1306
cristybb503372010-05-27 20:51:26 +00001307 size_t
cristy3ed852e2009-09-05 21:47:34 +00001308 number_modules;
1309
1310 /*
1311 Load all modules.
1312 */
1313 (void) GetMagickInfo((char *) NULL,exception);
1314 number_modules=0;
1315 modules=GetModuleList("*",&number_modules,exception);
1316 if (modules == (char **) NULL)
1317 return(MagickFalse);
cristybb503372010-05-27 20:51:26 +00001318 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001319 (void) OpenModule(modules[i],exception);
1320 /*
1321 Relinquish resources.
1322 */
cristybb503372010-05-27 20:51:26 +00001323 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001324 modules[i]=DestroyString(modules[i]);
1325 modules=(char **) RelinquishMagickMemory(modules);
1326 return(MagickTrue);
1327}
1328
1329/*
1330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331% %
1332% %
1333% %
1334% R e g i s t e r M o d u l e %
1335% %
1336% %
1337% %
1338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1339%
1340% RegisterModule() adds an entry to the module list. It returns a pointer to
1341% the registered entry on success.
1342%
1343% The format of the RegisterModule module is:
1344%
1345% ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1346% ExceptionInfo *exception)
1347%
1348% A description of each parameter follows:
1349%
1350% o info: a pointer to the registered entry is returned.
1351%
1352% o module_info: a pointer to the ModuleInfo structure to register.
1353%
1354% o exception: return any errors or warnings in this structure.
1355%
1356*/
1357static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1358 ExceptionInfo *exception)
1359{
1360 MagickBooleanType
1361 status;
1362
1363 assert(module_info != (ModuleInfo *) NULL);
1364 assert(module_info->signature == MagickSignature);
1365 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1366 if (module_list == (SplayTreeInfo *) NULL)
1367 return((const ModuleInfo *) NULL);
1368 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1369 if (status == MagickFalse)
1370 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1371 "MemoryAllocationFailed","`%s'",module_info->tag);
1372 return(module_info);
1373}
1374
1375/*
1376%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1377% %
1378% %
1379% %
1380% T a g T o C o d e r M o d u l e N a m e %
1381% %
1382% %
1383% %
1384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1385%
1386% TagToCoderModuleName() munges a module tag and obtains the filename of the
1387% corresponding module.
1388%
1389% The format of the TagToCoderModuleName module is:
1390%
1391% char *TagToCoderModuleName(const char *tag,char *name)
1392%
1393% A description of each parameter follows:
1394%
1395% o tag: a character string representing the module tag.
1396%
1397% o name: return the module name here.
1398%
1399*/
1400static void TagToCoderModuleName(const char *tag,char *name)
1401{
1402 assert(tag != (char *) NULL);
1403 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1404 assert(name != (char *) NULL);
1405#if defined(MAGICKCORE_LTDL_DELEGATE)
1406 (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
1407 (void) LocaleLower(name);
1408#else
cristy0157aea2010-04-24 21:12:18 +00001409#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001410 if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1411 (void) CopyMagickString(name,tag,MaxTextExtent);
1412 else
1413 {
1414#if defined(_DEBUG)
1415 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
1416#else
1417 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
1418#endif
1419 }
1420#endif
1421#endif
1422}
1423
1424/*
1425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1426% %
1427% %
1428% %
1429% T a g T o F i l t e r M o d u l e N a m e %
1430% %
1431% %
1432% %
1433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1434%
1435% TagToFilterModuleName() munges a module tag and returns the filename of the
1436% corresponding filter module.
1437%
1438% The format of the TagToFilterModuleName module is:
1439%
1440% void TagToFilterModuleName(const char *tag,char name)
1441%
1442% A description of each parameter follows:
1443%
1444% o tag: a character string representing the module tag.
1445%
1446% o name: return the filter name here.
1447%
1448*/
1449static void TagToFilterModuleName(const char *tag,char *name)
1450{
1451 assert(tag != (char *) NULL);
1452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1453 assert(name != (char *) NULL);
1454#if !defined(MAGICKCORE_LTDL_DELEGATE)
1455 (void) FormatMagickString(name,MaxTextExtent,"%s.dll",tag);
1456#else
1457 (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
1458 (void) LocaleLower(name);
1459#endif
1460}
1461
1462/*
1463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1464% %
1465% %
1466% %
1467% T a g T o M o d u l e N a m e %
1468% %
1469% %
1470% %
1471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1472%
1473% TagToModuleName() munges the module tag name and returns an upper-case tag
1474% name as the input string, and a user-provided format.
1475%
1476% The format of the TagToModuleName module is:
1477%
1478% TagToModuleName(const char *tag,const char *format,char *module)
1479%
1480% A description of each parameter follows:
1481%
1482% o tag: the module tag.
1483%
1484% o format: a sprintf-compatible format string containing %s where the
1485% upper-case tag name is to be inserted.
1486%
1487% o module: pointer to a destination buffer for the formatted result.
1488%
1489*/
1490static void TagToModuleName(const char *tag,const char *format,char *module)
1491{
1492 char
1493 name[MaxTextExtent];
1494
1495 assert(tag != (const char *) NULL);
1496 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1497 assert(format != (const char *) NULL);
1498 assert(module != (char *) NULL);
1499 (void) CopyMagickString(name,tag,MaxTextExtent);
1500 LocaleUpper(name);
1501#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1502 (void) FormatMagickString(module,MaxTextExtent,format,name);
1503#else
1504 {
1505 char
1506 prefix_format[MaxTextExtent];
1507
1508 (void) FormatMagickString(prefix_format,MaxTextExtent,"%s%s",
1509 MAGICKCORE_NAMESPACE_PREFIX,format);
1510 (void) FormatMagickString(module,MaxTextExtent,prefix_format,name);
1511 }
1512#endif
1513}
1514
1515/*
1516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1517% %
1518% %
1519% %
1520% U n r e g i s t e r M o d u l e %
1521% %
1522% %
1523% %
1524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1525%
1526% UnregisterModule() unloads a module, and invokes its de-registration module.
1527% Returns MagickTrue on success, and MagickFalse if there is an error.
1528%
1529% The format of the UnregisterModule module is:
1530%
1531% MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1532% ExceptionInfo *exception)
1533%
1534% A description of each parameter follows:
1535%
1536% o module_info: the module info.
1537%
1538% o exception: return any errors or warnings in this structure.
1539%
1540*/
1541static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1542 ExceptionInfo *exception)
1543{
1544 /*
1545 Locate and execute UnregisterFORMATImage module.
1546 */
1547 assert(module_info != (const ModuleInfo *) NULL);
1548 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1549 assert(exception != (ExceptionInfo *) NULL);
1550 if (module_info->unregister_module == NULL)
1551 return(MagickTrue);
1552 module_info->unregister_module();
1553 if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1554 {
1555 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1556 "UnableToCloseModule","`%s': %s",module_info->tag,lt_dlerror());
1557 return(MagickFalse);
1558 }
1559 return(MagickTrue);
1560}
1561#else
1562MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1563 ExceptionInfo *magick_unused(exception))
1564{
1565 return(MagickTrue);
1566}
1567
1568MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1569 Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1570{
1571#if !defined(MAGICKCORE_BUILD_MODULES)
1572 {
cristybb503372010-05-27 20:51:26 +00001573 extern size_t
cristya0b81c32010-01-22 02:54:33 +00001574 analyzeImage(Image **,const int,const char **,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +00001575
1576 ImageFilterHandler
1577 *image_filter;
1578
1579 image_filter=(ImageFilterHandler *) NULL;
1580 if (LocaleCompare("analyze",tag) == 0)
1581 image_filter=analyzeImage;
cristy3ed852e2009-09-05 21:47:34 +00001582 if (image_filter != (ImageFilterHandler *) NULL)
1583 {
cristybb503372010-05-27 20:51:26 +00001584 size_t
cristy3ed852e2009-09-05 21:47:34 +00001585 signature;
1586
1587 signature=image_filter(image,argc,argv,exception);
1588 if (signature != MagickImageFilterSignature)
1589 {
1590 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1591 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,signature,
1592 MagickImageFilterSignature);
1593 return(MagickFalse);
1594 }
1595 }
1596 }
1597#endif
1598 return(MagickTrue);
1599}
1600#endif