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;
108} ResourceInfo;
109
110/*
111 Global declarations.
112*/
113static RandomInfo
114 *random_info = (RandomInfo *) NULL;
115
116static ResourceInfo
117 resource_info =
118 {
119 MagickULLConstant(0), /* initial width */
120 MagickULLConstant(0), /* initial height */
121 MagickULLConstant(0), /* initial list length */
122 MagickULLConstant(0), /* initial area */
123 MagickULLConstant(0), /* initial memory */
124 MagickULLConstant(0), /* initial map */
125 MagickULLConstant(0), /* initial disk */
126 MagickULLConstant(0), /* initial file */
127 MagickULLConstant(0), /* initial thread */
128 MagickULLConstant(0), /* initial throttle */
129 MagickULLConstant(0), /* initial time */
130 (MagickSizeType) (MAGICK_SSIZE_MAX/sizeof(PixelPacket)/5), /* width limit */
131 (MagickSizeType) (MAGICK_SSIZE_MAX/sizeof(PixelPacket)/5), /* height limit */
132 MagickResourceInfinity, /* list length limit */
133 MagickULLConstant(3072)*1024*1024, /* area limit */
134 MagickULLConstant(1536)*1024*1024, /* memory limit */
135 MagickULLConstant(3072)*1024*1024, /* map limit */
136 MagickResourceInfinity, /* disk limit */
137 MagickULLConstant(768), /* file limit */
138 MagickULLConstant(1), /* thread limit */
139 MagickULLConstant(0), /* throttle limit */
140 MagickResourceInfinity, /* time limit */
141 };
142
143static SemaphoreInfo
144 *resource_semaphore[] = {
145 (SemaphoreInfo *) NULL,
146 (SemaphoreInfo *) NULL,
147 (SemaphoreInfo *) NULL,
148 (SemaphoreInfo *) NULL,
149 (SemaphoreInfo *) NULL,
150 (SemaphoreInfo *) NULL,
151 (SemaphoreInfo *) NULL,
152 (SemaphoreInfo *) NULL,
153 (SemaphoreInfo *) NULL,
154 (SemaphoreInfo *) NULL,
155 (SemaphoreInfo *) NULL,
156 (SemaphoreInfo *) NULL
157 };
158
159static SplayTreeInfo
160 *temporary_resources = (SplayTreeInfo *) NULL;
161
162/*
163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164% %
165% %
166% %
167% A c q u i r e M a g i c k R e s o u r c e %
168% %
169% %
170% %
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172%
173% AcquireMagickResource() acquires resources of the specified type.
174% MagickFalse is returned if the specified resource is exhausted otherwise
175% MagickTrue.
176%
177% The format of the AcquireMagickResource() method is:
178%
179% MagickBooleanType AcquireMagickResource(const ResourceType type,
180% const MagickSizeType size)
181%
182% A description of each parameter follows:
183%
184% o type: the type of resource.
185%
186% o size: the number of bytes needed from for this resource.
187%
188*/
189MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
190 const MagickSizeType size)
191{
192 char
193 resource_current[MaxTextExtent] = "",
194 resource_limit[MaxTextExtent] = "",
195 resource_request[MaxTextExtent] = "";
196
197 MagickBooleanType
198 logging,
199 status;
200
201 MagickOffsetType
202 request;
203
204 MagickSizeType
205 limit;
206
207 request=(MagickOffsetType) size;
208 if (request < 0)
209 return(MagickFalse);
210 status=MagickFalse;
211 logging=(GetLogEventMask() & ResourceEvent) != 0 ? MagickTrue : MagickFalse;
212 switch (type)
213 {
214 case DiskResource:
215 case FileResource:
216 case MapResource:
217 case MemoryResource:
218 case TimeResource:
219 {
220 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
221 ActivateSemaphoreInfo(&resource_semaphore[type]);
222 LockSemaphoreInfo(resource_semaphore[type]);
223 break;
224 }
225 default: ;
226 }
227 switch (type)
228 {
229 case AreaResource:
230 {
231 resource_info.area=(MagickOffsetType) size;
232 limit=resource_info.area_limit;
233 if ((limit == MagickResourceInfinity) || (size < limit))
234 status=MagickTrue;
235 if (logging != MagickFalse)
236 {
237 (void) FormatMagickSize(size,MagickFalse,resource_request);
238 (void) FormatMagickSize(size,MagickFalse,resource_current);
239 (void) FormatMagickSize(limit,MagickFalse,resource_limit);
240 }
241 break;
242 }
243 case DiskResource:
244 {
245 limit=resource_info.disk_limit;
246 if (((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 == MagickResourceInfinity) ||
394 (resource_info.time < (MagickOffsetType) 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
526 ExceptionInfo
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(MagickFalse);
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
626 StringInfo
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 count,
958 i,
959 j;
960
961 static const char
962 *bi_units[] =
963 {
964 "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", "Ri", "Qi", (char *) NULL
965 },
966 *traditional_units[] =
967 {
968 "", "K", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q", (char *) NULL
969 };
970
971 bytes=1000.0;
972 units=traditional_units;
973 if (bi != MagickFalse)
974 {
975 bytes=1024.0;
976 units=bi_units;
977 }
978#if defined(_MSC_VER) && (_MSC_VER == 1200)
979 length=(double) ((MagickOffsetType) size);
980#else
981 length=(double) size;
982#endif
983 for (i=0; (length >= bytes) && (units[i+1] != (const char *) NULL); i++)
984 length/=bytes;
985 count=0;
986 for (j=2; j < 12; j++)
987 {
988 count=FormatLocaleString(format,MaxTextExtent,"%.*g%sP",(int) (i+j),length,
989 units[i]);
990 if (strchr(format,'+') == (char *) NULL)
991 break;
992 }
993 return(count);
994}
995
996static void FormatTimeToLive(const MagickSizeType ttl,char *timeString)
997{
998 MagickSizeType
999 days,
1000 hours,
1001 minutes,
1002 months,
1003 seconds,
1004 weeks,
1005 years;
1006
1007 years=ttl/31536000;
1008 seconds=ttl % 31536000;
1009 if (seconds == 0)
1010 {
1011 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld years",years);
1012 return;
1013 }
1014 months=ttl/2628000;
1015 seconds=ttl % 2628000;
1016 if (seconds == 0)
1017 {
1018 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld months",
1019 months);
1020 return;
1021 }
1022 weeks=ttl/604800;
1023 seconds=ttl % 604800;
1024 if (seconds == 0)
1025 {
1026 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld weeks",weeks);
1027 return;
1028 }
1029 days=ttl/86400;
1030 seconds=ttl % 86400;
1031 if (seconds == 0)
1032 {
1033 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld days",days);
1034 return;
1035 }
1036 hours=ttl/3600;
1037 seconds=ttl % 3600;
1038 if (seconds == 0)
1039 {
1040 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld hours",hours);
1041 return;
1042 }
1043 minutes=ttl/60;
1044 seconds=ttl % 60;
1045 if (seconds == 0)
1046 {
1047 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld minutes",
1048 minutes);
1049 return;
1050 }
1051 (void) FormatLocaleString(timeString,MagickPathExtent,"%lld seconds",ttl);
1052}
1053
1054MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
1055 ExceptionInfo *magick_unused(exception))
1056{
1057 char
1058 area_limit[MaxTextExtent],
1059 disk_limit[MaxTextExtent],
1060 height_limit[MaxTextExtent],
1061 list_length_limit[MaxTextExtent],
1062 map_limit[MaxTextExtent],
1063 memory_limit[MaxTextExtent],
1064 time_limit[MaxTextExtent],
1065 width_limit[MaxTextExtent];
1066
1067 magick_unreferenced(exception);
1068
1069 if (file == (const FILE *) NULL)
1070 file=stdout;
1071 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
1072 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
1073 LockSemaphoreInfo(resource_semaphore[FileResource]);
1074 (void) FormatPixelSize(resource_info.width_limit,MagickFalse,width_limit);
1075 (void) FormatPixelSize(resource_info.height_limit,MagickFalse,height_limit);
1076 (void) FormatPixelSize(resource_info.area_limit,MagickFalse,area_limit);
1077 (void) CopyMagickString(list_length_limit,"unlimited",MaxTextExtent);
1078 if (resource_info.list_length_limit != MagickResourceInfinity)
1079 (void) FormatMagickSize(resource_info.list_length_limit,MagickTrue,
1080 list_length_limit);
1081 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
1082 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
1083 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
1084 if (resource_info.disk_limit != MagickResourceInfinity)
1085 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
1086 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
1087 if (resource_info.time_limit != MagickResourceInfinity)
1088 FormatTimeToLive(resource_info.time_limit,time_limit);
1089 (void) FormatLocaleFile(file,"Resource limits:\n");
1090 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
1091 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
1092 (void) FormatLocaleFile(file," List length: %s\n",list_length_limit);
1093 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
1094 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
1095 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
1096 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
1097 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
1098 resource_info.file_limit));
1099 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
1100 resource_info.thread_limit));
1101 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
1102 ((MagickOffsetType) resource_info.throttle_limit));
1103 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
1104 (void) fflush(file);
1105 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1106 return(MagickTrue);
1107}
1108
1109/*
1110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111% %
1112% %
1113% %
1114% R e l i n q u i s h M a g i c k R e s o u r c e %
1115% %
1116% %
1117% %
1118%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1119%
1120% RelinquishMagickResource() relinquishes resources of the specified type.
1121%
1122% The format of the RelinquishMagickResource() method is:
1123%
1124% void RelinquishMagickResource(const ResourceType type,
1125% const MagickSizeType size)
1126%
1127% A description of each parameter follows:
1128%
1129% o type: the type of resource.
1130%
1131% o size: the size of the resource.
1132%
1133*/
1134MagickExport void RelinquishMagickResource(const ResourceType type,
1135 const MagickSizeType size)
1136{
1137 char
1138 resource_current[MaxTextExtent],
1139 resource_limit[MaxTextExtent],
1140 resource_request[MaxTextExtent];
1141
1142 MagickBooleanType
1143 logging;
1144
1145 logging=(GetLogEventMask() & ResourceEvent) != 0 ? MagickTrue : MagickFalse;
1146 if (logging != MagickFalse)
1147 (void) FormatMagickSize(size,MagickFalse,resource_request);
1148 switch (type)
1149 {
1150 case DiskResource:
1151 case FileResource:
1152 case MapResource:
1153 case MemoryResource:
1154 case TimeResource:
1155 {
1156 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
1157 ActivateSemaphoreInfo(&resource_semaphore[type]);
1158 LockSemaphoreInfo(resource_semaphore[type]);
1159 break;
1160 }
1161 default: ;
1162 }
1163 switch (type)
1164 {
1165 case AreaResource:
1166 {
1167 resource_info.area=(MagickOffsetType) size;
1168 if (logging != MagickFalse)
1169 {
1170 (void) FormatMagickSize((MagickSizeType) resource_info.area,
1171 MagickFalse,resource_current);
1172 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
1173 resource_limit);
1174 }
1175 break;
1176 }
1177 case DiskResource:
1178 {
1179 resource_info.disk-=size;
1180 assert(resource_info.disk >= 0);
1181 if (logging != MagickFalse)
1182 {
1183 (void) FormatMagickSize((MagickSizeType) resource_info.disk,
1184 MagickTrue,resource_current);
1185 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
1186 resource_limit);
1187 }
1188 break;
1189 }
1190 case FileResource:
1191 {
1192 resource_info.file-=size;
1193 assert(resource_info.file >= 0);
1194 if (logging != MagickFalse)
1195 {
1196 (void) FormatMagickSize((MagickSizeType) resource_info.file,
1197 MagickFalse,resource_current);
1198 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
1199 MagickFalse,resource_limit);
1200 }
1201 break;
1202 }
1203 case HeightResource:
1204 {
1205 resource_info.height=(MagickOffsetType) size;
1206 if (logging != MagickFalse)
1207 {
1208 (void) FormatMagickSize((MagickSizeType) resource_info.height,
1209 MagickFalse,resource_current);
1210 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,
1211 resource_limit);
1212 }
1213 break;
1214 }
1215 case ListLengthResource:
1216 {
1217 resource_info.list_length=(MagickOffsetType) size;
1218 if (logging != MagickFalse)
1219 {
1220 (void) FormatMagickSize((MagickSizeType) resource_info.list_length,
1221 MagickFalse,resource_current);
1222 (void) FormatMagickSize(resource_info.list_length_limit,MagickFalse,
1223 resource_limit);
1224 }
1225 break;
1226 }
1227 case MapResource:
1228 {
1229 resource_info.map-=size;
1230 assert(resource_info.map >= 0);
1231 if (logging != MagickFalse)
1232 {
1233 (void) FormatMagickSize((MagickSizeType) resource_info.map,
1234 MagickTrue,resource_current);
1235 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
1236 resource_limit);
1237 }
1238 break;
1239 }
1240 case MemoryResource:
1241 {
1242 resource_info.memory-=size;
1243 assert(resource_info.memory >= 0);
1244 if (logging != MagickFalse)
1245 {
1246 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
1247 MagickTrue,resource_current);
1248 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
1249 resource_limit);
1250 }
1251 break;
1252 }
1253 case ThreadResource:
1254 {
1255 if (logging != MagickFalse)
1256 {
1257 (void) FormatMagickSize((MagickSizeType) resource_info.thread,
1258 MagickFalse,resource_current);
1259 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
1260 MagickFalse,resource_limit);
1261 }
1262 break;
1263 }
1264 case ThrottleResource:
1265 {
1266 if (logging != MagickFalse)
1267 {
1268 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
1269 MagickFalse,resource_current);
1270 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
1271 MagickFalse,resource_limit);
1272 }
1273 break;
1274 }
1275 case TimeResource:
1276 {
1277 resource_info.time-=size;
1278 assert(resource_info.time >= 0);
1279 if (logging != MagickFalse)
1280 {
1281 (void) FormatMagickSize((MagickSizeType) resource_info.time,
1282 MagickFalse,resource_current);
1283 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
1284 MagickFalse,resource_limit);
1285 }
1286 break;
1287 }
1288 case WidthResource:
1289 {
1290 resource_info.width=(MagickOffsetType) size;
1291 if (logging != MagickFalse)
1292 {
1293 (void) FormatMagickSize((MagickSizeType) resource_info.width,
1294 MagickFalse,resource_current);
1295 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,
1296 resource_limit);
1297 }
1298 break;
1299 }
1300 default:
1301 break;
1302 }
1303 switch (type)
1304 {
1305 case DiskResource:
1306 case FileResource:
1307 case MapResource:
1308 case MemoryResource:
1309 case TimeResource:
1310 {
1311 UnlockSemaphoreInfo(resource_semaphore[type]);
1312 break;
1313 }
1314 default: ;
1315 }
1316 if (logging != MagickFalse)
1317 {
1318 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
1319 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
1320 resource_request,resource_current,resource_limit);
1321 }
1322}
1323
1324/*
1325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326% %
1327% %
1328% %
1329% 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 %
1330% %
1331% %
1332% %
1333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1334%
1335% RelinquishUniqueFileResource() relinquishes a unique file resource.
1336%
1337% The format of the RelinquishUniqueFileResource() method is:
1338%
1339% MagickBooleanType RelinquishUniqueFileResource(const char *path)
1340%
1341% A description of each parameter follows:
1342%
1343% o name: the name of the temporary resource.
1344%
1345*/
1346MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
1347{
1348 char
1349 cache_path[MaxTextExtent];
1350
1351 MagickStatusType
1352 status;
1353
1354 assert(path != (const char *) NULL);
1355 status=MagickFalse;
1356 if ((GetLogEventMask() & ResourceEvent) != 0)
1357 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"Relinquish %s",path);
1358 if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
1359 ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
1360 LockSemaphoreInfo(resource_semaphore[FileResource]);
1361 if (temporary_resources != (SplayTreeInfo *) NULL)
1362 status=DeleteNodeFromSplayTree(temporary_resources, (const void *) path);
1363 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1364 (void) CopyMagickString(cache_path,path,MaxTextExtent);
1365 AppendImageFormat("cache",cache_path);
1366 if (access_utf8(cache_path,F_OK) == 0)
1367 {
1368 status=ShredFile(cache_path);
1369 status|=remove_utf8(cache_path);
1370 }
1371 if (status == MagickFalse)
1372 {
1373 status=ShredFile(path);
1374 status|=remove_utf8(path);
1375 }
1376 return(status == 0 ? MagickFalse : MagickTrue);
1377}
1378
1379/*
1380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381% %
1382% %
1383% %
1384+ R e s o u r c e C o m p o n e n t G e n e s i s %
1385% %
1386% %
1387% %
1388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1389%
1390% ResourceComponentGenesis() instantiates the resource component.
1391%
1392% The format of the ResourceComponentGenesis method is:
1393%
1394% MagickBooleanType ResourceComponentGenesis(void)
1395%
1396*/
1397MagickExport MagickBooleanType ResourceComponentGenesis(void)
1398{
1399 char
1400 *limit;
1401
1402 MagickSizeType
1403 memory;
1404
1405 ssize_t
1406 files,
1407 i,
1408 number_threads,
1409 pages,
1410 pagesize;
1411
1412 /*
1413 Set Magick resource limits.
1414 */
1415 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1416 if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
1417 ActivateSemaphoreInfo(&resource_semaphore[i]);
1418 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1419 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1420 if (limit != (char *) NULL)
1421 {
1422 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
1423 100.0));
1424 limit=DestroyString(limit);
1425 }
1426 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1427 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1428 if (limit != (char *) NULL)
1429 {
1430 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
1431 100.0));
1432 limit=DestroyString(limit);
1433 }
1434 pagesize=GetMagickPageSize();
1435 pages=(-1);
1436#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1437 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1438#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1439 pages=pages/2;
1440#endif
1441#endif
1442 memory=(MagickSizeType) pages*pagesize;
1443 if ((pagesize <= 0) || (pages <= 0))
1444 memory=2048UL*1024UL*1024UL;
1445#if defined(MAGICKCORE_PixelCacheThreshold)
1446 memory=StringToMagickSizeType(MAGICKCORE_PixelCacheThreshold,100.0);
1447#endif
1448 (void) SetMagickResourceLimit(AreaResource,4*memory);
1449 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1450 if (limit != (char *) NULL)
1451 {
1452 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
1453 limit=DestroyString(limit);
1454 }
1455 (void) SetMagickResourceLimit(MemoryResource,memory);
1456 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1457 if (limit != (char *) NULL)
1458 {
1459 (void) SetMagickResourceLimit(MemoryResource,
1460 StringToSizeType(limit,100.0));
1461 limit=DestroyString(limit);
1462 }
1463 (void) SetMagickResourceLimit(MapResource,2*memory);
1464 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1465 if (limit != (char *) NULL)
1466 {
1467 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1468 limit=DestroyString(limit);
1469 }
1470 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1471 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1472 if (limit != (char *) NULL)
1473 {
1474 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1475 limit=DestroyString(limit);
1476 }
1477 files=(-1);
1478#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1479 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1480#endif
1481#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1482 if (files < 0)
1483 {
1484 struct rlimit
1485 resources;
1486
1487 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1488 files=(ssize_t) resources.rlim_cur;
1489 }
1490#endif
1491#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1492 if (files < 0)
1493 files=(ssize_t) getdtablesize();
1494#endif
1495 if (files < 0)
1496 files=64;
1497 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1498 (3*files/4),64));
1499 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1500 if (limit != (char *) NULL)
1501 {
1502 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,100.0));
1503 limit=DestroyString(limit);
1504 }
1505 number_threads=(ssize_t) GetOpenMPMaximumThreads();
1506 if (number_threads > 1)
1507 number_threads--; /* reserve core for OS */
1508 (void) SetMagickResourceLimit(ThreadResource,(size_t) number_threads);
1509 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1510 if (limit != (char *) NULL)
1511 {
1512 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1513 100.0));
1514 limit=DestroyString(limit);
1515 }
1516 (void) SetMagickResourceLimit(ThrottleResource,0);
1517 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1518 if (limit != (char *) NULL)
1519 {
1520 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1521 100.0));
1522 limit=DestroyString(limit);
1523 }
1524 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1525 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1526 if (limit != (char *) NULL)
1527 {
1528 (void) SetMagickResourceLimit(TimeResource,(MagickSizeType)
1529 ParseMagickTimeToLive(limit));
1530 limit=DestroyString(limit);
1531 }
1532 (void) SetMagickResourceLimit(ListLengthResource,MagickResourceInfinity);
1533 limit=GetEnvironmentValue("MAGICK_LIST_LENGTH_LIMIT");
1534 if (limit != (char *) NULL)
1535 {
1536 (void) SetMagickResourceLimit(ListLengthResource,
1537 StringToSizeType(limit,100.0));
1538 limit=DestroyString(limit);
1539 }
1540 return(MagickTrue);
1541}
1542
1543/*
1544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1545% %
1546% %
1547% %
1548+ 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 %
1549% %
1550% %
1551% %
1552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1553%
1554% ResourceComponentTerminus() destroys the resource component.
1555%
1556% The format of the ResourceComponentTerminus() method is:
1557%
1558% ResourceComponentTerminus(void)
1559%
1560*/
1561MagickExport void ResourceComponentTerminus(void)
1562{
1563 ssize_t
1564 i;
1565
1566 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1567 if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
1568 ActivateSemaphoreInfo(&resource_semaphore[i]);
1569 LockSemaphoreInfo(resource_semaphore[FileResource]);
1570 if (temporary_resources != (SplayTreeInfo *) NULL)
1571 temporary_resources=DestroySplayTree(temporary_resources);
1572 if (random_info != (RandomInfo *) NULL)
1573 random_info=DestroyRandomInfo(random_info);
1574 UnlockSemaphoreInfo(resource_semaphore[FileResource]);
1575 for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
1576 DestroySemaphoreInfo(&resource_semaphore[i]);
1577}
1578
1579/*
1580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1581% %
1582% %
1583% %
1584% S e t M a g i c k R e s o u r c e L i m i t %
1585% %
1586% %
1587% %
1588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1589%
1590% SetMagickResourceLimit() sets the limit for a particular resource.
1591%
1592% The format of the SetMagickResourceLimit() method is:
1593%
1594% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1595% const MagickSizeType limit)
1596%
1597% A description of each parameter follows:
1598%
1599% o type: the type of resource.
1600%
1601% o limit: the maximum limit for the resource.
1602%
1603*/
1604
1605MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1606 const MagickSizeType limit)
1607{
1608 char
1609 *value;
1610
1611 MagickBooleanType
1612 status;
1613
1614 status=MagickTrue;
1615 if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
1616 ActivateSemaphoreInfo(&resource_semaphore[type]);
1617 LockSemaphoreInfo(resource_semaphore[type]);
1618 value=(char *) NULL;
1619 switch (type)
1620 {
1621 case AreaResource:
1622 {
1623 value=GetPolicyValue("resource:area");
1624 if (value == (char *) NULL)
1625 resource_info.area_limit=limit;
1626 else
1627 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1628 break;
1629 }
1630 case DiskResource:
1631 {
1632 value=GetPolicyValue("resource:disk");
1633 if (value == (char *) NULL)
1634 resource_info.disk_limit=limit;
1635 else
1636 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1637 break;
1638 }
1639 case FileResource:
1640 {
1641 value=GetPolicyValue("resource:file");
1642 if (value == (char *) NULL)
1643 resource_info.file_limit=limit;
1644 else
1645 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1646 break;
1647 }
1648 case HeightResource:
1649 {
1650 value=GetPolicyValue("resource:height");
1651 if (value == (char *) NULL)
1652 resource_info.height_limit=limit;
1653 else
1654 resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
1655 100.0));
1656 resource_info.height_limit=MagickMin(resource_info.height_limit,
1657 (MagickSizeType) MAGICK_SSIZE_MAX);
1658 break;
1659 }
1660 case ListLengthResource:
1661 {
1662 value=GetPolicyValue("resource:list-length");
1663 if (value == (char *) NULL)
1664 resource_info.list_length_limit=limit;
1665 else
1666 resource_info.list_length_limit=MagickMin(limit,
1667 StringToSizeType(value,100.0));
1668 break;
1669 }
1670 case MapResource:
1671 {
1672 value=GetPolicyValue("resource:map");
1673 if (value == (char *) NULL)
1674 resource_info.map_limit=limit;
1675 else
1676 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1677 break;
1678 }
1679 case MemoryResource:
1680 {
1681 value=GetPolicyValue("resource:memory");
1682 if (value == (char *) NULL)
1683 resource_info.memory_limit=limit;
1684 else
1685 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1686 100.0));
1687 break;
1688 }
1689 case ThreadResource:
1690 {
1691 value=GetPolicyValue("resource:thread");
1692 if (value == (char *) NULL)
1693 resource_info.thread_limit=limit;
1694 else
1695 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1696 100.0));
1697 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1698 resource_info.thread_limit=GetOpenMPMaximumThreads();
1699 else
1700 if (resource_info.thread_limit == 0)
1701 resource_info.thread_limit=1;
1702 break;
1703 }
1704 case ThrottleResource:
1705 {
1706 value=GetPolicyValue("resource:throttle");
1707 if (value == (char *) NULL)
1708 resource_info.throttle_limit=limit;
1709 else
1710 resource_info.throttle_limit=MagickMax(limit,StringToSizeType(value,
1711 100.0));
1712 break;
1713 }
1714 case TimeResource:
1715 {
1716 value=GetPolicyValue("resource:time");
1717 if (value == (char *) NULL)
1718 resource_info.time_limit=limit;
1719 else
1720 resource_info.time_limit=MagickMin(limit,(MagickSizeType)
1721 ParseMagickTimeToLive(value));
1722 break;
1723 }
1724 case WidthResource:
1725 {
1726 value=GetPolicyValue("resource:width");
1727 if (value == (char *) NULL)
1728 resource_info.width_limit=limit;
1729 else
1730 resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
1731 100.0));
1732 resource_info.width_limit=MagickMin(resource_info.width_limit,
1733 (MagickSizeType) MAGICK_SSIZE_MAX);
1734 break;
1735 }
1736 default:
1737 {
1738 status=MagickFalse;
1739 break;
1740 }
1741 }
1742 if (value != (char *) NULL)
1743 value=DestroyString(value);
1744 UnlockSemaphoreInfo(resource_semaphore[type]);
1745 return(status);
1746}