MagickCore 7.1.2-32
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
resource.c
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% RRRR EEEEE SSSSS OOO U U RRRR CCCC EEEEE %
7% R R E SS O O U U R R C E %
8% RRRR EEE SSS O O U U RRRR C EEE %
9% R R E SS O O U U R R C E %
10% R R EEEEE SSSSS OOO UUU R R CCCC EEEEE %
11% %
12% %
13% Get/Set MagickCore Resources %
14% %
15% Software Design %
16% Cristy %
17% September 2002 %
18% %
19% %
20% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% https://imagemagick.org/license/ %
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/configure.h"
45#include "MagickCore/exception.h"
46#include "MagickCore/exception-private.h"
47#include "MagickCore/linked-list.h"
48#include "MagickCore/log.h"
49#include "MagickCore/image.h"
50#include "MagickCore/image-private.h"
51#include "MagickCore/memory_.h"
52#include "MagickCore/nt-base-private.h"
53#include "MagickCore/option.h"
54#include "MagickCore/policy.h"
55#include "MagickCore/random_.h"
56#include "MagickCore/registry.h"
57#include "MagickCore/resource_.h"
58#include "MagickCore/resource-private.h"
59#include "MagickCore/semaphore.h"
60#include "MagickCore/signature-private.h"
61#include "MagickCore/string_.h"
62#include "MagickCore/string-private.h"
63#include "MagickCore/splay-tree.h"
64#include "MagickCore/thread-private.h"
65#include "MagickCore/timer-private.h"
66#include "MagickCore/token.h"
67#include "MagickCore/utility.h"
68#include "MagickCore/utility-private.h"
69
70/*
71 Define declarations.
72*/
73#define NumberOfResourceTypes \
74 (sizeof(resource_semaphore)/sizeof(*resource_semaphore))
75
76/*
77 Typedef declarations.
78*/
79typedef struct _ResourceInfo
80{
81 MagickOffsetType
82 width,
83 height,
84 list_length,
85 area,
86 memory,
87 map,
88 disk,
89 file,
90 thread,
91 throttle,
92 time;
93
94 MagickSizeType
95 width_limit,
96 height_limit,
97 list_length_limit,
98 area_limit,
99 memory_limit,
100 map_limit,
101 disk_limit,
102 file_limit,
103 thread_limit,
104 throttle_limit,
105 time_limit;
106} ResourceInfo;
107
108/*
109 Global declarations.
110*/
111static RandomInfo
112 *random_info = (RandomInfo *) NULL;
113
114static ResourceInfo
115 resource_info =
116 {
117 MagickULLConstant(0), /* initial width */
118 MagickULLConstant(0), /* initial height */
119 MagickULLConstant(0), /* initial list length */
120 MagickULLConstant(0), /* initial area */
121 MagickULLConstant(0), /* initial memory */
122 MagickULLConstant(0), /* initial map */
123 MagickULLConstant(0), /* initial disk */
124 MagickULLConstant(0), /* initial file */
125 MagickULLConstant(0), /* initial thread */
126 MagickULLConstant(0), /* initial throttle */
127 MagickULLConstant(0), /* initial time */
128 (MagickSizeType) (MAGICK_SSIZE_MAX/sizeof(Quantum)/MaxPixelChannels), /* width limit */
129 (MagickSizeType) (MAGICK_SSIZE_MAX/sizeof(Quantum)/MaxPixelChannels), /* height limit */
130 MagickResourceInfinity, /* list length limit */
131 MagickULLConstant(3072)*1024*1024, /* area limit */
132 MagickULLConstant(1536)*1024*1024, /* memory limit */
133 MagickULLConstant(3072)*1024*1024, /* map limit */
134 MagickResourceInfinity, /* disk limit */
135 MagickULLConstant(768), /* file limit */
136 MagickULLConstant(1), /* thread limit */
137 MagickULLConstant(0), /* throttle limit */
138 MagickResourceInfinity, /* time limit */
139 };
140
141static SemaphoreInfo
142 *resource_semaphore[] = {
143 (SemaphoreInfo *) NULL,
144 (SemaphoreInfo *) NULL,
145 (SemaphoreInfo *) NULL,
146 (SemaphoreInfo *) NULL,
147 (SemaphoreInfo *) NULL,
148 (SemaphoreInfo *) NULL,
149 (SemaphoreInfo *) NULL,
150 (SemaphoreInfo *) NULL,
151 (SemaphoreInfo *) NULL,
152 (SemaphoreInfo *) NULL,
153 (SemaphoreInfo *) NULL,
154 (SemaphoreInfo *) NULL
155 };
156
157static SplayTreeInfo
158 *temporary_resources = (SplayTreeInfo *) NULL;
159
160/*
161%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162% %
163% %
164% %
165% A c q u i r e M a g i c k R e s o u r c e %
166% %
167% %
168% %
169%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170%
171% AcquireMagickResource() acquires resources of the specified type.
172% MagickFalse is returned if the specified resource is exhausted otherwise
173% MagickTrue.
174%
175% The format of the AcquireMagickResource() method is:
176%
177% MagickBooleanType AcquireMagickResource(const ResourceType type,
178% const MagickSizeType size)
179%
180% A description of each parameter follows:
181%
182% o type: the type of resource.
183%
184% o size: the number of bytes needed from for this resource.
185%
186*/
187MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
188 const MagickSizeType size)
189{
190 MagickBooleanType
191 bi,
192 status;
193
194 MagickOffsetType
195 current,
196 request;
197
198 MagickSizeType
199 limit;
200
201 request=(MagickOffsetType) size;
202 if (request < 0)
203 return(MagickFalse);
204 limit=0;
205 current=0;
206 bi=MagickFalse;
207 status=MagickFalse;
208 switch (type)
209 {
210 case DiskResource:
211 case FileResource:
212 case MapResource:
213 case MemoryResource:
214 case TimeResource:
215 {
216 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
217 ActivateSemaphoreInfo(&resource_semaphore[type]);
218 LockSemaphoreInfo(resource_semaphore[type]);
219 break;
220 }
221 default: ;
222 }
223 switch (type)
224 {
225 case AreaResource:
226 {
227 bi=MagickTrue;
228 resource_info.area=request;
229 limit=resource_info.area_limit;
230 if ((limit == MagickResourceInfinity) || (size < limit))
231 status=MagickTrue;
232 break;
233 }
234 case DiskResource:
235 {
236 bi=MagickTrue;
237 limit=resource_info.disk_limit;
238 if (resource_info.disk <= (MagickOffsetMax-request))
239 {
240 resource_info.disk+=request;
241 if ((limit == MagickResourceInfinity) ||
242 (resource_info.disk < (MagickOffsetType) limit))
243 status=MagickTrue;
244 else
245 resource_info.disk-=request;
246 }
247 current=resource_info.disk;
248 break;
249 }
250 case FileResource:
251 {
252 limit=resource_info.file_limit;
253 if (resource_info.file <= (MagickOffsetMax-request))
254 {
255 resource_info.file+=request;
256 if ((limit == MagickResourceInfinity) ||
257 (resource_info.file < (MagickOffsetType) limit))
258 status=MagickTrue;
259 }
260 current=resource_info.file;
261 break;
262 }
263 case HeightResource:
264 {
265 bi=MagickTrue;
266 resource_info.height=request;
267 limit=resource_info.height_limit;
268 if ((limit == MagickResourceInfinity) || (size < limit))
269 status=MagickTrue;
270 break;
271 }
272 case ListLengthResource:
273 {
274 resource_info.list_length=request;
275 limit=resource_info.list_length_limit;
276 if ((limit == MagickResourceInfinity) || (size < limit))
277 status=MagickTrue;
278 break;
279 }
280 case MapResource:
281 {
282 bi=MagickTrue;
283 limit=resource_info.map_limit;
284 if (resource_info.map <= (MagickOffsetMax-request))
285 {
286 resource_info.map+=request;
287 if ((limit == MagickResourceInfinity) ||
288 (resource_info.map < (MagickOffsetType) limit))
289 status=MagickTrue;
290 else
291 resource_info.map-=request;
292 }
293 current=resource_info.map;
294 break;
295 }
296 case MemoryResource:
297 {
298 bi=MagickTrue;
299 limit=resource_info.memory_limit;
300 if (resource_info.memory <= (MagickOffsetMax-request))
301 {
302 resource_info.memory+=request;
303 if ((limit == MagickResourceInfinity) ||
304 (resource_info.memory < (MagickOffsetType) limit))
305 status=MagickTrue;
306 else
307 resource_info.memory-=request;
308 }
309 current=resource_info.memory;
310 break;
311 }
312 case ThreadResource:
313 {
314 limit=resource_info.thread_limit;
315 if ((limit == MagickResourceInfinity) ||
316 (resource_info.thread < (MagickOffsetType) limit))
317 status=MagickTrue;
318 break;
319 }
320 case ThrottleResource:
321 {
322 limit=resource_info.throttle_limit;
323 if ((limit == MagickResourceInfinity) ||
324 (resource_info.throttle < (MagickOffsetType) limit))
325 status=MagickTrue;
326 break;
327 }
328 case TimeResource:
329 {
330 limit=resource_info.time_limit;
331 if (resource_info.time <= (MagickOffsetMax-request))
332 {
333 resource_info.time+=request;
334 if ((limit == MagickResourceInfinity) ||
335 (resource_info.time < (MagickOffsetType) limit))
336 status=MagickTrue;
337 else
338 resource_info.time-=request;
339 }
340 current=resource_info.time;
341 break;
342 }
343 case WidthResource:
344 {
345 bi=MagickTrue;
346 resource_info.width=request;
347 limit=resource_info.width_limit;
348 if ((limit == MagickResourceInfinity) || (size < limit))
349 status=MagickTrue;
350 break;
351 }
352 default:
353 {
354 current=0;
355 break;
356 }
357 }
358 switch (type)
359 {
360 case DiskResource:
361 case FileResource:
362 case MapResource:
363 case MemoryResource:
364 case TimeResource:
365 {
366 UnlockSemaphoreInfo(resource_semaphore[type]);
367 break;
368 }
369 default: ;
370 }
371 if ((GetLogEventMask() & ResourceEvent) != 0)
372 {
373 char
374 resource_current[MagickFormatExtent],
375 resource_limit[MagickFormatExtent],
376 resource_request[MagickFormatExtent];
377
378 (void) FormatMagickSize(size,bi,(bi != MagickFalse) ? "B" :
379 (const char *) NULL,MagickFormatExtent,resource_request);
380 (void) FormatMagickSize((MagickSizeType) current,bi,(bi != MagickFalse) ?
381 "B" : (const char *) NULL,MagickFormatExtent,resource_current);
382 (void) FormatMagickSize(limit,bi,(bi != MagickFalse) ? "B" :
383 (const char *) NULL,MagickFormatExtent,resource_limit);
384 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
385 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
386 resource_request,resource_current,resource_limit);
387 }
388 return(status);
389}
390
391/*
392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393% %
394% %
395% %
396+ 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 %
397% %
398% %
399% %
400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401%
402% AsynchronousResourceComponentTerminus() destroys the resource environment.
403% It differs from ResourceComponentTerminus() in that it can be called from a
404% asynchronous signal handler.
405%
406% The format of the ResourceComponentTerminus() method is:
407%
408% ResourceComponentTerminus(void)
409%
410*/
411MagickExport void AsynchronousResourceComponentTerminus(void)
412{
413 const char
414 *path;
415
416 if (temporary_resources == (SplayTreeInfo *) NULL)
417 return;
418 /*
419 Remove any lingering temporary files.
420 */
421 ResetSplayTreeIterator(temporary_resources);
422 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
423 while (path != (const char *) NULL)
424 {
425 (void) ShredFile(path);
426 (void) remove_utf8(path);
427 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
428 }
429}
430
431/*
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433% %
434% %
435% %
436% 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 %
437% %
438% %
439% %
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441%
442% AcquireUniqueFileResource() returns a unique file name, and returns a file
443% descriptor for the file open for reading and writing.
444%
445% The format of the AcquireUniqueFileResource() method is:
446%
447% int AcquireUniqueFileResource(char *path)
448%
449% A description of each parameter follows:
450%
451% o path: Specifies a pointer to an array of characters. The unique path
452% name is returned in this array.
453%
454*/
455
456static void *DestroyTemporaryResources(void *temporary_resource)
457{
458 (void) ShredFile((char *) temporary_resource);
459 (void) remove_utf8((char *) temporary_resource);
460 temporary_resource=DestroyString((char *) temporary_resource);
461 return((void *) NULL);
462}
463
464MagickExport int AcquireUniqueFileResource(char *path)
465{
466 int
467 c,
468 file;
469
470 char
471 *p;
472
473 MagickBooleanType
474 status;
475
476 ssize_t
477 i;
478
479 static const char
480 portable_filename[65] =
481 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
482
483 StringInfo
484 *key;
485
486 struct stat
487 *attributes;
488
489 unsigned char
490 *datum;
491
492 assert(path != (char *) NULL);
493 if ((GetLogEventMask() & ResourceEvent) != 0)
494 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
495 if (random_info == (RandomInfo *) NULL)
496 {
497 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
498 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
499 LockSemaphoreInfo(resource_semaphore[FileResource]);
500 if (random_info == (RandomInfo *) NULL)
501 random_info=AcquireRandomInfo();
502 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
503 }
504 file=(-1);
505 for (i=0; i < (ssize_t) TMP_MAX; i++)
506 {
507 ssize_t
508 j;
509
510 /*
511 Get temporary pathname.
512 */
513 (void) GetPathTemplate(path);
514 key=GetRandomKey(random_info,strlen(MagickPathTemplate)-6);
515 p=path+strlen(path)-strlen(MagickPathTemplate);
516 datum=GetStringInfoDatum(key);
517 for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
518 {
519 c=(int) (datum[j] & 0x3f);
520 *p++=portable_filename[c];
521 }
522 key=DestroyStringInfo(key);
523#if defined(MAGICKCORE_HAVE_MKSTEMP)
524 file=mkstemp(path);
525 if (file != -1)
526 {
527#if defined(MAGICKCORE_HAVE_FCHMOD)
528 (void) fchmod(file,0600);
529#endif
530#if defined(__OS2__)
531 setmode(file,O_BINARY);
532#endif
533 break;
534 }
535#endif
536 key=GetRandomKey(random_info,strlen(MagickPathTemplate));
537 p=path+strlen(path)-strlen(MagickPathTemplate);
538 datum=GetStringInfoDatum(key);
539 for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
540 {
541 c=(int) (datum[j] & 0x3f);
542 *p++=portable_filename[c];
543 }
544 key=DestroyStringInfo(key);
545 file=open_utf8(path,O_RDWR | O_CLOEXEC | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
546 S_MODE);
547 if ((file >= 0) || (errno != EEXIST))
548 break;
549 }
550 if ((GetLogEventMask() & ResourceEvent) != 0)
551 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
552 if (file == -1)
553 return(file);
554 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
555 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
556 LockSemaphoreInfo(resource_semaphore[FileResource]);
557 if (temporary_resources == (SplayTreeInfo *) NULL)
558 temporary_resources=NewSplayTree(CompareSplayTreeString,
559 DestroyTemporaryResources,RelinquishMagickMemory);
560 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
561 attributes=(struct stat *) AcquireCriticalMemory(sizeof(struct stat));
562 status=GetPathAttributes(path,attributes);
563 if (status == MagickFalse)
564 attributes=(struct stat *) RelinquishMagickMemory(attributes);
565 else
566 status=AddValueToSplayTree(temporary_resources,ConstantString(path),
567 attributes);
568 if (status == MagickFalse)
569 file=close_utf8(file)-1;
570 return(file);
571}
572
573/*
574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575% %
576% %
577% %
578% G e t M a g i c k R e s o u r c e %
579% %
580% %
581% %
582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583%
584% GetMagickResource() returns the specified resource.
585%
586% The format of the GetMagickResource() method is:
587%
588% MagickSizeType GetMagickResource(const ResourceType type)
589%
590% A description of each parameter follows:
591%
592% o type: the type of resource.
593%
594*/
595MagickExport MagickSizeType GetMagickResource(const ResourceType type)
596{
597 MagickSizeType
598 resource;
599
600 resource=0;
601 switch (type)
602 {
603 case DiskResource:
604 case FileResource:
605 case MapResource:
606 case MemoryResource:
607 case TimeResource:
608 {
609 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
610 ActivateSemaphoreInfo(&resource_semaphore[type]);
611 LockSemaphoreInfo(resource_semaphore[type]);
612 break;
613 }
614 default: ;
615 }
616 switch (type)
617 {
618 case AreaResource:
619 {
620 resource=(MagickSizeType) resource_info.area;
621 break;
622 }
623 case DiskResource:
624 {
625 resource=(MagickSizeType) resource_info.disk;
626 break;
627 }
628 case FileResource:
629 {
630 resource=(MagickSizeType) resource_info.file;
631 break;
632 }
633 case HeightResource:
634 {
635 resource=(MagickSizeType) resource_info.height;
636 break;
637 }
638 case ListLengthResource:
639 {
640 resource=(MagickSizeType) resource_info.list_length;
641 break;
642 }
643 case MapResource:
644 {
645 resource=(MagickSizeType) resource_info.map;
646 break;
647 }
648 case MemoryResource:
649 {
650 resource=(MagickSizeType) resource_info.memory;
651 break;
652 }
653 case TimeResource:
654 {
655 resource=(MagickSizeType) resource_info.time;
656 break;
657 }
658 case ThreadResource:
659 {
660 resource=(MagickSizeType) resource_info.thread;
661 break;
662 }
663 case ThrottleResource:
664 {
665 resource=(MagickSizeType) resource_info.throttle;
666 break;
667 }
668 case WidthResource:
669 {
670 resource=(MagickSizeType) resource_info.width;
671 break;
672 }
673 default:
674 break;
675 }
676 switch (type)
677 {
678 case DiskResource:
679 case FileResource:
680 case MapResource:
681 case MemoryResource:
682 case TimeResource:
683 {
684 UnlockSemaphoreInfo(resource_semaphore[type]);
685 break;
686 }
687 default: ;
688 }
689 return(resource);
690}
691
692/*
693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
694% %
695% %
696% %
697% I s F i l e R e s o u r c e I d e n t i t y V a l i d %
698% %
699% %
700% %
701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702%
703% IsFileResourceIdentityValid() returns MagickTrue if the file resource
704% identity is valid.
705%
706% The format of the IsFileResourceIdentityValid() method is:
707%
708% MagickBooleanType IsFileResourceIdentityValid(const char *path)
709%
710% A description of each parameter follows:
711%
712% o path: the file resource path.
713%
714*/
715MagickExport MagickBooleanType IsFileResourceIdentityValid(const char *path)
716{
717 const struct stat
718 *temporary_attributes;
719
720 MagickBooleanType
721 status = MagickTrue;
722
723 struct stat
724 attributes;
725
726 if (temporary_resources == (SplayTreeInfo *) NULL)
727 return(MagickTrue);
728 LockSemaphoreInfo(resource_semaphore[FileResource]);
729 temporary_attributes=(const struct stat *) GetValueFromSplayTree(
730 temporary_resources,(const void *) path);
731 if (temporary_attributes != (const struct stat *) NULL)
732 {
733 status=GetPathAttributes(path,&attributes);
734 if (status != MagickFalse)
735 if ((attributes.st_dev != temporary_attributes->st_dev) ||
736 (attributes.st_ino != temporary_attributes->st_ino) ||
737 (attributes.st_mode != temporary_attributes->st_mode))
738 status=MagickFalse;
739 }
740 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
741 return(status);
742}
743
744/*
745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
746% %
747% %
748% %
749% G e t M a g i c k R e s o u r c e L i m i t %
750% %
751% %
752% %
753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754%
755% GetMagickResourceLimit() returns the specified resource limit.
756%
757% The format of the GetMagickResourceLimit() method is:
758%
759% MagickSizeType GetMagickResourceLimit(const ResourceType type)
760%
761% A description of each parameter follows:
762%
763% o type: the type of resource.
764%
765*/
766MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
767{
768 MagickSizeType
769 resource;
770
771 switch (type)
772 {
773 case AreaResource:
774 return(resource_info.area_limit);
775 case HeightResource:
776 return(resource_info.height_limit);
777 case ListLengthResource:
778 return(resource_info.list_length_limit);
779 case ThreadResource:
780 return(resource_info.thread_limit);
781 case ThrottleResource:
782 return(resource_info.throttle_limit);
783 case WidthResource:
784 return(resource_info.width_limit);
785 default: ;
786 }
787 resource=0;
788 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
789 ActivateSemaphoreInfo(&resource_semaphore[type]);
790 LockSemaphoreInfo(resource_semaphore[type]);
791 switch (type)
792 {
793 case DiskResource:
794 {
795 resource=resource_info.disk_limit;
796 break;
797 }
798 case FileResource:
799 {
800 resource=resource_info.file_limit;
801 break;
802 }
803 case MapResource:
804 {
805 resource=resource_info.map_limit;
806 break;
807 }
808 case MemoryResource:
809 {
810 resource=resource_info.memory_limit;
811 break;
812 }
813 case TimeResource:
814 {
815 resource=resource_info.time_limit;
816 break;
817 }
818 default:
819 break;
820 }
821 UnlockSemaphoreInfo(resource_semaphore[type]);
822 return(resource);
823}
824
825/*
826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827% %
828% %
829% %
830% L i s t M a g i c k R e s o u r c e I n f o %
831% %
832% %
833% %
834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835%
836% ListMagickResourceInfo() lists the resource info to a file.
837%
838% The format of the ListMagickResourceInfo method is:
839%
840% MagickBooleanType ListMagickResourceInfo(FILE *file,
841% ExceptionInfo *exception)
842%
843% A description of each parameter follows.
844%
845% o file: An pointer to a FILE.
846%
847% o exception: return any errors or warnings in this structure.
848%
849*/
850
851static void FormatTimeToLive(const MagickSizeType ttl,char *timeString)
852{
853 MagickSizeType
854 days,
855 hours,
856 minutes,
857 months,
858 seconds,
859 weeks,
860 years;
861
862 years=ttl/31536000;
863 seconds=ttl % 31536000;
864 if (seconds == 0)
865 {
866 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld years",years);
867 return;
868 }
869 months=ttl/2628000;
870 seconds=ttl % 2628000;
871 if (seconds == 0)
872 {
873 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld months",
874 months);
875 return;
876 }
877 weeks=ttl/604800;
878 seconds=ttl % 604800;
879 if (seconds == 0)
880 {
881 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld weeks",weeks);
882 return;
883 }
884 days=ttl/86400;
885 seconds=ttl % 86400;
886 if (seconds == 0)
887 {
888 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld days",days);
889 return;
890 }
891 hours=ttl/3600;
892 seconds=ttl % 3600;
893 if (seconds == 0)
894 {
895 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld hours",hours);
896 return;
897 }
898 minutes=ttl/60;
899 seconds=ttl % 60;
900 if (seconds == 0)
901 {
902 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld minutes",
903 minutes);
904 return;
905 }
906 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld seconds",ttl);
907}
908
909MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
910 ExceptionInfo *magick_unused(exception))
911{
912 char
913 area_limit[MagickFormatExtent],
914 disk_limit[MagickFormatExtent],
915 height_limit[MagickFormatExtent],
916 list_length_limit[MagickFormatExtent],
917 map_limit[MagickFormatExtent],
918 memory_limit[MagickFormatExtent],
919 time_limit[MagickFormatExtent],
920 width_limit[MagickFormatExtent];
921
922 magick_unreferenced(exception);
923
924 if (file == (const FILE *) NULL)
925 file=stdout;
926 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
927 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
928 LockSemaphoreInfo(resource_semaphore[FileResource]);
929 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
930 MagickFormatExtent,width_limit);
931 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
932 MagickFormatExtent,height_limit);
933 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"P",
934 MagickFormatExtent,area_limit);
935 (void) CopyMagickString(list_length_limit,"unlimited",MagickFormatExtent);
936 if (resource_info.list_length_limit != MagickResourceInfinity)
937 (void) FormatMagickSize(resource_info.list_length_limit,MagickTrue,"B",
938 MagickFormatExtent,list_length_limit);
939 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
940 MagickFormatExtent,memory_limit);
941 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
942 MagickFormatExtent,map_limit);
943 (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
944 if (resource_info.disk_limit != MagickResourceInfinity)
945 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
946 MagickFormatExtent,disk_limit);
947 (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
948 if (resource_info.time_limit != MagickResourceInfinity)
949 FormatTimeToLive(resource_info.time_limit,time_limit);
950 (void) FormatLocaleFile(file,"Resource limits:\n");
951 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
952 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
953 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
954 (void) FormatLocaleFile(file," List length: %s\n",list_length_limit);
955 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
956 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
957 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
958 (void) FormatLocaleFile(file," File: %.17g\n",(double) ((MagickOffsetType)
959 resource_info.file_limit));
960 (void) FormatLocaleFile(file," Thread: %.17g\n",(double) ((MagickOffsetType)
961 resource_info.thread_limit));
962 (void) FormatLocaleFile(file," Throttle: %.17g\n",(double)
963 ((MagickOffsetType) resource_info.throttle_limit));
964 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
965 (void) fflush(file);
966 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
967 return(MagickTrue);
968}
969
970/*
971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972% %
973% %
974% %
975% R e l i n q u i s h M a g i c k R e s o u r c e %
976% %
977% %
978% %
979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980%
981% RelinquishMagickResource() relinquishes resources of the specified type.
982%
983% The format of the RelinquishMagickResource() method is:
984%
985% void RelinquishMagickResource(const ResourceType type,
986% const MagickSizeType size)
987%
988% A description of each parameter follows:
989%
990% o type: the type of resource.
991%
992% o size: the size of the resource.
993%
994*/
995MagickExport void RelinquishMagickResource(const ResourceType type,
996 const MagickSizeType size)
997{
998 MagickBooleanType
999 bi;
1000
1001 MagickSizeType
1002 current,
1003 limit;
1004
1005 bi=MagickFalse;
1006 limit=0;
1007 current=0;
1008 switch (type)
1009 {
1010 case DiskResource:
1011 case FileResource:
1012 case MapResource:
1013 case MemoryResource:
1014 case TimeResource:
1015 {
1016 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
1017 ActivateSemaphoreInfo(&resource_semaphore[type]);
1018 LockSemaphoreInfo(resource_semaphore[type]);
1019 break;
1020 }
1021 default: ;
1022 }
1023 switch (type)
1024 {
1025 case DiskResource:
1026 {
1027 bi=MagickTrue;
1028 resource_info.disk-=(MagickOffsetType) size;
1029 current=(MagickSizeType) resource_info.disk;
1030 limit=resource_info.disk_limit;
1031 assert(resource_info.disk >= 0);
1032 break;
1033 }
1034 case FileResource:
1035 {
1036 resource_info.file-=(MagickOffsetType) size;
1037 current=(MagickSizeType) resource_info.file;
1038 limit=resource_info.file_limit;
1039 assert(resource_info.file >= 0);
1040 break;
1041 }
1042 case MapResource:
1043 {
1044 bi=MagickTrue;
1045 resource_info.map-=(MagickOffsetType) size;
1046 current=(MagickSizeType) resource_info.map;
1047 limit=resource_info.map_limit;
1048 assert(resource_info.map >= 0);
1049 break;
1050 }
1051 case MemoryResource:
1052 {
1053 bi=MagickTrue;
1054 resource_info.memory-=(MagickOffsetType) size;
1055 current=(MagickSizeType) resource_info.memory;
1056 limit=resource_info.memory_limit;
1057 assert(resource_info.memory >= 0);
1058 break;
1059 }
1060 case TimeResource:
1061 {
1062 bi=MagickTrue;
1063 resource_info.time-=(MagickOffsetType) size;
1064 current=(MagickSizeType) resource_info.time;
1065 limit=resource_info.time_limit;
1066 assert(resource_info.time >= 0);
1067 break;
1068 }
1069 default:
1070 {
1071 current=0;
1072 break;
1073 }
1074 }
1075 switch (type)
1076 {
1077 case DiskResource:
1078 case FileResource:
1079 case MapResource:
1080 case MemoryResource:
1081 case TimeResource:
1082 {
1083 UnlockSemaphoreInfo(resource_semaphore[type]);
1084 break;
1085 }
1086 default: ;
1087 }
1088 if ((GetLogEventMask() & ResourceEvent) != 0)
1089 {
1090 char
1091 resource_current[MagickFormatExtent],
1092 resource_limit[MagickFormatExtent],
1093 resource_request[MagickFormatExtent];
1094
1095 (void) FormatMagickSize(size,bi,(bi != MagickFalse) ? "B" :
1096 (const char *) NULL,MagickFormatExtent,resource_request);
1097 (void) FormatMagickSize(current,bi,(bi != MagickFalse) ? "B" :
1098 (const char *) NULL,MagickFormatExtent,resource_current);
1099 (void) FormatMagickSize(limit,bi,(bi != MagickFalse) ? "B" :
1100 (const char *) NULL,MagickFormatExtent,resource_limit);
1101 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
1102 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
1103 resource_request,resource_current,resource_limit);
1104 }
1105}
1106
1107/*
1108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109% %
1110% %
1111% %
1112% 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 %
1113% %
1114% %
1115% %
1116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117%
1118% RelinquishUniqueFileResource() relinquishes a unique file resource.
1119%
1120% The format of the RelinquishUniqueFileResource() method is:
1121%
1122% MagickBooleanType RelinquishUniqueFileResource(const char *path)
1123%
1124% A description of each parameter follows:
1125%
1126% o name: the name of the temporary resource.
1127%
1128*/
1129MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
1130{
1131 char
1132 cache_path[MagickPathExtent];
1133
1134 MagickStatusType
1135 status;
1136
1137 assert(path != (const char *) NULL);
1138 status=MagickFalse;
1139 if ((GetLogEventMask() & ResourceEvent) != 0)
1140 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
1141 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
1142 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
1143 LockSemaphoreInfo(resource_semaphore[FileResource]);
1144 if (temporary_resources != (SplayTreeInfo *) NULL)
1145 status=DeleteNodeFromSplayTree(temporary_resources,(const void *) path);
1146 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1147 (void) CopyMagickString(cache_path,path,MagickPathExtent);
1148 AppendImageFormat("cache",cache_path);
1149 if (access_utf8(cache_path,F_OK) == 0)
1150 {
1151 status=ShredFile(cache_path);
1152 status|=(MagickStatusType) remove_utf8(cache_path);
1153 }
1154 if (status == MagickFalse)
1155 {
1156 status=ShredFile(path);
1157 status|=(MagickStatusType) remove_utf8(path);
1158 }
1159 return(status == 0 ? MagickFalse : MagickTrue);
1160}
1161
1162/*
1163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164% %
1165% %
1166% %
1167+ R e s o u r c e C o m p o n e n t G e n e s i s %
1168% %
1169% %
1170% %
1171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172%
1173% ResourceComponentGenesis() instantiates the resource component.
1174%
1175% The format of the ResourceComponentGenesis method is:
1176%
1177% MagickBooleanType ResourceComponentGenesis(void)
1178%
1179*/
1180
1181MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1182{
1183 char
1184 *limit;
1185
1186 MagickSizeType
1187 memory;
1188
1189 ssize_t
1190 files,
1191 i,
1192 number_threads,
1193 pages,
1194 pagesize;
1195
1196 /*
1197 Set Magick resource limits.
1198 */
1199 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1200 if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
1201 resource_semaphore[i]=AcquireSemaphoreInfo();
1202 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1203 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1204 if (limit != (char *) NULL)
1205 {
1206 (void) SetMagickResourceLimit(WidthResource,StringToMagickSizeType(limit,
1207 100.0));
1208 limit=DestroyString(limit);
1209 }
1210 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1211 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1212 if (limit != (char *) NULL)
1213 {
1214 (void) SetMagickResourceLimit(HeightResource,StringToMagickSizeType(
1215 limit,100.0));
1216 limit=DestroyString(limit);
1217 }
1218 pagesize=GetMagickPageSize();
1219 pages=(-1);
1220#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1221 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1222#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1223 pages=pages/2;
1224#endif
1225#endif
1226 memory=(MagickSizeType) ((MagickOffsetType) pages*pagesize);
1227 if ((pagesize <= 0) || (pages <= 0))
1228 memory=2048UL*1024UL*1024UL;
1229#if defined(MAGICKCORE_PixelCacheThreshold)
1230 memory=StringToMagickSizeType(MAGICKCORE_PixelCacheThreshold,100.0);
1231#endif
1232 (void) SetMagickResourceLimit(AreaResource,4*memory);
1233 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1234 if (limit != (char *) NULL)
1235 {
1236 (void) SetMagickResourceLimit(AreaResource,StringToMagickSizeType(limit,
1237 100.0));
1238 limit=DestroyString(limit);
1239 }
1240 (void) SetMagickResourceLimit(MemoryResource,memory);
1241 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1242 if (limit != (char *) NULL)
1243 {
1244 (void) SetMagickResourceLimit(MemoryResource,StringToMagickSizeType(
1245 limit,100.0));
1246 limit=DestroyString(limit);
1247 }
1248 (void) SetMagickResourceLimit(MapResource,2*memory);
1249 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1250 if (limit != (char *) NULL)
1251 {
1252 (void) SetMagickResourceLimit(MapResource,StringToMagickSizeType(limit,
1253 100.0));
1254 limit=DestroyString(limit);
1255 }
1256 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1257 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1258 if (limit != (char *) NULL)
1259 {
1260 (void) SetMagickResourceLimit(DiskResource,StringToMagickSizeType(limit,
1261 100.0));
1262 limit=DestroyString(limit);
1263 }
1264 files=(-1);
1265#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1266 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1267#endif
1268#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1269 if (files < 0)
1270 {
1271 struct rlimit
1272 resources;
1273
1274 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1275 files=(ssize_t) resources.rlim_cur;
1276 }
1277#endif
1278#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1279 if (files < 0)
1280 files=(ssize_t) getdtablesize();
1281#endif
1282 if (files < 0)
1283 files=64;
1284 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1285 (3*files/4),64));
1286 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1287 if (limit != (char *) NULL)
1288 {
1289 (void) SetMagickResourceLimit(FileResource,StringToMagickSizeType(limit,
1290 100.0));
1291 limit=DestroyString(limit);
1292 }
1293 number_threads=(ssize_t) GetOpenMPMaximumThreads();
1294 if (number_threads > 1)
1295 number_threads--; /* reserve core for OS */
1296 (void) SetMagickResourceLimit(ThreadResource,(size_t) number_threads);
1297 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1298 if (limit != (char *) NULL)
1299 {
1300 (void) SetMagickResourceLimit(ThreadResource,StringToMagickSizeType(
1301 limit,100.0));
1302 limit=DestroyString(limit);
1303 }
1304 (void) SetMagickResourceLimit(ThrottleResource,0);
1305 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1306 if (limit != (char *) NULL)
1307 {
1308 (void) SetMagickResourceLimit(ThrottleResource,StringToMagickSizeType(
1309 limit,100.0));
1310 limit=DestroyString(limit);
1311 }
1312 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1313 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1314 if (limit != (char *) NULL)
1315 {
1316 (void) SetMagickResourceLimit(TimeResource,(MagickSizeType)
1317 ParseMagickTimeToLive(limit));
1318 limit=DestroyString(limit);
1319 }
1320 (void) SetMagickResourceLimit(ListLengthResource,MagickResourceInfinity);
1321 limit=GetEnvironmentValue("MAGICK_LIST_LENGTH_LIMIT");
1322 if (limit != (char *) NULL)
1323 {
1324 (void) SetMagickResourceLimit(ListLengthResource,
1325 StringToMagickSizeType(limit,100.0));
1326 limit=DestroyString(limit);
1327 }
1328 return(MagickTrue);
1329}
1330
1331#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1332/*
1333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1334% %
1335% %
1336% %
1337% R e s e t M a g i c k R e s o u r c e C o u n t e r s %
1338% %
1339% %
1340% %
1341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1342%
1343% ResetMagickResourceCounters() resets the current resource usage counters
1344% to zero. This is useful for fuzzing to ensure deterministic behavior
1345% between iterations.
1346%
1347% The format of the ResetMagickResourceCounters() method is:
1348%
1349% void ResetMagickResourceCounters(void)
1350%
1351*/
1352MagickExport void ResetMagickResourceCounters(void)
1353{
1354 resource_info.width=0;
1355 resource_info.height=0;
1356 resource_info.list_length=0;
1357 resource_info.area=0;
1358 resource_info.memory=0;
1359 resource_info.map=0;
1360 resource_info.disk=0;
1361 resource_info.file=0;
1362 resource_info.thread=0;
1363 resource_info.throttle=0;
1364 resource_info.time=0;
1365}
1366#endif
1367
1368/*
1369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1370% %
1371% %
1372% %
1373+ 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 %
1374% %
1375% %
1376% %
1377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1378%
1379% ResourceComponentTerminus() destroys the resource component.
1380%
1381% The format of the ResourceComponentTerminus() method is:
1382%
1383% ResourceComponentTerminus(void)
1384%
1385*/
1386MagickPrivate void ResourceComponentTerminus(void)
1387{
1388 ssize_t
1389 i;
1390
1391 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1392 if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
1393 resource_semaphore[i]=AcquireSemaphoreInfo();
1394 LockSemaphoreInfo(resource_semaphore[FileResource]);
1395 if (temporary_resources != (SplayTreeInfo *) NULL)
1396 temporary_resources=DestroySplayTree(temporary_resources);
1397 if (random_info != (RandomInfo *) NULL)
1398 random_info=DestroyRandomInfo(random_info);
1399 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1400 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1401 RelinquishSemaphoreInfo(&resource_semaphore[i]);
1402}
1403
1404/*
1405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1406% %
1407% %
1408% %
1409% S e t M a g i c k R e s o u r c e L i m i t %
1410% %
1411% %
1412% %
1413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414%
1415% SetMagickResourceLimit() sets the limit for a particular resource.
1416%
1417% The format of the SetMagickResourceLimit() method is:
1418%
1419% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1420% const MagickSizeType limit)
1421%
1422% A description of each parameter follows:
1423%
1424% o type: the type of resource.
1425%
1426% o limit: the maximum limit for the resource.
1427%
1428*/
1429MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1430 const MagickSizeType limit)
1431{
1432 char
1433 *value;
1434
1435 MagickBooleanType
1436 status;
1437
1438 status=MagickTrue;
1439 value=(char *) NULL;
1440 switch (type)
1441 {
1442 case DiskResource:
1443 case FileResource:
1444 case MapResource:
1445 case MemoryResource:
1446 case TimeResource:
1447 {
1448 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
1449 ActivateSemaphoreInfo(&resource_semaphore[type]);
1450 LockSemaphoreInfo(resource_semaphore[type]);
1451 break;
1452 }
1453 default: ;
1454 }
1455 switch (type)
1456 {
1457 case AreaResource:
1458 {
1459 value=GetPolicyValue("resource:area");
1460 if (value == (char *) NULL)
1461 resource_info.area_limit=limit;
1462 else
1463 resource_info.area_limit=MagickMin(limit,StringToMagickSizeType(value,
1464 100.0));
1465 break;
1466 }
1467 case DiskResource:
1468 {
1469 value=GetPolicyValue("resource:disk");
1470 if (value == (char *) NULL)
1471 resource_info.disk_limit=limit;
1472 else
1473 resource_info.disk_limit=MagickMin(limit,StringToMagickSizeType(value,
1474 100.0));
1475 break;
1476 }
1477 case FileResource:
1478 {
1479 value=GetPolicyValue("resource:file");
1480 if (value == (char *) NULL)
1481 resource_info.file_limit=limit;
1482 else
1483 resource_info.file_limit=MagickMin(limit,StringToMagickSizeType(value,
1484 100.0));
1485 break;
1486 }
1487 case HeightResource:
1488 {
1489 value=GetPolicyValue("resource:height");
1490 if (value == (char *) NULL)
1491 resource_info.height_limit=limit;
1492 else
1493 resource_info.height_limit=MagickMin(limit,StringToMagickSizeType(
1494 value,100.0));
1495 resource_info.height_limit=MagickMin(resource_info.height_limit,
1496 (MagickSizeType) MAGICK_SSIZE_MAX);
1497 break;
1498 }
1499 case ListLengthResource:
1500 {
1501 value=GetPolicyValue("resource:list-length");
1502 if (value == (char *) NULL)
1503 resource_info.list_length_limit=limit;
1504 else
1505 resource_info.list_length_limit=MagickMin(limit,
1506 StringToMagickSizeType(value,100.0));
1507 break;
1508 }
1509 case MapResource:
1510 {
1511 value=GetPolicyValue("resource:map");
1512 if (value == (char *) NULL)
1513 resource_info.map_limit=limit;
1514 else
1515 resource_info.map_limit=MagickMin(limit,StringToMagickSizeType(
1516 value,100.0));
1517 break;
1518 }
1519 case MemoryResource:
1520 {
1521 value=GetPolicyValue("resource:memory");
1522 if (value == (char *) NULL)
1523 resource_info.memory_limit=limit;
1524 else
1525 resource_info.memory_limit=MagickMin(limit,StringToMagickSizeType(
1526 value,100.0));
1527 break;
1528 }
1529 case ThreadResource:
1530 {
1531 value=GetPolicyValue("resource:thread");
1532 if (value == (char *) NULL)
1533 resource_info.thread_limit=limit;
1534 else
1535 resource_info.thread_limit=MagickMin(limit,StringToMagickSizeType(
1536 value,100.0));
1537 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1538 resource_info.thread_limit=GetOpenMPMaximumThreads();
1539 else
1540 if (resource_info.thread_limit == 0)
1541 resource_info.thread_limit=1;
1542 break;
1543 }
1544 case ThrottleResource:
1545 {
1546 value=GetPolicyValue("resource:throttle");
1547 if (value == (char *) NULL)
1548 resource_info.throttle_limit=limit;
1549 else
1550 resource_info.throttle_limit=MagickMax(limit,StringToMagickSizeType(
1551 value,100.0));
1552 break;
1553 }
1554 case TimeResource:
1555 {
1556 value=GetPolicyValue("resource:time");
1557 if (value == (char *) NULL)
1558 resource_info.time_limit=limit;
1559 else
1560 resource_info.time_limit=MagickMin(limit,(MagickSizeType)
1561 ParseMagickTimeToLive(value));
1562 break;
1563 }
1564 case WidthResource:
1565 {
1566 value=GetPolicyValue("resource:width");
1567 if (value == (char *) NULL)
1568 resource_info.width_limit=limit;
1569 else
1570 resource_info.width_limit=MagickMin(limit,StringToMagickSizeType(value,
1571 100.0));
1572 resource_info.width_limit=MagickMin(resource_info.width_limit,
1573 (MagickSizeType) MAGICK_SSIZE_MAX);
1574 break;
1575 }
1576 default:
1577 {
1578 status=MagickFalse;
1579 break;
1580 }
1581 }
1582 switch (type)
1583 {
1584 case DiskResource:
1585 case FileResource:
1586 case MapResource:
1587 case MemoryResource:
1588 case TimeResource:
1589 {
1590 UnlockSemaphoreInfo(resource_semaphore[type]);
1591 break;
1592 }
1593 default: ;
1594 }
1595 if (value != (char *) NULL)
1596 value=DestroyString(value);
1597 return(status);
1598}