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