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