MagickCore 7.1.2
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;
107} ResourceInfo;
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 (((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 == 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
471 ExceptionInfo
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
571 StringInfo
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/*
1358%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1359% %
1360% %
1361% %
1362+ 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 %
1363% %
1364% %
1365% %
1366%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1367%
1368% ResourceComponentTerminus() destroys the resource component.
1369%
1370% The format of the ResourceComponentTerminus() method is:
1371%
1372% ResourceComponentTerminus(void)
1373%
1374*/
1375MagickPrivate void ResourceComponentTerminus(void)
1376{
1377 ssize_t
1378 i;
1379
1380 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1381 if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
1382 resource_semaphore[i]=AcquireSemaphoreInfo();
1383 LockSemaphoreInfo(resource_semaphore[FileResource]);
1384 if (temporary_resources != (SplayTreeInfo *) NULL)
1385 temporary_resources=DestroySplayTree(temporary_resources);
1386 if (random_info != (RandomInfo *) NULL)
1387 random_info=DestroyRandomInfo(random_info);
1388 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1389 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1390 RelinquishSemaphoreInfo(&resource_semaphore[i]);
1391}
1392
1393/*
1394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395% %
1396% %
1397% %
1398% S e t M a g i c k R e s o u r c e L i m i t %
1399% %
1400% %
1401% %
1402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1403%
1404% SetMagickResourceLimit() sets the limit for a particular resource.
1405%
1406% The format of the SetMagickResourceLimit() method is:
1407%
1408% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1409% const MagickSizeType limit)
1410%
1411% A description of each parameter follows:
1412%
1413% o type: the type of resource.
1414%
1415% o limit: the maximum limit for the resource.
1416%
1417*/
1418MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1419 const MagickSizeType limit)
1420{
1421 char
1422 *value;
1423
1424 MagickBooleanType
1425 status;
1426
1427 status=MagickTrue;
1428 value=(char *) NULL;
1429 switch (type)
1430 {
1431 case DiskResource:
1432 case FileResource:
1433 case MapResource:
1434 case MemoryResource:
1435 case TimeResource:
1436 {
1437 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
1438 ActivateSemaphoreInfo(&resource_semaphore[type]);
1439 LockSemaphoreInfo(resource_semaphore[type]);
1440 break;
1441 }
1442 default: ;
1443 }
1444 switch (type)
1445 {
1446 case AreaResource:
1447 {
1448 value=GetPolicyValue("resource:area");
1449 if (value == (char *) NULL)
1450 resource_info.area_limit=limit;
1451 else
1452 resource_info.area_limit=MagickMin(limit,StringToMagickSizeType(value,
1453 100.0));
1454 break;
1455 }
1456 case DiskResource:
1457 {
1458 value=GetPolicyValue("resource:disk");
1459 if (value == (char *) NULL)
1460 resource_info.disk_limit=limit;
1461 else
1462 resource_info.disk_limit=MagickMin(limit,StringToMagickSizeType(value,
1463 100.0));
1464 break;
1465 }
1466 case FileResource:
1467 {
1468 value=GetPolicyValue("resource:file");
1469 if (value == (char *) NULL)
1470 resource_info.file_limit=limit;
1471 else
1472 resource_info.file_limit=MagickMin(limit,StringToMagickSizeType(value,
1473 100.0));
1474 break;
1475 }
1476 case HeightResource:
1477 {
1478 value=GetPolicyValue("resource:height");
1479 if (value == (char *) NULL)
1480 resource_info.height_limit=limit;
1481 else
1482 resource_info.height_limit=MagickMin(limit,StringToMagickSizeType(
1483 value,100.0));
1484 resource_info.height_limit=MagickMin(resource_info.height_limit,
1485 (MagickSizeType) MAGICK_SSIZE_MAX);
1486 break;
1487 }
1488 case ListLengthResource:
1489 {
1490 value=GetPolicyValue("resource:list-length");
1491 if (value == (char *) NULL)
1492 resource_info.list_length_limit=limit;
1493 else
1494 resource_info.list_length_limit=MagickMin(limit,
1495 StringToMagickSizeType(value,100.0));
1496 break;
1497 }
1498 case MapResource:
1499 {
1500 value=GetPolicyValue("resource:map");
1501 if (value == (char *) NULL)
1502 resource_info.map_limit=limit;
1503 else
1504 resource_info.map_limit=MagickMin(limit,StringToMagickSizeType(
1505 value,100.0));
1506 break;
1507 }
1508 case MemoryResource:
1509 {
1510 value=GetPolicyValue("resource:memory");
1511 if (value == (char *) NULL)
1512 resource_info.memory_limit=limit;
1513 else
1514 resource_info.memory_limit=MagickMin(limit,StringToMagickSizeType(
1515 value,100.0));
1516 break;
1517 }
1518 case ThreadResource:
1519 {
1520 value=GetPolicyValue("resource:thread");
1521 if (value == (char *) NULL)
1522 resource_info.thread_limit=limit;
1523 else
1524 resource_info.thread_limit=MagickMin(limit,StringToMagickSizeType(
1525 value,100.0));
1526 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1527 resource_info.thread_limit=GetOpenMPMaximumThreads();
1528 else
1529 if (resource_info.thread_limit == 0)
1530 resource_info.thread_limit=1;
1531 break;
1532 }
1533 case ThrottleResource:
1534 {
1535 value=GetPolicyValue("resource:throttle");
1536 if (value == (char *) NULL)
1537 resource_info.throttle_limit=limit;
1538 else
1539 resource_info.throttle_limit=MagickMax(limit,StringToMagickSizeType(
1540 value,100.0));
1541 break;
1542 }
1543 case TimeResource:
1544 {
1545 value=GetPolicyValue("resource:time");
1546 if (value == (char *) NULL)
1547 resource_info.time_limit=limit;
1548 else
1549 resource_info.time_limit=MagickMin(limit,(MagickSizeType)
1550 ParseMagickTimeToLive(value));
1551 break;
1552 }
1553 case WidthResource:
1554 {
1555 value=GetPolicyValue("resource:width");
1556 if (value == (char *) NULL)
1557 resource_info.width_limit=limit;
1558 else
1559 resource_info.width_limit=MagickMin(limit,StringToMagickSizeType(value,
1560 100.0));
1561 resource_info.width_limit=MagickMin(resource_info.width_limit,
1562 (MagickSizeType) MAGICK_SSIZE_MAX);
1563 break;
1564 }
1565 default:
1566 {
1567 status=MagickFalse;
1568 break;
1569 }
1570 }
1571 switch (type)
1572 {
1573 case DiskResource:
1574 case FileResource:
1575 case MapResource:
1576 case MemoryResource:
1577 case TimeResource:
1578 {
1579 UnlockSemaphoreInfo(resource_semaphore[type]);
1580 break;
1581 }
1582 default: ;
1583 }
1584 if (value != (char *) NULL)
1585 value=DestroyString(value);
1586 return(status);
1587}