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