Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %           RRRR    EEEEE   SSSSS   OOO   U   U  RRRR    CCCC  EEEEE          %
      7 %           R   R   E       SS     O   O  U   U  R   R  C      E              %
      8 %           RRRR    EEE      SSS   O   O  U   U  RRRR   C      EEE            %
      9 %           R R     E          SS  O   O  U   U  R R    C      E              %
     10 %           R  R    EEEEE   SSSSS   OOO    UUU   R  R    CCCC  EEEEE          %
     11 %                                                                             %
     12 %                                                                             %
     13 %                        Get/Set MagickCore Resources                         %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                               September 2002                                %
     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 /*
     41   Include declarations.
     42 */
     43 #include "MagickCore/studio.h"
     44 #include "MagickCore/cache.h"
     45 #include "MagickCore/cache-private.h"
     46 #include "MagickCore/configure.h"
     47 #include "MagickCore/exception.h"
     48 #include "MagickCore/exception-private.h"
     49 #include "MagickCore/linked-list.h"
     50 #include "MagickCore/log.h"
     51 #include "MagickCore/image.h"
     52 #include "MagickCore/image-private.h"
     53 #include "MagickCore/memory_.h"
     54 #include "MagickCore/nt-base-private.h"
     55 #include "MagickCore/option.h"
     56 #include "MagickCore/policy.h"
     57 #include "MagickCore/random_.h"
     58 #include "MagickCore/registry.h"
     59 #include "MagickCore/resource_.h"
     60 #include "MagickCore/resource-private.h"
     61 #include "MagickCore/semaphore.h"
     62 #include "MagickCore/signature-private.h"
     63 #include "MagickCore/string_.h"
     64 #include "MagickCore/string-private.h"
     65 #include "MagickCore/splay-tree.h"
     66 #include "MagickCore/thread-private.h"
     67 #include "MagickCore/token.h"
     68 #include "MagickCore/utility.h"
     69 #include "MagickCore/utility-private.h"
     70 
     71 /*
     73   Typedef declarations.
     74 */
     75 typedef struct _ResourceInfo
     76 {
     77   MagickOffsetType
     78     width,
     79     height,
     80     area,
     81     memory,
     82     map,
     83     disk,
     84     file,
     85     thread,
     86     throttle,
     87     time;
     88 
     89   MagickSizeType
     90     width_limit,
     91     height_limit,
     92     area_limit,
     93     memory_limit,
     94     map_limit,
     95     disk_limit,
     96     file_limit,
     97     thread_limit,
     98     throttle_limit,
     99     time_limit;
    100 } ResourceInfo;
    101 
    102 /*
    104   Global declarations.
    105 */
    106 static RandomInfo
    107   *random_info = (RandomInfo *) NULL;
    108 
    109 static ResourceInfo
    110   resource_info =
    111   {
    112     MagickULLConstant(0),              /* initial width */
    113     MagickULLConstant(0),              /* initial height */
    114     MagickULLConstant(0),              /* initial area */
    115     MagickULLConstant(0),              /* initial memory */
    116     MagickULLConstant(0),              /* initial map */
    117     MagickULLConstant(0),              /* initial disk */
    118     MagickULLConstant(0),              /* initial file */
    119     MagickULLConstant(0),              /* initial thread */
    120     MagickULLConstant(0),              /* initial throttle */
    121     MagickULLConstant(0),              /* initial time */
    122     (INT_MAX/(5*sizeof(Quantum))),     /* width limit */
    123     (INT_MAX/(5*sizeof(Quantum))),     /* height limit */
    124     MagickULLConstant(3072)*1024*1024, /* area limit */
    125     MagickULLConstant(1536)*1024*1024, /* memory limit */
    126     MagickULLConstant(3072)*1024*1024, /* map limit */
    127     MagickResourceInfinity,            /* disk limit */
    128     MagickULLConstant(768),            /* file limit */
    129     MagickULLConstant(1),              /* thread limit */
    130     MagickULLConstant(0),              /* throttle limit */
    131     MagickResourceInfinity             /* time limit */
    132   };
    133 
    134 static SemaphoreInfo
    135   *resource_semaphore = (SemaphoreInfo *) NULL;
    136 
    137 static SplayTreeInfo
    138   *temporary_resources = (SplayTreeInfo *) NULL;
    139 
    140 /*
    142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    143 %                                                                             %
    144 %                                                                             %
    145 %                                                                             %
    146 %   A c q u i r e M a g i c k R e s o u r c e                                 %
    147 %                                                                             %
    148 %                                                                             %
    149 %                                                                             %
    150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    151 %
    152 %  AcquireMagickResource() acquires resources of the specified type.
    153 %  MagickFalse is returned if the specified resource is exhausted otherwise
    154 %  MagickTrue.
    155 %
    156 %  The format of the AcquireMagickResource() method is:
    157 %
    158 %      MagickBooleanType AcquireMagickResource(const ResourceType type,
    159 %        const MagickSizeType size)
    160 %
    161 %  A description of each parameter follows:
    162 %
    163 %    o type: the type of resource.
    164 %
    165 %    o size: the number of bytes needed from for this resource.
    166 %
    167 */
    168 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
    169   const MagickSizeType size)
    170 {
    171   char
    172     resource_current[MagickFormatExtent],
    173     resource_limit[MagickFormatExtent],
    174     resource_request[MagickFormatExtent];
    175 
    176   MagickBooleanType
    177     status;
    178 
    179   MagickSizeType
    180     limit;
    181 
    182   status=MagickFalse;
    183   (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
    184     resource_request);
    185   if (resource_semaphore == (SemaphoreInfo *) NULL)
    186     ActivateSemaphoreInfo(&resource_semaphore);
    187   LockSemaphoreInfo(resource_semaphore);
    188   switch (type)
    189   {
    190     case AreaResource:
    191     {
    192       resource_info.area=(MagickOffsetType) size;
    193       limit=resource_info.area_limit;
    194       status=(resource_info.area_limit == MagickResourceInfinity) ||
    195         (size < limit) ? MagickTrue : MagickFalse;
    196       (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
    197         "B",MagickFormatExtent,resource_current);
    198       (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
    199         MagickFormatExtent,resource_limit);
    200       break;
    201     }
    202     case MemoryResource:
    203     {
    204       resource_info.memory+=size;
    205       limit=resource_info.memory_limit;
    206       status=(resource_info.memory_limit == MagickResourceInfinity) ||
    207         ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
    208         MagickFalse;
    209       (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
    210         "B",MagickFormatExtent,resource_current);
    211       (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
    212         MagickFormatExtent,resource_limit);
    213       break;
    214     }
    215     case MapResource:
    216     {
    217       resource_info.map+=size;
    218       limit=resource_info.map_limit;
    219       status=(resource_info.map_limit == MagickResourceInfinity) ||
    220         ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
    221       (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
    222         "B",MagickFormatExtent,resource_current);
    223       (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
    224         MagickFormatExtent,resource_limit);
    225       break;
    226     }
    227     case DiskResource:
    228     {
    229       resource_info.disk+=size;
    230       limit=resource_info.disk_limit;
    231       status=(resource_info.disk_limit == MagickResourceInfinity) ||
    232         ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
    233         MagickFalse;
    234       (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
    235         "B",MagickFormatExtent,resource_current);
    236       (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
    237         MagickFormatExtent,resource_limit);
    238       break;
    239     }
    240     case FileResource:
    241     {
    242       resource_info.file+=size;
    243       limit=resource_info.file_limit;
    244       status=(resource_info.file_limit == MagickResourceInfinity) ||
    245         ((MagickSizeType) resource_info.file < limit) ?
    246         MagickTrue : MagickFalse;
    247       (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
    248         "B",MagickFormatExtent,resource_current);
    249       (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
    250         MagickFalse,"B",MagickFormatExtent,resource_limit);
    251       break;
    252     }
    253     case HeightResource:
    254     {
    255       resource_info.area=(MagickOffsetType) size;
    256       limit=resource_info.height_limit;
    257       status=(resource_info.area_limit == MagickResourceInfinity) ||
    258         (size < limit) ? MagickTrue : MagickFalse;
    259       (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
    260         "P",MagickFormatExtent,resource_current);
    261       (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
    262         MagickFormatExtent,resource_limit);
    263       break;
    264     }
    265     case ThreadResource:
    266     {
    267       limit=resource_info.thread_limit;
    268       status=(resource_info.thread_limit == MagickResourceInfinity) ||
    269         ((MagickSizeType) resource_info.thread < limit) ?
    270         MagickTrue : MagickFalse;
    271       (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
    272         "B",MagickFormatExtent,resource_current);
    273       (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
    274         MagickFalse,"B",MagickFormatExtent,resource_limit);
    275       break;
    276     }
    277     case ThrottleResource:
    278     {
    279       limit=resource_info.throttle_limit;
    280       status=(resource_info.throttle_limit == MagickResourceInfinity) ||
    281         ((MagickSizeType) resource_info.throttle < limit) ?
    282         MagickTrue : MagickFalse;
    283       (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
    284         MagickFalse,"B",MagickFormatExtent,resource_current);
    285       (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
    286         MagickFalse,"B",MagickFormatExtent,resource_limit);
    287       break;
    288     }
    289     case TimeResource:
    290     {
    291       resource_info.time+=size;
    292       limit=resource_info.time_limit;
    293       status=(resource_info.time_limit == MagickResourceInfinity) ||
    294         ((MagickSizeType) resource_info.time < limit) ?
    295         MagickTrue : MagickFalse;
    296       (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
    297         "B",MagickFormatExtent,resource_current);
    298       (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
    299         MagickFalse,"B",MagickFormatExtent,resource_limit);
    300       break;
    301     }
    302     case WidthResource:
    303     {
    304       resource_info.area=(MagickOffsetType) size;
    305       limit=resource_info.width_limit;
    306       status=(resource_info.area_limit == MagickResourceInfinity) ||
    307         (size < limit) ? MagickTrue : MagickFalse;
    308       (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
    309         "P",MagickFormatExtent,resource_current);
    310       (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
    311         MagickFormatExtent,resource_limit);
    312       break;
    313     }
    314     default:
    315       break;
    316   }
    317   UnlockSemaphoreInfo(resource_semaphore);
    318   (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
    319     CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
    320     resource_request,resource_current,resource_limit);
    321   return(status);
    322 }
    323 
    324 /*
    326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    327 %                                                                             %
    328 %                                                                             %
    329 %                                                                             %
    330 +   A s y n c h r o n o u s R e s o u r c e C o m p o n e n t T e r m i n u s %
    331 %                                                                             %
    332 %                                                                             %
    333 %                                                                             %
    334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    335 %
    336 %  AsynchronousResourceComponentTerminus() destroys the resource environment.
    337 %  It differs from ResourceComponentTerminus() in that it can be called from a
    338 %  asynchronous signal handler.
    339 %
    340 %  The format of the ResourceComponentTerminus() method is:
    341 %
    342 %      ResourceComponentTerminus(void)
    343 %
    344 */
    345 MagickPrivate void AsynchronousResourceComponentTerminus(void)
    346 {
    347   const char
    348     *path;
    349 
    350   if (temporary_resources == (SplayTreeInfo *) NULL)
    351     return;
    352   /*
    353     Remove any lingering temporary files.
    354   */
    355   ResetSplayTreeIterator(temporary_resources);
    356   path=(const char *) GetNextKeyInSplayTree(temporary_resources);
    357   while (path != (const char *) NULL)
    358   {
    359     (void) ShredFile(path);
    360     path=(const char *) GetNextKeyInSplayTree(temporary_resources);
    361   }
    362 }
    363 
    364 /*
    366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    367 %                                                                             %
    368 %                                                                             %
    369 %                                                                             %
    370 %   A c q u i r e U n i q u e F i l e R e s o u r c e                         %
    371 %                                                                             %
    372 %                                                                             %
    373 %                                                                             %
    374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    375 %
    376 %  AcquireUniqueFileResource() returns a unique file name, and returns a file
    377 %  descriptor for the file open for reading and writing.
    378 %
    379 %  The format of the AcquireUniqueFileResource() method is:
    380 %
    381 %      int AcquireUniqueFileResource(char *path)
    382 %
    383 %  A description of each parameter follows:
    384 %
    385 %   o  path:  Specifies a pointer to an array of characters.  The unique path
    386 %      name is returned in this array.
    387 %
    388 */
    389 
    390 static void *DestroyTemporaryResources(void *temporary_resource)
    391 {
    392   (void) ShredFile((char *) temporary_resource);
    393   temporary_resource=DestroyString((char *) temporary_resource);
    394   return((void *) NULL);
    395 }
    396 
    397 MagickExport MagickBooleanType GetPathTemplate(char *path)
    398 {
    399   char
    400     *directory,
    401     *value;
    402 
    403   ExceptionInfo
    404     *exception;
    405 
    406   MagickBooleanType
    407     status;
    408 
    409   struct stat
    410     attributes;
    411 
    412   (void) FormatLocaleString(path,MagickPathExtent,"magick-%.20gXXXXXXXXXXXX",
    413     (double) getpid());
    414   exception=AcquireExceptionInfo();
    415   directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
    416     exception);
    417   exception=DestroyExceptionInfo(exception);
    418   if (directory == (char *) NULL)
    419     directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
    420   if (directory == (char *) NULL)
    421     directory=GetEnvironmentValue("MAGICK_TMPDIR");
    422   if (directory == (char *) NULL)
    423     directory=GetEnvironmentValue("TMPDIR");
    424 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
    425   if (directory == (char *) NULL)
    426     directory=GetEnvironmentValue("TMP");
    427   if (directory == (char *) NULL)
    428     directory=GetEnvironmentValue("TEMP");
    429 #endif
    430 #if defined(__VMS)
    431   if (directory == (char *) NULL)
    432     directory=GetEnvironmentValue("MTMPDIR");
    433 #endif
    434 #if defined(P_tmpdir)
    435   if (directory == (char *) NULL)
    436     directory=ConstantString(P_tmpdir);
    437 #endif
    438   if (directory == (char *) NULL)
    439     return(MagickTrue);
    440   value=GetPolicyValue("temporary-path");
    441   if (value != (char *) NULL)
    442     (void) CloneString(&directory,value);
    443   if (strlen(directory) > (MagickPathExtent-25))
    444     {
    445       directory=DestroyString(directory);
    446       return(MagickFalse);
    447     }
    448   status=GetPathAttributes(directory,&attributes);
    449   if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
    450     {
    451       directory=DestroyString(directory);
    452       return(MagickFalse);
    453     }
    454   if (directory[strlen(directory)-1] == *DirectorySeparator)
    455     (void) FormatLocaleString(path,MagickPathExtent,
    456       "%smagick-%.20gXXXXXXXXXXXX",directory,(double) getpid());
    457   else
    458     (void) FormatLocaleString(path,MagickPathExtent,
    459       "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,(double)
    460       getpid());
    461   directory=DestroyString(directory);
    462 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
    463   {
    464     register char
    465       *p;
    466 
    467     /*
    468       Ghostscript does not like backslashes so we need to replace them. The
    469       forward slash also works under Windows.
    470     */
    471     for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
    472       if (*p == *DirectorySeparator)
    473         *p='/';
    474   }
    475 #endif
    476   return(MagickTrue);
    477 }
    478 
    479 MagickExport int AcquireUniqueFileResource(char *path)
    480 {
    481 #if !defined(O_NOFOLLOW)
    482 #define O_NOFOLLOW 0
    483 #endif
    484 #if !defined(TMP_MAX)
    485 # define TMP_MAX  238328
    486 #endif
    487 
    488   int
    489     c,
    490     file;
    491 
    492   register char
    493     *p;
    494 
    495   register ssize_t
    496     i;
    497 
    498   static const char
    499     portable_filename[65] =
    500       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
    501 
    502   StringInfo
    503     *key;
    504 
    505   unsigned char
    506     *datum;
    507 
    508   assert(path != (char *) NULL);
    509   (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
    510   if (random_info == (RandomInfo *) NULL)
    511     {
    512       LockSemaphoreInfo(resource_semaphore);
    513       if (random_info == (RandomInfo *) NULL)
    514         random_info=AcquireRandomInfo();
    515       UnlockSemaphoreInfo(resource_semaphore);
    516     }
    517   file=(-1);
    518   for (i=0; i < (ssize_t) TMP_MAX; i++)
    519   {
    520     /*
    521       Get temporary pathname.
    522     */
    523     (void) GetPathTemplate(path);
    524     key=GetRandomKey(random_info,6);
    525     p=path+strlen(path)-12;
    526     datum=GetStringInfoDatum(key);
    527     for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
    528     {
    529       c=(int) (datum[i] & 0x3f);
    530       *p++=portable_filename[c];
    531     }
    532     key=DestroyStringInfo(key);
    533 #if defined(MAGICKCORE_HAVE_MKSTEMP)
    534     file=mkstemp(path);
    535     if (file != -1)
    536       {
    537 #if defined(MAGICKCORE_HAVE_FCHMOD)
    538         (void) fchmod(file,0600);
    539 #endif
    540 #if defined(__OS2__)
    541         setmode(file,O_BINARY);
    542 #endif
    543         break;
    544       }
    545 #endif
    546     key=GetRandomKey(random_info,12);
    547     p=path+strlen(path)-12;
    548     datum=GetStringInfoDatum(key);
    549     for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
    550     {
    551       c=(int) (datum[i] & 0x3f);
    552       *p++=portable_filename[c];
    553     }
    554     key=DestroyStringInfo(key);
    555     file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
    556       S_MODE);
    557     if ((file >= 0) || (errno != EEXIST))
    558       break;
    559   }
    560   (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
    561   if (file == -1)
    562     return(file);
    563   if (resource_semaphore == (SemaphoreInfo *) NULL)
    564     ActivateSemaphoreInfo(&resource_semaphore);
    565   LockSemaphoreInfo(resource_semaphore);
    566   if (temporary_resources == (SplayTreeInfo *) NULL)
    567     temporary_resources=NewSplayTree(CompareSplayTreeString,
    568       DestroyTemporaryResources,(void *(*)(void *)) NULL);
    569   UnlockSemaphoreInfo(resource_semaphore);
    570   (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
    571     (const void *) NULL);
    572   return(file);
    573 }
    574 
    575 /*
    577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    578 %                                                                             %
    579 %                                                                             %
    580 %                                                                             %
    581 %   G e t M a g i c k R e s o u r c e                                         %
    582 %                                                                             %
    583 %                                                                             %
    584 %                                                                             %
    585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    586 %
    587 %  GetMagickResource() returns the specified resource.
    588 %
    589 %  The format of the GetMagickResource() method is:
    590 %
    591 %      MagickSizeType GetMagickResource(const ResourceType type)
    592 %
    593 %  A description of each parameter follows:
    594 %
    595 %    o type: the type of resource.
    596 %
    597 */
    598 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
    599 {
    600   MagickSizeType
    601     resource;
    602 
    603   resource=0;
    604   LockSemaphoreInfo(resource_semaphore);
    605   switch (type)
    606   {
    607     case WidthResource:
    608     {
    609       resource=(MagickSizeType) resource_info.width;
    610       break;
    611     }
    612     case HeightResource:
    613     {
    614       resource=(MagickSizeType) resource_info.height;
    615       break;
    616     }
    617     case AreaResource:
    618     {
    619       resource=(MagickSizeType) resource_info.area;
    620       break;
    621     }
    622     case MemoryResource:
    623     {
    624       resource=(MagickSizeType) resource_info.memory;
    625       break;
    626     }
    627     case MapResource:
    628     {
    629       resource=(MagickSizeType) resource_info.map;
    630       break;
    631     }
    632     case DiskResource:
    633     {
    634       resource=(MagickSizeType) resource_info.disk;
    635       break;
    636     }
    637     case FileResource:
    638     {
    639       resource=(MagickSizeType) resource_info.file;
    640       break;
    641     }
    642     case ThreadResource:
    643     {
    644       resource=(MagickSizeType) resource_info.thread;
    645       break;
    646     }
    647     case ThrottleResource:
    648     {
    649       resource=(MagickSizeType) resource_info.throttle;
    650       break;
    651     }
    652     case TimeResource:
    653     {
    654       resource=(MagickSizeType) resource_info.time;
    655       break;
    656     }
    657     default:
    658       break;
    659   }
    660   UnlockSemaphoreInfo(resource_semaphore);
    661   return(resource);
    662 }
    663 
    664 /*
    666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    667 %                                                                             %
    668 %                                                                             %
    669 %                                                                             %
    670 %   G e t M a g i c k R e s o u r c e L i m i t                               %
    671 %                                                                             %
    672 %                                                                             %
    673 %                                                                             %
    674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    675 %
    676 %  GetMagickResourceLimit() returns the specified resource limit.
    677 %
    678 %  The format of the GetMagickResourceLimit() method is:
    679 %
    680 %      MagickSizeType GetMagickResourceLimit(const ResourceType type)
    681 %
    682 %  A description of each parameter follows:
    683 %
    684 %    o type: the type of resource.
    685 %
    686 */
    687 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
    688 {
    689   MagickSizeType
    690     resource;
    691 
    692   resource=0;
    693   if (resource_semaphore == (SemaphoreInfo *) NULL)
    694     ActivateSemaphoreInfo(&resource_semaphore);
    695   LockSemaphoreInfo(resource_semaphore);
    696   switch (type)
    697   {
    698     case WidthResource:
    699     {
    700       resource=resource_info.width_limit;
    701       break;
    702     }
    703     case HeightResource:
    704     {
    705       resource=resource_info.height_limit;
    706       break;
    707     }
    708     case AreaResource:
    709     {
    710       resource=resource_info.area_limit;
    711       break;
    712     }
    713     case MemoryResource:
    714     {
    715       resource=resource_info.memory_limit;
    716       break;
    717     }
    718     case MapResource:
    719     {
    720       resource=resource_info.map_limit;
    721       break;
    722     }
    723     case DiskResource:
    724     {
    725       resource=resource_info.disk_limit;
    726       break;
    727     }
    728     case FileResource:
    729     {
    730       resource=resource_info.file_limit;
    731       break;
    732     }
    733     case ThreadResource:
    734     {
    735       resource=resource_info.thread_limit;
    736       break;
    737     }
    738     case ThrottleResource:
    739     {
    740       resource=resource_info.throttle_limit;
    741       break;
    742     }
    743     case TimeResource:
    744     {
    745       resource=resource_info.time_limit;
    746       break;
    747     }
    748     default:
    749       break;
    750   }
    751   UnlockSemaphoreInfo(resource_semaphore);
    752   return(resource);
    753 }
    754 
    755 /*
    757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    758 %                                                                             %
    759 %                                                                             %
    760 %                                                                             %
    761 %  L i s t M a g i c k R e s o u r c e I n f o                                %
    762 %                                                                             %
    763 %                                                                             %
    764 %                                                                             %
    765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    766 %
    767 %  ListMagickResourceInfo() lists the resource info to a file.
    768 %
    769 %  The format of the ListMagickResourceInfo method is:
    770 %
    771 %      MagickBooleanType ListMagickResourceInfo(FILE *file,
    772 %        ExceptionInfo *exception)
    773 %
    774 %  A description of each parameter follows.
    775 %
    776 %    o file:  An pointer to a FILE.
    777 %
    778 %    o exception: return any errors or warnings in this structure.
    779 %
    780 */
    781 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
    782   ExceptionInfo *magick_unused(exception))
    783 {
    784   char
    785     area_limit[MagickFormatExtent],
    786     disk_limit[MagickFormatExtent],
    787     height_limit[MagickFormatExtent],
    788     map_limit[MagickFormatExtent],
    789     memory_limit[MagickFormatExtent],
    790     time_limit[MagickFormatExtent],
    791     width_limit[MagickFormatExtent];
    792 
    793   magick_unreferenced(exception);
    794 
    795   if (file == (const FILE *) NULL)
    796     file=stdout;
    797   if (resource_semaphore == (SemaphoreInfo *) NULL)
    798     ActivateSemaphoreInfo(&resource_semaphore);
    799   LockSemaphoreInfo(resource_semaphore);
    800   (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
    801     MagickFormatExtent,width_limit);
    802   (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
    803     MagickFormatExtent,height_limit);
    804   (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
    805     MagickFormatExtent,area_limit);
    806   (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
    807     MagickFormatExtent,memory_limit);
    808   (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
    809     MagickFormatExtent,map_limit);
    810   (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
    811   if (resource_info.disk_limit != MagickResourceInfinity)
    812     (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
    813       MagickFormatExtent,disk_limit);
    814   (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
    815   if (resource_info.time_limit != MagickResourceInfinity)
    816     (void) FormatLocaleString(time_limit,MagickFormatExtent,"%.20g",(double)
    817       ((MagickOffsetType) resource_info.time_limit));
    818   (void) FormatLocaleFile(file,"Resource limits:\n");
    819   (void) FormatLocaleFile(file,"  Width: %s\n",width_limit);
    820   (void) FormatLocaleFile(file,"  Height: %s\n",height_limit);
    821   (void) FormatLocaleFile(file,"  Area: %s\n",area_limit);
    822   (void) FormatLocaleFile(file,"  Memory: %s\n",memory_limit);
    823   (void) FormatLocaleFile(file,"  Map: %s\n",map_limit);
    824   (void) FormatLocaleFile(file,"  Disk: %s\n",disk_limit);
    825   (void) FormatLocaleFile(file,"  File: %.20g\n",(double) ((MagickOffsetType)
    826     resource_info.file_limit));
    827   (void) FormatLocaleFile(file,"  Thread: %.20g\n",(double) ((MagickOffsetType)
    828     resource_info.thread_limit));
    829   (void) FormatLocaleFile(file,"  Throttle: %.20g\n",(double)
    830     ((MagickOffsetType) resource_info.throttle_limit));
    831   (void) FormatLocaleFile(file,"  Time: %s\n",time_limit);
    832   (void) fflush(file);
    833   UnlockSemaphoreInfo(resource_semaphore);
    834   return(MagickTrue);
    835 }
    836 
    837 /*
    839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    840 %                                                                             %
    841 %                                                                             %
    842 %                                                                             %
    843 %   R e l i n q u i s h M a g i c k R e s o u r c e                           %
    844 %                                                                             %
    845 %                                                                             %
    846 %                                                                             %
    847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    848 %
    849 %  RelinquishMagickResource() relinquishes resources of the specified type.
    850 %
    851 %  The format of the RelinquishMagickResource() method is:
    852 %
    853 %      void RelinquishMagickResource(const ResourceType type,
    854 %        const MagickSizeType size)
    855 %
    856 %  A description of each parameter follows:
    857 %
    858 %    o type: the type of resource.
    859 %
    860 %    o size: the size of the resource.
    861 %
    862 */
    863 MagickExport void RelinquishMagickResource(const ResourceType type,
    864   const MagickSizeType size)
    865 {
    866   char
    867     resource_current[MagickFormatExtent],
    868     resource_limit[MagickFormatExtent],
    869     resource_request[MagickFormatExtent];
    870 
    871   (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
    872     resource_request);
    873   if (resource_semaphore == (SemaphoreInfo *) NULL)
    874 		ActivateSemaphoreInfo(&resource_semaphore);
    875   LockSemaphoreInfo(resource_semaphore);
    876   switch (type)
    877   {
    878     case WidthResource:
    879     {
    880       resource_info.width=(MagickOffsetType) size;
    881       (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
    882         "P",MagickFormatExtent,resource_current);
    883       (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
    884         MagickFormatExtent,resource_limit);
    885       break;
    886     }
    887     case HeightResource:
    888     {
    889       resource_info.height=(MagickOffsetType) size;
    890       (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
    891         "P",MagickFormatExtent,resource_current);
    892       (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
    893         MagickFormatExtent,resource_limit);
    894       break;
    895     }
    896     case AreaResource:
    897     {
    898       resource_info.area=(MagickOffsetType) size;
    899       (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
    900         "B",MagickFormatExtent,resource_current);
    901       (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
    902         MagickFormatExtent,resource_limit);
    903       break;
    904     }
    905     case MemoryResource:
    906     {
    907       resource_info.memory-=size;
    908       (void) FormatMagickSize((MagickSizeType) resource_info.memory,
    909         MagickTrue,"B",MagickFormatExtent,resource_current);
    910       (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
    911         MagickFormatExtent,resource_limit);
    912       break;
    913     }
    914     case MapResource:
    915     {
    916       resource_info.map-=size;
    917       (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
    918         "B",MagickFormatExtent,resource_current);
    919       (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
    920         MagickFormatExtent,resource_limit);
    921       break;
    922     }
    923     case DiskResource:
    924     {
    925       resource_info.disk-=size;
    926       (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
    927         "B",MagickFormatExtent,resource_current);
    928       (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
    929         MagickFormatExtent,resource_limit);
    930       break;
    931     }
    932     case FileResource:
    933     {
    934       resource_info.file-=size;
    935       (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
    936         "B",MagickFormatExtent,resource_current);
    937       (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
    938         MagickFalse,"B",MagickFormatExtent,resource_limit);
    939       break;
    940     }
    941     case ThreadResource:
    942     {
    943       (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
    944         "B",MagickFormatExtent,resource_current);
    945       (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
    946         MagickFalse,"B",MagickFormatExtent,resource_limit);
    947       break;
    948     }
    949     case ThrottleResource:
    950     {
    951       (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
    952         MagickFalse,"B",MagickFormatExtent,resource_current);
    953       (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
    954         MagickFalse,"B",MagickFormatExtent,resource_limit);
    955       break;
    956     }
    957     case TimeResource:
    958     {
    959       resource_info.time-=size;
    960       (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
    961         "B",MagickFormatExtent,resource_current);
    962       (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
    963         MagickFalse,"B",MagickFormatExtent,resource_limit);
    964       break;
    965     }
    966     default:
    967       break;
    968   }
    969   UnlockSemaphoreInfo(resource_semaphore);
    970   (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
    971     CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
    972       resource_request,resource_current,resource_limit);
    973 }
    974 
    975 /*
    977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    978 %                                                                             %
    979 %                                                                             %
    980 %                                                                             %
    981 %    R e l i n q u i s h U n i q u e F i l e R e s o u r c e                  %
    982 %                                                                             %
    983 %                                                                             %
    984 %                                                                             %
    985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    986 %
    987 %  RelinquishUniqueFileResource() relinquishes a unique file resource.
    988 %
    989 %  The format of the RelinquishUniqueFileResource() method is:
    990 %
    991 %      MagickBooleanType RelinquishUniqueFileResource(const char *path)
    992 %
    993 %  A description of each parameter follows:
    994 %
    995 %    o name: the name of the temporary resource.
    996 %
    997 */
    998 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
    999 {
   1000   char
   1001     cache_path[MagickPathExtent];
   1002 
   1003   MagickBooleanType
   1004     status;
   1005 
   1006   assert(path != (const char *) NULL);
   1007   status=MagickFalse;
   1008   (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
   1009   if (resource_semaphore == (SemaphoreInfo *) NULL)
   1010     ActivateSemaphoreInfo(&resource_semaphore);
   1011   LockSemaphoreInfo(resource_semaphore);
   1012   if (temporary_resources != (SplayTreeInfo *) NULL)
   1013     status=DeleteNodeFromSplayTree(temporary_resources, (const void *) path);
   1014   UnlockSemaphoreInfo(resource_semaphore);
   1015   (void) CopyMagickString(cache_path,path,MagickPathExtent);
   1016   AppendImageFormat("cache",cache_path);
   1017   (void) ShredFile(cache_path);
   1018   if (status == MagickFalse)
   1019     status=ShredFile(path);
   1020   return(status);
   1021 }
   1022 
   1023 /*
   1025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1026 %                                                                             %
   1027 %                                                                             %
   1028 %                                                                             %
   1029 +   R e s o u r c e C o m p o n e n t G e n e s i s                           %
   1030 %                                                                             %
   1031 %                                                                             %
   1032 %                                                                             %
   1033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1034 %
   1035 %  ResourceComponentGenesis() instantiates the resource component.
   1036 %
   1037 %  The format of the ResourceComponentGenesis method is:
   1038 %
   1039 %      MagickBooleanType ResourceComponentGenesis(void)
   1040 %
   1041 */
   1042 
   1043 static inline MagickSizeType StringToSizeType(const char *string,
   1044   const double interval)
   1045 {
   1046   double
   1047     value;
   1048 
   1049   value=SiPrefixToDoubleInterval(string,interval);
   1050   if (value >= (double) MagickULLConstant(~0))
   1051     return(MagickULLConstant(~0));
   1052   return((MagickSizeType) value);
   1053 }
   1054 
   1055 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
   1056 {
   1057   char
   1058     *limit;
   1059 
   1060   MagickSizeType
   1061     memory;
   1062 
   1063   ssize_t
   1064     files,
   1065     pages,
   1066     pagesize;
   1067 
   1068   /*
   1069     Set Magick resource limits.
   1070   */
   1071   if (resource_semaphore == (SemaphoreInfo *) NULL)
   1072     resource_semaphore=AcquireSemaphoreInfo();
   1073   (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
   1074   limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
   1075   if (limit != (char *) NULL)
   1076     {
   1077       (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
   1078         100.0));
   1079       limit=DestroyString(limit);
   1080     }
   1081   (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
   1082   limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
   1083   if (limit != (char *) NULL)
   1084     {
   1085       (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
   1086         100.0));
   1087       limit=DestroyString(limit);
   1088     }
   1089   pagesize=GetMagickPageSize();
   1090   pages=(-1);
   1091 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
   1092   pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
   1093 #endif
   1094   memory=(MagickSizeType) pages*pagesize;
   1095   if ((pagesize <= 0) || (pages <= 0))
   1096     memory=2048UL*1024UL*1024UL;
   1097 #if defined(PixelCacheThreshold)
   1098   memory=PixelCacheThreshold;
   1099 #endif
   1100   (void) SetMagickResourceLimit(AreaResource,2*memory);
   1101   limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
   1102   if (limit != (char *) NULL)
   1103     {
   1104       (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
   1105       limit=DestroyString(limit);
   1106     }
   1107   (void) SetMagickResourceLimit(MemoryResource,memory);
   1108   limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
   1109   if (limit != (char *) NULL)
   1110     {
   1111       (void) SetMagickResourceLimit(MemoryResource,
   1112         StringToSizeType(limit,100.0));
   1113       limit=DestroyString(limit);
   1114     }
   1115   (void) SetMagickResourceLimit(MapResource,2*memory);
   1116   limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
   1117   if (limit != (char *) NULL)
   1118     {
   1119       (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
   1120       limit=DestroyString(limit);
   1121     }
   1122   (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
   1123   limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
   1124   if (limit != (char *) NULL)
   1125     {
   1126       (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
   1127       limit=DestroyString(limit);
   1128     }
   1129   files=(-1);
   1130 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
   1131   files=(ssize_t) sysconf(_SC_OPEN_MAX);
   1132 #endif
   1133 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
   1134   if (files < 0)
   1135     {
   1136       struct rlimit
   1137         resources;
   1138 
   1139       if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
   1140         files=(ssize_t) resources.rlim_cur;
   1141   }
   1142 #endif
   1143 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
   1144   if (files < 0)
   1145     files=(ssize_t) getdtablesize();
   1146 #endif
   1147   if (files < 0)
   1148     files=64;
   1149   (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
   1150     (3*files/4),64));
   1151   limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
   1152   if (limit != (char *) NULL)
   1153     {
   1154       (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
   1155         100.0));
   1156       limit=DestroyString(limit);
   1157     }
   1158   (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
   1159   limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
   1160   if (limit != (char *) NULL)
   1161     {
   1162       (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
   1163         100.0));
   1164       limit=DestroyString(limit);
   1165     }
   1166   (void) SetMagickResourceLimit(ThrottleResource,0);
   1167   limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
   1168   if (limit != (char *) NULL)
   1169     {
   1170       (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
   1171         100.0));
   1172       limit=DestroyString(limit);
   1173     }
   1174   (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
   1175   limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
   1176   if (limit != (char *) NULL)
   1177     {
   1178       (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
   1179       limit=DestroyString(limit);
   1180     }
   1181   return(MagickTrue);
   1182 }
   1183 
   1184 /*
   1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1187 %                                                                             %
   1188 %                                                                             %
   1189 %                                                                             %
   1190 +   R e s o u r c e C o m p o n e n t T e r m i n u s                         %
   1191 %                                                                             %
   1192 %                                                                             %
   1193 %                                                                             %
   1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1195 %
   1196 %  ResourceComponentTerminus() destroys the resource component.
   1197 %
   1198 %  The format of the ResourceComponentTerminus() method is:
   1199 %
   1200 %      ResourceComponentTerminus(void)
   1201 %
   1202 */
   1203 MagickPrivate void ResourceComponentTerminus(void)
   1204 {
   1205   if (resource_semaphore == (SemaphoreInfo *) NULL)
   1206     resource_semaphore=AcquireSemaphoreInfo();
   1207   LockSemaphoreInfo(resource_semaphore);
   1208   if (temporary_resources != (SplayTreeInfo *) NULL)
   1209     temporary_resources=DestroySplayTree(temporary_resources);
   1210   if (random_info != (RandomInfo *) NULL)
   1211     random_info=DestroyRandomInfo(random_info);
   1212   UnlockSemaphoreInfo(resource_semaphore);
   1213   RelinquishSemaphoreInfo(&resource_semaphore);
   1214 }
   1215 
   1216 /*
   1218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1219 %                                                                             %
   1220 %                                                                             %
   1221 %                                                                             %
   1222 %   S e t M a g i c k R e s o u r c e L i m i t                               %
   1223 %                                                                             %
   1224 %                                                                             %
   1225 %                                                                             %
   1226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1227 %
   1228 %  SetMagickResourceLimit() sets the limit for a particular resource.
   1229 %
   1230 %  The format of the SetMagickResourceLimit() method is:
   1231 %
   1232 %      MagickBooleanType SetMagickResourceLimit(const ResourceType type,
   1233 %        const MagickSizeType limit)
   1234 %
   1235 %  A description of each parameter follows:
   1236 %
   1237 %    o type: the type of resource.
   1238 %
   1239 %    o limit: the maximum limit for the resource.
   1240 %
   1241 */
   1242 
   1243 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
   1244   const MagickSizeType limit)
   1245 {
   1246   char
   1247     *value;
   1248 
   1249   if (resource_semaphore == (SemaphoreInfo *) NULL)
   1250     resource_semaphore=AcquireSemaphoreInfo();
   1251   LockSemaphoreInfo(resource_semaphore);
   1252   value=(char *) NULL;
   1253   switch (type)
   1254   {
   1255     case WidthResource:
   1256     {
   1257       resource_info.width_limit=limit;
   1258       value=GetPolicyValue("width");
   1259       if (value != (char *) NULL)
   1260         resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
   1261           100.0));
   1262       break;
   1263     }
   1264     case HeightResource:
   1265     {
   1266       resource_info.height_limit=limit;
   1267       value=GetPolicyValue("height");
   1268       if (value != (char *) NULL)
   1269         resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
   1270           100.0));
   1271       break;
   1272     }
   1273     case AreaResource:
   1274     {
   1275       resource_info.area_limit=limit;
   1276       value=GetPolicyValue("area");
   1277       if (value != (char *) NULL)
   1278         resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
   1279       break;
   1280     }
   1281     case MemoryResource:
   1282     {
   1283       resource_info.memory_limit=limit;
   1284       value=GetPolicyValue("memory");
   1285       if (value != (char *) NULL)
   1286         resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
   1287           100.0));
   1288       break;
   1289     }
   1290     case MapResource:
   1291     {
   1292       resource_info.map_limit=limit;
   1293       value=GetPolicyValue("map");
   1294       if (value != (char *) NULL)
   1295         resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
   1296       break;
   1297     }
   1298     case DiskResource:
   1299     {
   1300       resource_info.disk_limit=limit;
   1301       value=GetPolicyValue("disk");
   1302       if (value != (char *) NULL)
   1303         resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
   1304       break;
   1305     }
   1306     case FileResource:
   1307     {
   1308       resource_info.file_limit=limit;
   1309       value=GetPolicyValue("file");
   1310       if (value != (char *) NULL)
   1311         resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
   1312       break;
   1313     }
   1314     case ThreadResource:
   1315     {
   1316       resource_info.thread_limit=limit;
   1317       value=GetPolicyValue("thread");
   1318       if (value != (char *) NULL)
   1319         resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
   1320           100.0));
   1321       if (resource_info.thread_limit > GetOpenMPMaximumThreads())
   1322         resource_info.thread_limit=GetOpenMPMaximumThreads();
   1323       else if (resource_info.thread_limit == 0)
   1324         resource_info.thread_limit=1;
   1325       break;
   1326     }
   1327     case ThrottleResource:
   1328     {
   1329       resource_info.throttle_limit=limit;
   1330       value=GetPolicyValue("throttle");
   1331       if (value != (char *) NULL)
   1332         resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
   1333           100.0));
   1334       if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
   1335         resource_info.throttle_limit=GetOpenMPMaximumThreads();
   1336       break;
   1337     }
   1338     case TimeResource:
   1339     {
   1340       resource_info.time_limit=limit;
   1341       value=GetPolicyValue("time");
   1342       if (value != (char *) NULL)
   1343         resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
   1344       ResetPixelCacheEpoch();
   1345       break;
   1346     }
   1347     default:
   1348       break;
   1349   }
   1350   if (value != (char *) NULL)
   1351     value=DestroyString(value);
   1352   UnlockSemaphoreInfo(resource_semaphore);
   1353   return(MagickTrue);
   1354 }
   1355