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-2016 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 % http://www.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 Typedef declarations.
72 */
73 typedef struct _ResourceInfo
74 {
75 MagickOffsetType
76 width,
77 height,
78 area,
79 memory,
80 map,
81 disk,
82 file,
83 thread,
84 throttle,
85 time;
86
87 MagickSizeType
88 width_limit,
89 height_limit,
90 area_limit,
91 memory_limit,
92 map_limit,
93 disk_limit,
94 file_limit,
95 thread_limit,
96 throttle_limit,
97 time_limit;
98 } ResourceInfo;
99
100 /*
101 Global declarations.
102 */
103 static RandomInfo
104 *random_info = (RandomInfo *) NULL;
105
106 static ResourceInfo
107 resource_info =
108 {
109 MagickULLConstant(0), /* initial width */
110 MagickULLConstant(0), /* initial height */
111 MagickULLConstant(0), /* initial area */
112 MagickULLConstant(0), /* initial memory */
113 MagickULLConstant(0), /* initial map */
114 MagickULLConstant(0), /* initial disk */
115 MagickULLConstant(0), /* initial file */
116 MagickULLConstant(0), /* initial thread */
117 MagickULLConstant(0), /* initial throttle */
118 MagickULLConstant(0), /* initial time */
119 (INT_MAX/(5*sizeof(Quantum))), /* width limit */
120 (INT_MAX/(5*sizeof(Quantum))), /* height limit */
121 MagickULLConstant(3072)*1024*1024, /* area limit */
122 MagickULLConstant(1536)*1024*1024, /* memory limit */
123 MagickULLConstant(3072)*1024*1024, /* map limit */
124 MagickResourceInfinity, /* disk limit */
125 MagickULLConstant(768), /* file limit */
126 MagickULLConstant(1), /* thread limit */
127 MagickULLConstant(0), /* throttle limit */
128 MagickResourceInfinity /* time limit */
129 };
130
131 static SemaphoreInfo
132 *resource_semaphore = (SemaphoreInfo *) NULL;
133
134 static SplayTreeInfo
135 *temporary_resources = (SplayTreeInfo *) NULL;
136
137 /*
138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139 % %
140 % %
141 % %
142 % A c q u i r e M a g i c k R e s o u r c e %
143 % %
144 % %
145 % %
146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147 %
148 % AcquireMagickResource() acquires resources of the specified type.
149 % MagickFalse is returned if the specified resource is exhausted otherwise
150 % MagickTrue.
151 %
152 % The format of the AcquireMagickResource() method is:
153 %
154 % MagickBooleanType AcquireMagickResource(const ResourceType type,
155 % const MagickSizeType size)
156 %
157 % A description of each parameter follows:
158 %
159 % o type: the type of resource.
160 %
161 % o size: the number of bytes needed from for this resource.
162 %
163 */
AcquireMagickResource(const ResourceType type,const MagickSizeType size)164 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
165 const MagickSizeType size)
166 {
167 char
168 resource_current[MagickFormatExtent],
169 resource_limit[MagickFormatExtent],
170 resource_request[MagickFormatExtent];
171
172 MagickBooleanType
173 status;
174
175 MagickSizeType
176 limit;
177
178 status=MagickFalse;
179 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
180 resource_request);
181 if (resource_semaphore == (SemaphoreInfo *) NULL)
182 ActivateSemaphoreInfo(&resource_semaphore);
183 LockSemaphoreInfo(resource_semaphore);
184 switch (type)
185 {
186 case AreaResource:
187 {
188 resource_info.area=(MagickOffsetType) size;
189 limit=resource_info.area_limit;
190 status=(resource_info.area_limit == MagickResourceInfinity) ||
191 (size < limit) ? MagickTrue : MagickFalse;
192 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
193 "B",MagickFormatExtent,resource_current);
194 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
195 MagickFormatExtent,resource_limit);
196 break;
197 }
198 case MemoryResource:
199 {
200 resource_info.memory+=size;
201 limit=resource_info.memory_limit;
202 status=(resource_info.memory_limit == MagickResourceInfinity) ||
203 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
204 MagickFalse;
205 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
206 "B",MagickFormatExtent,resource_current);
207 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
208 MagickFormatExtent,resource_limit);
209 break;
210 }
211 case MapResource:
212 {
213 resource_info.map+=size;
214 limit=resource_info.map_limit;
215 status=(resource_info.map_limit == MagickResourceInfinity) ||
216 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
217 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
218 "B",MagickFormatExtent,resource_current);
219 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
220 MagickFormatExtent,resource_limit);
221 break;
222 }
223 case DiskResource:
224 {
225 resource_info.disk+=size;
226 limit=resource_info.disk_limit;
227 status=(resource_info.disk_limit == MagickResourceInfinity) ||
228 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
229 MagickFalse;
230 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
231 "B",MagickFormatExtent,resource_current);
232 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
233 MagickFormatExtent,resource_limit);
234 break;
235 }
236 case FileResource:
237 {
238 resource_info.file+=size;
239 limit=resource_info.file_limit;
240 status=(resource_info.file_limit == MagickResourceInfinity) ||
241 ((MagickSizeType) resource_info.file < limit) ?
242 MagickTrue : MagickFalse;
243 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
244 "B",MagickFormatExtent,resource_current);
245 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
246 MagickFalse,"B",MagickFormatExtent,resource_limit);
247 break;
248 }
249 case HeightResource:
250 {
251 resource_info.area=(MagickOffsetType) size;
252 limit=resource_info.height_limit;
253 status=(resource_info.area_limit == MagickResourceInfinity) ||
254 (size < limit) ? MagickTrue : MagickFalse;
255 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
256 "P",MagickFormatExtent,resource_current);
257 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
258 MagickFormatExtent,resource_limit);
259 break;
260 }
261 case ThreadResource:
262 {
263 limit=resource_info.thread_limit;
264 status=(resource_info.thread_limit == MagickResourceInfinity) ||
265 ((MagickSizeType) resource_info.thread < limit) ?
266 MagickTrue : MagickFalse;
267 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
268 "B",MagickFormatExtent,resource_current);
269 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
270 MagickFalse,"B",MagickFormatExtent,resource_limit);
271 break;
272 }
273 case ThrottleResource:
274 {
275 limit=resource_info.throttle_limit;
276 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
277 ((MagickSizeType) resource_info.throttle < limit) ?
278 MagickTrue : MagickFalse;
279 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
280 MagickFalse,"B",MagickFormatExtent,resource_current);
281 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
282 MagickFalse,"B",MagickFormatExtent,resource_limit);
283 break;
284 }
285 case TimeResource:
286 {
287 resource_info.time+=size;
288 limit=resource_info.time_limit;
289 status=(resource_info.time_limit == MagickResourceInfinity) ||
290 ((MagickSizeType) resource_info.time < limit) ?
291 MagickTrue : MagickFalse;
292 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
293 "B",MagickFormatExtent,resource_current);
294 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
295 MagickFalse,"B",MagickFormatExtent,resource_limit);
296 break;
297 }
298 case WidthResource:
299 {
300 resource_info.area=(MagickOffsetType) size;
301 limit=resource_info.width_limit;
302 status=(resource_info.area_limit == MagickResourceInfinity) ||
303 (size < limit) ? MagickTrue : MagickFalse;
304 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
305 "P",MagickFormatExtent,resource_current);
306 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
307 MagickFormatExtent,resource_limit);
308 break;
309 }
310 default:
311 break;
312 }
313 UnlockSemaphoreInfo(resource_semaphore);
314 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
315 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
316 resource_request,resource_current,resource_limit);
317 return(status);
318 }
319
320 /*
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322 % %
323 % %
324 % %
325 + 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 %
326 % %
327 % %
328 % %
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 %
331 % AsynchronousResourceComponentTerminus() destroys the resource environment.
332 % It differs from ResourceComponentTerminus() in that it can be called from a
333 % asynchronous signal handler.
334 %
335 % The format of the ResourceComponentTerminus() method is:
336 %
337 % ResourceComponentTerminus(void)
338 %
339 */
AsynchronousResourceComponentTerminus(void)340 MagickPrivate void AsynchronousResourceComponentTerminus(void)
341 {
342 const char
343 *path;
344
345 if (temporary_resources == (SplayTreeInfo *) NULL)
346 return;
347 /*
348 Remove any lingering temporary files.
349 */
350 ResetSplayTreeIterator(temporary_resources);
351 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
352 while (path != (const char *) NULL)
353 {
354 (void) ShredFile(path);
355 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
356 }
357 }
358
359 /*
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 % %
362 % %
363 % %
364 % 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 %
365 % %
366 % %
367 % %
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 %
370 % AcquireUniqueFileResource() returns a unique file name, and returns a file
371 % descriptor for the file open for reading and writing.
372 %
373 % The format of the AcquireUniqueFileResource() method is:
374 %
375 % int AcquireUniqueFileResource(char *path)
376 %
377 % A description of each parameter follows:
378 %
379 % o path: Specifies a pointer to an array of characters. The unique path
380 % name is returned in this array.
381 %
382 */
383
DestroyTemporaryResources(void * temporary_resource)384 static void *DestroyTemporaryResources(void *temporary_resource)
385 {
386 (void) ShredFile((char *) temporary_resource);
387 temporary_resource=DestroyString((char *) temporary_resource);
388 return((void *) NULL);
389 }
390
GetPathTemplate(char * path)391 MagickExport MagickBooleanType GetPathTemplate(char *path)
392 {
393 char
394 *directory,
395 *value;
396
397 ExceptionInfo
398 *exception;
399
400 MagickBooleanType
401 status;
402
403 struct stat
404 attributes;
405
406 (void) FormatLocaleString(path,MagickPathExtent,"magick-%.20gXXXXXXXXXXXX",
407 (double) getpid());
408 exception=AcquireExceptionInfo();
409 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
410 exception);
411 exception=DestroyExceptionInfo(exception);
412 if (directory == (char *) NULL)
413 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
414 if (directory == (char *) NULL)
415 directory=GetEnvironmentValue("MAGICK_TMPDIR");
416 if (directory == (char *) NULL)
417 directory=GetEnvironmentValue("TMPDIR");
418 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
419 if (directory == (char *) NULL)
420 directory=GetEnvironmentValue("TMP");
421 if (directory == (char *) NULL)
422 directory=GetEnvironmentValue("TEMP");
423 #endif
424 #if defined(__VMS)
425 if (directory == (char *) NULL)
426 directory=GetEnvironmentValue("MTMPDIR");
427 #endif
428 #if defined(P_tmpdir)
429 if (directory == (char *) NULL)
430 directory=ConstantString(P_tmpdir);
431 #endif
432 if (directory == (char *) NULL)
433 return(MagickTrue);
434 value=GetPolicyValue("temporary-path");
435 if (value != (char *) NULL)
436 (void) CloneString(&directory,value);
437 if (strlen(directory) > (MagickPathExtent-25))
438 {
439 directory=DestroyString(directory);
440 return(MagickFalse);
441 }
442 status=GetPathAttributes(directory,&attributes);
443 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
444 {
445 directory=DestroyString(directory);
446 return(MagickFalse);
447 }
448 if (directory[strlen(directory)-1] == *DirectorySeparator)
449 (void) FormatLocaleString(path,MagickPathExtent,
450 "%smagick-%.20gXXXXXXXXXXXX",directory,(double) getpid());
451 else
452 (void) FormatLocaleString(path,MagickPathExtent,
453 "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,(double)
454 getpid());
455 directory=DestroyString(directory);
456 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
457 {
458 register char
459 *p;
460
461 /*
462 Ghostscript does not like backslashes so we need to replace them. The
463 forward slash also works under Windows.
464 */
465 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
466 if (*p == *DirectorySeparator)
467 *p='/';
468 }
469 #endif
470 return(MagickTrue);
471 }
472
AcquireUniqueFileResource(char * path)473 MagickExport int AcquireUniqueFileResource(char *path)
474 {
475 #if !defined(O_NOFOLLOW)
476 #define O_NOFOLLOW 0
477 #endif
478 #if !defined(TMP_MAX)
479 # define TMP_MAX 238328
480 #endif
481
482 int
483 c,
484 file;
485
486 register char
487 *p;
488
489 register ssize_t
490 i;
491
492 static const char
493 portable_filename[65] =
494 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
495
496 StringInfo
497 *key;
498
499 unsigned char
500 *datum;
501
502 assert(path != (char *) NULL);
503 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
504 if (random_info == (RandomInfo *) NULL)
505 {
506 LockSemaphoreInfo(resource_semaphore);
507 if (random_info == (RandomInfo *) NULL)
508 random_info=AcquireRandomInfo();
509 UnlockSemaphoreInfo(resource_semaphore);
510 }
511 file=(-1);
512 for (i=0; i < (ssize_t) TMP_MAX; i++)
513 {
514 /*
515 Get temporary pathname.
516 */
517 (void) GetPathTemplate(path);
518 key=GetRandomKey(random_info,6);
519 p=path+strlen(path)-12;
520 datum=GetStringInfoDatum(key);
521 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
522 {
523 c=(int) (datum[i] & 0x3f);
524 *p++=portable_filename[c];
525 }
526 key=DestroyStringInfo(key);
527 #if defined(MAGICKCORE_HAVE_MKSTEMP)
528 file=mkstemp(path);
529 if (file != -1)
530 {
531 #if defined(MAGICKCORE_HAVE_FCHMOD)
532 (void) fchmod(file,0600);
533 #endif
534 #if defined(__OS2__)
535 setmode(file,O_BINARY);
536 #endif
537 break;
538 }
539 #endif
540 key=GetRandomKey(random_info,12);
541 p=path+strlen(path)-12;
542 datum=GetStringInfoDatum(key);
543 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
544 {
545 c=(int) (datum[i] & 0x3f);
546 *p++=portable_filename[c];
547 }
548 key=DestroyStringInfo(key);
549 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
550 S_MODE);
551 if ((file >= 0) || (errno != EEXIST))
552 break;
553 }
554 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
555 if (file == -1)
556 return(file);
557 if (resource_semaphore == (SemaphoreInfo *) NULL)
558 ActivateSemaphoreInfo(&resource_semaphore);
559 LockSemaphoreInfo(resource_semaphore);
560 if (temporary_resources == (SplayTreeInfo *) NULL)
561 temporary_resources=NewSplayTree(CompareSplayTreeString,
562 DestroyTemporaryResources,(void *(*)(void *)) NULL);
563 UnlockSemaphoreInfo(resource_semaphore);
564 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
565 (const void *) NULL);
566 return(file);
567 }
568
569 /*
570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 % %
572 % %
573 % %
574 % G e t M a g i c k R e s o u r c e %
575 % %
576 % %
577 % %
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
579 %
580 % GetMagickResource() returns the specified resource.
581 %
582 % The format of the GetMagickResource() method is:
583 %
584 % MagickSizeType GetMagickResource(const ResourceType type)
585 %
586 % A description of each parameter follows:
587 %
588 % o type: the type of resource.
589 %
590 */
GetMagickResource(const ResourceType type)591 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
592 {
593 MagickSizeType
594 resource;
595
596 resource=0;
597 LockSemaphoreInfo(resource_semaphore);
598 switch (type)
599 {
600 case WidthResource:
601 {
602 resource=(MagickSizeType) resource_info.width;
603 break;
604 }
605 case HeightResource:
606 {
607 resource=(MagickSizeType) resource_info.height;
608 break;
609 }
610 case AreaResource:
611 {
612 resource=(MagickSizeType) resource_info.area;
613 break;
614 }
615 case MemoryResource:
616 {
617 resource=(MagickSizeType) resource_info.memory;
618 break;
619 }
620 case MapResource:
621 {
622 resource=(MagickSizeType) resource_info.map;
623 break;
624 }
625 case DiskResource:
626 {
627 resource=(MagickSizeType) resource_info.disk;
628 break;
629 }
630 case FileResource:
631 {
632 resource=(MagickSizeType) resource_info.file;
633 break;
634 }
635 case ThreadResource:
636 {
637 resource=(MagickSizeType) resource_info.thread;
638 break;
639 }
640 case ThrottleResource:
641 {
642 resource=(MagickSizeType) resource_info.throttle;
643 break;
644 }
645 case TimeResource:
646 {
647 resource=(MagickSizeType) resource_info.time;
648 break;
649 }
650 default:
651 break;
652 }
653 UnlockSemaphoreInfo(resource_semaphore);
654 return(resource);
655 }
656
657 /*
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 % %
660 % %
661 % %
662 % G e t M a g i c k R e s o u r c e L i m i t %
663 % %
664 % %
665 % %
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 %
668 % GetMagickResourceLimit() returns the specified resource limit.
669 %
670 % The format of the GetMagickResourceLimit() method is:
671 %
672 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
673 %
674 % A description of each parameter follows:
675 %
676 % o type: the type of resource.
677 %
678 */
GetMagickResourceLimit(const ResourceType type)679 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
680 {
681 MagickSizeType
682 resource;
683
684 resource=0;
685 if (resource_semaphore == (SemaphoreInfo *) NULL)
686 ActivateSemaphoreInfo(&resource_semaphore);
687 LockSemaphoreInfo(resource_semaphore);
688 switch (type)
689 {
690 case WidthResource:
691 {
692 resource=resource_info.width_limit;
693 break;
694 }
695 case HeightResource:
696 {
697 resource=resource_info.height_limit;
698 break;
699 }
700 case AreaResource:
701 {
702 resource=resource_info.area_limit;
703 break;
704 }
705 case MemoryResource:
706 {
707 resource=resource_info.memory_limit;
708 break;
709 }
710 case MapResource:
711 {
712 resource=resource_info.map_limit;
713 break;
714 }
715 case DiskResource:
716 {
717 resource=resource_info.disk_limit;
718 break;
719 }
720 case FileResource:
721 {
722 resource=resource_info.file_limit;
723 break;
724 }
725 case ThreadResource:
726 {
727 resource=resource_info.thread_limit;
728 break;
729 }
730 case ThrottleResource:
731 {
732 resource=resource_info.throttle_limit;
733 break;
734 }
735 case TimeResource:
736 {
737 resource=resource_info.time_limit;
738 break;
739 }
740 default:
741 break;
742 }
743 UnlockSemaphoreInfo(resource_semaphore);
744 return(resource);
745 }
746
747 /*
748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 % %
750 % %
751 % %
752 % L i s t M a g i c k R e s o u r c e I n f o %
753 % %
754 % %
755 % %
756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
757 %
758 % ListMagickResourceInfo() lists the resource info to a file.
759 %
760 % The format of the ListMagickResourceInfo method is:
761 %
762 % MagickBooleanType ListMagickResourceInfo(FILE *file,
763 % ExceptionInfo *exception)
764 %
765 % A description of each parameter follows.
766 %
767 % o file: An pointer to a FILE.
768 %
769 % o exception: return any errors or warnings in this structure.
770 %
771 */
ListMagickResourceInfo(FILE * file,ExceptionInfo * magick_unused (exception))772 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
773 ExceptionInfo *magick_unused(exception))
774 {
775 char
776 area_limit[MagickFormatExtent],
777 disk_limit[MagickFormatExtent],
778 height_limit[MagickFormatExtent],
779 map_limit[MagickFormatExtent],
780 memory_limit[MagickFormatExtent],
781 time_limit[MagickFormatExtent],
782 width_limit[MagickFormatExtent];
783
784 magick_unreferenced(exception);
785
786 if (file == (const FILE *) NULL)
787 file=stdout;
788 if (resource_semaphore == (SemaphoreInfo *) NULL)
789 ActivateSemaphoreInfo(&resource_semaphore);
790 LockSemaphoreInfo(resource_semaphore);
791 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
792 MagickFormatExtent,width_limit);
793 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
794 MagickFormatExtent,height_limit);
795 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
796 MagickFormatExtent,area_limit);
797 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
798 MagickFormatExtent,memory_limit);
799 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
800 MagickFormatExtent,map_limit);
801 (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
802 if (resource_info.disk_limit != MagickResourceInfinity)
803 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
804 MagickFormatExtent,disk_limit);
805 (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
806 if (resource_info.time_limit != MagickResourceInfinity)
807 (void) FormatLocaleString(time_limit,MagickFormatExtent,"%.20g",(double)
808 ((MagickOffsetType) resource_info.time_limit));
809 (void) FormatLocaleFile(file,"Resource limits:\n");
810 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
811 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
812 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
813 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
814 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
815 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
816 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
817 resource_info.file_limit));
818 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
819 resource_info.thread_limit));
820 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
821 ((MagickOffsetType) resource_info.throttle_limit));
822 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
823 (void) fflush(file);
824 UnlockSemaphoreInfo(resource_semaphore);
825 return(MagickTrue);
826 }
827
828 /*
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 % %
831 % %
832 % %
833 % R e l i n q u i s h M a g i c k R e s o u r c e %
834 % %
835 % %
836 % %
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838 %
839 % RelinquishMagickResource() relinquishes resources of the specified type.
840 %
841 % The format of the RelinquishMagickResource() method is:
842 %
843 % void RelinquishMagickResource(const ResourceType type,
844 % const MagickSizeType size)
845 %
846 % A description of each parameter follows:
847 %
848 % o type: the type of resource.
849 %
850 % o size: the size of the resource.
851 %
852 */
RelinquishMagickResource(const ResourceType type,const MagickSizeType size)853 MagickExport void RelinquishMagickResource(const ResourceType type,
854 const MagickSizeType size)
855 {
856 char
857 resource_current[MagickFormatExtent],
858 resource_limit[MagickFormatExtent],
859 resource_request[MagickFormatExtent];
860
861 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
862 resource_request);
863 if (resource_semaphore == (SemaphoreInfo *) NULL)
864 ActivateSemaphoreInfo(&resource_semaphore);
865 LockSemaphoreInfo(resource_semaphore);
866 switch (type)
867 {
868 case WidthResource:
869 {
870 resource_info.width=(MagickOffsetType) size;
871 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
872 "P",MagickFormatExtent,resource_current);
873 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
874 MagickFormatExtent,resource_limit);
875 break;
876 }
877 case HeightResource:
878 {
879 resource_info.height=(MagickOffsetType) size;
880 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
881 "P",MagickFormatExtent,resource_current);
882 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
883 MagickFormatExtent,resource_limit);
884 break;
885 }
886 case AreaResource:
887 {
888 resource_info.area=(MagickOffsetType) size;
889 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
890 "B",MagickFormatExtent,resource_current);
891 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
892 MagickFormatExtent,resource_limit);
893 break;
894 }
895 case MemoryResource:
896 {
897 resource_info.memory-=size;
898 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
899 MagickTrue,"B",MagickFormatExtent,resource_current);
900 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
901 MagickFormatExtent,resource_limit);
902 break;
903 }
904 case MapResource:
905 {
906 resource_info.map-=size;
907 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
908 "B",MagickFormatExtent,resource_current);
909 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
910 MagickFormatExtent,resource_limit);
911 break;
912 }
913 case DiskResource:
914 {
915 resource_info.disk-=size;
916 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
917 "B",MagickFormatExtent,resource_current);
918 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
919 MagickFormatExtent,resource_limit);
920 break;
921 }
922 case FileResource:
923 {
924 resource_info.file-=size;
925 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
926 "B",MagickFormatExtent,resource_current);
927 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
928 MagickFalse,"B",MagickFormatExtent,resource_limit);
929 break;
930 }
931 case ThreadResource:
932 {
933 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
934 "B",MagickFormatExtent,resource_current);
935 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
936 MagickFalse,"B",MagickFormatExtent,resource_limit);
937 break;
938 }
939 case ThrottleResource:
940 {
941 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
942 MagickFalse,"B",MagickFormatExtent,resource_current);
943 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
944 MagickFalse,"B",MagickFormatExtent,resource_limit);
945 break;
946 }
947 case TimeResource:
948 {
949 resource_info.time-=size;
950 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
951 "B",MagickFormatExtent,resource_current);
952 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
953 MagickFalse,"B",MagickFormatExtent,resource_limit);
954 break;
955 }
956 default:
957 break;
958 }
959 UnlockSemaphoreInfo(resource_semaphore);
960 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
961 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
962 resource_request,resource_current,resource_limit);
963 }
964
965 /*
966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
967 % %
968 % %
969 % %
970 % 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 %
971 % %
972 % %
973 % %
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975 %
976 % RelinquishUniqueFileResource() relinquishes a unique file resource.
977 %
978 % The format of the RelinquishUniqueFileResource() method is:
979 %
980 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
981 %
982 % A description of each parameter follows:
983 %
984 % o name: the name of the temporary resource.
985 %
986 */
RelinquishUniqueFileResource(const char * path)987 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
988 {
989 char
990 cache_path[MagickPathExtent];
991
992 MagickBooleanType
993 status;
994
995 assert(path != (const char *) NULL);
996 status=MagickFalse;
997 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
998 if (resource_semaphore == (SemaphoreInfo *) NULL)
999 ActivateSemaphoreInfo(&resource_semaphore);
1000 LockSemaphoreInfo(resource_semaphore);
1001 if (temporary_resources != (SplayTreeInfo *) NULL)
1002 status=DeleteNodeFromSplayTree(temporary_resources, (const void *) path);
1003 UnlockSemaphoreInfo(resource_semaphore);
1004 (void) CopyMagickString(cache_path,path,MagickPathExtent);
1005 AppendImageFormat("cache",cache_path);
1006 (void) ShredFile(cache_path);
1007 if (status == MagickFalse)
1008 status=ShredFile(path);
1009 return(status);
1010 }
1011
1012 /*
1013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1014 % %
1015 % %
1016 % %
1017 + R e s o u r c e C o m p o n e n t G e n e s i s %
1018 % %
1019 % %
1020 % %
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022 %
1023 % ResourceComponentGenesis() instantiates the resource component.
1024 %
1025 % The format of the ResourceComponentGenesis method is:
1026 %
1027 % MagickBooleanType ResourceComponentGenesis(void)
1028 %
1029 */
1030
StringToSizeType(const char * string,const double interval)1031 static inline MagickSizeType StringToSizeType(const char *string,
1032 const double interval)
1033 {
1034 double
1035 value;
1036
1037 value=SiPrefixToDoubleInterval(string,interval);
1038 if (value >= (double) MagickULLConstant(~0))
1039 return(MagickULLConstant(~0));
1040 return((MagickSizeType) value);
1041 }
1042
ResourceComponentGenesis(void)1043 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1044 {
1045 char
1046 *limit;
1047
1048 MagickSizeType
1049 memory;
1050
1051 ssize_t
1052 files,
1053 pages,
1054 pagesize;
1055
1056 /*
1057 Set Magick resource limits.
1058 */
1059 if (resource_semaphore == (SemaphoreInfo *) NULL)
1060 resource_semaphore=AcquireSemaphoreInfo();
1061 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1062 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1063 if (limit != (char *) NULL)
1064 {
1065 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
1066 100.0));
1067 limit=DestroyString(limit);
1068 }
1069 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1070 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1071 if (limit != (char *) NULL)
1072 {
1073 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
1074 100.0));
1075 limit=DestroyString(limit);
1076 }
1077 pagesize=GetMagickPageSize();
1078 pages=(-1);
1079 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1080 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1081 #endif
1082 memory=(MagickSizeType) pages*pagesize;
1083 if ((pagesize <= 0) || (pages <= 0))
1084 memory=2048UL*1024UL*1024UL;
1085 #if defined(PixelCacheThreshold)
1086 memory=PixelCacheThreshold;
1087 #endif
1088 (void) SetMagickResourceLimit(AreaResource,2*memory);
1089 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1090 if (limit != (char *) NULL)
1091 {
1092 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
1093 limit=DestroyString(limit);
1094 }
1095 (void) SetMagickResourceLimit(MemoryResource,memory);
1096 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1097 if (limit != (char *) NULL)
1098 {
1099 (void) SetMagickResourceLimit(MemoryResource,
1100 StringToSizeType(limit,100.0));
1101 limit=DestroyString(limit);
1102 }
1103 (void) SetMagickResourceLimit(MapResource,2*memory);
1104 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1105 if (limit != (char *) NULL)
1106 {
1107 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1108 limit=DestroyString(limit);
1109 }
1110 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1111 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1112 if (limit != (char *) NULL)
1113 {
1114 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1115 limit=DestroyString(limit);
1116 }
1117 files=(-1);
1118 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1119 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1120 #endif
1121 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1122 if (files < 0)
1123 {
1124 struct rlimit
1125 resources;
1126
1127 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1128 files=(ssize_t) resources.rlim_cur;
1129 }
1130 #endif
1131 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1132 if (files < 0)
1133 files=(ssize_t) getdtablesize();
1134 #endif
1135 if (files < 0)
1136 files=64;
1137 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1138 (3*files/4),64));
1139 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1140 if (limit != (char *) NULL)
1141 {
1142 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1143 100.0));
1144 limit=DestroyString(limit);
1145 }
1146 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1147 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1148 if (limit != (char *) NULL)
1149 {
1150 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1151 100.0));
1152 limit=DestroyString(limit);
1153 }
1154 (void) SetMagickResourceLimit(ThrottleResource,0);
1155 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1156 if (limit != (char *) NULL)
1157 {
1158 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1159 100.0));
1160 limit=DestroyString(limit);
1161 }
1162 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1163 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1164 if (limit != (char *) NULL)
1165 {
1166 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1167 limit=DestroyString(limit);
1168 }
1169 return(MagickTrue);
1170 }
1171
1172 /*
1173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1174 % %
1175 % %
1176 % %
1177 + 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 %
1178 % %
1179 % %
1180 % %
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1182 %
1183 % ResourceComponentTerminus() destroys the resource component.
1184 %
1185 % The format of the ResourceComponentTerminus() method is:
1186 %
1187 % ResourceComponentTerminus(void)
1188 %
1189 */
ResourceComponentTerminus(void)1190 MagickPrivate void ResourceComponentTerminus(void)
1191 {
1192 if (resource_semaphore == (SemaphoreInfo *) NULL)
1193 resource_semaphore=AcquireSemaphoreInfo();
1194 LockSemaphoreInfo(resource_semaphore);
1195 if (temporary_resources != (SplayTreeInfo *) NULL)
1196 temporary_resources=DestroySplayTree(temporary_resources);
1197 if (random_info != (RandomInfo *) NULL)
1198 random_info=DestroyRandomInfo(random_info);
1199 UnlockSemaphoreInfo(resource_semaphore);
1200 RelinquishSemaphoreInfo(&resource_semaphore);
1201 }
1202
1203 /*
1204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1205 % %
1206 % %
1207 % %
1208 % S e t M a g i c k R e s o u r c e L i m i t %
1209 % %
1210 % %
1211 % %
1212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1213 %
1214 % SetMagickResourceLimit() sets the limit for a particular resource.
1215 %
1216 % The format of the SetMagickResourceLimit() method is:
1217 %
1218 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1219 % const MagickSizeType limit)
1220 %
1221 % A description of each parameter follows:
1222 %
1223 % o type: the type of resource.
1224 %
1225 % o limit: the maximum limit for the resource.
1226 %
1227 */
1228
SetMagickResourceLimit(const ResourceType type,const MagickSizeType limit)1229 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1230 const MagickSizeType limit)
1231 {
1232 char
1233 *value;
1234
1235 if (resource_semaphore == (SemaphoreInfo *) NULL)
1236 resource_semaphore=AcquireSemaphoreInfo();
1237 LockSemaphoreInfo(resource_semaphore);
1238 value=(char *) NULL;
1239 switch (type)
1240 {
1241 case WidthResource:
1242 {
1243 resource_info.width_limit=limit;
1244 value=GetPolicyValue("width");
1245 if (value != (char *) NULL)
1246 resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
1247 100.0));
1248 break;
1249 }
1250 case HeightResource:
1251 {
1252 resource_info.height_limit=limit;
1253 value=GetPolicyValue("height");
1254 if (value != (char *) NULL)
1255 resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
1256 100.0));
1257 break;
1258 }
1259 case AreaResource:
1260 {
1261 resource_info.area_limit=limit;
1262 value=GetPolicyValue("area");
1263 if (value != (char *) NULL)
1264 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1265 break;
1266 }
1267 case MemoryResource:
1268 {
1269 resource_info.memory_limit=limit;
1270 value=GetPolicyValue("memory");
1271 if (value != (char *) NULL)
1272 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1273 100.0));
1274 break;
1275 }
1276 case MapResource:
1277 {
1278 resource_info.map_limit=limit;
1279 value=GetPolicyValue("map");
1280 if (value != (char *) NULL)
1281 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1282 break;
1283 }
1284 case DiskResource:
1285 {
1286 resource_info.disk_limit=limit;
1287 value=GetPolicyValue("disk");
1288 if (value != (char *) NULL)
1289 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1290 break;
1291 }
1292 case FileResource:
1293 {
1294 resource_info.file_limit=limit;
1295 value=GetPolicyValue("file");
1296 if (value != (char *) NULL)
1297 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1298 break;
1299 }
1300 case ThreadResource:
1301 {
1302 resource_info.thread_limit=limit;
1303 value=GetPolicyValue("thread");
1304 if (value != (char *) NULL)
1305 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1306 100.0));
1307 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1308 resource_info.thread_limit=GetOpenMPMaximumThreads();
1309 else if (resource_info.thread_limit == 0)
1310 resource_info.thread_limit=1;
1311 break;
1312 }
1313 case ThrottleResource:
1314 {
1315 resource_info.throttle_limit=limit;
1316 value=GetPolicyValue("throttle");
1317 if (value != (char *) NULL)
1318 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1319 100.0));
1320 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1321 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1322 break;
1323 }
1324 case TimeResource:
1325 {
1326 resource_info.time_limit=limit;
1327 value=GetPolicyValue("time");
1328 if (value != (char *) NULL)
1329 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1330 ResetPixelCacheEpoch();
1331 break;
1332 }
1333 default:
1334 break;
1335 }
1336 if (value != (char *) NULL)
1337 value=DestroyString(value);
1338 UnlockSemaphoreInfo(resource_semaphore);
1339 return(MagickTrue);
1340 }
1341