blob: 091c10061f40e903d363c14e6aa6b54b2b32f7d9 [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
cristyd1df72d2010-06-29 02:17:03 +0000424 max_entries;
cristy3ed852e2009-09-05 21:47:34 +0000425
426 struct dirent
427 *buffer,
428 *entry;
429
cristy3ed852e2009-09-05 21:47:34 +0000430 /*
431 Locate all modules in the coder path.
432 */
433 TagToCoderModuleName("magick",filename);
cristyd1df72d2010-06-29 02:17:03 +0000434 status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
cristy3ed852e2009-09-05 21:47:34 +0000435 exception);
cristyd1df72d2010-06-29 02:17:03 +0000436 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000437 return((char **) NULL);
438 GetPathComponent(module_path,HeadPath,path);
439 max_entries=255;
440 modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
441 sizeof(*modules));
442 if (modules == (char **) NULL)
443 return((char **) NULL);
444 *modules=(char *) NULL;
445 directory=opendir(path);
446 if (directory == (DIR *) NULL)
447 {
448 modules=(char **) RelinquishMagickMemory(modules);
449 return((char **) NULL);
450 }
cristyd1df72d2010-06-29 02:17:03 +0000451 buffer=(struct dirent *) AcquireAlignedMemory(1,sizeof(*buffer)+
452 FILENAME_MAX+1);
cristy3ed852e2009-09-05 21:47:34 +0000453 if (buffer == (struct dirent *) NULL)
454 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
455 i=0;
456 while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
457 (entry != (struct dirent *) NULL))
458 {
459 status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
460 if (status == MagickFalse)
461 continue;
462 if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
463 continue;
cristybb503372010-05-27 20:51:26 +0000464 if (i >= (ssize_t) max_entries)
cristy3ed852e2009-09-05 21:47:34 +0000465 {
466 modules=(char **) NULL;
467 if (~max_entries > max_entries)
468 modules=(char **) ResizeQuantumMemory(modules,(size_t)
469 (max_entries << 1),sizeof(*modules));
470 max_entries<<=1;
471 if (modules == (char **) NULL)
472 break;
473 }
474 /*
475 Add new module name to list.
476 */
477 modules[i]=AcquireString((char *) NULL);
478 GetPathComponent(entry->d_name,BasePath,modules[i]);
479 LocaleUpper(modules[i]);
480 if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
481 {
482 (void) CopyMagickString(modules[i],modules[i]+10,MaxTextExtent);
483 modules[i][strlen(modules[i])-1]='\0';
484 }
485 i++;
486 }
487 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
488 (void) closedir(directory);
489 if (modules == (char **) NULL)
490 {
491 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
492 "MemoryAllocationFailed","`%s'",pattern);
493 return((char **) NULL);
494 }
495 qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
496 modules[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000497 *number_modules=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000498 return(modules);
499}
500
501/*
502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503% %
504% %
505% %
506% G e t M a g i c k M o d u l e P a t h %
507% %
508% %
509% %
510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511%
512% GetMagickModulePath() finds a module with the specified module type and
513% filename.
514%
515% The format of the GetMagickModulePath module is:
516%
517% MagickBooleanType GetMagickModulePath(const char *filename,
518% MagickModuleType module_type,char *path,ExceptionInfo *exception)
519%
520% A description of each parameter follows:
521%
522% o filename: the module file name.
523%
524% o module_type: the module type: MagickImageCoderModule or
525% MagickImageFilterModule.
526%
527% o path: the path associated with the filename.
528%
529% o exception: return any errors or warnings in this structure.
530%
531*/
532static MagickBooleanType GetMagickModulePath(const char *filename,
533 MagickModuleType module_type,char *path,ExceptionInfo *exception)
534{
535 char
536 *module_path;
537
538 assert(filename != (const char *) NULL);
539 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
540 assert(path != (char *) NULL);
541 assert(exception != (ExceptionInfo *) NULL);
542 (void) CopyMagickString(path,filename,MaxTextExtent);
543 module_path=(char *) NULL;
544 switch (module_type)
545 {
546 case MagickImageCoderModule:
547 default:
548 {
549 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
550 "Searching for coder module file \"%s\" ...",filename);
551 module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
552#if defined(MAGICKCORE_CODER_PATH)
553 if (module_path == (char *) NULL)
554 module_path=AcquireString(MAGICKCORE_CODER_PATH);
555#endif
556 break;
557 }
558 case MagickImageFilterModule:
559 {
560 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
561 "Searching for filter module file \"%s\" ...",filename);
562 module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
563#if defined(MAGICKCORE_FILTER_PATH)
564 if (module_path == (char *) NULL)
565 module_path=AcquireString(MAGICKCORE_FILTER_PATH);
566#endif
567 break;
568 }
569 }
570 if (module_path != (char *) NULL)
571 {
572 register char
573 *p,
574 *q;
575
576 for (p=module_path-1; p != (char *) NULL; )
577 {
578 (void) CopyMagickString(path,p+1,MaxTextExtent);
579 q=strchr(path,DirectoryListSeparator);
580 if (q != (char *) NULL)
581 *q='\0';
582 q=path+strlen(path)-1;
583 if ((q >= path) && (*q != *DirectorySeparator))
584 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
585 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
586 if (IsPathAccessible(path) != MagickFalse)
587 {
588 module_path=DestroyString(module_path);
589 return(MagickTrue);
590 }
591 p=strchr(p+1,DirectoryListSeparator);
592 }
593 module_path=DestroyString(module_path);
594 }
595#if defined(MAGICKCORE_INSTALLED_SUPPORT)
cristyd1df72d2010-06-29 02:17:03 +0000596 else
cristy3ed852e2009-09-05 21:47:34 +0000597#if defined(MAGICKCORE_CODER_PATH)
598 {
599 const char
600 *directory;
601
602 /*
603 Search hard coded paths.
604 */
605 switch (module_type)
606 {
607 case MagickImageCoderModule:
608 default:
609 {
610 directory=MAGICKCORE_CODER_PATH;
611 break;
612 }
613 case MagickImageFilterModule:
614 {
615 directory=MAGICKCORE_FILTER_PATH;
616 break;
617 }
618 }
619 (void) FormatMagickString(path,MaxTextExtent,"%s%s",directory,filename);
620 if (IsPathAccessible(path) == MagickFalse)
621 {
622 ThrowFileException(exception,ConfigureWarning,
623 "UnableToOpenModuleFile",path);
624 return(MagickFalse);
625 }
626 return(MagickTrue);
627 }
628#else
cristy0157aea2010-04-24 21:12:18 +0000629#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000630 {
631 const char
632 *registery_key;
633
634 unsigned char
635 *key_value;
636
637 /*
638 Locate path via registry key.
639 */
640 switch (module_type)
641 {
642 case MagickImageCoderModule:
643 default:
644 {
645 registery_key="CoderModulesPath";
646 break;
647 }
648 case MagickImageFilterModule:
649 {
650 registery_key="FilterModulesPath";
651 break;
652 }
653 }
654 key_value=NTRegistryKeyLookup(registery_key);
655 if (key_value == (unsigned char *) NULL)
656 {
657 ThrowMagickException(exception,GetMagickModule(),ConfigureError,
658 "RegistryKeyLookupFailed","`%s'",registery_key);
659 return(MagickFalse);
660 }
661 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",(char *) key_value,
662 DirectorySeparator,filename);
663 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
664 if (IsPathAccessible(path) == MagickFalse)
665 {
666 ThrowFileException(exception,ConfigureWarning,
667 "UnableToOpenModuleFile",path);
668 return(MagickFalse);
669 }
670 return(MagickTrue);
671 }
672#endif
673#endif
cristy0157aea2010-04-24 21:12:18 +0000674#if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
675# error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
cristy3ed852e2009-09-05 21:47:34 +0000676#endif
677#else
678 {
679 char
680 *home;
681
682 home=GetEnvironmentValue("MAGICK_HOME");
683 if (home != (char *) NULL)
684 {
685 /*
686 Search MAGICK_HOME.
687 */
688#if !defined(MAGICKCORE_POSIX_SUPPORT)
689 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",home,
690 DirectorySeparator,filename);
691#else
692 const char
693 *directory;
694
695 switch (module_type)
696 {
697 case MagickImageCoderModule:
698 default:
699 {
700 directory=MAGICKCORE_CODER_RELATIVE_PATH;
701 break;
702 }
703 case MagickImageFilterModule:
704 {
705 directory=MAGICKCORE_FILTER_RELATIVE_PATH;
706 break;
707 }
708 }
709 (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/%s",home,
710 directory,filename);
711#endif
712 home=DestroyString(home);
713 if (IsPathAccessible(path) != MagickFalse)
714 return(MagickTrue);
715 }
716 }
717 if (*GetClientPath() != '\0')
718 {
719 /*
720 Search based on executable directory.
721 */
722#if !defined(MAGICKCORE_POSIX_SUPPORT)
723 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
724 DirectorySeparator,filename);
725#else
726 char
727 prefix[MaxTextExtent];
728
729 const char
730 *directory;
731
732 switch (module_type)
733 {
734 case MagickImageCoderModule:
735 default:
736 {
737 directory="modules";
738 break;
739 }
740 case MagickImageFilterModule:
741 {
742 directory="filters";
743 break;
744 }
745 }
746 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
747 ChopPathComponents(prefix,1);
748 (void) FormatMagickString(path,MaxTextExtent,
749 "%s/lib/%s/modules-Q%d/%s/%s",prefix,MAGICKCORE_LIBRARY_RELATIVE_PATH,
750 MAGICKCORE_QUANTUM_DEPTH,directory,filename);
751#endif
752 if (IsPathAccessible(path) != MagickFalse)
753 return(MagickTrue);
754 }
cristy0157aea2010-04-24 21:12:18 +0000755#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000756 {
757 /*
758 Search module path.
759 */
760 if ((NTGetModulePath("CORE_RL_magick_.dll",path) != MagickFalse) ||
761 (NTGetModulePath("CORE_DB_magick_.dll",path) != MagickFalse) ||
762 (NTGetModulePath("Magick.dll",path) != MagickFalse))
763 {
764 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
765 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
766 if (IsPathAccessible(path) != MagickFalse)
767 return(MagickTrue);
768 }
769 }
770#endif
771 {
772 char
773 *home;
774
775 home=GetEnvironmentValue("HOME");
776 if (home == (char *) NULL)
777 home=GetEnvironmentValue("USERPROFILE");
778 if (home != (char *) NULL)
779 {
780 /*
781 Search $HOME/.magick.
782 */
783 (void) FormatMagickString(path,MaxTextExtent,"%s%s.magick%s%s",home,
784 DirectorySeparator,DirectorySeparator,filename);
785 home=DestroyString(home);
786 if (IsPathAccessible(path) != MagickFalse)
787 return(MagickTrue);
788 }
789 }
790 /*
791 Search current directory.
792 */
793 if (IsPathAccessible(path) != MagickFalse)
794 return(MagickTrue);
795 if (exception->severity < ConfigureError)
796 ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
797 path);
798 return(MagickFalse);
799#endif
800 return(MagickFalse);
801}
802
803/*
804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
805% %
806% %
807% %
cristy498543d2009-10-11 03:14:50 +0000808% 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 +0000809% %
810% %
811% %
812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813%
814% InitializeModuleList() initializes the module loader.
815%
816% The format of the InitializeModuleList() method is:
817%
818% InitializeModuleList(Exceptioninfo *exception)
819%
820% A description of each parameter follows.
821%
822% o exception: return any errors or warnings in this structure.
823%
824*/
825
826static void *DestroyModuleNode(void *module_info)
827{
828 ExceptionInfo
829 *exception;
830
831 register ModuleInfo
832 *p;
833
834 exception=AcquireExceptionInfo();
835 p=(ModuleInfo *) module_info;
836 if (UnregisterModule(p,exception) == MagickFalse)
837 CatchException(exception);
838 if (p->tag != (char *) NULL)
839 p->tag=DestroyString(p->tag);
840 if (p->path != (char *) NULL)
841 p->path=DestroyString(p->path);
842 exception=DestroyExceptionInfo(exception);
843 return(RelinquishMagickMemory(p));
844}
845
cristy498543d2009-10-11 03:14:50 +0000846MagickExport MagickBooleanType InitializeModuleList(
cristy3ed852e2009-09-05 21:47:34 +0000847 ExceptionInfo *magick_unused(exception))
848{
849 if ((module_list == (SplayTreeInfo *) NULL) &&
850 (instantiate_module == MagickFalse))
851 {
cristy4e1dff62009-10-25 20:36:03 +0000852 if (module_semaphore == (SemaphoreInfo *) NULL)
853 AcquireSemaphoreInfo(&module_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000854 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000855 if ((module_list == (SplayTreeInfo *) NULL) &&
856 (instantiate_module == MagickFalse))
857 {
858 MagickBooleanType
859 status;
860
861 ModuleInfo
862 *module_info;
863
864 module_list=NewSplayTree(CompareSplayTreeString,
865 (void *(*)(void *)) NULL,DestroyModuleNode);
866 if (module_list == (SplayTreeInfo *) NULL)
867 ThrowFatalException(ResourceLimitFatalError,
868 "MemoryAllocationFailed");
869 module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
870 module_info->stealth=MagickTrue;
871 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
872 if (status == MagickFalse)
873 ThrowFatalException(ResourceLimitFatalError,
874 "MemoryAllocationFailed");
875 if (lt_dlinit() != 0)
876 ThrowFatalException(ModuleFatalError,
877 "UnableToInitializeModuleLoader");
878 instantiate_module=MagickTrue;
879 }
cristyf84a1932010-01-03 18:00:18 +0000880 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000881 }
882 return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
883}
884
885/*
886%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887% %
888% %
889% %
cristy3ed852e2009-09-05 21:47:34 +0000890% I n v o k e D y n a m i c I m a g e F i l t e r %
891% %
892% %
893% %
894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895%
896% InvokeDynamicImageFilter() invokes a dynamic image filter.
897%
898% The format of the InvokeDynamicImageFilter module is:
899%
900% MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
901% const int argc,const char **argv,ExceptionInfo *exception)
902%
903% A description of each parameter follows:
904%
905% o tag: a character string that represents the name of the particular
906% module.
907%
908% o image: the image.
909%
910% o argc: a pointer to an integer describing the number of elements in the
911% argument vector.
912%
913% o argv: a pointer to a text array containing the command line arguments.
914%
915% o exception: return any errors or warnings in this structure.
916%
917*/
918MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
919 Image **images,const int argc,const char **argv,ExceptionInfo *exception)
920{
921 char
922 name[MaxTextExtent],
923 path[MaxTextExtent];
924
925 ImageFilterHandler
926 *image_filter;
927
cristyd1df72d2010-06-29 02:17:03 +0000928 MagickBooleanType
929 status;
930
cristy3ed852e2009-09-05 21:47:34 +0000931 ModuleHandle
932 handle;
933
934 PolicyRights
935 rights;
936
cristy3ed852e2009-09-05 21:47:34 +0000937 /*
938 Find the module.
939 */
940 assert(images != (Image **) NULL);
941 assert((*images)->signature == MagickSignature);
942 if ((*images)->debug != MagickFalse)
943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
944 (*images)->filename);
945#if !defined(MAGICKCORE_BUILD_MODULES)
946 {
947 MagickBooleanType
948 status;
949
950 status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
951 if (status != MagickFalse)
952 return(status);
953 }
954#endif
955 rights=ReadPolicyRights;
956 if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
957 {
cristya9197f62010-01-12 02:23:34 +0000958 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +0000959 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
960 "NotAuthorized","`%s'",tag);
961 return(MagickFalse);
962 }
963 TagToFilterModuleName(tag,name);
cristyd1df72d2010-06-29 02:17:03 +0000964 status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
965 if (status == MagickFalse)
966 {
967 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
968 "UnableToLoadModule","`%s': %s",name,path);
969 return(MagickFalse);
970 }
cristy3ed852e2009-09-05 21:47:34 +0000971 /*
972 Open the module.
973 */
974 handle=(ModuleHandle) lt_dlopen(path);
975 if (handle == (ModuleHandle) NULL)
976 {
977 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
978 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
979 return(MagickFalse);
980 }
981 /*
982 Locate the module.
983 */
984#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
985 (void) FormatMagickString(name,MaxTextExtent,"%sImage",tag);
986#else
987 (void) FormatMagickString(name,MaxTextExtent,"%s%sImage",
988 MAGICKCORE_NAMESPACE_PREFIX,tag);
989#endif
990 /*
991 Execute the module.
992 */
cristyfe12d6c2010-05-07 01:38:41 +0000993 ClearMagickException(exception);
cristy3ed852e2009-09-05 21:47:34 +0000994 image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
995 if (image_filter == (ImageFilterHandler *) NULL)
996 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
997 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
998 else
999 {
cristybb503372010-05-27 20:51:26 +00001000 size_t
cristy3ed852e2009-09-05 21:47:34 +00001001 signature;
1002
1003 if ((*images)->debug != MagickFalse)
1004 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1005 "Invoking \"%s\" dynamic image filter",tag);
1006 signature=image_filter(images,argc,argv,exception);
1007 if ((*images)->debug != MagickFalse)
1008 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1009 tag);
1010 if (signature != MagickImageFilterSignature)
cristyfe12d6c2010-05-07 01:38:41 +00001011 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
cristyf1d91242010-05-28 02:23:19 +00001012 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,
1013 (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
cristy3ed852e2009-09-05 21:47:34 +00001014 }
1015 /*
1016 Close the module.
1017 */
1018 if (lt_dlclose(handle) != 0)
cristyfe12d6c2010-05-07 01:38:41 +00001019 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1020 "UnableToCloseModule","`%s': %s",name,lt_dlerror());
1021 return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001022}
1023
1024/*
1025%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026% %
1027% %
1028% %
1029% L i s t M o d u l e I n f o %
1030% %
1031% %
1032% %
1033%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034%
1035% ListModuleInfo() lists the module info to a file.
1036%
1037% The format of the ListModuleInfo module is:
1038%
1039% MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1040%
1041% A description of each parameter follows.
1042%
1043% o file: An pointer to a FILE.
1044%
1045% o exception: return any errors or warnings in this structure.
1046%
1047*/
1048MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1049 ExceptionInfo *exception)
1050{
1051 const ModuleInfo
1052 **module_info;
1053
cristybb503372010-05-27 20:51:26 +00001054 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001055 i;
1056
cristybb503372010-05-27 20:51:26 +00001057 size_t
cristy3ed852e2009-09-05 21:47:34 +00001058 number_modules;
1059
1060 if (file == (const FILE *) NULL)
1061 file=stdout;
1062 module_info=GetModuleInfoList("*",&number_modules,exception);
1063 if (module_info == (const ModuleInfo **) NULL)
1064 return(MagickFalse);
1065 if (module_info[0]->path != (char *) NULL)
1066 {
1067 char
1068 path[MaxTextExtent];
1069
1070 GetPathComponent(module_info[0]->path,HeadPath,path);
1071 (void) fprintf(file,"\nPath: %s\n\n",path);
1072 }
1073 (void) fprintf(file,"Module\n");
1074 (void) fprintf(file,"-------------------------------------------------"
1075 "------------------------------\n");
cristybb503372010-05-27 20:51:26 +00001076 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001077 {
1078 if (module_info[i]->stealth != MagickFalse)
1079 continue;
1080 (void) fprintf(file,"%s",module_info[i]->tag);
1081 (void) fprintf(file,"\n");
1082 }
1083 (void) fflush(file);
1084 module_info=(const ModuleInfo **)
1085 RelinquishMagickMemory((void *) module_info);
1086 return(MagickTrue);
1087}
1088
1089/*
1090%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091% %
1092% %
1093% %
cristyf34a1452009-10-24 22:29:27 +00001094+ M o d u l e C o m p o n e n t G e n e s i s %
1095% %
1096% %
1097% %
1098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1099%
1100% ModuleComponentGenesis() instantiates the module component.
1101%
1102% The format of the ModuleComponentGenesis method is:
1103%
1104% MagickBooleanType ModuleComponentGenesis(void)
1105%
1106*/
1107MagickExport MagickBooleanType ModuleComponentGenesis(void)
1108{
1109 ExceptionInfo
1110 *exception;
1111
cristycee97112010-05-28 00:44:52 +00001112 MagickBooleanType
1113 status;
1114
cristy165b6092009-10-26 13:52:10 +00001115 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001116 exception=AcquireExceptionInfo();
cristycee97112010-05-28 00:44:52 +00001117 status=InitializeModuleList(exception);
cristyf34a1452009-10-24 22:29:27 +00001118 exception=DestroyExceptionInfo(exception);
cristycee97112010-05-28 00:44:52 +00001119 return(status);
cristyf34a1452009-10-24 22:29:27 +00001120}
1121
1122/*
1123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1124% %
1125% %
1126% %
1127+ M o d u l e C o m p o n e n t T e r m i n u s %
1128% %
1129% %
1130% %
1131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132%
1133% ModuleComponentTerminus() destroys the module component.
1134%
1135% The format of the ModuleComponentTerminus method is:
1136%
1137% ModuleComponentTerminus(void)
1138%
1139*/
1140MagickExport void ModuleComponentTerminus(void)
1141{
cristy18b17442009-10-25 18:36:48 +00001142 if (module_semaphore == (SemaphoreInfo *) NULL)
1143 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001144 DestroyModuleList();
1145 DestroySemaphoreInfo(&module_semaphore);
1146}
1147
1148/*
1149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1150% %
1151% %
1152% %
cristy3ed852e2009-09-05 21:47:34 +00001153% O p e n M o d u l e %
1154% %
1155% %
1156% %
1157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1158%
1159% OpenModule() loads a module, and invokes its registration module. It
1160% returns MagickTrue on success, and MagickFalse if there is an error.
1161%
1162% The format of the OpenModule module is:
1163%
1164% MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1165%
1166% A description of each parameter follows:
1167%
1168% o module: a character string that indicates the module to load.
1169%
1170% o exception: return any errors or warnings in this structure.
1171%
1172*/
1173MagickExport MagickBooleanType OpenModule(const char *module,
1174 ExceptionInfo *exception)
1175{
1176 char
1177 filename[MaxTextExtent],
1178 module_name[MaxTextExtent],
1179 name[MaxTextExtent],
1180 path[MaxTextExtent];
1181
cristyd1df72d2010-06-29 02:17:03 +00001182 MagickBooleanType
1183 status;
1184
cristy3ed852e2009-09-05 21:47:34 +00001185 ModuleHandle
1186 handle;
1187
1188 ModuleInfo
1189 *module_info;
1190
1191 register const CoderInfo
1192 *p;
1193
1194 size_t
cristy3ed852e2009-09-05 21:47:34 +00001195 signature;
1196
1197 /*
1198 Assign module name from alias.
1199 */
1200 assert(module != (const char *) NULL);
1201 module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1202 if (module_info != (ModuleInfo *) NULL)
1203 return(MagickTrue);
1204 (void) CopyMagickString(module_name,module,MaxTextExtent);
1205 p=GetCoderInfo(module,exception);
1206 if (p != (CoderInfo *) NULL)
1207 (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1208 if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1209 return(MagickTrue); /* module already opened, return */
1210 /*
1211 Locate module.
1212 */
1213 handle=(ModuleHandle) NULL;
1214 TagToCoderModuleName(module_name,filename);
1215 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1216 "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1217 *path='\0';
cristyd1df72d2010-06-29 02:17:03 +00001218 status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1219 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001220 return(MagickFalse);
1221 /*
1222 Load module
1223 */
1224 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1225 "Opening module at path \"%s\"",path);
1226 handle=(ModuleHandle) lt_dlopen(path);
1227 if (handle == (ModuleHandle) NULL)
1228 {
1229 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1230 "UnableToLoadModule","`%s': %s",path,lt_dlerror());
1231 return(MagickFalse);
1232 }
1233 /*
1234 Register module.
1235 */
1236 module_info=AcquireModuleInfo(path,module_name);
1237 module_info->handle=handle;
1238 if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1239 return(MagickFalse);
1240 /*
1241 Define RegisterFORMATImage method.
1242 */
1243 TagToModuleName(module_name,"Register%sImage",name);
cristybb503372010-05-27 20:51:26 +00001244 module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1245 if (module_info->register_module == (size_t (*)(void)) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001246 {
1247 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1248 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1249 return(MagickFalse);
1250 }
1251 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1252 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1253 (void *) module_info->register_module);
1254 /*
1255 Define UnregisterFORMATImage method.
1256 */
1257 TagToModuleName(module_name,"Unregister%sImage",name);
1258 module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1259 if (module_info->unregister_module == (void (*)(void)) NULL)
1260 {
1261 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1262 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1263 return(MagickFalse);
1264 }
1265 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1266 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1267 (void *) module_info->unregister_module);
1268 signature=module_info->register_module();
1269 if (signature != MagickImageCoderSignature)
1270 {
1271 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1272 "ImageCoderSignatureMismatch","`%s': %8lx != %8lx",module_name,
cristyf1d91242010-05-28 02:23:19 +00001273 (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
cristy3ed852e2009-09-05 21:47:34 +00001274 return(MagickFalse);
1275 }
1276 return(MagickTrue);
1277}
1278
1279/*
1280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1281% %
1282% %
1283% %
1284% O p e n M o d u l e s %
1285% %
1286% %
1287% %
1288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1289%
1290% OpenModules() loads all available modules.
1291%
1292% The format of the OpenModules module is:
1293%
1294% MagickBooleanType OpenModules(ExceptionInfo *exception)
1295%
1296% A description of each parameter follows:
1297%
1298% o exception: return any errors or warnings in this structure.
1299%
1300*/
1301MagickExport MagickBooleanType OpenModules(ExceptionInfo *exception)
1302{
1303 char
1304 **modules;
1305
cristybb503372010-05-27 20:51:26 +00001306 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001307 i;
1308
cristybb503372010-05-27 20:51:26 +00001309 size_t
cristy3ed852e2009-09-05 21:47:34 +00001310 number_modules;
1311
1312 /*
1313 Load all modules.
1314 */
1315 (void) GetMagickInfo((char *) NULL,exception);
1316 number_modules=0;
1317 modules=GetModuleList("*",&number_modules,exception);
1318 if (modules == (char **) NULL)
1319 return(MagickFalse);
cristybb503372010-05-27 20:51:26 +00001320 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001321 (void) OpenModule(modules[i],exception);
1322 /*
1323 Relinquish resources.
1324 */
cristybb503372010-05-27 20:51:26 +00001325 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001326 modules[i]=DestroyString(modules[i]);
1327 modules=(char **) RelinquishMagickMemory(modules);
1328 return(MagickTrue);
1329}
1330
1331/*
1332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1333% %
1334% %
1335% %
1336% R e g i s t e r M o d u l e %
1337% %
1338% %
1339% %
1340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341%
1342% RegisterModule() adds an entry to the module list. It returns a pointer to
1343% the registered entry on success.
1344%
1345% The format of the RegisterModule module is:
1346%
1347% ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1348% ExceptionInfo *exception)
1349%
1350% A description of each parameter follows:
1351%
1352% o info: a pointer to the registered entry is returned.
1353%
1354% o module_info: a pointer to the ModuleInfo structure to register.
1355%
1356% o exception: return any errors or warnings in this structure.
1357%
1358*/
1359static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1360 ExceptionInfo *exception)
1361{
1362 MagickBooleanType
1363 status;
1364
1365 assert(module_info != (ModuleInfo *) NULL);
1366 assert(module_info->signature == MagickSignature);
1367 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1368 if (module_list == (SplayTreeInfo *) NULL)
1369 return((const ModuleInfo *) NULL);
1370 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1371 if (status == MagickFalse)
1372 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1373 "MemoryAllocationFailed","`%s'",module_info->tag);
1374 return(module_info);
1375}
1376
1377/*
1378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379% %
1380% %
1381% %
1382% T a g T o C o d e r M o d u l e N a m e %
1383% %
1384% %
1385% %
1386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387%
1388% TagToCoderModuleName() munges a module tag and obtains the filename of the
1389% corresponding module.
1390%
1391% The format of the TagToCoderModuleName module is:
1392%
1393% char *TagToCoderModuleName(const char *tag,char *name)
1394%
1395% A description of each parameter follows:
1396%
1397% o tag: a character string representing the module tag.
1398%
1399% o name: return the module name here.
1400%
1401*/
1402static void TagToCoderModuleName(const char *tag,char *name)
1403{
1404 assert(tag != (char *) NULL);
1405 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1406 assert(name != (char *) NULL);
1407#if defined(MAGICKCORE_LTDL_DELEGATE)
1408 (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
1409 (void) LocaleLower(name);
1410#else
cristy0157aea2010-04-24 21:12:18 +00001411#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001412 if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1413 (void) CopyMagickString(name,tag,MaxTextExtent);
1414 else
1415 {
1416#if defined(_DEBUG)
1417 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
1418#else
1419 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
1420#endif
1421 }
1422#endif
1423#endif
1424}
1425
1426/*
1427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428% %
1429% %
1430% %
1431% T a g T o F i l t e r M o d u l e N a m e %
1432% %
1433% %
1434% %
1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436%
1437% TagToFilterModuleName() munges a module tag and returns the filename of the
1438% corresponding filter module.
1439%
1440% The format of the TagToFilterModuleName module is:
1441%
1442% void TagToFilterModuleName(const char *tag,char name)
1443%
1444% A description of each parameter follows:
1445%
1446% o tag: a character string representing the module tag.
1447%
1448% o name: return the filter name here.
1449%
1450*/
1451static void TagToFilterModuleName(const char *tag,char *name)
1452{
1453 assert(tag != (char *) NULL);
1454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1455 assert(name != (char *) NULL);
1456#if !defined(MAGICKCORE_LTDL_DELEGATE)
1457 (void) FormatMagickString(name,MaxTextExtent,"%s.dll",tag);
1458#else
1459 (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
cristy3ed852e2009-09-05 21:47:34 +00001460#endif
1461}
1462
1463/*
1464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465% %
1466% %
1467% %
1468% T a g T o M o d u l e N a m e %
1469% %
1470% %
1471% %
1472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473%
1474% TagToModuleName() munges the module tag name and returns an upper-case tag
1475% name as the input string, and a user-provided format.
1476%
1477% The format of the TagToModuleName module is:
1478%
1479% TagToModuleName(const char *tag,const char *format,char *module)
1480%
1481% A description of each parameter follows:
1482%
1483% o tag: the module tag.
1484%
1485% o format: a sprintf-compatible format string containing %s where the
1486% upper-case tag name is to be inserted.
1487%
1488% o module: pointer to a destination buffer for the formatted result.
1489%
1490*/
1491static void TagToModuleName(const char *tag,const char *format,char *module)
1492{
1493 char
1494 name[MaxTextExtent];
1495
1496 assert(tag != (const char *) NULL);
1497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1498 assert(format != (const char *) NULL);
1499 assert(module != (char *) NULL);
1500 (void) CopyMagickString(name,tag,MaxTextExtent);
1501 LocaleUpper(name);
1502#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1503 (void) FormatMagickString(module,MaxTextExtent,format,name);
1504#else
1505 {
1506 char
1507 prefix_format[MaxTextExtent];
1508
1509 (void) FormatMagickString(prefix_format,MaxTextExtent,"%s%s",
1510 MAGICKCORE_NAMESPACE_PREFIX,format);
1511 (void) FormatMagickString(module,MaxTextExtent,prefix_format,name);
1512 }
1513#endif
1514}
1515
1516/*
1517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1518% %
1519% %
1520% %
1521% U n r e g i s t e r M o d u l e %
1522% %
1523% %
1524% %
1525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1526%
1527% UnregisterModule() unloads a module, and invokes its de-registration module.
1528% Returns MagickTrue on success, and MagickFalse if there is an error.
1529%
1530% The format of the UnregisterModule module is:
1531%
1532% MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1533% ExceptionInfo *exception)
1534%
1535% A description of each parameter follows:
1536%
1537% o module_info: the module info.
1538%
1539% o exception: return any errors or warnings in this structure.
1540%
1541*/
1542static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1543 ExceptionInfo *exception)
1544{
1545 /*
1546 Locate and execute UnregisterFORMATImage module.
1547 */
1548 assert(module_info != (const ModuleInfo *) NULL);
1549 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1550 assert(exception != (ExceptionInfo *) NULL);
1551 if (module_info->unregister_module == NULL)
1552 return(MagickTrue);
1553 module_info->unregister_module();
1554 if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1555 {
1556 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1557 "UnableToCloseModule","`%s': %s",module_info->tag,lt_dlerror());
1558 return(MagickFalse);
1559 }
1560 return(MagickTrue);
1561}
1562#else
1563MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1564 ExceptionInfo *magick_unused(exception))
1565{
1566 return(MagickTrue);
1567}
1568
1569MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1570 Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1571{
1572#if !defined(MAGICKCORE_BUILD_MODULES)
1573 {
cristybb503372010-05-27 20:51:26 +00001574 extern size_t
cristya0b81c32010-01-22 02:54:33 +00001575 analyzeImage(Image **,const int,const char **,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +00001576
1577 ImageFilterHandler
1578 *image_filter;
1579
1580 image_filter=(ImageFilterHandler *) NULL;
1581 if (LocaleCompare("analyze",tag) == 0)
1582 image_filter=analyzeImage;
cristy3ed852e2009-09-05 21:47:34 +00001583 if (image_filter != (ImageFilterHandler *) NULL)
1584 {
cristybb503372010-05-27 20:51:26 +00001585 size_t
cristy3ed852e2009-09-05 21:47:34 +00001586 signature;
1587
1588 signature=image_filter(image,argc,argv,exception);
1589 if (signature != MagickImageFilterSignature)
1590 {
1591 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1592 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,signature,
1593 MagickImageFilterSignature);
1594 return(MagickFalse);
1595 }
1596 }
1597 }
1598#endif
1599 return(MagickTrue);
1600}
1601#endif