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