blob: d441c8c5b86ac85f6add96b839b1b332b9b661e1 [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
cristy73bd4a52010-10-05 11:24:23 +0000141 module_info=(ModuleInfo *) AcquireMagickMemory(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%
cristya6de29a2010-06-30 14:34:26 +0000359% char **GetModuleList(const char *pattern,const MagickModuleType type,
360% size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000361%
362% A description of each parameter follows:
363%
364% o pattern: Specifies a pointer to a text string containing a pattern.
365%
cristya6de29a2010-06-30 14:34:26 +0000366% o type: choose from MagickImageCoderModule or MagickImageFilterModule.
367%
cristy3ed852e2009-09-05 21:47:34 +0000368% o number_modules: This integer returns the number of modules in the
369% list.
370%
371% o exception: return any errors or warnings in this structure.
372%
373*/
374
375#if defined(__cplusplus) || defined(c_plusplus)
376extern "C" {
377#endif
378
379static int ModuleCompare(const void *x,const void *y)
380{
381 register const char
382 **p,
383 **q;
384
385 p=(const char **) x;
386 q=(const char **) y;
387 return(LocaleCompare(*p,*q));
388}
389
390#if defined(__cplusplus) || defined(c_plusplus)
391}
392#endif
393
394static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
395 struct dirent **result)
396{
397#if defined(MAGICKCORE_HAVE_READDIR_R)
398 return(readdir_r(directory,entry,result));
399#else
400 (void) entry;
401 errno=0;
402 *result=readdir(directory);
403 return(errno);
404#endif
405}
406
407MagickExport char **GetModuleList(const char *pattern,
cristya6de29a2010-06-30 14:34:26 +0000408 const MagickModuleType type,size_t *number_modules,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000409{
410 char
411 **modules,
412 filename[MaxTextExtent],
413 module_path[MaxTextExtent],
414 path[MaxTextExtent];
415
416 DIR
417 *directory;
418
419 MagickBooleanType
420 status;
421
cristybb503372010-05-27 20:51:26 +0000422 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000423 i;
424
425 size_t
cristyd1df72d2010-06-29 02:17:03 +0000426 max_entries;
cristy3ed852e2009-09-05 21:47:34 +0000427
428 struct dirent
429 *buffer,
430 *entry;
431
cristy3ed852e2009-09-05 21:47:34 +0000432 /*
cristya6de29a2010-06-30 14:34:26 +0000433 Locate all modules in the image coder or filter path.
cristy3ed852e2009-09-05 21:47:34 +0000434 */
cristya6de29a2010-06-30 14:34:26 +0000435 switch (type)
436 {
437 case MagickImageCoderModule:
438 default:
439 {
440 TagToCoderModuleName("magick",filename);
441 status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
442 exception);
443 break;
444 }
445 case MagickImageFilterModule:
446 {
447 TagToFilterModuleName("analyze",filename);
448 status=GetMagickModulePath(filename,MagickImageFilterModule,module_path,
449 exception);
450 break;
451 }
452 }
cristyd1df72d2010-06-29 02:17:03 +0000453 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000454 return((char **) NULL);
455 GetPathComponent(module_path,HeadPath,path);
456 max_entries=255;
457 modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
458 sizeof(*modules));
459 if (modules == (char **) NULL)
460 return((char **) NULL);
461 *modules=(char *) NULL;
462 directory=opendir(path);
463 if (directory == (DIR *) NULL)
464 {
465 modules=(char **) RelinquishMagickMemory(modules);
466 return((char **) NULL);
467 }
cristy73bd4a52010-10-05 11:24:23 +0000468 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
cristyd1df72d2010-06-29 02:17:03 +0000469 FILENAME_MAX+1);
cristy3ed852e2009-09-05 21:47:34 +0000470 if (buffer == (struct dirent *) NULL)
471 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
472 i=0;
473 while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
474 (entry != (struct dirent *) NULL))
475 {
476 status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
477 if (status == MagickFalse)
478 continue;
479 if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
480 continue;
cristybb503372010-05-27 20:51:26 +0000481 if (i >= (ssize_t) max_entries)
cristy3ed852e2009-09-05 21:47:34 +0000482 {
483 modules=(char **) NULL;
484 if (~max_entries > max_entries)
485 modules=(char **) ResizeQuantumMemory(modules,(size_t)
486 (max_entries << 1),sizeof(*modules));
487 max_entries<<=1;
488 if (modules == (char **) NULL)
489 break;
490 }
491 /*
492 Add new module name to list.
493 */
494 modules[i]=AcquireString((char *) NULL);
495 GetPathComponent(entry->d_name,BasePath,modules[i]);
cristy3ed852e2009-09-05 21:47:34 +0000496 if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
497 {
498 (void) CopyMagickString(modules[i],modules[i]+10,MaxTextExtent);
499 modules[i][strlen(modules[i])-1]='\0';
500 }
501 i++;
502 }
503 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
504 (void) closedir(directory);
505 if (modules == (char **) NULL)
506 {
507 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
508 "MemoryAllocationFailed","`%s'",pattern);
509 return((char **) NULL);
510 }
511 qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
512 modules[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000513 *number_modules=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000514 return(modules);
515}
516
517/*
518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519% %
520% %
521% %
522% G e t M a g i c k M o d u l e P a t h %
523% %
524% %
525% %
526%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527%
528% GetMagickModulePath() finds a module with the specified module type and
529% filename.
530%
531% The format of the GetMagickModulePath module is:
532%
533% MagickBooleanType GetMagickModulePath(const char *filename,
534% MagickModuleType module_type,char *path,ExceptionInfo *exception)
535%
536% A description of each parameter follows:
537%
538% o filename: the module file name.
539%
540% o module_type: the module type: MagickImageCoderModule or
541% MagickImageFilterModule.
542%
543% o path: the path associated with the filename.
544%
545% o exception: return any errors or warnings in this structure.
546%
547*/
548static MagickBooleanType GetMagickModulePath(const char *filename,
549 MagickModuleType module_type,char *path,ExceptionInfo *exception)
550{
551 char
552 *module_path;
553
554 assert(filename != (const char *) NULL);
555 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
556 assert(path != (char *) NULL);
557 assert(exception != (ExceptionInfo *) NULL);
558 (void) CopyMagickString(path,filename,MaxTextExtent);
559 module_path=(char *) NULL;
560 switch (module_type)
561 {
562 case MagickImageCoderModule:
563 default:
564 {
565 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
566 "Searching for coder module file \"%s\" ...",filename);
567 module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
568#if defined(MAGICKCORE_CODER_PATH)
569 if (module_path == (char *) NULL)
570 module_path=AcquireString(MAGICKCORE_CODER_PATH);
571#endif
572 break;
573 }
574 case MagickImageFilterModule:
575 {
576 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
577 "Searching for filter module file \"%s\" ...",filename);
578 module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
579#if defined(MAGICKCORE_FILTER_PATH)
580 if (module_path == (char *) NULL)
581 module_path=AcquireString(MAGICKCORE_FILTER_PATH);
582#endif
583 break;
584 }
585 }
586 if (module_path != (char *) NULL)
587 {
588 register char
589 *p,
590 *q;
591
592 for (p=module_path-1; p != (char *) NULL; )
593 {
594 (void) CopyMagickString(path,p+1,MaxTextExtent);
595 q=strchr(path,DirectoryListSeparator);
596 if (q != (char *) NULL)
597 *q='\0';
598 q=path+strlen(path)-1;
599 if ((q >= path) && (*q != *DirectorySeparator))
600 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
601 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
602 if (IsPathAccessible(path) != MagickFalse)
603 {
604 module_path=DestroyString(module_path);
605 return(MagickTrue);
606 }
607 p=strchr(p+1,DirectoryListSeparator);
608 }
609 module_path=DestroyString(module_path);
610 }
611#if defined(MAGICKCORE_INSTALLED_SUPPORT)
cristyd1df72d2010-06-29 02:17:03 +0000612 else
cristy3ed852e2009-09-05 21:47:34 +0000613#if defined(MAGICKCORE_CODER_PATH)
614 {
615 const char
616 *directory;
617
618 /*
619 Search hard coded paths.
620 */
621 switch (module_type)
622 {
623 case MagickImageCoderModule:
624 default:
625 {
626 directory=MAGICKCORE_CODER_PATH;
627 break;
628 }
629 case MagickImageFilterModule:
630 {
631 directory=MAGICKCORE_FILTER_PATH;
632 break;
633 }
634 }
635 (void) FormatMagickString(path,MaxTextExtent,"%s%s",directory,filename);
636 if (IsPathAccessible(path) == MagickFalse)
637 {
638 ThrowFileException(exception,ConfigureWarning,
639 "UnableToOpenModuleFile",path);
640 return(MagickFalse);
641 }
642 return(MagickTrue);
643 }
644#else
cristy0157aea2010-04-24 21:12:18 +0000645#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000646 {
647 const char
648 *registery_key;
649
650 unsigned char
651 *key_value;
652
653 /*
654 Locate path via registry key.
655 */
656 switch (module_type)
657 {
658 case MagickImageCoderModule:
659 default:
660 {
661 registery_key="CoderModulesPath";
662 break;
663 }
664 case MagickImageFilterModule:
665 {
666 registery_key="FilterModulesPath";
667 break;
668 }
669 }
670 key_value=NTRegistryKeyLookup(registery_key);
671 if (key_value == (unsigned char *) NULL)
672 {
673 ThrowMagickException(exception,GetMagickModule(),ConfigureError,
674 "RegistryKeyLookupFailed","`%s'",registery_key);
675 return(MagickFalse);
676 }
677 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",(char *) key_value,
678 DirectorySeparator,filename);
679 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
680 if (IsPathAccessible(path) == MagickFalse)
681 {
682 ThrowFileException(exception,ConfigureWarning,
683 "UnableToOpenModuleFile",path);
684 return(MagickFalse);
685 }
686 return(MagickTrue);
687 }
688#endif
689#endif
cristy0157aea2010-04-24 21:12:18 +0000690#if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
691# error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
cristy3ed852e2009-09-05 21:47:34 +0000692#endif
693#else
694 {
695 char
696 *home;
697
698 home=GetEnvironmentValue("MAGICK_HOME");
699 if (home != (char *) NULL)
700 {
701 /*
702 Search MAGICK_HOME.
703 */
704#if !defined(MAGICKCORE_POSIX_SUPPORT)
705 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",home,
706 DirectorySeparator,filename);
707#else
708 const char
709 *directory;
710
711 switch (module_type)
712 {
713 case MagickImageCoderModule:
714 default:
715 {
716 directory=MAGICKCORE_CODER_RELATIVE_PATH;
717 break;
718 }
719 case MagickImageFilterModule:
720 {
721 directory=MAGICKCORE_FILTER_RELATIVE_PATH;
722 break;
723 }
724 }
725 (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/%s",home,
726 directory,filename);
727#endif
728 home=DestroyString(home);
729 if (IsPathAccessible(path) != MagickFalse)
730 return(MagickTrue);
731 }
732 }
733 if (*GetClientPath() != '\0')
734 {
735 /*
736 Search based on executable directory.
737 */
738#if !defined(MAGICKCORE_POSIX_SUPPORT)
739 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
740 DirectorySeparator,filename);
741#else
742 char
743 prefix[MaxTextExtent];
744
745 const char
746 *directory;
747
748 switch (module_type)
749 {
750 case MagickImageCoderModule:
751 default:
752 {
753 directory="modules";
754 break;
755 }
756 case MagickImageFilterModule:
757 {
758 directory="filters";
759 break;
760 }
761 }
762 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
763 ChopPathComponents(prefix,1);
764 (void) FormatMagickString(path,MaxTextExtent,
765 "%s/lib/%s/modules-Q%d/%s/%s",prefix,MAGICKCORE_LIBRARY_RELATIVE_PATH,
766 MAGICKCORE_QUANTUM_DEPTH,directory,filename);
767#endif
768 if (IsPathAccessible(path) != MagickFalse)
769 return(MagickTrue);
770 }
cristy0157aea2010-04-24 21:12:18 +0000771#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000772 {
773 /*
774 Search module path.
775 */
776 if ((NTGetModulePath("CORE_RL_magick_.dll",path) != MagickFalse) ||
777 (NTGetModulePath("CORE_DB_magick_.dll",path) != MagickFalse) ||
778 (NTGetModulePath("Magick.dll",path) != MagickFalse))
779 {
780 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
781 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
782 if (IsPathAccessible(path) != MagickFalse)
783 return(MagickTrue);
784 }
785 }
786#endif
787 {
788 char
789 *home;
790
791 home=GetEnvironmentValue("HOME");
792 if (home == (char *) NULL)
793 home=GetEnvironmentValue("USERPROFILE");
794 if (home != (char *) NULL)
795 {
796 /*
797 Search $HOME/.magick.
798 */
799 (void) FormatMagickString(path,MaxTextExtent,"%s%s.magick%s%s",home,
800 DirectorySeparator,DirectorySeparator,filename);
801 home=DestroyString(home);
802 if (IsPathAccessible(path) != MagickFalse)
803 return(MagickTrue);
804 }
805 }
806 /*
807 Search current directory.
808 */
809 if (IsPathAccessible(path) != MagickFalse)
810 return(MagickTrue);
811 if (exception->severity < ConfigureError)
812 ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
813 path);
814 return(MagickFalse);
815#endif
816 return(MagickFalse);
817}
818
819/*
820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821% %
822% %
823% %
cristy498543d2009-10-11 03:14:50 +0000824% 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 +0000825% %
826% %
827% %
828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829%
830% InitializeModuleList() initializes the module loader.
831%
832% The format of the InitializeModuleList() method is:
833%
834% InitializeModuleList(Exceptioninfo *exception)
835%
836% A description of each parameter follows.
837%
838% o exception: return any errors or warnings in this structure.
839%
840*/
841
842static void *DestroyModuleNode(void *module_info)
843{
844 ExceptionInfo
845 *exception;
846
847 register ModuleInfo
848 *p;
849
850 exception=AcquireExceptionInfo();
851 p=(ModuleInfo *) module_info;
852 if (UnregisterModule(p,exception) == MagickFalse)
853 CatchException(exception);
854 if (p->tag != (char *) NULL)
855 p->tag=DestroyString(p->tag);
856 if (p->path != (char *) NULL)
857 p->path=DestroyString(p->path);
858 exception=DestroyExceptionInfo(exception);
859 return(RelinquishMagickMemory(p));
860}
861
cristy498543d2009-10-11 03:14:50 +0000862MagickExport MagickBooleanType InitializeModuleList(
cristy3ed852e2009-09-05 21:47:34 +0000863 ExceptionInfo *magick_unused(exception))
864{
865 if ((module_list == (SplayTreeInfo *) NULL) &&
866 (instantiate_module == MagickFalse))
867 {
cristy4e1dff62009-10-25 20:36:03 +0000868 if (module_semaphore == (SemaphoreInfo *) NULL)
869 AcquireSemaphoreInfo(&module_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000870 LockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000871 if ((module_list == (SplayTreeInfo *) NULL) &&
872 (instantiate_module == MagickFalse))
873 {
874 MagickBooleanType
875 status;
876
877 ModuleInfo
878 *module_info;
879
880 module_list=NewSplayTree(CompareSplayTreeString,
881 (void *(*)(void *)) NULL,DestroyModuleNode);
882 if (module_list == (SplayTreeInfo *) NULL)
883 ThrowFatalException(ResourceLimitFatalError,
884 "MemoryAllocationFailed");
885 module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
886 module_info->stealth=MagickTrue;
887 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
888 if (status == MagickFalse)
889 ThrowFatalException(ResourceLimitFatalError,
890 "MemoryAllocationFailed");
891 if (lt_dlinit() != 0)
892 ThrowFatalException(ModuleFatalError,
893 "UnableToInitializeModuleLoader");
894 instantiate_module=MagickTrue;
895 }
cristyf84a1932010-01-03 18:00:18 +0000896 UnlockSemaphoreInfo(module_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000897 }
898 return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
899}
900
901/*
902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903% %
904% %
905% %
cristy3ed852e2009-09-05 21:47:34 +0000906% I n v o k e D y n a m i c I m a g e F i l t e r %
907% %
908% %
909% %
910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
911%
912% InvokeDynamicImageFilter() invokes a dynamic image filter.
913%
914% The format of the InvokeDynamicImageFilter module is:
915%
916% MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
917% const int argc,const char **argv,ExceptionInfo *exception)
918%
919% A description of each parameter follows:
920%
921% o tag: a character string that represents the name of the particular
922% module.
923%
924% o image: the image.
925%
926% o argc: a pointer to an integer describing the number of elements in the
927% argument vector.
928%
929% o argv: a pointer to a text array containing the command line arguments.
930%
931% o exception: return any errors or warnings in this structure.
932%
933*/
934MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
935 Image **images,const int argc,const char **argv,ExceptionInfo *exception)
936{
937 char
938 name[MaxTextExtent],
939 path[MaxTextExtent];
940
941 ImageFilterHandler
942 *image_filter;
943
cristyd1df72d2010-06-29 02:17:03 +0000944 MagickBooleanType
945 status;
946
cristy3ed852e2009-09-05 21:47:34 +0000947 ModuleHandle
948 handle;
949
950 PolicyRights
951 rights;
952
cristy3ed852e2009-09-05 21:47:34 +0000953 /*
954 Find the module.
955 */
956 assert(images != (Image **) NULL);
957 assert((*images)->signature == MagickSignature);
958 if ((*images)->debug != MagickFalse)
959 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
960 (*images)->filename);
961#if !defined(MAGICKCORE_BUILD_MODULES)
962 {
963 MagickBooleanType
964 status;
965
966 status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
967 if (status != MagickFalse)
968 return(status);
969 }
970#endif
971 rights=ReadPolicyRights;
972 if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
973 {
cristya9197f62010-01-12 02:23:34 +0000974 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +0000975 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
976 "NotAuthorized","`%s'",tag);
977 return(MagickFalse);
978 }
979 TagToFilterModuleName(tag,name);
cristyd1df72d2010-06-29 02:17:03 +0000980 status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
981 if (status == MagickFalse)
982 {
983 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
984 "UnableToLoadModule","`%s': %s",name,path);
985 return(MagickFalse);
986 }
cristy3ed852e2009-09-05 21:47:34 +0000987 /*
988 Open the module.
989 */
990 handle=(ModuleHandle) lt_dlopen(path);
991 if (handle == (ModuleHandle) NULL)
992 {
993 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
994 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
995 return(MagickFalse);
996 }
997 /*
998 Locate the module.
999 */
1000#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1001 (void) FormatMagickString(name,MaxTextExtent,"%sImage",tag);
1002#else
1003 (void) FormatMagickString(name,MaxTextExtent,"%s%sImage",
1004 MAGICKCORE_NAMESPACE_PREFIX,tag);
1005#endif
1006 /*
1007 Execute the module.
1008 */
cristyfe12d6c2010-05-07 01:38:41 +00001009 ClearMagickException(exception);
cristy3ed852e2009-09-05 21:47:34 +00001010 image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
1011 if (image_filter == (ImageFilterHandler *) NULL)
1012 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1013 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
1014 else
1015 {
cristybb503372010-05-27 20:51:26 +00001016 size_t
cristy3ed852e2009-09-05 21:47:34 +00001017 signature;
1018
1019 if ((*images)->debug != MagickFalse)
1020 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1021 "Invoking \"%s\" dynamic image filter",tag);
1022 signature=image_filter(images,argc,argv,exception);
1023 if ((*images)->debug != MagickFalse)
1024 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1025 tag);
1026 if (signature != MagickImageFilterSignature)
cristyfe12d6c2010-05-07 01:38:41 +00001027 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
cristyf1d91242010-05-28 02:23:19 +00001028 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,
1029 (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
cristy3ed852e2009-09-05 21:47:34 +00001030 }
1031 /*
1032 Close the module.
1033 */
1034 if (lt_dlclose(handle) != 0)
cristyfe12d6c2010-05-07 01:38:41 +00001035 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1036 "UnableToCloseModule","`%s': %s",name,lt_dlerror());
1037 return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001038}
1039
1040/*
1041%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1042% %
1043% %
1044% %
1045% L i s t M o d u l e I n f o %
1046% %
1047% %
1048% %
1049%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1050%
1051% ListModuleInfo() lists the module info to a file.
1052%
1053% The format of the ListModuleInfo module is:
1054%
1055% MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1056%
1057% A description of each parameter follows.
1058%
1059% o file: An pointer to a FILE.
1060%
1061% o exception: return any errors or warnings in this structure.
1062%
1063*/
1064MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1065 ExceptionInfo *exception)
1066{
cristya6de29a2010-06-30 14:34:26 +00001067 char
1068 filename[MaxTextExtent],
1069 module_path[MaxTextExtent],
1070 **modules,
1071 path[MaxTextExtent];
cristy3ed852e2009-09-05 21:47:34 +00001072
cristybb503372010-05-27 20:51:26 +00001073 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001074 i;
1075
cristybb503372010-05-27 20:51:26 +00001076 size_t
cristy3ed852e2009-09-05 21:47:34 +00001077 number_modules;
1078
1079 if (file == (const FILE *) NULL)
1080 file=stdout;
cristya6de29a2010-06-30 14:34:26 +00001081 /*
1082 List image coders.
1083 */
1084 modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1085 if (modules == (char **) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001086 return(MagickFalse);
cristya6de29a2010-06-30 14:34:26 +00001087 TagToCoderModuleName("magick",filename);
1088 (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
1089 exception);
1090 GetPathComponent(module_path,HeadPath,path);
1091 (void) fprintf(file,"\nPath: %s\n\n",path);
1092 (void) fprintf(file,"Image Coder\n");
cristy3ed852e2009-09-05 21:47:34 +00001093 (void) fprintf(file,"-------------------------------------------------"
1094 "------------------------------\n");
cristybb503372010-05-27 20:51:26 +00001095 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001096 {
cristya6de29a2010-06-30 14:34:26 +00001097 (void) fprintf(file,"%s",modules[i]);
cristy3ed852e2009-09-05 21:47:34 +00001098 (void) fprintf(file,"\n");
1099 }
1100 (void) fflush(file);
cristya6de29a2010-06-30 14:34:26 +00001101 /*
1102 Relinquish resources.
1103 */
1104 for (i=0; i < (ssize_t) number_modules; i++)
1105 modules[i]=DestroyString(modules[i]);
1106 modules=(char **) RelinquishMagickMemory(modules);
1107 /*
1108 List image filters.
1109 */
1110 modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
1111 if (modules == (char **) NULL)
1112 return(MagickFalse);
1113 TagToFilterModuleName("analyze",filename);
1114 (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
1115 exception);
1116 GetPathComponent(module_path,HeadPath,path);
1117 (void) fprintf(file,"\nPath: %s\n\n",path);
1118 (void) fprintf(file,"Image Filter\n");
1119 (void) fprintf(file,"-------------------------------------------------"
1120 "------------------------------\n");
1121 for (i=0; i < (ssize_t) number_modules; i++)
1122 {
1123 (void) fprintf(file,"%s",modules[i]);
1124 (void) fprintf(file,"\n");
1125 }
1126 (void) fflush(file);
1127 /*
1128 Relinquish resources.
1129 */
1130 for (i=0; i < (ssize_t) number_modules; i++)
1131 modules[i]=DestroyString(modules[i]);
1132 modules=(char **) RelinquishMagickMemory(modules);
cristy3ed852e2009-09-05 21:47:34 +00001133 return(MagickTrue);
1134}
1135
1136/*
1137%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1138% %
1139% %
1140% %
cristyf34a1452009-10-24 22:29:27 +00001141+ M o d u l e C o m p o n e n t G e n e s i s %
1142% %
1143% %
1144% %
1145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1146%
1147% ModuleComponentGenesis() instantiates the module component.
1148%
1149% The format of the ModuleComponentGenesis method is:
1150%
1151% MagickBooleanType ModuleComponentGenesis(void)
1152%
1153*/
1154MagickExport MagickBooleanType ModuleComponentGenesis(void)
1155{
1156 ExceptionInfo
1157 *exception;
1158
cristycee97112010-05-28 00:44:52 +00001159 MagickBooleanType
1160 status;
1161
cristy165b6092009-10-26 13:52:10 +00001162 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001163 exception=AcquireExceptionInfo();
cristycee97112010-05-28 00:44:52 +00001164 status=InitializeModuleList(exception);
cristyf34a1452009-10-24 22:29:27 +00001165 exception=DestroyExceptionInfo(exception);
cristycee97112010-05-28 00:44:52 +00001166 return(status);
cristyf34a1452009-10-24 22:29:27 +00001167}
1168
1169/*
1170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1171% %
1172% %
1173% %
1174+ M o d u l e C o m p o n e n t T e r m i n u s %
1175% %
1176% %
1177% %
1178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1179%
1180% ModuleComponentTerminus() destroys the module component.
1181%
1182% The format of the ModuleComponentTerminus method is:
1183%
1184% ModuleComponentTerminus(void)
1185%
1186*/
1187MagickExport void ModuleComponentTerminus(void)
1188{
cristy18b17442009-10-25 18:36:48 +00001189 if (module_semaphore == (SemaphoreInfo *) NULL)
1190 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001191 DestroyModuleList();
1192 DestroySemaphoreInfo(&module_semaphore);
1193}
1194
1195/*
1196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1197% %
1198% %
1199% %
cristy3ed852e2009-09-05 21:47:34 +00001200% O p e n M o d u l e %
1201% %
1202% %
1203% %
1204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1205%
1206% OpenModule() loads a module, and invokes its registration module. It
1207% returns MagickTrue on success, and MagickFalse if there is an error.
1208%
1209% The format of the OpenModule module is:
1210%
1211% MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1212%
1213% A description of each parameter follows:
1214%
1215% o module: a character string that indicates the module to load.
1216%
1217% o exception: return any errors or warnings in this structure.
1218%
1219*/
1220MagickExport MagickBooleanType OpenModule(const char *module,
1221 ExceptionInfo *exception)
1222{
1223 char
1224 filename[MaxTextExtent],
1225 module_name[MaxTextExtent],
1226 name[MaxTextExtent],
1227 path[MaxTextExtent];
1228
cristyd1df72d2010-06-29 02:17:03 +00001229 MagickBooleanType
1230 status;
1231
cristy3ed852e2009-09-05 21:47:34 +00001232 ModuleHandle
1233 handle;
1234
1235 ModuleInfo
1236 *module_info;
1237
1238 register const CoderInfo
1239 *p;
1240
1241 size_t
cristy3ed852e2009-09-05 21:47:34 +00001242 signature;
1243
1244 /*
1245 Assign module name from alias.
1246 */
1247 assert(module != (const char *) NULL);
1248 module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1249 if (module_info != (ModuleInfo *) NULL)
1250 return(MagickTrue);
1251 (void) CopyMagickString(module_name,module,MaxTextExtent);
1252 p=GetCoderInfo(module,exception);
1253 if (p != (CoderInfo *) NULL)
1254 (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1255 if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1256 return(MagickTrue); /* module already opened, return */
1257 /*
1258 Locate module.
1259 */
1260 handle=(ModuleHandle) NULL;
1261 TagToCoderModuleName(module_name,filename);
1262 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1263 "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1264 *path='\0';
cristyd1df72d2010-06-29 02:17:03 +00001265 status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1266 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001267 return(MagickFalse);
1268 /*
1269 Load module
1270 */
1271 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1272 "Opening module at path \"%s\"",path);
1273 handle=(ModuleHandle) lt_dlopen(path);
1274 if (handle == (ModuleHandle) NULL)
1275 {
1276 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1277 "UnableToLoadModule","`%s': %s",path,lt_dlerror());
1278 return(MagickFalse);
1279 }
1280 /*
1281 Register module.
1282 */
1283 module_info=AcquireModuleInfo(path,module_name);
1284 module_info->handle=handle;
1285 if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1286 return(MagickFalse);
1287 /*
1288 Define RegisterFORMATImage method.
1289 */
1290 TagToModuleName(module_name,"Register%sImage",name);
cristybb503372010-05-27 20:51:26 +00001291 module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1292 if (module_info->register_module == (size_t (*)(void)) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001293 {
1294 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1295 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1296 return(MagickFalse);
1297 }
1298 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1299 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1300 (void *) module_info->register_module);
1301 /*
1302 Define UnregisterFORMATImage method.
1303 */
1304 TagToModuleName(module_name,"Unregister%sImage",name);
1305 module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1306 if (module_info->unregister_module == (void (*)(void)) NULL)
1307 {
1308 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1309 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1310 return(MagickFalse);
1311 }
1312 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1313 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1314 (void *) module_info->unregister_module);
1315 signature=module_info->register_module();
1316 if (signature != MagickImageCoderSignature)
1317 {
1318 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1319 "ImageCoderSignatureMismatch","`%s': %8lx != %8lx",module_name,
cristyf1d91242010-05-28 02:23:19 +00001320 (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
cristy3ed852e2009-09-05 21:47:34 +00001321 return(MagickFalse);
1322 }
1323 return(MagickTrue);
1324}
1325
1326/*
1327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1328% %
1329% %
1330% %
1331% O p e n M o d u l e s %
1332% %
1333% %
1334% %
1335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1336%
1337% OpenModules() loads all available modules.
1338%
1339% The format of the OpenModules module is:
1340%
1341% MagickBooleanType OpenModules(ExceptionInfo *exception)
1342%
1343% A description of each parameter follows:
1344%
1345% o exception: return any errors or warnings in this structure.
1346%
1347*/
1348MagickExport MagickBooleanType OpenModules(ExceptionInfo *exception)
1349{
1350 char
1351 **modules;
1352
cristybb503372010-05-27 20:51:26 +00001353 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001354 i;
1355
cristybb503372010-05-27 20:51:26 +00001356 size_t
cristy3ed852e2009-09-05 21:47:34 +00001357 number_modules;
1358
1359 /*
1360 Load all modules.
1361 */
1362 (void) GetMagickInfo((char *) NULL,exception);
1363 number_modules=0;
cristya6de29a2010-06-30 14:34:26 +00001364 modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
cristy3ed852e2009-09-05 21:47:34 +00001365 if (modules == (char **) NULL)
1366 return(MagickFalse);
cristybb503372010-05-27 20:51:26 +00001367 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001368 (void) OpenModule(modules[i],exception);
1369 /*
1370 Relinquish resources.
1371 */
cristybb503372010-05-27 20:51:26 +00001372 for (i=0; i < (ssize_t) number_modules; i++)
cristy3ed852e2009-09-05 21:47:34 +00001373 modules[i]=DestroyString(modules[i]);
1374 modules=(char **) RelinquishMagickMemory(modules);
1375 return(MagickTrue);
1376}
1377
1378/*
1379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1380% %
1381% %
1382% %
1383% R e g i s t e r M o d u l e %
1384% %
1385% %
1386% %
1387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1388%
1389% RegisterModule() adds an entry to the module list. It returns a pointer to
1390% the registered entry on success.
1391%
1392% The format of the RegisterModule module is:
1393%
1394% ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1395% ExceptionInfo *exception)
1396%
1397% A description of each parameter follows:
1398%
1399% o info: a pointer to the registered entry is returned.
1400%
1401% o module_info: a pointer to the ModuleInfo structure to register.
1402%
1403% o exception: return any errors or warnings in this structure.
1404%
1405*/
1406static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1407 ExceptionInfo *exception)
1408{
1409 MagickBooleanType
1410 status;
1411
1412 assert(module_info != (ModuleInfo *) NULL);
1413 assert(module_info->signature == MagickSignature);
1414 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1415 if (module_list == (SplayTreeInfo *) NULL)
1416 return((const ModuleInfo *) NULL);
1417 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1418 if (status == MagickFalse)
1419 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1420 "MemoryAllocationFailed","`%s'",module_info->tag);
1421 return(module_info);
1422}
1423
1424/*
1425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1426% %
1427% %
1428% %
1429% T a g T o C o d e r M o d u l e N a m e %
1430% %
1431% %
1432% %
1433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1434%
1435% TagToCoderModuleName() munges a module tag and obtains the filename of the
1436% corresponding module.
1437%
1438% The format of the TagToCoderModuleName module is:
1439%
1440% char *TagToCoderModuleName(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 module name here.
1447%
1448*/
1449static void TagToCoderModuleName(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.la",tag);
1456 (void) LocaleLower(name);
1457#else
cristy0157aea2010-04-24 21:12:18 +00001458#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001459 if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1460 (void) CopyMagickString(name,tag,MaxTextExtent);
1461 else
1462 {
1463#if defined(_DEBUG)
1464 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
1465#else
1466 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
1467#endif
1468 }
1469#endif
1470#endif
1471}
1472
1473/*
1474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1475% %
1476% %
1477% %
1478% T a g T o F i l t e r M o d u l e N a m e %
1479% %
1480% %
1481% %
1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483%
1484% TagToFilterModuleName() munges a module tag and returns the filename of the
1485% corresponding filter module.
1486%
1487% The format of the TagToFilterModuleName module is:
1488%
1489% void TagToFilterModuleName(const char *tag,char name)
1490%
1491% A description of each parameter follows:
1492%
1493% o tag: a character string representing the module tag.
1494%
1495% o name: return the filter name here.
1496%
1497*/
1498static void TagToFilterModuleName(const char *tag,char *name)
1499{
1500 assert(tag != (char *) NULL);
1501 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1502 assert(name != (char *) NULL);
1503#if !defined(MAGICKCORE_LTDL_DELEGATE)
1504 (void) FormatMagickString(name,MaxTextExtent,"%s.dll",tag);
1505#else
1506 (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
cristy3ed852e2009-09-05 21:47:34 +00001507#endif
1508}
1509
1510/*
1511%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1512% %
1513% %
1514% %
1515% T a g T o M o d u l e N a m e %
1516% %
1517% %
1518% %
1519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1520%
1521% TagToModuleName() munges the module tag name and returns an upper-case tag
1522% name as the input string, and a user-provided format.
1523%
1524% The format of the TagToModuleName module is:
1525%
1526% TagToModuleName(const char *tag,const char *format,char *module)
1527%
1528% A description of each parameter follows:
1529%
1530% o tag: the module tag.
1531%
1532% o format: a sprintf-compatible format string containing %s where the
1533% upper-case tag name is to be inserted.
1534%
1535% o module: pointer to a destination buffer for the formatted result.
1536%
1537*/
1538static void TagToModuleName(const char *tag,const char *format,char *module)
1539{
1540 char
1541 name[MaxTextExtent];
1542
1543 assert(tag != (const char *) NULL);
1544 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1545 assert(format != (const char *) NULL);
1546 assert(module != (char *) NULL);
1547 (void) CopyMagickString(name,tag,MaxTextExtent);
1548 LocaleUpper(name);
1549#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1550 (void) FormatMagickString(module,MaxTextExtent,format,name);
1551#else
1552 {
1553 char
1554 prefix_format[MaxTextExtent];
1555
1556 (void) FormatMagickString(prefix_format,MaxTextExtent,"%s%s",
1557 MAGICKCORE_NAMESPACE_PREFIX,format);
1558 (void) FormatMagickString(module,MaxTextExtent,prefix_format,name);
1559 }
1560#endif
1561}
1562
1563/*
1564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565% %
1566% %
1567% %
1568% U n r e g i s t e r M o d u l e %
1569% %
1570% %
1571% %
1572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573%
1574% UnregisterModule() unloads a module, and invokes its de-registration module.
1575% Returns MagickTrue on success, and MagickFalse if there is an error.
1576%
1577% The format of the UnregisterModule module is:
1578%
1579% MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1580% ExceptionInfo *exception)
1581%
1582% A description of each parameter follows:
1583%
1584% o module_info: the module info.
1585%
1586% o exception: return any errors or warnings in this structure.
1587%
1588*/
1589static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1590 ExceptionInfo *exception)
1591{
1592 /*
1593 Locate and execute UnregisterFORMATImage module.
1594 */
1595 assert(module_info != (const ModuleInfo *) NULL);
1596 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1597 assert(exception != (ExceptionInfo *) NULL);
1598 if (module_info->unregister_module == NULL)
1599 return(MagickTrue);
1600 module_info->unregister_module();
1601 if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1602 {
1603 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1604 "UnableToCloseModule","`%s': %s",module_info->tag,lt_dlerror());
1605 return(MagickFalse);
1606 }
1607 return(MagickTrue);
1608}
1609#else
1610MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1611 ExceptionInfo *magick_unused(exception))
1612{
1613 return(MagickTrue);
1614}
1615
1616MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1617 Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1618{
cristya6de29a2010-06-30 14:34:26 +00001619 PolicyRights
1620 rights;
1621
1622 assert(image != (Image **) NULL);
1623 assert((*image)->signature == MagickSignature);
1624 if ((*image)->debug != MagickFalse)
1625 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1626 rights=ReadPolicyRights;
1627 if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
1628 {
1629 errno=EPERM;
1630 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1631 "NotAuthorized","`%s'",tag);
1632 return(MagickFalse);
1633 }
1634#if defined(MAGICKCORE_BUILD_MODULES)
1635 (void) tag;
1636 (void) argc;
1637 (void) argv;
1638 (void) exception;
1639#else
cristy3ed852e2009-09-05 21:47:34 +00001640 {
cristybb503372010-05-27 20:51:26 +00001641 extern size_t
cristyd9a29192010-10-16 16:49:53 +00001642 analyzeImage(Image **,const int,const char **,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +00001643
1644 ImageFilterHandler
1645 *image_filter;
1646
1647 image_filter=(ImageFilterHandler *) NULL;
1648 if (LocaleCompare("analyze",tag) == 0)
cristya6de29a2010-06-30 14:34:26 +00001649 image_filter=(ImageFilterHandler *) analyzeImage;
1650 if (image_filter == (ImageFilterHandler *) NULL)
1651 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1652 "UnableToLoadModule","`%s'",tag);
1653 else
cristy3ed852e2009-09-05 21:47:34 +00001654 {
cristybb503372010-05-27 20:51:26 +00001655 size_t
cristy3ed852e2009-09-05 21:47:34 +00001656 signature;
1657
cristya6de29a2010-06-30 14:34:26 +00001658 if ((*image)->debug != MagickFalse)
1659 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1660 "Invoking \"%s\" static image filter",tag);
cristy3ed852e2009-09-05 21:47:34 +00001661 signature=image_filter(image,argc,argv,exception);
cristya6de29a2010-06-30 14:34:26 +00001662 if ((*image)->debug != MagickFalse)
1663 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
1664 tag);
cristy3ed852e2009-09-05 21:47:34 +00001665 if (signature != MagickImageFilterSignature)
1666 {
1667 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
cristya6de29a2010-06-30 14:34:26 +00001668 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,
1669 (unsigned long) signature,(unsigned long)
cristy3ed852e2009-09-05 21:47:34 +00001670 MagickImageFilterSignature);
1671 return(MagickFalse);
1672 }
1673 }
1674 }
1675#endif
1676 return(MagickTrue);
1677}
1678#endif