% MagickCore Utility Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% January 1993 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2014 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 %
#include "MagickCore/geometry.h"
#include "MagickCore/list.h"
#include "MagickCore/log.h"
+#include "MagickCore/magick-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/semaphore.h"
#include "MagickCore/signature-private.h"
#include "MagickCore/statistic.h"
#include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
#include "MagickCore/token.h"
+#include "MagickCore/token-private.h"
#include "MagickCore/utility.h"
+#include "MagickCore/utility-private.h"
#if defined(MAGICKCORE_HAVE_PROCESS_H)
#include <process.h>
#endif
%
*/
-static inline size_t MagickMin(const size_t x,const size_t y)
+static inline MagickSizeType MagickMin(const MagickSizeType x,
+ const MagickSizeType y)
{
if (x < y)
return(x);
destination_file=AcquireUniqueFileResource(destination);
if (destination_file == -1)
return(MagickFalse);
- source_file=open(source,O_RDONLY | O_BINARY);
+ source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
if (source_file == -1)
{
(void) close(destination_file);
}
quantum=(size_t) MagickMaxBufferExtent;
if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
- quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
+ quantum=(size_t) MagickMin((size_t) attributes.st_size,
+ MagickMaxBufferExtent);
buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
if (buffer == (unsigned char *) NULL)
{
% o components: The number of components to chop.
%
*/
-MagickExport void ChopPathComponents(char *path,const size_t components)
+MagickPrivate void ChopPathComponents(char *path,const size_t components)
{
register ssize_t
i;
% path.
%
*/
-MagickExport void ExpandFilename(char *path)
+MagickPrivate void ExpandFilename(char *path)
{
char
expand_path[MaxTextExtent];
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% ExpandFilenames() checks each argument of the command line vector and
-% expands it if they have a wildcard character. For example, *.jpg might
-% expand to: bird.jpg rose.jpg tiki.jpg.
+% ExpandFilenames() checks each argument of the given argument array, and
+% expands it if they have a wildcard character.
+%
+% Any coder prefix (EG: 'coder:filename') or read modifier postfix (EG:
+% 'filename[...]') are ignored during the file the expansion, but will be
+% included in the final argument. If no filename matching the meta-character
+% 'glob' is found the original argument is returned.
+%
+% For example, an argument of '*.gif[20x20]' will be replaced by the list
+% 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]'
+% if such filenames exist, (in the current directory in this case).
+%
+% Meta-characters handled...
+% @ read a list of filenames (no further expansion performed)
+% ~ At start of filename expands to HOME environemtn variable
+% * matches any string including an empty string
+% ? matches by any single character
+%
+% WARNING: filenames starting with '.' (hidden files in a UNIX file system)
+% will never be expanded. Attempting to epand '.*' will produce no change.
+%
+% Expansion is ignored for coders "label:" "caption:" "pango:" and "vid:".
+% Which provide their own '@' meta-character handling.
+%
+% You can see the results of the expansion using "Configure" log events.
+%
+% The returned list should be freed using DestroyStringList().
+%
+% However the strings in the original pointed to argv are not
+% freed (TO BE CHECKED). So a copy of the original pointer (and count)
+% should be kept separate if they need to be freed later.
%
% The format of the ExpandFilenames function is:
%
*path='\0';
*filename='\0';
*subimage='\0';
+ number_files=0;
vector[count++]=ConstantString(option);
destroy=MagickTrue;
parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
GetPathComponent(option,MagickPath,magick);
if ((LocaleCompare(magick,"CAPTION") == 0) ||
(LocaleCompare(magick,"LABEL") == 0) ||
+ (LocaleCompare(magick,"PANGO") == 0) ||
(LocaleCompare(magick,"VID") == 0))
continue;
- if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
+ if ((IsGlob(filename) == MagickFalse) && (*option != '@'))
continue;
- if (*filename != '@')
+ if (*option != '@')
{
/*
Generate file list from wildcard filename (e.g. *.jpg).
Generate file list from file list (e.g. @filelist.txt).
*/
exception=AcquireExceptionInfo();
- files=FileToString(filename+1,~0,exception);
+ files=FileToString(option+1,~0UL,exception);
exception=DestroyExceptionInfo(exception);
if (files == (char *) NULL)
continue;
if (*path != '\0')
(void) ConcatenateMagickString(filename,DirectorySeparator,
MaxTextExtent);
- (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
+ if (filelist[j] != (char *) NULL)
+ (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
filelist[j]=DestroyString(filelist[j]);
if (strlen(filename) >= (MaxTextExtent-1))
ThrowFatalException(OptionFatalError,"FilenameTruncated");
% o extent: the maximum extent of the path.
%
*/
-MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
+MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
{
char
*directory;
program_name=(char *) RelinquishMagickMemory(program_name);
execution_path=(char *) RelinquishMagickMemory(execution_path);
}
+#endif
+#if defined(__OpenBSD__)
+ {
+ extern char
+ *__progname;
+
+ (void) CopyMagickString(path,__progname,extent);
+ }
#endif
return(IsPathAccessible(path));
}
% ssize_t GetMagickPageSize()
%
*/
-MagickExport ssize_t GetMagickPageSize(void)
+MagickPrivate ssize_t GetMagickPageSize(void)
{
static ssize_t
page_size = -1;
% o attributes: the path attributes are returned here.
%
*/
-
-#if defined(MAGICKCORE_HAVE__WFOPEN)
-static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
-{
- register const unsigned char
- *p;
-
- if (utf16 != (wchar_t *) NULL)
- {
- register wchar_t
- *q;
-
- wchar_t
- c;
-
- /*
- Convert UTF-8 to UTF-16.
- */
- q=utf16;
- for (p=utf8; *p != '\0'; p++)
- {
- if ((*p & 0x80) == 0)
- *q=(*p);
- else
- if ((*p & 0xE0) == 0xC0)
- {
- c=(*p);
- *q=(c & 0x1F) << 6;
- p++;
- if ((*p & 0xC0) != 0x80)
- return(0);
- *q|=(*p & 0x3F);
- }
- else
- if ((*p & 0xF0) == 0xE0)
- {
- c=(*p);
- *q=c << 12;
- p++;
- if ((*p & 0xC0) != 0x80)
- return(0);
- c=(*p);
- *q|=(c & 0x3F) << 6;
- p++;
- if ((*p & 0xC0) != 0x80)
- return(0);
- *q|=(*p & 0x3F);
- }
- else
- return(0);
- q++;
- }
- *q++='\0';
- return(q-utf16);
- }
- /*
- Compute UTF-16 string length.
- */
- for (p=utf8; *p != '\0'; p++)
- {
- if ((*p & 0x80) == 0)
- ;
- else
- if ((*p & 0xE0) == 0xC0)
- {
- p++;
- if ((*p & 0xC0) != 0x80)
- return(0);
- }
- else
- if ((*p & 0xF0) == 0xE0)
- {
- p++;
- if ((*p & 0xC0) != 0x80)
- return(0);
- p++;
- if ((*p & 0xC0) != 0x80)
- return(0);
- }
- else
- return(0);
- }
- return(p-utf8);
-}
-
-static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
-{
- size_t
- length;
-
- wchar_t
- *utf16;
-
- length=UTF8ToUTF16(source,(wchar_t *) NULL);
- if (length == 0)
- {
- register ssize_t
- i;
-
- /*
- Not UTF-8, just copy.
- */
- length=strlen((const char *) source);
- utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
- if (utf16 == (wchar_t *) NULL)
- return((wchar_t *) NULL);
- for (i=0; i <= (ssize_t) length; i++)
- utf16[i]=source[i];
- return(utf16);
- }
- utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
- if (utf16 == (wchar_t *) NULL)
- return((wchar_t *) NULL);
- length=UTF8ToUTF16(source,utf16);
- return(utf16);
-}
-#endif
-
MagickExport MagickBooleanType GetPathAttributes(const char *path,
void *attributes)
{
errno=EINVAL;
return(MagickFalse);
}
-#if !defined(MAGICKCORE_HAVE__WSTAT)
- status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
-#else
- {
- int
- count;
-
- wchar_t
- *unicode_path;
-
- count=MultiByteToWideChar(CP_ACP,0,path,-1,NULL,0);
- unicode_path=(wchar_t *) AcquireQuantumMemory(count,sizeof(*unicode_path));
- if (unicode_path == (wchar_t *) NULL)
- return(MagickFalse);
- status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
- MagickFalse;
- unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
- }
-#endif
+ status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
+ MagickFalse;
return(status);
}
\f
% GetPathComponent() returns the parent directory name, filename, basename, or
% extension of a file path.
%
+% The component string pointed to must have at least MaxTextExtent space
+% for the results to be stored.
+%
% The format of the GetPathComponent function is:
%
% GetPathComponent(const char *path,PathType type,char *component)
}
(void) CopyMagickString(component,path,MaxTextExtent);
*magick='\0';
- *subimage='\0';
- p=component;
- if (*p != '\0')
- p=component+strlen(component)-1;
- if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
- (IsPathAccessible(path) == MagickFalse))
- {
- /*
- Look for scene specification (e.g. img0001.pcd[4]).
- */
- for (q=p-1; q > component; q--)
- if (*q == '[')
- break;
- if (*q == '[')
- {
- (void) CopyMagickString(subimage,q+1,MaxTextExtent);
- subimage[p-q-1]='\0';
- if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
- (IsGeometry(subimage) == MagickFalse))
- *subimage='\0';
- else
- *q='\0';
- }
- }
#if defined(__OS2__)
- if (path[1] != ':')
+ if (path[1] != ":")
#endif
for (p=component; *p != '\0'; p++)
{
if (*p == '\0')
break;
}
- if ((*p == ':') && (IsPathDirectory(component) < 0) &&
- (IsPathAccessible(component) == MagickFalse))
+ if ((*p == ':') && (IsPathDirectory(path) < 0) &&
+ (IsPathAccessible(path) == MagickFalse))
{
/*
Look for image format specification (e.g. ps3:image).
break;
}
}
+ *subimage='\0';
+ p=component;
+ if (*p != '\0')
+ p=component+strlen(component)-1;
+ if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
+ (IsPathAccessible(path) == MagickFalse))
+ {
+ /*
+ Look for scene specification (e.g. img0001.pcd[4]).
+ */
+ for (q=p-1; q > component; q--)
+ if (*q == '[')
+ break;
+ if (*q == '[')
+ {
+ (void) CopyMagickString(subimage,q+1,MaxTextExtent);
+ subimage[p-q-1]='\0';
+ if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
+ (IsGeometry(subimage) == MagickFalse))
+ *subimage='\0';
+ else
+ *q='\0';
+ }
+ }
p=component;
if (*p != '\0')
for (p=component+strlen(component)-1; p > component; p--)
% o number_components: return the number of components in the list
%
*/
-MagickExport char **GetPathComponents(const char *path,
+MagickPrivate char **GetPathComponents(const char *path,
size_t *number_components)
{
char
%
% The format of the IsPathAccessible method is:
%
-% MagickBooleanType IsPathAccessible(const char *filename)
+% MagickBooleanType IsPathAccessible(const char *path)
%
% A description of each parameter follows.
%
return(status);
if (S_ISREG(attributes.st_mode) == 0)
return(MagickFalse);
- if (access(path,F_OK) != 0)
+ if (access_utf8(path,F_OK) != 0)
return(MagickFalse);
return(MagickTrue);
}
% %
% %
% %
-% I s M a g i c k T r u e %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% IsMagickTrue() returns MagickTrue if the value is "true", "on", "yes" or
-% "1".
-%
-% The format of the IsMagickTrue method is:
-%
-% MagickBooleanType IsMagickTrue(const char *value)
-%
-% A description of each parameter follows:
-%
-% o option: either MagickTrue or MagickFalse depending on the value
-% parameter.
-%
-% o value: Specifies a pointer to a character array.
-%
-*/
-MagickExport MagickBooleanType IsMagickTrue(const char *value)
-{
- if (value == (const char *) NULL)
- return(MagickFalse);
- if (LocaleCompare(value,"true") == 0)
- return(MagickTrue);
- if (LocaleCompare(value,"on") == 0)
- return(MagickTrue);
- if (LocaleCompare(value,"yes") == 0)
- return(MagickTrue);
- if (LocaleCompare(value,"1") == 0)
- return(MagickTrue);
- return(MagickFalse);
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
% L i s t F i l e s %
% %
% %
#endif
}
-MagickExport char **ListFiles(const char *directory,const char *pattern,
+MagickPrivate char **ListFiles(const char *directory,const char *pattern,
size_t *number_entries)
{
char
% returning.
%
*/
-MagickExport void MagickDelay(const MagickSizeType milliseconds)
+MagickPrivate void MagickDelay(const MagickSizeType milliseconds)
{
if (milliseconds == 0)
return;
%
% o label: This character string is the label.
%
-%
*/
MagickExport size_t MultilineCensus(const char *label)
{
% %
% %
% %
-% O p e n M a g i c k S t r e a m %
+% S h r e a d F i l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% OpenMagickStream() opens the file at the specified path and return the
-% associated stream.
+% ShredFile() overwrites the specified file with zeros or random data and then
+% removes it. The overwrite is optional and is only required to help keep
+% the contents of the file private. On the first pass, the file is zeroed.
+% For subsequent passes, random data is written.
%
-% The path of the OpenMagickStream method is:
+% The format of the ShredFile method is:
%
-% FILE *OpenMagickStream(const char *path,const char *mode)
+% MagickBooleanType ShredFile(const char *path)
%
% A description of each parameter follows.
%
-% o path: the file path.
-%
-% o mode: the file mode.
+% o path: Specifies a path to a file.
%
*/
-MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
+MagickPrivate MagickBooleanType ShredFile(const char *path)
{
- FILE
- *file;
+ char
+ *passes;
+
+ int
+ file,
+ status;
- if ((path == (const char *) NULL) || (mode == (const char *) NULL))
+ MagickSizeType
+ length;
+
+ register ssize_t
+ i;
+
+ size_t
+ quantum;
+
+ struct stat
+ file_stats;
+
+ if ((path == (const char *) NULL) || (*path == '\0'))
+ return(MagickFalse);
+ passes=GetEnvironmentValue("MAGICK_SHRED_PASSES");
+ if (passes == (char *) NULL)
{
- errno=EINVAL;
- return((FILE *) NULL);
+ /*
+ Don't shred the file, just remove it.
+ */
+ status=remove_utf8(path);
+ if (status == -1)
+ return(MagickFalse);
+ return(MagickTrue);
+ }
+ file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
+ if (file == -1)
+ {
+ /*
+ Don't shred the file, just remove it.
+ */
+ status=remove_utf8(path);
+ return(MagickFalse);
}
- file=(FILE *) NULL;
-#if defined(MAGICKCORE_HAVE__WFOPEN)
+ /*
+ Shred the file.
+ */
+ quantum=(size_t) MagickMaxBufferExtent;
+ if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
+ quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
+ MagickMaxBufferExtent);
+ length=(MagickSizeType) file_stats.st_size;
+ for (i=0; i < (ssize_t) StringToInteger(passes); i++)
{
- int
+ RandomInfo
+ *random_info;
+
+ register MagickOffsetType
+ j;
+
+ ssize_t
count;
- wchar_t
- *unicode_mode,
- *unicode_path;
-
- count=MultiByteToWideChar(CP_ACP,0,path,-1,NULL,0);
- unicode_path=(wchar_t *) AcquireQuantumMemory(count,sizeof(*unicode_path));
- if (unicode_path == (wchar_t *) NULL)
- return((FILE *) NULL);
- count=MultiByteToWideChar(CP_ACP,0,mode,-1,NULL,0);
- unicode_mode=(wchar_t *) AcquireQuantumMemory(count,sizeof(*unicode_mode));
- if (unicode_mode == (wchar_t *) NULL)
- {
- unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
- return((FILE *) NULL);
- }
- file=_wfopen(unicode_path,unicode_mode);
- unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
- unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
+ if (lseek(file,0,SEEK_SET) < 0)
+ break;
+ random_info=AcquireRandomInfo();
+ for (j=0; j < (MagickOffsetType) length; j+=count)
+ {
+ StringInfo
+ *key;
+
+ key=GetRandomKey(random_info,quantum);
+ if (i == 0)
+ ResetStringInfo(key); /* zero on first pass */
+ count=write(file,GetStringInfoDatum(key),(size_t)
+ MagickMin(quantum,length-j));
+ key=DestroyStringInfo(key);
+ if (count <= 0)
+ {
+ count=0;
+ if (errno != EINTR)
+ break;
+ }
+ }
+ random_info=DestroyRandomInfo(random_info);
+ if (j < (MagickOffsetType) length)
+ break;
}
-#endif
- if (file == (FILE *) NULL)
- file=fopen(path,mode);
- return(file);
+ status=close(file);
+ status=remove_utf8(path);
+ if (status == -1)
+ return(MagickFalse);
+ return(i < (ssize_t) StringToInteger(passes) ? MagickFalse : MagickTrue);
}
\f
/*
arguments=StringToArgv(command,&number_arguments);
if (arguments == (char **) NULL)
return(status);
+ if (*arguments[1] == '\0')
+ {
+ for (i=0; i < (ssize_t) number_arguments; i++)
+ arguments[i]=DestroyString(arguments[i]);
+ arguments=(char **) RelinquishMagickMemory(arguments);
+ return(-1);
+ }
rights=ExecutePolicyRights;
domain=DelegatePolicyDomain;
if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
#if !defined(MAGICKCORE_HAVE_EXECVP)
status=system(shell_command);
#else
- if ((asynchronous != MagickFalse) || (strspn(shell_command,"&;<>|") == 0))
+ if ((asynchronous != MagickFalse) ||
+ (strpbrk(shell_command,"&;<>|") != (char *) NULL))
status=system(shell_command);
else
{
/*
Call application directly rather than from a shell.
*/
- child_pid=fork();
+ child_pid=(pid_t) fork();
if (child_pid == (pid_t) -1)
status=system(command);
else
pid;
child_status=0;
- pid=waitpid(child_pid,&child_status,0);
+ pid=(pid_t) waitpid(child_pid,&child_status,0);
if (pid == -1)
status=(-1);
else
}
#endif
#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
- {
- int
- mode;
-
- mode=_P_WAIT;
- if (asynchronous != MagickFalse)
- mode=_P_NOWAIT;
- status=spawnvp(mode,arguments[1],(const char **) (arguments+1));
- }
+ status=NTSystemCommand(shell_command);
#elif defined(macintosh)
status=MACSystemCommand(shell_command);
#elif defined(vms)
#endif
if (status < 0)
(void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
- "`%s' (%d)",command,status);
+ "'%s' (%d)",command,status);
if (shell_command != command)
shell_command=DestroyString(shell_command);
for (i=0; i < (ssize_t) number_arguments; i++)