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