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