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