MagickCore 7.1.1
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/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "MagickCore/studio.h"
43#include "MagickCore/cache.h"
44#include "MagickCore/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 MagickULLConstant(0), /* 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 (((MagickSizeType) resource_info.disk+(MagickSizeType) request) > (MagickSizeType) resource_info.disk)
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 (((MagickSizeType) resource_info.file+(MagickSizeType) request) > (MagickSizeType) resource_info.file)
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 (((MagickSizeType) resource_info.map+(MagickSizeType) request) > (MagickSizeType) resource_info.map)
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 (((MagickSizeType) resource_info.memory+(MagickSizeType) request) > (MagickSizeType) resource_info.memory)
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 (((MagickSizeType) resource_info.time+(MagickSizeType) request) > (MagickSizeType) resource_info.time)
333 {
334 resource_info.time+=request;
335 if ((limit == 0) || (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 MagickBooleanType GetPathTemplate(char *path)
465{
466 char
467 *directory,
468 *value;
469
471 *exception;
472
473 MagickBooleanType
474 status;
475
476 struct stat
477 attributes;
478
479 (void) FormatLocaleString(path,MagickPathExtent,"magick-" MagickPathTemplate);
480 exception=AcquireExceptionInfo();
481 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
482 exception);
483 exception=DestroyExceptionInfo(exception);
484 if (directory == (char *) NULL)
485 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
486 if (directory == (char *) NULL)
487 directory=GetEnvironmentValue("MAGICK_TMPDIR");
488 if (directory == (char *) NULL)
489 directory=GetEnvironmentValue("TMPDIR");
490#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
491 if (directory == (char *) NULL)
492 directory=GetEnvironmentValue("TMP");
493 if (directory == (char *) NULL)
494 directory=GetEnvironmentValue("TEMP");
495#endif
496#if defined(__VMS)
497 if (directory == (char *) NULL)
498 directory=GetEnvironmentValue("MTMPDIR");
499#endif
500#if defined(P_tmpdir)
501 if (directory == (char *) NULL)
502 directory=ConstantString(P_tmpdir);
503#endif
504 if (directory == (char *) NULL)
505 return(MagickTrue);
506 value=GetPolicyValue("resource:temporary-path");
507 if (value != (char *) NULL)
508 {
509 (void) CloneString(&directory,value);
510 value=DestroyString(value);
511 }
512 if (strlen(directory) > (MagickPathExtent-25))
513 {
514 directory=DestroyString(directory);
515 return(MagickFalse);
516 }
517 status=GetPathAttributes(directory,&attributes);
518 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
519 {
520 directory=DestroyString(directory);
521 return(MagickFalse);
522 }
523 if (directory[strlen(directory)-1] == *DirectorySeparator)
524 (void) FormatLocaleString(path,MagickPathExtent,"%smagick-"
525 MagickPathTemplate,directory);
526 else
527 (void) FormatLocaleString(path,MagickPathExtent,
528 "%s%smagick-" MagickPathTemplate,directory,DirectorySeparator);
529 directory=DestroyString(directory);
530#if defined(MAGICKCORE_WINDOWS_SUPPORT)
531 {
532 char
533 *p;
534
535 /*
536 Ghostscript does not like backslashes so we need to replace them. The
537 forward slash also works under Windows.
538 */
539 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
540 if (*p == *DirectorySeparator)
541 *p='/';
542 }
543#endif
544 return(MagickTrue);
545}
546
547MagickExport int AcquireUniqueFileResource(char *path)
548{
549#if !defined(O_NOFOLLOW)
550#define O_NOFOLLOW 0
551#endif
552#if !defined(TMP_MAX)
553# define TMP_MAX 238328
554#endif
555
556 int
557 c,
558 file;
559
560 char
561 *p;
562
563 ssize_t
564 i;
565
566 static const char
567 portable_filename[65] =
568 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
569
571 *key;
572
573 unsigned char
574 *datum;
575
576 assert(path != (char *) NULL);
577 if ((GetLogEventMask() & ResourceEvent) != 0)
578 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
579 if (random_info == (RandomInfo *) NULL)
580 {
581 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
582 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
583 LockSemaphoreInfo(resource_semaphore[FileResource]);
584 if (random_info == (RandomInfo *) NULL)
585 random_info=AcquireRandomInfo();
586 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
587 }
588 file=(-1);
589 for (i=0; i < (ssize_t) TMP_MAX; i++)
590 {
591 ssize_t
592 j;
593
594 /*
595 Get temporary pathname.
596 */
597 (void) GetPathTemplate(path);
598 key=GetRandomKey(random_info,strlen(MagickPathTemplate)-6);
599 p=path+strlen(path)-strlen(MagickPathTemplate);
600 datum=GetStringInfoDatum(key);
601 for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
602 {
603 c=(int) (datum[j] & 0x3f);
604 *p++=portable_filename[c];
605 }
606 key=DestroyStringInfo(key);
607#if defined(MAGICKCORE_HAVE_MKSTEMP)
608 file=mkstemp(path);
609 if (file != -1)
610 {
611#if defined(MAGICKCORE_HAVE_FCHMOD)
612 (void) fchmod(file,0600);
613#endif
614#if defined(__OS2__)
615 setmode(file,O_BINARY);
616#endif
617 break;
618 }
619#endif
620 key=GetRandomKey(random_info,strlen(MagickPathTemplate));
621 p=path+strlen(path)-strlen(MagickPathTemplate);
622 datum=GetStringInfoDatum(key);
623 for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
624 {
625 c=(int) (datum[j] & 0x3f);
626 *p++=portable_filename[c];
627 }
628 key=DestroyStringInfo(key);
629 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
630 S_MODE);
631 if ((file >= 0) || (errno != EEXIST))
632 break;
633 }
634 if ((GetLogEventMask() & ResourceEvent) != 0)
635 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
636 if (file == -1)
637 return(file);
638 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
639 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
640 LockSemaphoreInfo(resource_semaphore[FileResource]);
641 if (temporary_resources == (SplayTreeInfo *) NULL)
642 temporary_resources=NewSplayTree(CompareSplayTreeString,
643 DestroyTemporaryResources,(void *(*)(void *)) NULL);
644 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
645 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
646 (const void *) NULL);
647 return(file);
648}
649
650/*
651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652% %
653% %
654% %
655% G e t M a g i c k R e s o u r c e %
656% %
657% %
658% %
659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
660%
661% GetMagickResource() returns the specified resource.
662%
663% The format of the GetMagickResource() method is:
664%
665% MagickSizeType GetMagickResource(const ResourceType type)
666%
667% A description of each parameter follows:
668%
669% o type: the type of resource.
670%
671*/
672MagickExport MagickSizeType GetMagickResource(const ResourceType type)
673{
674 MagickSizeType
675 resource;
676
677 resource=0;
678 switch (type)
679 {
680 case DiskResource:
681 case FileResource:
682 case MapResource:
683 case MemoryResource:
684 case TimeResource:
685 {
686 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
687 ActivateSemaphoreInfo(&resource_semaphore[type]);
688 LockSemaphoreInfo(resource_semaphore[type]);
689 break;
690 }
691 default: ;
692 }
693 switch (type)
694 {
695 case AreaResource:
696 {
697 resource=(MagickSizeType) resource_info.area;
698 break;
699 }
700 case DiskResource:
701 {
702 resource=(MagickSizeType) resource_info.disk;
703 break;
704 }
705 case FileResource:
706 {
707 resource=(MagickSizeType) resource_info.file;
708 break;
709 }
710 case HeightResource:
711 {
712 resource=(MagickSizeType) resource_info.height;
713 break;
714 }
715 case ListLengthResource:
716 {
717 resource=(MagickSizeType) resource_info.list_length;
718 break;
719 }
720 case MapResource:
721 {
722 resource=(MagickSizeType) resource_info.map;
723 break;
724 }
725 case MemoryResource:
726 {
727 resource=(MagickSizeType) resource_info.memory;
728 break;
729 }
730 case TimeResource:
731 {
732 resource=(MagickSizeType) resource_info.time;
733 break;
734 }
735 case ThreadResource:
736 {
737 resource=(MagickSizeType) resource_info.thread;
738 break;
739 }
740 case ThrottleResource:
741 {
742 resource=(MagickSizeType) resource_info.throttle;
743 break;
744 }
745 case WidthResource:
746 {
747 resource=(MagickSizeType) resource_info.width;
748 break;
749 }
750 default:
751 break;
752 }
753 switch (type)
754 {
755 case DiskResource:
756 case FileResource:
757 case MapResource:
758 case MemoryResource:
759 case TimeResource:
760 {
761 UnlockSemaphoreInfo(resource_semaphore[type]);
762 break;
763 }
764 default: ;
765 }
766 return(resource);
767}
768
769/*
770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771% %
772% %
773% %
774% G e t M a g i c k R e s o u r c e L i m i t %
775% %
776% %
777% %
778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779%
780% GetMagickResourceLimit() returns the specified resource limit.
781%
782% The format of the GetMagickResourceLimit() method is:
783%
784% MagickSizeType GetMagickResourceLimit(const ResourceType type)
785%
786% A description of each parameter follows:
787%
788% o type: the type of resource.
789%
790*/
791MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
792{
793 MagickSizeType
794 resource;
795
796 switch (type)
797 {
798 case AreaResource:
799 return(resource_info.area_limit);
800 case HeightResource:
801 return(resource_info.height_limit);
802 case ListLengthResource:
803 return(resource_info.list_length_limit);
804 case ThreadResource:
805 return(resource_info.thread_limit);
806 case ThrottleResource:
807 return(resource_info.throttle_limit);
808 case WidthResource:
809 return(resource_info.width_limit);
810 default: ;
811 }
812 resource=0;
813 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
814 ActivateSemaphoreInfo(&resource_semaphore[type]);
815 LockSemaphoreInfo(resource_semaphore[type]);
816 switch (type)
817 {
818 case DiskResource:
819 {
820 resource=resource_info.disk_limit;
821 break;
822 }
823 case FileResource:
824 {
825 resource=resource_info.file_limit;
826 break;
827 }
828 case MapResource:
829 {
830 resource=resource_info.map_limit;
831 break;
832 }
833 case MemoryResource:
834 {
835 resource=resource_info.memory_limit;
836 break;
837 }
838 case TimeResource:
839 {
840 resource=resource_info.time_limit;
841 break;
842 }
843 default:
844 break;
845 }
846 UnlockSemaphoreInfo(resource_semaphore[type]);
847 return(resource);
848}
849
850/*
851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852% %
853% %
854% %
855% L i s t M a g i c k R e s o u r c e I n f o %
856% %
857% %
858% %
859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860%
861% ListMagickResourceInfo() lists the resource info to a file.
862%
863% The format of the ListMagickResourceInfo method is:
864%
865% MagickBooleanType ListMagickResourceInfo(FILE *file,
866% ExceptionInfo *exception)
867%
868% A description of each parameter follows.
869%
870% o file: An pointer to a FILE.
871%
872% o exception: return any errors or warnings in this structure.
873%
874*/
875
876static void FormatTimeToLive(const MagickSizeType ttl,char *timeString)
877{
878 MagickSizeType
879 days,
880 hours,
881 minutes,
882 months,
883 seconds,
884 weeks,
885 years;
886
887 years=ttl/31536000;
888 seconds=ttl % 31536000;
889 if (seconds == 0)
890 {
891 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld years",years);
892 return;
893 }
894 months=ttl/2628000;
895 seconds=ttl % 2628000;
896 if (seconds == 0)
897 {
898 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld months",
899 months);
900 return;
901 }
902 weeks=ttl/604800;
903 seconds=ttl % 604800;
904 if (seconds == 0)
905 {
906 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld weeks",weeks);
907 return;
908 }
909 days=ttl/86400;
910 seconds=ttl % 86400;
911 if (seconds == 0)
912 {
913 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld days",days);
914 return;
915 }
916 hours=ttl/3600;
917 seconds=ttl % 3600;
918 if (seconds == 0)
919 {
920 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld hours",hours);
921 return;
922 }
923 minutes=ttl/60;
924 seconds=ttl % 60;
925 if (seconds == 0)
926 {
927 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld minutes",
928 minutes);
929 return;
930 }
931 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld seconds",ttl);
932}
933
934MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
935 ExceptionInfo *magick_unused(exception))
936{
937 char
938 area_limit[MagickFormatExtent],
939 disk_limit[MagickFormatExtent],
940 height_limit[MagickFormatExtent],
941 list_length_limit[MagickFormatExtent],
942 map_limit[MagickFormatExtent],
943 memory_limit[MagickFormatExtent],
944 time_limit[MagickFormatExtent],
945 width_limit[MagickFormatExtent];
946
947 magick_unreferenced(exception);
948
949 if (file == (const FILE *) NULL)
950 file=stdout;
951 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
952 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
953 LockSemaphoreInfo(resource_semaphore[FileResource]);
954 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
955 MagickFormatExtent,width_limit);
956 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
957 MagickFormatExtent,height_limit);
958 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"P",
959 MagickFormatExtent,area_limit);
960 (void) CopyMagickString(list_length_limit,"unlimited",MagickFormatExtent);
961 if (resource_info.list_length_limit != MagickResourceInfinity)
962 (void) FormatMagickSize(resource_info.list_length_limit,MagickTrue,"B",
963 MagickFormatExtent,list_length_limit);
964 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
965 MagickFormatExtent,memory_limit);
966 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
967 MagickFormatExtent,map_limit);
968 (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
969 if (resource_info.disk_limit != MagickResourceInfinity)
970 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
971 MagickFormatExtent,disk_limit);
972 (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
973 if (resource_info.time_limit != 0)
974 FormatTimeToLive(resource_info.time_limit,time_limit);
975 (void) FormatLocaleFile(file,"Resource limits:\n");
976 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
977 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
978 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
979 (void) FormatLocaleFile(file," List length: %s\n",list_length_limit);
980 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
981 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
982 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
983 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
984 resource_info.file_limit));
985 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
986 resource_info.thread_limit));
987 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
988 ((MagickOffsetType) resource_info.throttle_limit));
989 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
990 (void) fflush(file);
991 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
992 return(MagickTrue);
993}
994
995/*
996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997% %
998% %
999% %
1000% R e l i n q u i s h M a g i c k R e s o u r c e %
1001% %
1002% %
1003% %
1004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005%
1006% RelinquishMagickResource() relinquishes resources of the specified type.
1007%
1008% The format of the RelinquishMagickResource() method is:
1009%
1010% void RelinquishMagickResource(const ResourceType type,
1011% const MagickSizeType size)
1012%
1013% A description of each parameter follows:
1014%
1015% o type: the type of resource.
1016%
1017% o size: the size of the resource.
1018%
1019*/
1020MagickExport void RelinquishMagickResource(const ResourceType type,
1021 const MagickSizeType size)
1022{
1023 MagickBooleanType
1024 bi;
1025
1026 MagickSizeType
1027 current,
1028 limit;
1029
1030 bi=MagickFalse;
1031 limit=0;
1032 current=0;
1033 switch (type)
1034 {
1035 case DiskResource:
1036 case FileResource:
1037 case MapResource:
1038 case MemoryResource:
1039 case TimeResource:
1040 {
1041 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
1042 ActivateSemaphoreInfo(&resource_semaphore[type]);
1043 LockSemaphoreInfo(resource_semaphore[type]);
1044 break;
1045 }
1046 default: ;
1047 }
1048 switch (type)
1049 {
1050 case DiskResource:
1051 {
1052 bi=MagickTrue;
1053 resource_info.disk-=(MagickOffsetType) size;
1054 current=(MagickSizeType) resource_info.disk;
1055 limit=resource_info.disk_limit;
1056 assert(resource_info.disk >= 0);
1057 break;
1058 }
1059 case FileResource:
1060 {
1061 resource_info.file-=(MagickOffsetType) size;
1062 current=(MagickSizeType) resource_info.file;
1063 limit=resource_info.file_limit;
1064 assert(resource_info.file >= 0);
1065 break;
1066 }
1067 case MapResource:
1068 {
1069 bi=MagickTrue;
1070 resource_info.map-=(MagickOffsetType) size;
1071 current=(MagickSizeType) resource_info.map;
1072 limit=resource_info.map_limit;
1073 assert(resource_info.map >= 0);
1074 break;
1075 }
1076 case MemoryResource:
1077 {
1078 bi=MagickTrue;
1079 resource_info.memory-=(MagickOffsetType) size;
1080 current=(MagickSizeType) resource_info.memory;
1081 limit=resource_info.memory_limit;
1082 assert(resource_info.memory >= 0);
1083 break;
1084 }
1085 case TimeResource:
1086 {
1087 bi=MagickTrue;
1088 resource_info.time-=(MagickOffsetType) size;
1089 current=(MagickSizeType) resource_info.time;
1090 limit=resource_info.time_limit;
1091 assert(resource_info.time >= 0);
1092 break;
1093 }
1094 default:
1095 {
1096 current=0;
1097 break;
1098 }
1099 }
1100 switch (type)
1101 {
1102 case DiskResource:
1103 case FileResource:
1104 case MapResource:
1105 case MemoryResource:
1106 case TimeResource:
1107 {
1108 UnlockSemaphoreInfo(resource_semaphore[type]);
1109 break;
1110 }
1111 default: ;
1112 }
1113 if ((GetLogEventMask() & ResourceEvent) != 0)
1114 {
1115 char
1116 resource_current[MagickFormatExtent],
1117 resource_limit[MagickFormatExtent],
1118 resource_request[MagickFormatExtent];
1119
1120 (void) FormatMagickSize(size,bi,(bi != MagickFalse) ? "B" :
1121 (const char *) NULL,MagickFormatExtent,resource_request);
1122 (void) FormatMagickSize(current,bi,(bi != MagickFalse) ? "B" :
1123 (const char *) NULL,MagickFormatExtent,resource_current);
1124 (void) FormatMagickSize(limit,bi,(bi != MagickFalse) ? "B" :
1125 (const char *) NULL,MagickFormatExtent,resource_limit);
1126 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
1127 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
1128 resource_request,resource_current,resource_limit);
1129 }
1130}
1131
1132/*
1133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1134% %
1135% %
1136% %
1137% 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 %
1138% %
1139% %
1140% %
1141%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1142%
1143% RelinquishUniqueFileResource() relinquishes a unique file resource.
1144%
1145% The format of the RelinquishUniqueFileResource() method is:
1146%
1147% MagickBooleanType RelinquishUniqueFileResource(const char *path)
1148%
1149% A description of each parameter follows:
1150%
1151% o name: the name of the temporary resource.
1152%
1153*/
1154MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
1155{
1156 char
1157 cache_path[MagickPathExtent];
1158
1159 MagickStatusType
1160 status;
1161
1162 assert(path != (const char *) NULL);
1163 status=MagickFalse;
1164 if ((GetLogEventMask() & ResourceEvent) != 0)
1165 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
1166 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
1167 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
1168 LockSemaphoreInfo(resource_semaphore[FileResource]);
1169 if (temporary_resources != (SplayTreeInfo *) NULL)
1170 status=DeleteNodeFromSplayTree(temporary_resources,(const void *) path);
1171 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1172 (void) CopyMagickString(cache_path,path,MagickPathExtent);
1173 AppendImageFormat("cache",cache_path);
1174 if (access_utf8(cache_path,F_OK) == 0)
1175 {
1176 status=ShredFile(cache_path);
1177 status|=(MagickStatusType) remove_utf8(cache_path);
1178 }
1179 if (status == MagickFalse)
1180 {
1181 status=ShredFile(path);
1182 status|=(MagickStatusType) remove_utf8(path);
1183 }
1184 return(status == 0 ? MagickFalse : MagickTrue);
1185}
1186
1187/*
1188%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189% %
1190% %
1191% %
1192+ R e s o u r c e C o m p o n e n t G e n e s i s %
1193% %
1194% %
1195% %
1196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1197%
1198% ResourceComponentGenesis() instantiates the resource component.
1199%
1200% The format of the ResourceComponentGenesis method is:
1201%
1202% MagickBooleanType ResourceComponentGenesis(void)
1203%
1204*/
1205
1206MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1207{
1208 char
1209 *limit;
1210
1211 MagickSizeType
1212 memory;
1213
1214 ssize_t
1215 files,
1216 i,
1217 number_threads,
1218 pages,
1219 pagesize;
1220
1221 /*
1222 Set Magick resource limits.
1223 */
1224 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1225 if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
1226 resource_semaphore[i]=AcquireSemaphoreInfo();
1227 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1228 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1229 if (limit != (char *) NULL)
1230 {
1231 (void) SetMagickResourceLimit(WidthResource,StringToMagickSizeType(limit,
1232 100.0));
1233 limit=DestroyString(limit);
1234 }
1235 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1236 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1237 if (limit != (char *) NULL)
1238 {
1239 (void) SetMagickResourceLimit(HeightResource,StringToMagickSizeType(
1240 limit,100.0));
1241 limit=DestroyString(limit);
1242 }
1243 pagesize=GetMagickPageSize();
1244 pages=(-1);
1245#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1246 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1247#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1248 pages=pages/2;
1249#endif
1250#endif
1251 memory=(MagickSizeType) ((MagickOffsetType) pages*pagesize);
1252 if ((pagesize <= 0) || (pages <= 0))
1253 memory=2048UL*1024UL*1024UL;
1254#if defined(MAGICKCORE_PixelCacheThreshold)
1255 memory=MAGICKCORE_PixelCacheThreshold;
1256#endif
1257 (void) SetMagickResourceLimit(AreaResource,4*memory);
1258 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1259 if (limit != (char *) NULL)
1260 {
1261 (void) SetMagickResourceLimit(AreaResource,StringToMagickSizeType(limit,
1262 100.0));
1263 limit=DestroyString(limit);
1264 }
1265 (void) SetMagickResourceLimit(MemoryResource,memory);
1266 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1267 if (limit != (char *) NULL)
1268 {
1269 (void) SetMagickResourceLimit(MemoryResource,StringToMagickSizeType(
1270 limit,100.0));
1271 limit=DestroyString(limit);
1272 }
1273 (void) SetMagickResourceLimit(MapResource,2*memory);
1274 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1275 if (limit != (char *) NULL)
1276 {
1277 (void) SetMagickResourceLimit(MapResource,StringToMagickSizeType(limit,
1278 100.0));
1279 limit=DestroyString(limit);
1280 }
1281 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1282 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1283 if (limit != (char *) NULL)
1284 {
1285 (void) SetMagickResourceLimit(DiskResource,StringToMagickSizeType(limit,
1286 100.0));
1287 limit=DestroyString(limit);
1288 }
1289 files=(-1);
1290#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1291 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1292#endif
1293#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1294 if (files < 0)
1295 {
1296 struct rlimit
1297 resources;
1298
1299 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1300 files=(ssize_t) resources.rlim_cur;
1301 }
1302#endif
1303#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1304 if (files < 0)
1305 files=(ssize_t) getdtablesize();
1306#endif
1307 if (files < 0)
1308 files=64;
1309 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1310 (3*files/4),64));
1311 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1312 if (limit != (char *) NULL)
1313 {
1314 (void) SetMagickResourceLimit(FileResource,StringToMagickSizeType(limit,
1315 100.0));
1316 limit=DestroyString(limit);
1317 }
1318 number_threads=(ssize_t) GetOpenMPMaximumThreads();
1319 if (number_threads > 1)
1320 number_threads--; /* reserve core for OS */
1321 (void) SetMagickResourceLimit(ThreadResource,(size_t) number_threads);
1322 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1323 if (limit != (char *) NULL)
1324 {
1325 (void) SetMagickResourceLimit(ThreadResource,StringToMagickSizeType(
1326 limit,100.0));
1327 limit=DestroyString(limit);
1328 }
1329 (void) SetMagickResourceLimit(ThrottleResource,0);
1330 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1331 if (limit != (char *) NULL)
1332 {
1333 (void) SetMagickResourceLimit(ThrottleResource,StringToMagickSizeType(
1334 limit,100.0));
1335 limit=DestroyString(limit);
1336 }
1337 (void) SetMagickResourceLimit(TimeResource,0);
1338 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1339 if (limit != (char *) NULL)
1340 {
1341 (void) SetMagickResourceLimit(TimeResource,(MagickSizeType)
1342 ParseMagickTimeToLive(limit));
1343 limit=DestroyString(limit);
1344 }
1345 (void) SetMagickResourceLimit(ListLengthResource,MagickResourceInfinity);
1346 limit=GetEnvironmentValue("MAGICK_LIST_LENGTH_LIMIT");
1347 if (limit != (char *) NULL)
1348 {
1349 (void) SetMagickResourceLimit(ListLengthResource,
1350 StringToMagickSizeType(limit,100.0));
1351 limit=DestroyString(limit);
1352 }
1353 return(MagickTrue);
1354}
1355
1356/*
1357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358% %
1359% %
1360% %
1361+ 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 %
1362% %
1363% %
1364% %
1365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1366%
1367% ResourceComponentTerminus() destroys the resource component.
1368%
1369% The format of the ResourceComponentTerminus() method is:
1370%
1371% ResourceComponentTerminus(void)
1372%
1373*/
1374MagickPrivate void ResourceComponentTerminus(void)
1375{
1376 ssize_t
1377 i;
1378
1379 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1380 if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
1381 resource_semaphore[i]=AcquireSemaphoreInfo();
1382 LockSemaphoreInfo(resource_semaphore[FileResource]);
1383 if (temporary_resources != (SplayTreeInfo *) NULL)
1384 temporary_resources=DestroySplayTree(temporary_resources);
1385 if (random_info != (RandomInfo *) NULL)
1386 random_info=DestroyRandomInfo(random_info);
1387 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1388 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1389 RelinquishSemaphoreInfo(&resource_semaphore[i]);
1390}
1391
1392/*
1393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1394% %
1395% %
1396% %
1397% S e t M a g i c k R e s o u r c e L i m i t %
1398% %
1399% %
1400% %
1401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1402%
1403% SetMagickResourceLimit() sets the limit for a particular resource.
1404%
1405% The format of the SetMagickResourceLimit() method is:
1406%
1407% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1408% const MagickSizeType limit)
1409%
1410% A description of each parameter follows:
1411%
1412% o type: the type of resource.
1413%
1414% o limit: the maximum limit for the resource.
1415%
1416*/
1417MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1418 const MagickSizeType limit)
1419{
1420 char
1421 *value;
1422
1423 MagickBooleanType
1424 status;
1425
1426 status=MagickTrue;
1427 value=(char *) NULL;
1428 switch (type)
1429 {
1430 case DiskResource:
1431 case FileResource:
1432 case MapResource:
1433 case MemoryResource:
1434 case TimeResource:
1435 {
1436 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
1437 ActivateSemaphoreInfo(&resource_semaphore[type]);
1438 LockSemaphoreInfo(resource_semaphore[type]);
1439 break;
1440 }
1441 default: ;
1442 }
1443 switch (type)
1444 {
1445 case AreaResource:
1446 {
1447 value=GetPolicyValue("resource:area");
1448 if (value == (char *) NULL)
1449 resource_info.area_limit=limit;
1450 else
1451 resource_info.area_limit=MagickMin(limit,StringToMagickSizeType(value,
1452 100.0));
1453 break;
1454 }
1455 case DiskResource:
1456 {
1457 value=GetPolicyValue("resource:disk");
1458 if (value == (char *) NULL)
1459 resource_info.disk_limit=limit;
1460 else
1461 resource_info.disk_limit=MagickMin(limit,StringToMagickSizeType(value,
1462 100.0));
1463 break;
1464 }
1465 case FileResource:
1466 {
1467 value=GetPolicyValue("resource:file");
1468 if (value == (char *) NULL)
1469 resource_info.file_limit=limit;
1470 else
1471 resource_info.file_limit=MagickMin(limit,StringToMagickSizeType(value,
1472 100.0));
1473 break;
1474 }
1475 case HeightResource:
1476 {
1477 value=GetPolicyValue("resource:height");
1478 if (value == (char *) NULL)
1479 resource_info.height_limit=limit;
1480 else
1481 resource_info.height_limit=MagickMin(limit,StringToMagickSizeType(
1482 value,100.0));
1483 resource_info.height_limit=MagickMin(resource_info.height_limit,
1484 (MagickSizeType) MAGICK_SSIZE_MAX);
1485 break;
1486 }
1487 case ListLengthResource:
1488 {
1489 value=GetPolicyValue("resource:list-length");
1490 if (value == (char *) NULL)
1491 resource_info.list_length_limit=limit;
1492 else
1493 resource_info.list_length_limit=MagickMin(limit,
1494 StringToMagickSizeType(value,100.0));
1495 break;
1496 }
1497 case MapResource:
1498 {
1499 value=GetPolicyValue("resource:map");
1500 if (value == (char *) NULL)
1501 resource_info.map_limit=limit;
1502 else
1503 resource_info.map_limit=MagickMin(limit,StringToMagickSizeType(
1504 value,100.0));
1505 break;
1506 }
1507 case MemoryResource:
1508 {
1509 value=GetPolicyValue("resource:memory");
1510 if (value == (char *) NULL)
1511 resource_info.memory_limit=limit;
1512 else
1513 resource_info.memory_limit=MagickMin(limit,StringToMagickSizeType(
1514 value,100.0));
1515 break;
1516 }
1517 case ThreadResource:
1518 {
1519 value=GetPolicyValue("resource:thread");
1520 if (value == (char *) NULL)
1521 resource_info.thread_limit=limit;
1522 else
1523 resource_info.thread_limit=MagickMin(limit,StringToMagickSizeType(
1524 value,100.0));
1525 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1526 resource_info.thread_limit=GetOpenMPMaximumThreads();
1527 else
1528 if (resource_info.thread_limit == 0)
1529 resource_info.thread_limit=1;
1530 break;
1531 }
1532 case ThrottleResource:
1533 {
1534 value=GetPolicyValue("resource:throttle");
1535 if (value == (char *) NULL)
1536 resource_info.throttle_limit=limit;
1537 else
1538 resource_info.throttle_limit=MagickMax(limit,StringToMagickSizeType(
1539 value,100.0));
1540 break;
1541 }
1542 case TimeResource:
1543 {
1544 value=GetPolicyValue("resource:time");
1545 if (value == (char *) NULL)
1546 resource_info.time_limit=limit;
1547 else
1548 resource_info.time_limit=MagickMin(limit,(MagickSizeType)
1549 ParseMagickTimeToLive(value));
1550 break;
1551 }
1552 case WidthResource:
1553 {
1554 value=GetPolicyValue("resource:width");
1555 if (value == (char *) NULL)
1556 resource_info.width_limit=limit;
1557 else
1558 resource_info.width_limit=MagickMin(limit,StringToMagickSizeType(value,
1559 100.0));
1560 resource_info.width_limit=MagickMin(resource_info.width_limit,
1561 (MagickSizeType) MAGICK_SSIZE_MAX);
1562 break;
1563 }
1564 default:
1565 {
1566 status=MagickFalse;
1567 break;
1568 }
1569 }
1570 switch (type)
1571 {
1572 case DiskResource:
1573 case FileResource:
1574 case MapResource:
1575 case MemoryResource:
1576 case TimeResource:
1577 {
1578 UnlockSemaphoreInfo(resource_semaphore[type]);
1579 break;
1580 }
1581 default: ;
1582 }
1583 if (value != (char *) NULL)
1584 value=DestroyString(value);
1585 return(status);
1586}