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