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