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