|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% RRRR EEEEE SSSSS OOO U U RRRR CCCC EEEEE %
|
|
|
% R R E SS O O U U R R C E %
|
|
|
% RRRR EEE SSS O O U U RRRR C EEE %
|
|
|
% R R E SS O O U U R R C E %
|
|
|
% R R EEEEE SSSSS OOO UUU R R CCCC EEEEE %
|
|
|
% %
|
|
|
% %
|
|
|
% Get/Set MagickCore Resources %
|
|
|
% %
|
|
|
% Software Design %
|
|
|
% Cristy %
|
|
|
% September 2002 %
|
|
|
% %
|
|
|
% %
|
|
|
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
|
|
|
% dedicated to making software imaging solutions freely available. %
|
|
|
% %
|
|
|
% You may not use this file except in compliance with the License. You may %
|
|
|
% obtain a copy of the License at %
|
|
|
% %
|
|
|
% https://imagemagick.org/script/license.php %
|
|
|
% %
|
|
|
% Unless required by applicable law or agreed to in writing, software %
|
|
|
% distributed under the License is distributed on an "AS IS" BASIS, %
|
|
|
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
|
|
|
% See the License for the specific language governing permissions and %
|
|
|
% limitations under the License. %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
%
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
Include declarations.
|
|
|
*/
|
|
|
#include "MagickCore/studio.h"
|
|
|
#include "MagickCore/cache.h"
|
|
|
#include "MagickCore/cache-private.h"
|
|
|
#include "MagickCore/configure.h"
|
|
|
#include "MagickCore/exception.h"
|
|
|
#include "MagickCore/exception-private.h"
|
|
|
#include "MagickCore/linked-list.h"
|
|
|
#include "MagickCore/log.h"
|
|
|
#include "MagickCore/image.h"
|
|
|
#include "MagickCore/image-private.h"
|
|
|
#include "MagickCore/memory_.h"
|
|
|
#include "MagickCore/nt-base-private.h"
|
|
|
#include "MagickCore/option.h"
|
|
|
#include "MagickCore/policy.h"
|
|
|
#include "MagickCore/random_.h"
|
|
|
#include "MagickCore/registry.h"
|
|
|
#include "MagickCore/resource_.h"
|
|
|
#include "MagickCore/resource-private.h"
|
|
|
#include "MagickCore/semaphore.h"
|
|
|
#include "MagickCore/signature-private.h"
|
|
|
#include "MagickCore/string_.h"
|
|
|
#include "MagickCore/string-private.h"
|
|
|
#include "MagickCore/splay-tree.h"
|
|
|
#include "MagickCore/thread-private.h"
|
|
|
#include "MagickCore/token.h"
|
|
|
#include "MagickCore/utility.h"
|
|
|
#include "MagickCore/utility-private.h"
|
|
|
|
|
|
/*
|
|
|
Define declarations.
|
|
|
*/
|
|
|
#define MagickPathTemplate "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" /* min 6 X's */
|
|
|
#define NumberOfResourceTypes \
|
|
|
(sizeof(resource_semaphore)/sizeof(*resource_semaphore))
|
|
|
|
|
|
/*
|
|
|
Typedef declarations.
|
|
|
*/
|
|
|
typedef struct _ResourceInfo
|
|
|
{
|
|
|
MagickOffsetType
|
|
|
width,
|
|
|
height,
|
|
|
list_length,
|
|
|
area,
|
|
|
memory,
|
|
|
map,
|
|
|
disk,
|
|
|
file,
|
|
|
thread,
|
|
|
throttle,
|
|
|
time;
|
|
|
|
|
|
MagickSizeType
|
|
|
width_limit,
|
|
|
height_limit,
|
|
|
list_length_limit,
|
|
|
area_limit,
|
|
|
memory_limit,
|
|
|
map_limit,
|
|
|
disk_limit,
|
|
|
file_limit,
|
|
|
thread_limit,
|
|
|
throttle_limit,
|
|
|
time_limit;
|
|
|
} ResourceInfo;
|
|
|
|
|
|
/*
|
|
|
Global declarations.
|
|
|
*/
|
|
|
static RandomInfo
|
|
|
*random_info = (RandomInfo *) NULL;
|
|
|
|
|
|
static ResourceInfo
|
|
|
resource_info =
|
|
|
{
|
|
|
MagickULLConstant(0), /* initial width */
|
|
|
MagickULLConstant(0), /* initial height */
|
|
|
MagickULLConstant(0), /* initial list length */
|
|
|
MagickULLConstant(0), /* initial area */
|
|
|
MagickULLConstant(0), /* initial memory */
|
|
|
MagickULLConstant(0), /* initial map */
|
|
|
MagickULLConstant(0), /* initial disk */
|
|
|
MagickULLConstant(0), /* initial file */
|
|
|
MagickULLConstant(0), /* initial thread */
|
|
|
MagickULLConstant(0), /* initial throttle */
|
|
|
MagickULLConstant(0), /* initial time */
|
|
|
MAGICK_SSIZE_MAX/sizeof(Quantum)/5,/* width limit */
|
|
|
MAGICK_SSIZE_MAX/sizeof(Quantum)/5,/* height limit */
|
|
|
MagickResourceInfinity, /* list length limit */
|
|
|
MagickULLConstant(3072)*1024*1024, /* area limit */
|
|
|
MagickULLConstant(1536)*1024*1024, /* memory limit */
|
|
|
MagickULLConstant(3072)*1024*1024, /* map limit */
|
|
|
MagickResourceInfinity, /* disk limit */
|
|
|
MagickULLConstant(768), /* file limit */
|
|
|
MagickULLConstant(1), /* thread limit */
|
|
|
MagickULLConstant(0), /* throttle limit */
|
|
|
MagickResourceInfinity /* time limit */
|
|
|
};
|
|
|
|
|
|
static SemaphoreInfo
|
|
|
*resource_semaphore[] = {
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL,
|
|
|
(SemaphoreInfo *) NULL
|
|
|
};
|
|
|
|
|
|
static SplayTreeInfo
|
|
|
*temporary_resources = (SplayTreeInfo *) NULL;
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% A c q u i r e M a g i c k R e s o u r c e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% AcquireMagickResource() acquires resources of the specified type.
|
|
|
% MagickFalse is returned if the specified resource is exhausted otherwise
|
|
|
% MagickTrue.
|
|
|
%
|
|
|
% The format of the AcquireMagickResource() method is:
|
|
|
%
|
|
|
% MagickBooleanType AcquireMagickResource(const ResourceType type,
|
|
|
% const MagickSizeType size)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o type: the type of resource.
|
|
|
%
|
|
|
% o size: the number of bytes needed from for this resource.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
|
|
|
const MagickSizeType size)
|
|
|
{
|
|
|
MagickBooleanType
|
|
|
bi,
|
|
|
status;
|
|
|
|
|
|
MagickOffsetType
|
|
|
current,
|
|
|
request;
|
|
|
|
|
|
MagickSizeType
|
|
|
limit;
|
|
|
|
|
|
request=(MagickOffsetType) size;
|
|
|
if (request < 0)
|
|
|
return(MagickFalse);
|
|
|
limit=0;
|
|
|
current=0;
|
|
|
bi=MagickFalse;
|
|
|
status=MagickFalse;
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[type]);
|
|
|
LockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case AreaResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
resource_info.area=request;
|
|
|
limit=resource_info.area_limit;
|
|
|
if ((limit == MagickResourceInfinity) || (size < limit))
|
|
|
status=MagickTrue;
|
|
|
break;
|
|
|
}
|
|
|
case DiskResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
limit=resource_info.disk_limit;
|
|
|
if (((MagickSizeType) resource_info.disk+request) >
|
|
|
(MagickSizeType) resource_info.disk)
|
|
|
{
|
|
|
resource_info.disk+=request;
|
|
|
if ((limit == MagickResourceInfinity) ||
|
|
|
(resource_info.disk < (MagickOffsetType) limit))
|
|
|
status=MagickTrue;
|
|
|
else
|
|
|
resource_info.disk-=request;
|
|
|
}
|
|
|
current=resource_info.disk;
|
|
|
break;
|
|
|
}
|
|
|
case FileResource:
|
|
|
{
|
|
|
limit=resource_info.file_limit;
|
|
|
if (((MagickSizeType) resource_info.file+request) >
|
|
|
(MagickSizeType) resource_info.file)
|
|
|
{
|
|
|
resource_info.file+=request;
|
|
|
if ((limit == MagickResourceInfinity) ||
|
|
|
(resource_info.file < (MagickOffsetType) limit))
|
|
|
status=MagickTrue;
|
|
|
}
|
|
|
current=resource_info.file;
|
|
|
break;
|
|
|
}
|
|
|
case HeightResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
resource_info.height=request;
|
|
|
limit=resource_info.height_limit;
|
|
|
if ((limit == MagickResourceInfinity) || (size < limit))
|
|
|
status=MagickTrue;
|
|
|
break;
|
|
|
}
|
|
|
case ListLengthResource:
|
|
|
{
|
|
|
resource_info.list_length=request;
|
|
|
limit=resource_info.list_length_limit;
|
|
|
if ((limit == MagickResourceInfinity) || (size < limit))
|
|
|
status=MagickTrue;
|
|
|
break;
|
|
|
}
|
|
|
case MapResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
limit=resource_info.map_limit;
|
|
|
if (((MagickSizeType) resource_info.map+request) >
|
|
|
(MagickSizeType) resource_info.map)
|
|
|
{
|
|
|
resource_info.map+=request;
|
|
|
if ((limit == MagickResourceInfinity) ||
|
|
|
(resource_info.map < (MagickOffsetType) limit))
|
|
|
status=MagickTrue;
|
|
|
else
|
|
|
resource_info.map-=request;
|
|
|
}
|
|
|
current=resource_info.map;
|
|
|
break;
|
|
|
}
|
|
|
case MemoryResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
limit=resource_info.memory_limit;
|
|
|
if (((MagickSizeType) resource_info.memory+request) >
|
|
|
(MagickSizeType) resource_info.memory)
|
|
|
{
|
|
|
resource_info.memory+=request;
|
|
|
if ((limit == MagickResourceInfinity) ||
|
|
|
(resource_info.memory < (MagickOffsetType) limit))
|
|
|
status=MagickTrue;
|
|
|
else
|
|
|
resource_info.memory-=request;
|
|
|
}
|
|
|
current=resource_info.memory;
|
|
|
break;
|
|
|
}
|
|
|
case ThreadResource:
|
|
|
{
|
|
|
limit=resource_info.thread_limit;
|
|
|
if ((limit == MagickResourceInfinity) ||
|
|
|
(resource_info.thread < (MagickOffsetType) limit))
|
|
|
status=MagickTrue;
|
|
|
break;
|
|
|
}
|
|
|
case ThrottleResource:
|
|
|
{
|
|
|
limit=resource_info.throttle_limit;
|
|
|
if ((limit == MagickResourceInfinity) ||
|
|
|
(resource_info.throttle < (MagickOffsetType) limit))
|
|
|
status=MagickTrue;
|
|
|
break;
|
|
|
}
|
|
|
case TimeResource:
|
|
|
{
|
|
|
limit=resource_info.time_limit;
|
|
|
if (((MagickSizeType) resource_info.time+request) >
|
|
|
(MagickSizeType) resource_info.time)
|
|
|
{
|
|
|
resource_info.time+=request;
|
|
|
if ((limit == MagickResourceInfinity) ||
|
|
|
(resource_info.time < (MagickOffsetType) limit))
|
|
|
status=MagickTrue;
|
|
|
else
|
|
|
resource_info.time-=request;
|
|
|
}
|
|
|
current=resource_info.time;
|
|
|
break;
|
|
|
}
|
|
|
case WidthResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
resource_info.width=request;
|
|
|
limit=resource_info.width_limit;
|
|
|
if ((limit == MagickResourceInfinity) || (size < limit))
|
|
|
status=MagickTrue;
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
{
|
|
|
current=0;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
UnlockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
if (IsEventLogging() != MagickFalse)
|
|
|
{
|
|
|
char
|
|
|
resource_current[MagickFormatExtent],
|
|
|
resource_limit[MagickFormatExtent],
|
|
|
resource_request[MagickFormatExtent];
|
|
|
|
|
|
(void) FormatMagickSize(size,bi,(bi != MagickFalse) ? "B" :
|
|
|
(const char *) NULL,MagickFormatExtent,resource_request);
|
|
|
(void) FormatMagickSize((MagickSizeType) current,bi,(bi != MagickFalse) ?
|
|
|
"B" : (const char *) NULL,MagickFormatExtent,resource_current);
|
|
|
(void) FormatMagickSize(limit,bi,(bi != MagickFalse) ? "B" :
|
|
|
(const char *) NULL,MagickFormatExtent,resource_limit);
|
|
|
(void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
|
|
|
CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
|
|
|
resource_request,resource_current,resource_limit);
|
|
|
}
|
|
|
return(status);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
+ 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 %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% AsynchronousResourceComponentTerminus() destroys the resource environment.
|
|
|
% It differs from ResourceComponentTerminus() in that it can be called from a
|
|
|
% asynchronous signal handler.
|
|
|
%
|
|
|
% The format of the ResourceComponentTerminus() method is:
|
|
|
%
|
|
|
% ResourceComponentTerminus(void)
|
|
|
%
|
|
|
*/
|
|
|
MagickPrivate void AsynchronousResourceComponentTerminus(void)
|
|
|
{
|
|
|
const char
|
|
|
*path;
|
|
|
|
|
|
if (temporary_resources == (SplayTreeInfo *) NULL)
|
|
|
return;
|
|
|
/*
|
|
|
Remove any lingering temporary files.
|
|
|
*/
|
|
|
ResetSplayTreeIterator(temporary_resources);
|
|
|
path=(const char *) GetNextKeyInSplayTree(temporary_resources);
|
|
|
while (path != (const char *) NULL)
|
|
|
{
|
|
|
(void) ShredFile(path);
|
|
|
path=(const char *) GetNextKeyInSplayTree(temporary_resources);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% 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 %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% AcquireUniqueFileResource() returns a unique file name, and returns a file
|
|
|
% descriptor for the file open for reading and writing.
|
|
|
%
|
|
|
% The format of the AcquireUniqueFileResource() method is:
|
|
|
%
|
|
|
% int AcquireUniqueFileResource(char *path)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o path: Specifies a pointer to an array of characters. The unique path
|
|
|
% name is returned in this array.
|
|
|
%
|
|
|
*/
|
|
|
|
|
|
static void *DestroyTemporaryResources(void *temporary_resource)
|
|
|
{
|
|
|
(void) ShredFile((char *) temporary_resource);
|
|
|
temporary_resource=DestroyString((char *) temporary_resource);
|
|
|
return((void *) NULL);
|
|
|
}
|
|
|
|
|
|
MagickExport MagickBooleanType GetPathTemplate(char *path)
|
|
|
{
|
|
|
char
|
|
|
*directory,
|
|
|
*value;
|
|
|
|
|
|
ExceptionInfo
|
|
|
*exception;
|
|
|
|
|
|
MagickBooleanType
|
|
|
status;
|
|
|
|
|
|
struct stat
|
|
|
attributes;
|
|
|
|
|
|
(void) FormatLocaleString(path,MagickPathExtent,"magick-" MagickPathTemplate);
|
|
|
exception=AcquireExceptionInfo();
|
|
|
directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
|
|
|
exception);
|
|
|
exception=DestroyExceptionInfo(exception);
|
|
|
if (directory == (char *) NULL)
|
|
|
directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
|
|
|
if (directory == (char *) NULL)
|
|
|
directory=GetEnvironmentValue("MAGICK_TMPDIR");
|
|
|
if (directory == (char *) NULL)
|
|
|
directory=GetEnvironmentValue("TMPDIR");
|
|
|
#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
|
|
|
if (directory == (char *) NULL)
|
|
|
directory=GetEnvironmentValue("TMP");
|
|
|
if (directory == (char *) NULL)
|
|
|
directory=GetEnvironmentValue("TEMP");
|
|
|
#endif
|
|
|
#if defined(__VMS)
|
|
|
if (directory == (char *) NULL)
|
|
|
directory=GetEnvironmentValue("MTMPDIR");
|
|
|
#endif
|
|
|
#if defined(P_tmpdir)
|
|
|
if (directory == (char *) NULL)
|
|
|
directory=ConstantString(P_tmpdir);
|
|
|
#endif
|
|
|
if (directory == (char *) NULL)
|
|
|
return(MagickTrue);
|
|
|
value=GetPolicyValue("resource:temporary-path");
|
|
|
if (value != (char *) NULL)
|
|
|
{
|
|
|
(void) CloneString(&directory,value);
|
|
|
value=DestroyString(value);
|
|
|
}
|
|
|
if (strlen(directory) > (MagickPathExtent-25))
|
|
|
{
|
|
|
directory=DestroyString(directory);
|
|
|
return(MagickFalse);
|
|
|
}
|
|
|
status=GetPathAttributes(directory,&attributes);
|
|
|
if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
|
|
|
{
|
|
|
directory=DestroyString(directory);
|
|
|
return(MagickFalse);
|
|
|
}
|
|
|
if (directory[strlen(directory)-1] == *DirectorySeparator)
|
|
|
(void) FormatLocaleString(path,MagickPathExtent,"%smagick-"
|
|
|
MagickPathTemplate,directory);
|
|
|
else
|
|
|
(void) FormatLocaleString(path,MagickPathExtent,
|
|
|
"%s%smagick-" MagickPathTemplate,directory,DirectorySeparator);
|
|
|
directory=DestroyString(directory);
|
|
|
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
|
|
|
{
|
|
|
char
|
|
|
*p;
|
|
|
|
|
|
/*
|
|
|
Ghostscript does not like backslashes so we need to replace them. The
|
|
|
forward slash also works under Windows.
|
|
|
*/
|
|
|
for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
|
|
|
if (*p == *DirectorySeparator)
|
|
|
*p='/';
|
|
|
}
|
|
|
#endif
|
|
|
return(MagickTrue);
|
|
|
}
|
|
|
|
|
|
MagickExport int AcquireUniqueFileResource(char *path)
|
|
|
{
|
|
|
#if !defined(O_NOFOLLOW)
|
|
|
#define O_NOFOLLOW 0
|
|
|
#endif
|
|
|
#if !defined(TMP_MAX)
|
|
|
# define TMP_MAX 238328
|
|
|
#endif
|
|
|
|
|
|
int
|
|
|
c,
|
|
|
file;
|
|
|
|
|
|
char
|
|
|
*p;
|
|
|
|
|
|
ssize_t
|
|
|
i;
|
|
|
|
|
|
static const char
|
|
|
portable_filename[65] =
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
|
|
|
|
|
|
StringInfo
|
|
|
*key;
|
|
|
|
|
|
unsigned char
|
|
|
*datum;
|
|
|
|
|
|
assert(path != (char *) NULL);
|
|
|
(void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
|
|
|
if (random_info == (RandomInfo *) NULL)
|
|
|
{
|
|
|
if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
|
|
|
LockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
if (random_info == (RandomInfo *) NULL)
|
|
|
random_info=AcquireRandomInfo();
|
|
|
UnlockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
}
|
|
|
file=(-1);
|
|
|
for (i=0; i < (ssize_t) TMP_MAX; i++)
|
|
|
{
|
|
|
ssize_t
|
|
|
j;
|
|
|
|
|
|
/*
|
|
|
Get temporary pathname.
|
|
|
*/
|
|
|
(void) GetPathTemplate(path);
|
|
|
key=GetRandomKey(random_info,strlen(MagickPathTemplate)-6);
|
|
|
p=path+strlen(path)-strlen(MagickPathTemplate);
|
|
|
datum=GetStringInfoDatum(key);
|
|
|
for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
|
|
|
{
|
|
|
c=(int) (datum[j] & 0x3f);
|
|
|
*p++=portable_filename[c];
|
|
|
}
|
|
|
key=DestroyStringInfo(key);
|
|
|
#if defined(MAGICKCORE_HAVE_MKSTEMP)
|
|
|
file=mkstemp(path);
|
|
|
if (file != -1)
|
|
|
{
|
|
|
#if defined(MAGICKCORE_HAVE_FCHMOD)
|
|
|
(void) fchmod(file,0600);
|
|
|
#endif
|
|
|
#if defined(__OS2__)
|
|
|
setmode(file,O_BINARY);
|
|
|
#endif
|
|
|
break;
|
|
|
}
|
|
|
#endif
|
|
|
key=GetRandomKey(random_info,strlen(MagickPathTemplate));
|
|
|
p=path+strlen(path)-strlen(MagickPathTemplate);
|
|
|
datum=GetStringInfoDatum(key);
|
|
|
for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
|
|
|
{
|
|
|
c=(int) (datum[j] & 0x3f);
|
|
|
*p++=portable_filename[c];
|
|
|
}
|
|
|
key=DestroyStringInfo(key);
|
|
|
file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
|
|
|
S_MODE);
|
|
|
if ((file >= 0) || (errno != EEXIST))
|
|
|
break;
|
|
|
}
|
|
|
(void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
|
|
|
if (file == -1)
|
|
|
return(file);
|
|
|
if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
|
|
|
LockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
if (temporary_resources == (SplayTreeInfo *) NULL)
|
|
|
temporary_resources=NewSplayTree(CompareSplayTreeString,
|
|
|
DestroyTemporaryResources,(void *(*)(void *)) NULL);
|
|
|
UnlockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
(void) AddValueToSplayTree(temporary_resources,ConstantString(path),
|
|
|
(const void *) NULL);
|
|
|
return(file);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% G e t M a g i c k R e s o u r c e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% GetMagickResource() returns the specified resource.
|
|
|
%
|
|
|
% The format of the GetMagickResource() method is:
|
|
|
%
|
|
|
% MagickSizeType GetMagickResource(const ResourceType type)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o type: the type of resource.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport MagickSizeType GetMagickResource(const ResourceType type)
|
|
|
{
|
|
|
MagickSizeType
|
|
|
resource;
|
|
|
|
|
|
resource=0;
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[type]);
|
|
|
LockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case AreaResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.area;
|
|
|
break;
|
|
|
}
|
|
|
case DiskResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.disk;
|
|
|
break;
|
|
|
}
|
|
|
case FileResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.file;
|
|
|
break;
|
|
|
}
|
|
|
case HeightResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.height;
|
|
|
break;
|
|
|
}
|
|
|
case ListLengthResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.list_length;
|
|
|
break;
|
|
|
}
|
|
|
case MapResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.map;
|
|
|
break;
|
|
|
}
|
|
|
case MemoryResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.memory;
|
|
|
break;
|
|
|
}
|
|
|
case TimeResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.time;
|
|
|
break;
|
|
|
}
|
|
|
case ThreadResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.thread;
|
|
|
break;
|
|
|
}
|
|
|
case ThrottleResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.throttle;
|
|
|
break;
|
|
|
}
|
|
|
case WidthResource:
|
|
|
{
|
|
|
resource=(MagickSizeType) resource_info.width;
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
UnlockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
return(resource);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% G e t M a g i c k R e s o u r c e L i m i t %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% GetMagickResourceLimit() returns the specified resource limit.
|
|
|
%
|
|
|
% The format of the GetMagickResourceLimit() method is:
|
|
|
%
|
|
|
% MagickSizeType GetMagickResourceLimit(const ResourceType type)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o type: the type of resource.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
|
|
|
{
|
|
|
MagickSizeType
|
|
|
resource;
|
|
|
|
|
|
switch (type)
|
|
|
{
|
|
|
case AreaResource:
|
|
|
return(resource_info.area_limit);
|
|
|
case HeightResource:
|
|
|
return(resource_info.height_limit);
|
|
|
case ListLengthResource:
|
|
|
return(resource_info.list_length_limit);
|
|
|
case ThreadResource:
|
|
|
return(resource_info.thread_limit);
|
|
|
case ThrottleResource:
|
|
|
return(resource_info.throttle_limit);
|
|
|
case WidthResource:
|
|
|
return(resource_info.width_limit);
|
|
|
default: ;
|
|
|
}
|
|
|
resource=0;
|
|
|
if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[type]);
|
|
|
LockSemaphoreInfo(resource_semaphore[type]);
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
{
|
|
|
resource=resource_info.disk_limit;
|
|
|
break;
|
|
|
}
|
|
|
case FileResource:
|
|
|
{
|
|
|
resource=resource_info.file_limit;
|
|
|
break;
|
|
|
}
|
|
|
case MapResource:
|
|
|
{
|
|
|
resource=resource_info.map_limit;
|
|
|
break;
|
|
|
}
|
|
|
case MemoryResource:
|
|
|
{
|
|
|
resource=resource_info.memory_limit;
|
|
|
break;
|
|
|
}
|
|
|
case TimeResource:
|
|
|
{
|
|
|
resource=resource_info.time_limit;
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
UnlockSemaphoreInfo(resource_semaphore[type]);
|
|
|
return(resource);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% L i s t M a g i c k R e s o u r c e I n f o %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% ListMagickResourceInfo() lists the resource info to a file.
|
|
|
%
|
|
|
% The format of the ListMagickResourceInfo method is:
|
|
|
%
|
|
|
% MagickBooleanType ListMagickResourceInfo(FILE *file,
|
|
|
% ExceptionInfo *exception)
|
|
|
%
|
|
|
% A description of each parameter follows.
|
|
|
%
|
|
|
% o file: An pointer to a FILE.
|
|
|
%
|
|
|
% o exception: return any errors or warnings in this structure.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
|
|
|
ExceptionInfo *magick_unused(exception))
|
|
|
{
|
|
|
char
|
|
|
area_limit[MagickFormatExtent],
|
|
|
disk_limit[MagickFormatExtent],
|
|
|
height_limit[MagickFormatExtent],
|
|
|
list_length_limit[MagickFormatExtent],
|
|
|
map_limit[MagickFormatExtent],
|
|
|
memory_limit[MagickFormatExtent],
|
|
|
time_limit[MagickFormatExtent],
|
|
|
width_limit[MagickFormatExtent];
|
|
|
|
|
|
magick_unreferenced(exception);
|
|
|
|
|
|
if (file == (const FILE *) NULL)
|
|
|
file=stdout;
|
|
|
if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
|
|
|
LockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
(void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
|
|
|
MagickFormatExtent,width_limit);
|
|
|
(void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
|
|
|
MagickFormatExtent,height_limit);
|
|
|
(void) FormatMagickSize(resource_info.area_limit,MagickFalse,"P",
|
|
|
MagickFormatExtent,area_limit);
|
|
|
(void) CopyMagickString(list_length_limit,"unlimited",MagickFormatExtent);
|
|
|
if (resource_info.list_length_limit != MagickResourceInfinity)
|
|
|
(void) FormatMagickSize(resource_info.list_length_limit,MagickTrue,"B",
|
|
|
MagickFormatExtent,list_length_limit);
|
|
|
(void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
|
|
|
MagickFormatExtent,memory_limit);
|
|
|
(void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
|
|
|
MagickFormatExtent,map_limit);
|
|
|
(void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
|
|
|
if (resource_info.disk_limit != MagickResourceInfinity)
|
|
|
(void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
|
|
|
MagickFormatExtent,disk_limit);
|
|
|
(void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
|
|
|
if (resource_info.time_limit != MagickResourceInfinity)
|
|
|
(void) FormatLocaleString(time_limit,MagickFormatExtent,"%.20g",(double)
|
|
|
((MagickOffsetType) resource_info.time_limit));
|
|
|
(void) FormatLocaleFile(file,"Resource limits:\n");
|
|
|
(void) FormatLocaleFile(file," Width: %s\n",width_limit);
|
|
|
(void) FormatLocaleFile(file," Height: %s\n",height_limit);
|
|
|
(void) FormatLocaleFile(file," Area: %s\n",area_limit);
|
|
|
(void) FormatLocaleFile(file," List length: %s\n",list_length_limit);
|
|
|
(void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
|
|
|
(void) FormatLocaleFile(file," Map: %s\n",map_limit);
|
|
|
(void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
|
|
|
(void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
|
|
|
resource_info.file_limit));
|
|
|
(void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
|
|
|
resource_info.thread_limit));
|
|
|
(void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
|
|
|
((MagickOffsetType) resource_info.throttle_limit));
|
|
|
(void) FormatLocaleFile(file," Time: %s\n",time_limit);
|
|
|
(void) fflush(file);
|
|
|
UnlockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
return(MagickTrue);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% R e l i n q u i s h M a g i c k R e s o u r c e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% RelinquishMagickResource() relinquishes resources of the specified type.
|
|
|
%
|
|
|
% The format of the RelinquishMagickResource() method is:
|
|
|
%
|
|
|
% void RelinquishMagickResource(const ResourceType type,
|
|
|
% const MagickSizeType size)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o type: the type of resource.
|
|
|
%
|
|
|
% o size: the size of the resource.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport void RelinquishMagickResource(const ResourceType type,
|
|
|
const MagickSizeType size)
|
|
|
{
|
|
|
MagickBooleanType
|
|
|
bi;
|
|
|
|
|
|
MagickSizeType
|
|
|
current,
|
|
|
limit;
|
|
|
|
|
|
bi=MagickFalse;
|
|
|
limit=0;
|
|
|
current=0;
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[type]);
|
|
|
LockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
resource_info.disk-=size;
|
|
|
current=(MagickSizeType) resource_info.disk;
|
|
|
limit=resource_info.disk_limit;
|
|
|
assert(resource_info.disk >= 0);
|
|
|
break;
|
|
|
}
|
|
|
case FileResource:
|
|
|
{
|
|
|
resource_info.file-=size;
|
|
|
current=(MagickSizeType) resource_info.file;
|
|
|
limit=resource_info.file_limit;
|
|
|
assert(resource_info.file >= 0);
|
|
|
break;
|
|
|
}
|
|
|
case MapResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
resource_info.map-=size;
|
|
|
current=(MagickSizeType) resource_info.map;
|
|
|
limit=resource_info.map_limit;
|
|
|
assert(resource_info.map >= 0);
|
|
|
break;
|
|
|
}
|
|
|
case MemoryResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
resource_info.memory-=size;
|
|
|
current=(MagickSizeType) resource_info.memory;
|
|
|
limit=resource_info.memory_limit;
|
|
|
assert(resource_info.memory >= 0);
|
|
|
break;
|
|
|
}
|
|
|
case TimeResource:
|
|
|
{
|
|
|
bi=MagickTrue;
|
|
|
resource_info.time-=size;
|
|
|
current=(MagickSizeType) resource_info.time;
|
|
|
limit=resource_info.time_limit;
|
|
|
assert(resource_info.time >= 0);
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
{
|
|
|
current=0;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
UnlockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
if (IsEventLogging() != MagickFalse)
|
|
|
{
|
|
|
char
|
|
|
resource_current[MagickFormatExtent],
|
|
|
resource_limit[MagickFormatExtent],
|
|
|
resource_request[MagickFormatExtent];
|
|
|
|
|
|
(void) FormatMagickSize(size,bi,(bi != MagickFalse) ? "B" :
|
|
|
(const char *) NULL,MagickFormatExtent,resource_request);
|
|
|
(void) FormatMagickSize(current,bi,(bi != MagickFalse) ? "B" :
|
|
|
(const char *) NULL,MagickFormatExtent,resource_current);
|
|
|
(void) FormatMagickSize(limit,bi,(bi != MagickFalse) ? "B" :
|
|
|
(const char *) NULL,MagickFormatExtent,resource_limit);
|
|
|
(void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
|
|
|
CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
|
|
|
resource_request,resource_current,resource_limit);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% 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 %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% RelinquishUniqueFileResource() relinquishes a unique file resource.
|
|
|
%
|
|
|
% The format of the RelinquishUniqueFileResource() method is:
|
|
|
%
|
|
|
% MagickBooleanType RelinquishUniqueFileResource(const char *path)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o name: the name of the temporary resource.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
|
|
|
{
|
|
|
char
|
|
|
cache_path[MagickPathExtent];
|
|
|
|
|
|
MagickBooleanType
|
|
|
status;
|
|
|
|
|
|
assert(path != (const char *) NULL);
|
|
|
status=MagickFalse;
|
|
|
(void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
|
|
|
if (resource_semaphore[FileResource] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[FileResource]);
|
|
|
LockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
if (temporary_resources != (SplayTreeInfo *) NULL)
|
|
|
status=DeleteNodeFromSplayTree(temporary_resources,(const void *) path);
|
|
|
UnlockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
(void) CopyMagickString(cache_path,path,MagickPathExtent);
|
|
|
AppendImageFormat("cache",cache_path);
|
|
|
if (access_utf8(cache_path,F_OK) == 0)
|
|
|
(void) ShredFile(cache_path);
|
|
|
if (status == MagickFalse)
|
|
|
status=ShredFile(path);
|
|
|
return(status);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
+ R e s o u r c e C o m p o n e n t G e n e s i s %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% ResourceComponentGenesis() instantiates the resource component.
|
|
|
%
|
|
|
% The format of the ResourceComponentGenesis method is:
|
|
|
%
|
|
|
% MagickBooleanType ResourceComponentGenesis(void)
|
|
|
%
|
|
|
*/
|
|
|
|
|
|
MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
|
|
|
{
|
|
|
char
|
|
|
*limit;
|
|
|
|
|
|
MagickSizeType
|
|
|
memory;
|
|
|
|
|
|
ssize_t
|
|
|
i;
|
|
|
|
|
|
ssize_t
|
|
|
files,
|
|
|
pages,
|
|
|
pagesize;
|
|
|
|
|
|
/*
|
|
|
Set Magick resource limits.
|
|
|
*/
|
|
|
for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
|
|
|
if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
|
|
|
resource_semaphore[i]=AcquireSemaphoreInfo();
|
|
|
(void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
|
|
|
limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(WidthResource,StringToMagickSizeType(limit,
|
|
|
100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
|
|
|
limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(HeightResource,StringToMagickSizeType(
|
|
|
limit,100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
pagesize=GetMagickPageSize();
|
|
|
pages=(-1);
|
|
|
#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
|
|
|
pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
|
|
|
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
|
|
|
pages=pages/2;
|
|
|
#endif
|
|
|
#endif
|
|
|
memory=(MagickSizeType) pages*pagesize;
|
|
|
if ((pagesize <= 0) || (pages <= 0))
|
|
|
memory=2048UL*1024UL*1024UL;
|
|
|
#if defined(PixelCacheThreshold)
|
|
|
memory=PixelCacheThreshold;
|
|
|
#endif
|
|
|
(void) SetMagickResourceLimit(AreaResource,2*memory);
|
|
|
limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(AreaResource,StringToMagickSizeType(limit,
|
|
|
100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(MemoryResource,memory);
|
|
|
limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(MemoryResource,StringToMagickSizeType(
|
|
|
limit,100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(MapResource,2*memory);
|
|
|
limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(MapResource,StringToMagickSizeType(limit,
|
|
|
100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
|
|
|
limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(DiskResource,StringToMagickSizeType(limit,
|
|
|
100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
files=(-1);
|
|
|
#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
|
|
|
files=(ssize_t) sysconf(_SC_OPEN_MAX);
|
|
|
#endif
|
|
|
#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
|
|
|
if (files < 0)
|
|
|
{
|
|
|
struct rlimit
|
|
|
resources;
|
|
|
|
|
|
if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
|
|
|
files=(ssize_t) resources.rlim_cur;
|
|
|
}
|
|
|
#endif
|
|
|
#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
|
|
|
if (files < 0)
|
|
|
files=(ssize_t) getdtablesize();
|
|
|
#endif
|
|
|
if (files < 0)
|
|
|
files=64;
|
|
|
(void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
|
|
|
(3*files/4),64));
|
|
|
limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(FileResource,StringToMagickSizeType(limit,
|
|
|
100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
|
|
|
limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(ThreadResource,StringToMagickSizeType(
|
|
|
limit,100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(ThrottleResource,0);
|
|
|
limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(ThrottleResource,StringToMagickSizeType(
|
|
|
limit,100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
|
|
|
limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(TimeResource,StringToMagickSizeType(limit,
|
|
|
100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
(void) SetMagickResourceLimit(ListLengthResource,MagickResourceInfinity);
|
|
|
limit=GetEnvironmentValue("MAGICK_LIST_LENGTH_LIMIT");
|
|
|
if (limit != (char *) NULL)
|
|
|
{
|
|
|
(void) SetMagickResourceLimit(ListLengthResource,
|
|
|
StringToMagickSizeType(limit,100.0));
|
|
|
limit=DestroyString(limit);
|
|
|
}
|
|
|
return(MagickTrue);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
+ 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 %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% ResourceComponentTerminus() destroys the resource component.
|
|
|
%
|
|
|
% The format of the ResourceComponentTerminus() method is:
|
|
|
%
|
|
|
% ResourceComponentTerminus(void)
|
|
|
%
|
|
|
*/
|
|
|
MagickPrivate void ResourceComponentTerminus(void)
|
|
|
{
|
|
|
ssize_t
|
|
|
i;
|
|
|
|
|
|
for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
|
|
|
if (resource_semaphore[i] == (SemaphoreInfo *) NULL)
|
|
|
resource_semaphore[i]=AcquireSemaphoreInfo();
|
|
|
LockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
if (temporary_resources != (SplayTreeInfo *) NULL)
|
|
|
temporary_resources=DestroySplayTree(temporary_resources);
|
|
|
if (random_info != (RandomInfo *) NULL)
|
|
|
random_info=DestroyRandomInfo(random_info);
|
|
|
UnlockSemaphoreInfo(resource_semaphore[FileResource]);
|
|
|
for (i=0; i < (ssize_t) NumberOfResourceTypes; i++)
|
|
|
RelinquishSemaphoreInfo(&resource_semaphore[i]);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% S e t M a g i c k R e s o u r c e L i m i t %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% SetMagickResourceLimit() sets the limit for a particular resource.
|
|
|
%
|
|
|
% The format of the SetMagickResourceLimit() method is:
|
|
|
%
|
|
|
% MagickBooleanType SetMagickResourceLimit(const ResourceType type,
|
|
|
% const MagickSizeType limit)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o type: the type of resource.
|
|
|
%
|
|
|
% o limit: the maximum limit for the resource.
|
|
|
%
|
|
|
*/
|
|
|
MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
|
|
|
const MagickSizeType limit)
|
|
|
{
|
|
|
char
|
|
|
*value;
|
|
|
|
|
|
MagickBooleanType
|
|
|
status;
|
|
|
|
|
|
status=MagickTrue;
|
|
|
value=(char *) NULL;
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
if (resource_semaphore[type] == (SemaphoreInfo *) NULL)
|
|
|
ActivateSemaphoreInfo(&resource_semaphore[type]);
|
|
|
LockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case AreaResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:area");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.area_limit=limit;
|
|
|
else
|
|
|
resource_info.area_limit=MagickMin(limit,StringToMagickSizeType(value,
|
|
|
100.0));
|
|
|
break;
|
|
|
}
|
|
|
case DiskResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:disk");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.disk_limit=limit;
|
|
|
else
|
|
|
resource_info.disk_limit=MagickMin(limit,StringToMagickSizeType(value,
|
|
|
100.0));
|
|
|
break;
|
|
|
}
|
|
|
case FileResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:file");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.file_limit=limit;
|
|
|
else
|
|
|
resource_info.file_limit=MagickMin(limit,StringToMagickSizeType(value,
|
|
|
100.0));
|
|
|
break;
|
|
|
}
|
|
|
case HeightResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:height");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.height_limit=limit;
|
|
|
else
|
|
|
resource_info.height_limit=MagickMin(limit,StringToMagickSizeType(
|
|
|
value,100.0));
|
|
|
resource_info.height_limit=MagickMin(resource_info.height_limit,
|
|
|
(MagickSizeType) MAGICK_SSIZE_MAX);
|
|
|
break;
|
|
|
}
|
|
|
case ListLengthResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:list-length");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.list_length_limit=limit;
|
|
|
else
|
|
|
resource_info.list_length_limit=MagickMin(limit,
|
|
|
StringToMagickSizeType(value,100.0));
|
|
|
break;
|
|
|
}
|
|
|
case MapResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:map");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.map_limit=limit;
|
|
|
else
|
|
|
resource_info.map_limit=MagickMin(limit,StringToMagickSizeType(
|
|
|
value,100.0));
|
|
|
break;
|
|
|
}
|
|
|
case MemoryResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:memory");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.memory_limit=limit;
|
|
|
else
|
|
|
resource_info.memory_limit=MagickMin(limit,StringToMagickSizeType(
|
|
|
value,100.0));
|
|
|
break;
|
|
|
}
|
|
|
case ThreadResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:thread");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.thread_limit=limit;
|
|
|
else
|
|
|
resource_info.thread_limit=MagickMin(limit,StringToMagickSizeType(
|
|
|
value,100.0));
|
|
|
if (resource_info.thread_limit > GetOpenMPMaximumThreads())
|
|
|
resource_info.thread_limit=GetOpenMPMaximumThreads();
|
|
|
else
|
|
|
if (resource_info.thread_limit == 0)
|
|
|
resource_info.thread_limit=1;
|
|
|
break;
|
|
|
}
|
|
|
case ThrottleResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:throttle");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.throttle_limit=limit;
|
|
|
else
|
|
|
resource_info.throttle_limit=MagickMax(limit,StringToMagickSizeType(
|
|
|
value,100.0));
|
|
|
break;
|
|
|
}
|
|
|
case TimeResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:time");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.time_limit=limit;
|
|
|
else
|
|
|
resource_info.time_limit=MagickMin(limit,StringToMagickSizeType(value,
|
|
|
100.0));
|
|
|
ResetPixelCacheEpoch();
|
|
|
break;
|
|
|
}
|
|
|
case WidthResource:
|
|
|
{
|
|
|
value=GetPolicyValue("resource:width");
|
|
|
if (value == (char *) NULL)
|
|
|
resource_info.width_limit=limit;
|
|
|
else
|
|
|
resource_info.width_limit=MagickMin(limit,StringToMagickSizeType(value,
|
|
|
100.0));
|
|
|
resource_info.width_limit=MagickMin(resource_info.width_limit,
|
|
|
(MagickSizeType) MAGICK_SSIZE_MAX);
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
{
|
|
|
status=MagickFalse;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
switch (type)
|
|
|
{
|
|
|
case DiskResource:
|
|
|
case FileResource:
|
|
|
case MapResource:
|
|
|
case MemoryResource:
|
|
|
case TimeResource:
|
|
|
{
|
|
|
UnlockSemaphoreInfo(resource_semaphore[type]);
|
|
|
break;
|
|
|
}
|
|
|
default: ;
|
|
|
}
|
|
|
if (value != (char *) NULL)
|
|
|
value=DestroyString(value);
|
|
|
return(status);
|
|
|
}
|