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