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