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