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