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