utility.c revision fe676ee3a9cf43404bdc9ba8b27f597b5e4e28f7
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
7%             U   U    T      I    L        I      T     Y Y                  %
8%             U   U    T      I    L        I      T      Y                   %
9%             U   U    T      I    L        I      T      Y                   %
10%              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
11%                                                                             %
12%                                                                             %
13%                       MagickCore Utility Methods                            %
14%                                                                             %
15%                             Software Design                                 %
16%                               John Cristy                                   %
17%                              January 1993                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include "MagickCore/studio.h"
43#include "MagickCore/property.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/color.h"
46#include "MagickCore/exception.h"
47#include "MagickCore/exception-private.h"
48#include "MagickCore/geometry.h"
49#include "MagickCore/list.h"
50#include "MagickCore/log.h"
51#include "MagickCore/magick-private.h"
52#include "MagickCore/memory_.h"
53#include "MagickCore/nt-base-private.h"
54#include "MagickCore/option.h"
55#include "MagickCore/policy.h"
56#include "MagickCore/random_.h"
57#include "MagickCore/registry.h"
58#include "MagickCore/resource_.h"
59#include "MagickCore/semaphore.h"
60#include "MagickCore/signature-private.h"
61#include "MagickCore/statistic.h"
62#include "MagickCore/string_.h"
63#include "MagickCore/string-private.h"
64#include "MagickCore/token.h"
65#include "MagickCore/token-private.h"
66#include "MagickCore/utility.h"
67#include "MagickCore/utility-private.h"
68#if defined(MAGICKCORE_HAVE_PROCESS_H)
69#include <process.h>
70#endif
71#if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
72#include <mach-o/dyld.h>
73#endif
74
75/*
76  Static declarations.
77*/
78static const char
79  Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
80
81/*
82  Forward declaration.
83*/
84static int
85  IsPathDirectory(const char *);
86
87/*
88%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89%                                                                             %
90%                                                                             %
91%                                                                             %
92%   A c q u i r e U n i q u e F i l e n a m e                                 %
93%                                                                             %
94%                                                                             %
95%                                                                             %
96%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97%
98%  AcquireUniqueFilename() replaces the contents of path by a unique path name.
99%
100%  The format of the AcquireUniqueFilename method is:
101%
102%      MagickBooleanType AcquireUniqueFilename(char *path)
103%
104%  A description of each parameter follows.
105%
106%   o  path:  Specifies a pointer to an array of characters.  The unique path
107%      name is returned in this array.
108%
109*/
110MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
111{
112  int
113    file;
114
115  file=AcquireUniqueFileResource(path);
116  if (file == -1)
117    return(MagickFalse);
118  file=close(file)-1;
119  return(MagickTrue);
120}
121
122/*
123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124%                                                                             %
125%                                                                             %
126%                                                                             %
127%   A c q u i r e U n i q u e S ym b o l i c L i n k                          %
128%                                                                             %
129%                                                                             %
130%                                                                             %
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132%
133%  AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified
134%  source path and returns MagickTrue on success otherwise MagickFalse.  If the
135%  symlink() method fails or is not available, a unique file name is generated
136%  and the source file copied to it.  When you are finished with the file, use
137%  RelinquishUniqueFilename() to destroy it.
138%
139%  The format of the AcquireUniqueSymbolicLink method is:
140%
141%      MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
142%        char destination)
143%
144%  A description of each parameter follows.
145%
146%   o  source:  the source path.
147%
148%   o  destination:  the destination path.
149%
150*/
151
152static inline MagickSizeType MagickMin(const MagickSizeType x,
153  const MagickSizeType y)
154{
155  if (x < y)
156    return(x);
157  return(y);
158}
159
160MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
161  char *destination)
162{
163  int
164    destination_file,
165    source_file;
166
167  size_t
168    length,
169    quantum;
170
171  ssize_t
172    count;
173
174  struct stat
175    attributes;
176
177  unsigned char
178    *buffer;
179
180  assert(source != (const char *) NULL);
181  assert(destination != (char *) NULL);
182#if defined(MAGICKCORE_HAVE_SYMLINK)
183  (void) AcquireUniqueFilename(destination);
184  (void) RelinquishUniqueFileResource(destination);
185  if (*source == *DirectorySeparator)
186    {
187      if (symlink(source,destination) == 0)
188        return(MagickTrue);
189    }
190  else
191    {
192      char
193        path[MaxTextExtent];
194
195      *path='\0';
196      if (getcwd(path,MaxTextExtent) == (char *) NULL)
197        return(MagickFalse);
198      (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
199      (void) ConcatenateMagickString(path,source,MaxTextExtent);
200      if (symlink(path,destination) == 0)
201        return(MagickTrue);
202    }
203#endif
204  destination_file=AcquireUniqueFileResource(destination);
205  if (destination_file == -1)
206    return(MagickFalse);
207  source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
208  if (source_file == -1)
209    {
210      (void) close(destination_file);
211      (void) RelinquishUniqueFileResource(destination);
212      return(MagickFalse);
213    }
214  quantum=(size_t) MagickMaxBufferExtent;
215  if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
216    quantum=(size_t) MagickMin((size_t) attributes.st_size,
217      MagickMaxBufferExtent);
218  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
219  if (buffer == (unsigned char *) NULL)
220    {
221      (void) close(source_file);
222      (void) close(destination_file);
223      (void) RelinquishUniqueFileResource(destination);
224      return(MagickFalse);
225    }
226  for (length=0; ; )
227  {
228    count=(ssize_t) read(source_file,buffer,quantum);
229    if (count <= 0)
230      break;
231    length=(size_t) count;
232    count=(ssize_t) write(destination_file,buffer,length);
233    if ((size_t) count != length)
234      {
235        (void) close(destination_file);
236        (void) close(source_file);
237        buffer=(unsigned char *) RelinquishMagickMemory(buffer);
238        (void) RelinquishUniqueFileResource(destination);
239        return(MagickFalse);
240      }
241  }
242  (void) close(destination_file);
243  (void) close(source_file);
244  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
245  return(MagickTrue);
246}
247
248/*
249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250%                                                                             %
251%                                                                             %
252%                                                                             %
253%  A p p e n d I m a g e F o r m a t                                          %
254%                                                                             %
255%                                                                             %
256%                                                                             %
257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258%
259%  AppendImageFormat() appends the image format type to the filename.  If an
260%  extension to the file already exists, it is first removed.
261%
262%  The format of the AppendImageFormat method is:
263%
264%      void AppendImageFormat(const char *format,char *filename)
265%
266%  A description of each parameter follows.
267%
268%   o  format:  Specifies a pointer to an array of characters.  This the
269%      format of the image.
270%
271%   o  filename:  Specifies a pointer to an array of characters.  The unique
272%      file name is returned in this array.
273%
274*/
275MagickExport void AppendImageFormat(const char *format,char *filename)
276{
277  char
278    extension[MaxTextExtent],
279    root[MaxTextExtent];
280
281  assert(format != (char *) NULL);
282  assert(filename != (char *) NULL);
283  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
284  if ((*format == '\0') || (*filename == '\0'))
285    return;
286  if (LocaleCompare(filename,"-") == 0)
287    {
288      char
289        message[MaxTextExtent];
290
291      (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",format,filename);
292      (void) CopyMagickString(filename,message,MaxTextExtent);
293      return;
294    }
295  GetPathComponent(filename,ExtensionPath,extension);
296  if ((LocaleCompare(extension,"Z") == 0) ||
297      (LocaleCompare(extension,"bz2") == 0) ||
298      (LocaleCompare(extension,"gz") == 0) ||
299      (LocaleCompare(extension,"wmz") == 0) ||
300      (LocaleCompare(extension,"svgz") == 0))
301    {
302      GetPathComponent(filename,RootPath,root);
303      (void) CopyMagickString(filename,root,MaxTextExtent);
304      GetPathComponent(filename,RootPath,root);
305      (void) FormatLocaleString(filename,MaxTextExtent,"%s.%s.%s",root,format,
306        extension);
307      return;
308    }
309  GetPathComponent(filename,RootPath,root);
310  (void) FormatLocaleString(filename,MaxTextExtent,"%s.%s",root,format);
311}
312
313/*
314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315%                                                                             %
316%                                                                             %
317%                                                                             %
318%   B a s e 6 4 D e c o d e                                                   %
319%                                                                             %
320%                                                                             %
321%                                                                             %
322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323%
324%  Base64Decode() decodes Base64-encoded text and returns its binary
325%  equivalent.  NULL is returned if the text is not valid Base64 data, or a
326%  memory allocation failure occurs.
327%
328%  The format of the Base64Decode method is:
329%
330%      unsigned char *Base64Decode(const char *source,length_t *length)
331%
332%  A description of each parameter follows:
333%
334%    o source:  A pointer to a Base64-encoded string.
335%
336%    o length: the number of bytes decoded.
337%
338*/
339MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
340{
341  int
342    state;
343
344  register const char
345    *p,
346    *q;
347
348  register size_t
349    i;
350
351  unsigned char
352    *decode;
353
354  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
355  assert(source != (char *) NULL);
356  assert(length != (size_t *) NULL);
357  *length=0;
358  decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
359    3*sizeof(*decode));
360  if (decode == (unsigned char *) NULL)
361    return((unsigned char *) NULL);
362  i=0;
363  state=0;
364  for (p=source; *p != '\0'; p++)
365  {
366    if (isspace((int) ((unsigned char) *p)) != 0)
367      continue;
368    if (*p == '=')
369      break;
370    q=strchr(Base64,*p);
371    if (q == (char *) NULL)
372      {
373        decode=(unsigned char *) RelinquishMagickMemory(decode);
374        return((unsigned char *) NULL);  /* non-Base64 character */
375      }
376    switch (state)
377    {
378      case 0:
379      {
380        decode[i]=(q-Base64) << 2;
381        state++;
382        break;
383      }
384      case 1:
385      {
386        decode[i++]|=(q-Base64) >> 4;
387        decode[i]=((q-Base64) & 0x0f) << 4;
388        state++;
389        break;
390      }
391      case 2:
392      {
393        decode[i++]|=(q-Base64) >> 2;
394        decode[i]=((q-Base64) & 0x03) << 6;
395        state++;
396        break;
397      }
398      case 3:
399      {
400        decode[i++]|=(q-Base64);
401        state=0;
402        break;
403      }
404    }
405  }
406  /*
407    Verify Base-64 string has proper terminal characters.
408  */
409  if (*p != '=')
410    {
411      if (state != 0)
412        {
413          decode=(unsigned char *) RelinquishMagickMemory(decode);
414          return((unsigned char *) NULL);
415        }
416    }
417  else
418    {
419      p++;
420      switch (state)
421      {
422        case 0:
423        case 1:
424        {
425          /*
426            Unrecognized '=' character.
427          */
428          decode=(unsigned char *) RelinquishMagickMemory(decode);
429          return((unsigned char *) NULL);
430        }
431        case 2:
432        {
433          for ( ; *p != '\0'; p++)
434            if (isspace((int) ((unsigned char) *p)) == 0)
435              break;
436          if (*p != '=')
437            {
438              decode=(unsigned char *) RelinquishMagickMemory(decode);
439              return((unsigned char *) NULL);
440            }
441          p++;
442        }
443        case 3:
444        {
445          for ( ; *p != '\0'; p++)
446            if (isspace((int) ((unsigned char) *p)) == 0)
447              {
448                decode=(unsigned char *) RelinquishMagickMemory(decode);
449                return((unsigned char *) NULL);
450              }
451          if ((int) decode[i] != 0)
452            {
453              decode=(unsigned char *) RelinquishMagickMemory(decode);
454              return((unsigned char *) NULL);
455            }
456        }
457      }
458    }
459  *length=i;
460  return(decode);
461}
462
463/*
464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465%                                                                             %
466%                                                                             %
467%                                                                             %
468%   B a s e 6 4 E n c o d e                                                   %
469%                                                                             %
470%                                                                             %
471%                                                                             %
472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473%
474%  Base64Encode() encodes arbitrary binary data to Base64 encoded format as
475%  described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and
476%  returns the result as a null-terminated ASCII string.  NULL is returned if
477%  a memory allocation failure occurs.
478%
479%  The format of the Base64Encode method is:
480%
481%      char *Base64Encode(const unsigned char *blob,const size_t blob_length,
482%        size_t *encode_length)
483%
484%  A description of each parameter follows:
485%
486%    o blob:  A pointer to binary data to encode.
487%
488%    o blob_length: the number of bytes to encode.
489%
490%    o encode_length:  The number of bytes encoded.
491%
492*/
493MagickExport char *Base64Encode(const unsigned char *blob,
494  const size_t blob_length,size_t *encode_length)
495{
496  char
497    *encode;
498
499  register const unsigned char
500    *p;
501
502  register size_t
503    i;
504
505  size_t
506    remainder;
507
508  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
509  assert(blob != (const unsigned char *) NULL);
510  assert(blob_length != 0);
511  assert(encode_length != (size_t *) NULL);
512  *encode_length=0;
513  encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
514  if (encode == (char *) NULL)
515    return((char *) NULL);
516  i=0;
517  for (p=blob; p < (blob+blob_length-2); p+=3)
518  {
519    encode[i++]=Base64[(int) (*p >> 2)];
520    encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
521    encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
522    encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
523  }
524  remainder=blob_length % 3;
525  if (remainder != 0)
526    {
527      ssize_t
528        j;
529
530      unsigned char
531        code[3];
532
533      code[0]='\0';
534      code[1]='\0';
535      code[2]='\0';
536      for (j=0; j < (ssize_t) remainder; j++)
537        code[j]=(*p++);
538      encode[i++]=Base64[(int) (code[0] >> 2)];
539      encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
540      if (remainder == 1)
541        encode[i++]='=';
542      else
543        encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
544      encode[i++]='=';
545    }
546  *encode_length=i;
547  encode[i++]='\0';
548  return(encode);
549}
550
551/*
552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553%                                                                             %
554%                                                                             %
555%                                                                             %
556%   C h o p P a t h C o m p o n e n t s                                       %
557%                                                                             %
558%                                                                             %
559%                                                                             %
560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561%
562%  ChopPathComponents() removes the number of specified file components from a
563%  path.
564%
565%  The format of the ChopPathComponents method is:
566%
567%      ChopPathComponents(char *path,size_t components)
568%
569%  A description of each parameter follows:
570%
571%    o path:  The path.
572%
573%    o components:  The number of components to chop.
574%
575*/
576MagickPrivate void ChopPathComponents(char *path,const size_t components)
577{
578  register ssize_t
579    i;
580
581  for (i=0; i < (ssize_t) components; i++)
582    GetPathComponent(path,HeadPath,path);
583}
584
585/*
586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587%                                                                             %
588%                                                                             %
589%                                                                             %
590%   E x p a n d F i l e n a m e                                               %
591%                                                                             %
592%                                                                             %
593%                                                                             %
594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595%
596%  ExpandFilename() expands '~' in a path.
597%
598%  The format of the ExpandFilename function is:
599%
600%      ExpandFilename(char *path)
601%
602%  A description of each parameter follows:
603%
604%    o path: Specifies a pointer to a character array that contains the
605%      path.
606%
607*/
608MagickPrivate void ExpandFilename(char *path)
609{
610  char
611    expand_path[MaxTextExtent];
612
613  if (path == (char *) NULL)
614    return;
615  if (*path != '~')
616    return;
617  (void) CopyMagickString(expand_path,path,MaxTextExtent);
618  if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
619    {
620      char
621        *home;
622
623      /*
624        Substitute ~ with $HOME.
625      */
626      (void) CopyMagickString(expand_path,".",MaxTextExtent);
627      (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
628      home=GetEnvironmentValue("HOME");
629      if (home == (char *) NULL)
630        home=GetEnvironmentValue("USERPROFILE");
631      if (home != (char *) NULL)
632        {
633          (void) CopyMagickString(expand_path,home,MaxTextExtent);
634          (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
635          home=DestroyString(home);
636        }
637    }
638  else
639    {
640#if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
641      char
642        username[MaxTextExtent];
643
644      register char
645        *p;
646
647      struct passwd
648        *entry;
649
650      /*
651        Substitute ~ with home directory from password file.
652      */
653      (void) CopyMagickString(username,path+1,MaxTextExtent);
654      p=strchr(username,'/');
655      if (p != (char *) NULL)
656        *p='\0';
657      entry=getpwnam(username);
658      if (entry == (struct passwd *) NULL)
659        return;
660      (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
661      if (p != (char *) NULL)
662        {
663          (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
664          (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
665        }
666#endif
667    }
668  (void) CopyMagickString(path,expand_path,MaxTextExtent);
669}
670
671/*
672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673%                                                                             %
674%                                                                             %
675%                                                                             %
676%   E x p a n d F i l e n a m e s                                             %
677%                                                                             %
678%                                                                             %
679%                                                                             %
680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
681%
682%  ExpandFilenames() checks each argument of the given argument array, and
683%  expands it if they have a wildcard character.
684%
685%  Any coder prefix (EG: 'coder:filename') or read modifier postfix (EG:
686%  'filename[...]') are ignored during the file the expansion, but will be
687%  included in the final argument.  If no filename matching the meta-character
688%  'glob' is found the original argument is returned.
689%
690%  For example, an argument of '*.gif[20x20]' will be replaced by the list
691%    'abc.gif[20x20]',  'foobar.gif[20x20]',  'xyzzy.gif[20x20]'
692%  if such filenames exist, (in the current directory in this case).
693%
694%  Meta-characters handled...
695%     @    read a list of filenames (no further expansion performed)
696%     ~    At start of filename expands to HOME environemtn variable
697%     *    matches any string including an empty string
698%     ?    matches by any single character
699%
700%  WARNING: filenames starting with '.' (hidden files in a UNIX file system)
701%  will never be expanded.  Attempting to epand '.*' will produce no change.
702%
703%  Expansion is ignored for coders "label:" "caption:" "pango:" and "vid:".
704%  Which provide their own '@' meta-character handling.
705%
706%  You can see the results of the expansion using "Configure" log events.
707%
708%  The returned list should be freed using  DestroyStringList().
709%
710%  However the strings in the original pointed to argv are not
711%  freed  (TO BE CHECKED).  So a copy of the original pointer (and count)
712%  should be kept separate if they need to be freed later.
713%
714%  The format of the ExpandFilenames function is:
715%
716%      status=ExpandFilenames(int *number_arguments,char ***arguments)
717%
718%  A description of each parameter follows:
719%
720%    o number_arguments: Specifies a pointer to an integer describing the
721%      number of elements in the argument vector.
722%
723%    o arguments: Specifies a pointer to a text array containing the command
724%      line arguments.
725%
726*/
727MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
728  char ***arguments)
729{
730  char
731    *directory,
732    home_directory[MaxTextExtent],
733    **vector;
734
735  register ssize_t
736    i,
737    j;
738
739  size_t
740    number_files;
741
742  ssize_t
743    count,
744    parameters;
745
746  /*
747    Allocate argument vector.
748  */
749  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
750  assert(number_arguments != (int *) NULL);
751  assert(arguments != (char ***) NULL);
752  vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
753    sizeof(*vector));
754  if (vector == (char **) NULL)
755    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
756  /*
757    Expand any wildcard filenames.
758  */
759  *home_directory='\0';
760  count=0;
761  for (i=0; i < (ssize_t) *number_arguments; i++)
762  {
763    char
764      **filelist,
765      filename[MaxTextExtent],
766      magick[MaxTextExtent],
767      *option,
768      path[MaxTextExtent],
769      subimage[MaxTextExtent];
770
771    MagickBooleanType
772      destroy;
773
774    option=(*arguments)[i];
775    *magick='\0';
776    *path='\0';
777    *filename='\0';
778    *subimage='\0';
779    vector[count++]=ConstantString(option);
780    destroy=MagickTrue;
781    parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
782    if (parameters > 0)
783      {
784        /*
785          Do not expand command option parameters.
786        */
787        for (j=0; j < parameters; j++)
788        {
789          i++;
790          if (i == (ssize_t) *number_arguments)
791            break;
792          option=(*arguments)[i];
793          vector[count++]=ConstantString(option);
794        }
795        continue;
796      }
797    if ((*option == '"') || (*option == '\''))
798      continue;
799    GetPathComponent(option,TailPath,filename);
800    GetPathComponent(option,MagickPath,magick);
801    if ((LocaleCompare(magick,"CAPTION") == 0) ||
802        (LocaleCompare(magick,"LABEL") == 0) ||
803        (LocaleCompare(magick,"PANGO") == 0) ||
804        (LocaleCompare(magick,"VID") == 0))
805      continue;
806    if ((IsGlob(filename) == MagickFalse) && (*option != '@'))
807      continue;
808    if (*option != '@')
809      {
810        /*
811          Generate file list from wildcard filename (e.g. *.jpg).
812        */
813        GetPathComponent(option,HeadPath,path);
814        GetPathComponent(option,SubimagePath,subimage);
815        ExpandFilename(path);
816        if (*home_directory == '\0')
817          directory=getcwd(home_directory,MaxTextExtent-1);
818        (void) directory;
819        filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
820          &number_files);
821      }
822    else
823      {
824        char
825          *files;
826
827        ExceptionInfo
828          *exception;
829
830        int
831          length;
832
833        /*
834          Generate file list from file list (e.g. @filelist.txt).
835        */
836        exception=AcquireExceptionInfo();
837        files=FileToString(option+1,~0UL,exception);
838        exception=DestroyExceptionInfo(exception);
839        if (files == (char *) NULL)
840          continue;
841        filelist=StringToArgv(files,&length);
842        if (filelist == (char **) NULL)
843          continue;
844        files=DestroyString(files);
845        filelist[0]=DestroyString(filelist[0]);
846        for (j=0; j < (ssize_t) (length-1); j++)
847          filelist[j]=filelist[j+1];
848        number_files=(size_t) length-1;
849      }
850    if (filelist == (char **) NULL)
851      continue;
852    for (j=0; j < (ssize_t) number_files; j++)
853      if (IsPathDirectory(filelist[j]) <= 0)
854        break;
855    if (j == (ssize_t) number_files)
856      {
857        for (j=0; j < (ssize_t) number_files; j++)
858          filelist[j]=DestroyString(filelist[j]);
859        filelist=(char **) RelinquishMagickMemory(filelist);
860        continue;
861      }
862    /*
863      Transfer file list to argument vector.
864    */
865    vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
866      count+number_files+1,sizeof(*vector));
867    if (vector == (char **) NULL)
868      return(MagickFalse);
869    for (j=0; j < (ssize_t) number_files; j++)
870    {
871      option=filelist[j];
872      parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
873      if (parameters > 0)
874        {
875          ssize_t
876            k;
877
878          /*
879            Do not expand command option parameters.
880          */
881          vector[count++]=ConstantString(option);
882          for (k=0; k < parameters; k++)
883          {
884            j++;
885            if (j == (ssize_t) number_files)
886              break;
887            option=filelist[j];
888            vector[count++]=ConstantString(option);
889          }
890          continue;
891        }
892      (void) CopyMagickString(filename,path,MaxTextExtent);
893      if (*path != '\0')
894        (void) ConcatenateMagickString(filename,DirectorySeparator,
895          MaxTextExtent);
896      (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
897      filelist[j]=DestroyString(filelist[j]);
898      if (strlen(filename) >= (MaxTextExtent-1))
899        ThrowFatalException(OptionFatalError,"FilenameTruncated");
900      if (IsPathDirectory(filename) <= 0)
901        {
902          char
903            path[MaxTextExtent];
904
905          *path='\0';
906          if (*magick != '\0')
907            {
908              (void) ConcatenateMagickString(path,magick,MaxTextExtent);
909              (void) ConcatenateMagickString(path,":",MaxTextExtent);
910            }
911          (void) ConcatenateMagickString(path,filename,MaxTextExtent);
912          if (*subimage != '\0')
913            {
914              (void) ConcatenateMagickString(path,"[",MaxTextExtent);
915              (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
916              (void) ConcatenateMagickString(path,"]",MaxTextExtent);
917            }
918          if (strlen(path) >= (MaxTextExtent-1))
919            ThrowFatalException(OptionFatalError,"FilenameTruncated");
920          if (destroy != MagickFalse)
921            {
922              count--;
923              vector[count]=DestroyString(vector[count]);
924              destroy=MagickFalse;
925            }
926          vector[count++]=ConstantString(path);
927        }
928    }
929    filelist=(char **) RelinquishMagickMemory(filelist);
930  }
931  vector[count]=(char *) NULL;
932  if (IsEventLogging() != MagickFalse)
933    {
934      char
935        *command_line;
936
937      command_line=AcquireString(vector[0]);
938      for (i=1; i < count; i++)
939      {
940        (void) ConcatenateString(&command_line," {");
941        (void) ConcatenateString(&command_line,vector[i]);
942        (void) ConcatenateString(&command_line,"}");
943      }
944      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
945        "Command line: %s",command_line);
946      command_line=DestroyString(command_line);
947    }
948  *number_arguments=(int) count;
949  *arguments=vector;
950  return(MagickTrue);
951}
952
953/*
954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955%                                                                             %
956%                                                                             %
957%                                                                             %
958%   G e t E x e c u t i o n P a t h                                           %
959%                                                                             %
960%                                                                             %
961%                                                                             %
962%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963%
964%  GetExecutionPath() returns the pathname of the executable that started
965%  the process.  On success MagickTrue is returned, otherwise MagickFalse.
966%
967%  The format of the GetExecutionPath method is:
968%
969%      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
970%
971%  A description of each parameter follows:
972%
973%    o path: the pathname of the executable that started the process.
974%
975%    o extent: the maximum extent of the path.
976%
977*/
978MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
979{
980  char
981    *directory;
982
983  *path='\0';
984  directory=getcwd(path,(unsigned long) extent);
985  (void) directory;
986#if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
987  {
988    char
989      link_path[MaxTextExtent],
990      execution_path[PATH_MAX+1];
991
992    ssize_t
993      count;
994
995    (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe",
996      (double) getpid());
997    count=readlink(link_path,execution_path,PATH_MAX);
998    if (count == -1)
999      {
1000        (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file",
1001          (double) getpid());
1002        count=readlink(link_path,execution_path,PATH_MAX);
1003      }
1004    if ((count > 0) && (count <= (ssize_t) PATH_MAX))
1005      {
1006        execution_path[count]='\0';
1007        (void) CopyMagickString(path,execution_path,extent);
1008      }
1009  }
1010#endif
1011#if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
1012  {
1013    char
1014      executable_path[PATH_MAX << 1],
1015      execution_path[PATH_MAX+1];
1016
1017    uint32_t
1018      length;
1019
1020    length=sizeof(executable_path);
1021    if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
1022        (realpath(executable_path,execution_path) != (char *) NULL))
1023      (void) CopyMagickString(path,execution_path,extent);
1024  }
1025#endif
1026#if defined(MAGICKCORE_HAVE_GETEXECNAME)
1027  {
1028    const char
1029      *execution_path;
1030
1031    execution_path=(const char *) getexecname();
1032    if (execution_path != (const char *) NULL)
1033      {
1034        if (*execution_path != *DirectorySeparator)
1035          (void) ConcatenateMagickString(path,DirectorySeparator,extent);
1036        (void) ConcatenateMagickString(path,execution_path,extent);
1037      }
1038  }
1039#endif
1040#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1041  NTGetExecutionPath(path,extent);
1042#endif
1043#if defined(__GNU__)
1044  {
1045    char
1046      *program_name,
1047      *execution_path;
1048
1049    ssize_t
1050      count;
1051
1052    count=0;
1053    execution_path=(char *) NULL;
1054    program_name=program_invocation_name;
1055    if (*program_invocation_name != '/')
1056      {
1057        size_t
1058          extent;
1059
1060        extent=strlen(directory)+strlen(program_name)+2;
1061        program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1062        if (program_name == (char *) NULL)
1063          program_name=program_invocation_name;
1064        else
1065          count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1066            program_invocation_name);
1067      }
1068    if (count != -1)
1069      {
1070        execution_path=realpath(program_name,NULL);
1071        if (execution_path != (char *) NULL)
1072          (void) CopyMagickString(path,execution_path,extent);
1073      }
1074    if (program_name != program_invocation_name)
1075      program_name=(char *) RelinquishMagickMemory(program_name);
1076    execution_path=(char *) RelinquishMagickMemory(execution_path);
1077  }
1078#endif
1079#if defined(__OpenBSD__)
1080  {
1081    extern char
1082      *__progname;
1083
1084    (void) CopyMagickString(path,__progname,extent);
1085  }
1086#endif
1087  return(IsPathAccessible(path));
1088}
1089
1090/*
1091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1092%                                                                             %
1093%                                                                             %
1094%                                                                             %
1095%   G e t M a g i c k P a g e S i z e                                         %
1096%                                                                             %
1097%                                                                             %
1098%                                                                             %
1099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100%
1101%  GetMagickPageSize() returns the memory page size.
1102%
1103%  The format of the GetMagickPageSize method is:
1104%
1105%      ssize_t GetMagickPageSize()
1106%
1107*/
1108MagickPrivate ssize_t GetMagickPageSize(void)
1109{
1110  static ssize_t
1111    page_size = -1;
1112
1113  if (page_size > 0)
1114    return(page_size);
1115#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1116  page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1117#else
1118#if defined(MAGICKCORE_HAVE_GETPAGESIZE)
1119  page_size=(ssize_t) getpagesize();
1120#endif
1121#endif
1122  if (page_size <= 0)
1123    page_size=16384;
1124  return(page_size);
1125}
1126
1127/*
1128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1129%                                                                             %
1130%                                                                             %
1131%                                                                             %
1132%   G e t P a t h A t t r i b u t e s                                         %
1133%                                                                             %
1134%                                                                             %
1135%                                                                             %
1136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1137%
1138%  GetPathAttributes() returns attributes (e.g. size of file) about a path.
1139%
1140%  The path of the GetPathAttributes method is:
1141%
1142%      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1143%
1144%  A description of each parameter follows.
1145%
1146%   o  path: the file path.
1147%
1148%   o  attributes: the path attributes are returned here.
1149%
1150*/
1151MagickExport MagickBooleanType GetPathAttributes(const char *path,
1152  void *attributes)
1153{
1154  MagickBooleanType
1155    status;
1156
1157  if (path == (const char *) NULL)
1158    {
1159      errno=EINVAL;
1160      return(MagickFalse);
1161    }
1162  status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
1163    MagickFalse;
1164  return(status);
1165}
1166
1167/*
1168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1169%                                                                             %
1170%                                                                             %
1171%                                                                             %
1172%   G e t P a t h C o m p o n e n t                                           %
1173%                                                                             %
1174%                                                                             %
1175%                                                                             %
1176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1177%
1178%  GetPathComponent() returns the parent directory name, filename, basename, or
1179%  extension of a file path.
1180%
1181%  The component string pointed to must have at least MaxTextExtent space
1182%  for the results to be stored.
1183%
1184%  The format of the GetPathComponent function is:
1185%
1186%      GetPathComponent(const char *path,PathType type,char *component)
1187%
1188%  A description of each parameter follows:
1189%
1190%    o path: Specifies a pointer to a character array that contains the
1191%      file path.
1192%
1193%    o type: Specififies which file path component to return.
1194%
1195%    o component: the selected file path component is returned here.
1196%
1197*/
1198MagickExport void GetPathComponent(const char *path,PathType type,
1199  char *component)
1200{
1201  char
1202    magick[MaxTextExtent],
1203    *q,
1204    subimage[MaxTextExtent];
1205
1206  register char
1207    *p;
1208
1209  assert(path != (const char *) NULL);
1210  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1211  assert(component != (char *) NULL);
1212  if (*path == '\0')
1213    {
1214      *component='\0';
1215      return;
1216    }
1217  (void) CopyMagickString(component,path,MaxTextExtent);
1218  *magick='\0';
1219#if defined(__OS2__)
1220  if (path[1] != ":")
1221#endif
1222  for (p=component; *p != '\0'; p++)
1223  {
1224    if ((*p == '%') && (*(p+1) == '['))
1225      {
1226        /*
1227          Skip over %[...].
1228        */
1229        for (p++; (*p != ']') && (*p != '\0'); p++) ;
1230        if (*p == '\0')
1231          break;
1232      }
1233    if ((*p == ':') && (IsPathDirectory(path) < 0) &&
1234        (IsPathAccessible(path) == MagickFalse))
1235      {
1236        /*
1237          Look for image format specification (e.g. ps3:image).
1238        */
1239        (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1240        if (IsMagickConflict(magick) != MagickFalse)
1241          *magick='\0';
1242        else
1243          for (q=component; *q != '\0'; q++)
1244            *q=(*++p);
1245        break;
1246      }
1247  }
1248  *subimage='\0';
1249  p=component;
1250  if (*p != '\0')
1251    p=component+strlen(component)-1;
1252  if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1253      (IsPathAccessible(path) == MagickFalse))
1254    {
1255      /*
1256        Look for scene specification (e.g. img0001.pcd[4]).
1257      */
1258      for (q=p-1; q > component; q--)
1259        if (*q == '[')
1260          break;
1261      if (*q == '[')
1262        {
1263          (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1264          subimage[p-q-1]='\0';
1265          if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1266              (IsGeometry(subimage) == MagickFalse))
1267            *subimage='\0';
1268          else
1269            *q='\0';
1270        }
1271    }
1272  p=component;
1273  if (*p != '\0')
1274    for (p=component+strlen(component)-1; p > component; p--)
1275      if (IsBasenameSeparator(*p) != MagickFalse)
1276        break;
1277  switch (type)
1278  {
1279    case MagickPath:
1280    {
1281      (void) CopyMagickString(component,magick,MaxTextExtent);
1282      break;
1283    }
1284    case RootPath:
1285    {
1286      for (p=component+(strlen(component)-1); p > component; p--)
1287      {
1288        if (IsBasenameSeparator(*p) != MagickFalse)
1289          break;
1290        if (*p == '.')
1291          break;
1292      }
1293      if (*p == '.')
1294        *p='\0';
1295      break;
1296    }
1297    case HeadPath:
1298    {
1299      *p='\0';
1300      break;
1301    }
1302    case TailPath:
1303    {
1304      if (IsBasenameSeparator(*p) != MagickFalse)
1305        (void) CopyMagickMemory((unsigned char *) component,
1306          (const unsigned char *) (p+1),strlen(p+1)+1);
1307      break;
1308    }
1309    case BasePath:
1310    {
1311      if (IsBasenameSeparator(*p) != MagickFalse)
1312        (void) CopyMagickString(component,p+1,MaxTextExtent);
1313      for (p=component+(strlen(component)-1); p > component; p--)
1314        if (*p == '.')
1315          {
1316            *p='\0';
1317            break;
1318          }
1319      break;
1320    }
1321    case ExtensionPath:
1322    {
1323      if (IsBasenameSeparator(*p) != MagickFalse)
1324        (void) CopyMagickString(component,p+1,MaxTextExtent);
1325      p=component;
1326      if (*p != '\0')
1327        for (p=component+strlen(component)-1; p > component; p--)
1328          if (*p == '.')
1329            break;
1330      *component='\0';
1331      if (*p == '.')
1332        (void) CopyMagickString(component,p+1,MaxTextExtent);
1333      break;
1334    }
1335    case SubimagePath:
1336    {
1337      (void) CopyMagickString(component,subimage,MaxTextExtent);
1338      break;
1339    }
1340    case CanonicalPath:
1341    case UndefinedPath:
1342      break;
1343  }
1344}
1345
1346/*
1347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1348%                                                                             %
1349%                                                                             %
1350%                                                                             %
1351%  G e t P a t h C o m p o n e n t s                                          %
1352%                                                                             %
1353%                                                                             %
1354%                                                                             %
1355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1356%
1357%  GetPathComponents() returns a list of path components.
1358%
1359%  The format of the GetPathComponents method is:
1360%
1361%      char **GetPathComponents(const char *path,
1362%        size_t *number_componenets)
1363%
1364%  A description of each parameter follows:
1365%
1366%    o path:  Specifies the string to segment into a list.
1367%
1368%    o number_components:  return the number of components in the list
1369%
1370*/
1371MagickPrivate char **GetPathComponents(const char *path,
1372  size_t *number_components)
1373{
1374  char
1375    **components;
1376
1377  register const char
1378    *p,
1379    *q;
1380
1381  register ssize_t
1382    i;
1383
1384  if (path == (char *) NULL)
1385    return((char **) NULL);
1386  *number_components=1;
1387  for (p=path; *p != '\0'; p++)
1388    if (IsBasenameSeparator(*p))
1389      (*number_components)++;
1390  components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1391    sizeof(*components));
1392  if (components == (char **) NULL)
1393    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1394  p=path;
1395  for (i=0; i < (ssize_t) *number_components; i++)
1396  {
1397    for (q=p; *q != '\0'; q++)
1398      if (IsBasenameSeparator(*q))
1399        break;
1400    components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1401      sizeof(**components));
1402    if (components[i] == (char *) NULL)
1403      ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1404    (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1405    p=q+1;
1406  }
1407  components[i]=(char *) NULL;
1408  return(components);
1409}
1410
1411/*
1412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1413%                                                                             %
1414%                                                                             %
1415%                                                                             %
1416%  I s P a t h A c c e s s i b l e                                            %
1417%                                                                             %
1418%                                                                             %
1419%                                                                             %
1420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1421%
1422%  IsPathAccessible() returns MagickTrue if the file as defined by the path is
1423%  accessible.
1424%
1425%  The format of the IsPathAccessible method is:
1426%
1427%      MagickBooleanType IsPathAccessible(const char *path)
1428%
1429%  A description of each parameter follows.
1430%
1431%    o path:  Specifies a path to a file.
1432%
1433*/
1434MagickExport MagickBooleanType IsPathAccessible(const char *path)
1435{
1436  MagickBooleanType
1437    status;
1438
1439  struct stat
1440    attributes;
1441
1442  if ((path == (const char *) NULL) || (*path == '\0'))
1443    return(MagickFalse);
1444  status=GetPathAttributes(path,&attributes);
1445  if (status == MagickFalse)
1446    return(status);
1447  if (S_ISREG(attributes.st_mode) == 0)
1448    return(MagickFalse);
1449  if (access_utf8(path,F_OK) != 0)
1450    return(MagickFalse);
1451  return(MagickTrue);
1452}
1453
1454/*
1455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1456%                                                                             %
1457%                                                                             %
1458%                                                                             %
1459+  I s P a t h D i r e c t o r y                                              %
1460%                                                                             %
1461%                                                                             %
1462%                                                                             %
1463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1464%
1465%  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
1466%  if the path represents a directory otherwise 0.
1467%
1468%  The format of the IsPathDirectory method is:
1469%
1470%      int IsPathDirectory(const char *path)
1471%
1472%  A description of each parameter follows.
1473%
1474%   o  path:  The directory path.
1475%
1476*/
1477static int IsPathDirectory(const char *path)
1478{
1479  MagickBooleanType
1480    status;
1481
1482  struct stat
1483    attributes;
1484
1485  if ((path == (const char *) NULL) || (*path == '\0'))
1486    return(MagickFalse);
1487  status=GetPathAttributes(path,&attributes);
1488  if (status == MagickFalse)
1489    return(-1);
1490  if (S_ISDIR(attributes.st_mode) == 0)
1491    return(0);
1492  return(1);
1493}
1494
1495/*
1496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497%                                                                             %
1498%                                                                             %
1499%                                                                             %
1500%   L i s t F i l e s                                                         %
1501%                                                                             %
1502%                                                                             %
1503%                                                                             %
1504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505%
1506%  ListFiles() reads the directory specified and returns a list of filenames
1507%  contained in the directory sorted in ascending alphabetic order.
1508%
1509%  The format of the ListFiles function is:
1510%
1511%      char **ListFiles(const char *directory,const char *pattern,
1512%        ssize_t *number_entries)
1513%
1514%  A description of each parameter follows:
1515%
1516%    o filelist: Method ListFiles returns a list of filenames contained
1517%      in the directory.  If the directory specified cannot be read or it is
1518%      a file a NULL list is returned.
1519%
1520%    o directory: Specifies a pointer to a text string containing a directory
1521%      name.
1522%
1523%    o pattern: Specifies a pointer to a text string containing a pattern.
1524%
1525%    o number_entries:  This integer returns the number of filenames in the
1526%      list.
1527%
1528*/
1529
1530#if defined(__cplusplus) || defined(c_plusplus)
1531extern "C" {
1532#endif
1533
1534static int FileCompare(const void *x,const void *y)
1535{
1536  register const char
1537    **p,
1538    **q;
1539
1540  p=(const char **) x;
1541  q=(const char **) y;
1542  return(LocaleCompare(*p,*q));
1543}
1544
1545#if defined(__cplusplus) || defined(c_plusplus)
1546}
1547#endif
1548
1549static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1550  struct dirent **result)
1551{
1552#if defined(MAGICKCORE_HAVE_READDIR_R)
1553  return(readdir_r(directory,entry,result));
1554#else
1555  (void) entry;
1556  errno=0;
1557  *result=readdir(directory);
1558  return(errno);
1559#endif
1560}
1561
1562MagickPrivate char **ListFiles(const char *directory,const char *pattern,
1563  size_t *number_entries)
1564{
1565  char
1566    **filelist;
1567
1568  DIR
1569    *current_directory;
1570
1571  struct dirent
1572    *buffer,
1573    *entry;
1574
1575  size_t
1576    max_entries;
1577
1578  /*
1579    Open directory.
1580  */
1581  assert(directory != (const char *) NULL);
1582  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1583  assert(pattern != (const char *) NULL);
1584  assert(number_entries != (size_t *) NULL);
1585  *number_entries=0;
1586  current_directory=opendir(directory);
1587  if (current_directory == (DIR *) NULL)
1588    return((char **) NULL);
1589  /*
1590    Allocate filelist.
1591  */
1592  max_entries=2048;
1593  filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1594    sizeof(*filelist));
1595  if (filelist == (char **) NULL)
1596    {
1597      (void) closedir(current_directory);
1598      return((char **) NULL);
1599    }
1600  /*
1601    Save the current and change to the new directory.
1602  */
1603  buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
1604    FILENAME_MAX+1);
1605  if (buffer == (struct dirent *) NULL)
1606    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1607  while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1608         (entry != (struct dirent *) NULL))
1609  {
1610    if (*entry->d_name == '.')
1611      continue;
1612    if ((IsPathDirectory(entry->d_name) > 0) ||
1613#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1614        (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1615#else
1616        (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1617#endif
1618      {
1619        if (*number_entries >= max_entries)
1620          {
1621            /*
1622              Extend the file list.
1623            */
1624            max_entries<<=1;
1625            filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1626              max_entries,sizeof(*filelist));
1627            if (filelist == (char **) NULL)
1628              break;
1629          }
1630#if defined(vms)
1631        {
1632          register char
1633            *p;
1634
1635          p=strchr(entry->d_name,';');
1636          if (p)
1637            *p='\0';
1638          if (*number_entries > 0)
1639            if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1640              continue;
1641        }
1642#endif
1643        filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1644        (*number_entries)++;
1645      }
1646  }
1647  buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1648  (void) closedir(current_directory);
1649  if (filelist == (char **) NULL)
1650    return((char **) NULL);
1651  /*
1652    Sort filelist in ascending order.
1653  */
1654  qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1655    FileCompare);
1656  return(filelist);
1657}
1658
1659/*
1660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1661%                                                                             %
1662%                                                                             %
1663%                                                                             %
1664%   M a g i c k D e l a y                                                     %
1665%                                                                             %
1666%                                                                             %
1667%                                                                             %
1668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1669%
1670%  MagickDelay() suspends program execution for the number of milliseconds
1671%  specified.
1672%
1673%  The format of the Delay method is:
1674%
1675%      void MagickDelay(const MagickSizeType milliseconds)
1676%
1677%  A description of each parameter follows:
1678%
1679%    o milliseconds: Specifies the number of milliseconds to delay before
1680%      returning.
1681%
1682*/
1683MagickPrivate void MagickDelay(const MagickSizeType milliseconds)
1684{
1685  if (milliseconds == 0)
1686    return;
1687#if defined(MAGICKCORE_HAVE_NANOSLEEP)
1688  {
1689    struct timespec
1690      timer;
1691
1692    timer.tv_sec=(time_t) (milliseconds/1000);
1693    timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1694    (void) nanosleep(&timer,(struct timespec *) NULL);
1695  }
1696#elif defined(MAGICKCORE_HAVE_USLEEP)
1697  usleep(1000*milliseconds);
1698#elif defined(MAGICKCORE_HAVE_SELECT)
1699  {
1700    struct timeval
1701      timer;
1702
1703    timer.tv_sec=(long) milliseconds/1000;
1704    timer.tv_usec=(long) (milliseconds % 1000)*1000;
1705    (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1706  }
1707#elif defined(MAGICKCORE_HAVE_POLL)
1708  (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1709#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1710  Sleep((long) milliseconds);
1711#elif defined(vms)
1712  {
1713    float
1714      timer;
1715
1716    timer=milliseconds/1000.0;
1717    lib$wait(&timer);
1718  }
1719#elif defined(__BEOS__)
1720  snooze(1000*milliseconds);
1721#else
1722# error "Time delay method not defined."
1723#endif
1724}
1725
1726/*
1727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1728%                                                                             %
1729%                                                                             %
1730%                                                                             %
1731%  M u l t i l i n e C e n s u s                                              %
1732%                                                                             %
1733%                                                                             %
1734%                                                                             %
1735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1736%
1737%  MultilineCensus() returns the number of lines within a label.  A line is
1738%  represented by a \n character.
1739%
1740%  The format of the MultilineCenus method is:
1741%
1742%      size_t MultilineCensus(const char *label)
1743%
1744%  A description of each parameter follows.
1745%
1746%   o  label:  This character string is the label.
1747%
1748*/
1749MagickExport size_t MultilineCensus(const char *label)
1750{
1751  size_t
1752    number_lines;
1753
1754  /*
1755    Determine the number of lines within this label.
1756  */
1757  if (label == (char *) NULL)
1758    return(0);
1759  for (number_lines=1; *label != '\0'; label++)
1760    if (*label == '\n')
1761      number_lines++;
1762  return(number_lines);
1763}
1764
1765/*
1766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1767%                                                                             %
1768%                                                                             %
1769%                                                                             %
1770%   S h r e a d F i l e                                                       %
1771%                                                                             %
1772%                                                                             %
1773%                                                                             %
1774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775%
1776%  ShredFile() overwrites the specified file with zeros or random data and then
1777%  removes it.  The overwrite is optional and is only required to help keep
1778%  the contents of the file private.  On the first pass, the file is zeroed.
1779%  For subsequent passes, random data is written.
1780%
1781%  The format of the ShredFile method is:
1782%
1783%      MagickBooleanType ShredFile(const char *path)
1784%
1785%  A description of each parameter follows.
1786%
1787%    o path:  Specifies a path to a file.
1788%
1789*/
1790MagickPrivate MagickBooleanType ShredFile(const char *path)
1791{
1792  char
1793    *passes;
1794
1795  ExceptionInfo
1796    *exception;
1797
1798  int
1799    file,
1800    status;
1801
1802  MagickSizeType
1803    length;
1804
1805  register ssize_t
1806    i;
1807
1808  size_t
1809    quantum;
1810
1811  struct stat
1812    file_stats;
1813
1814  if ((path == (const char *) NULL) || (*path == '\0'))
1815    return(MagickFalse);
1816  exception=AcquireExceptionInfo();
1817  passes=(char *) GetImageRegistry(StringRegistryType,"shred-passes",exception);
1818  exception=DestroyExceptionInfo(exception);
1819  if (passes == (char *) NULL)
1820    passes=GetEnvironmentValue("MAGICK_SHRED_PASSES");
1821  if (passes == (char *) NULL)
1822    {
1823      /*
1824        Don't shred the file, just remove it.
1825      */
1826      status=remove_utf8(path);
1827      if (status == -1)
1828        return(MagickFalse);
1829      return(MagickTrue);
1830    }
1831  file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
1832  if (file == -1)
1833    {
1834      /*
1835        Don't shred the file, just remove it.
1836      */
1837      status=remove_utf8(path);
1838      return(MagickFalse);
1839    }
1840  /*
1841    Shred the file.
1842  */
1843  quantum=(size_t) MagickMaxBufferExtent;
1844  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1845    quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
1846      MagickMaxBufferExtent);
1847  length=(MagickSizeType) file_stats.st_size;
1848  for (i=0; i < (ssize_t) StringToInteger(passes); i++)
1849  {
1850    RandomInfo
1851      *random_info;
1852
1853    register MagickOffsetType
1854      j;
1855
1856    ssize_t
1857      count;
1858
1859    if (lseek(file,0,SEEK_SET) < 0)
1860      break;
1861    random_info=AcquireRandomInfo();
1862    for (j=0; j < (MagickOffsetType) length; j+=count)
1863    {
1864      StringInfo
1865        *key;
1866
1867      key=GetRandomKey(random_info,quantum);
1868      if (i == 0)
1869        ResetStringInfo(key);  /* zero on first pass */
1870      count=write(file,GetStringInfoDatum(key),(size_t)
1871        MagickMin(quantum,length-j));
1872      key=DestroyStringInfo(key);
1873      if (count <= 0)
1874        {
1875          count=0;
1876          if (errno != EINTR)
1877            break;
1878        }
1879    }
1880    random_info=DestroyRandomInfo(random_info);
1881    if (j < (MagickOffsetType) length)
1882      break;
1883  }
1884  status=close(file);
1885  status=remove_utf8(path);
1886  if (status == -1)
1887    return(MagickFalse);
1888  return(i < (ssize_t) StringToInteger(passes) ? MagickFalse : MagickTrue);
1889}
1890
1891/*
1892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1893%                                                                             %
1894%                                                                             %
1895%                                                                             %
1896%   S y s t e m C o m m a n d                                                 %
1897%                                                                             %
1898%                                                                             %
1899%                                                                             %
1900%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1901%
1902%  SystemCommand() executes the specified command and waits until it
1903%  terminates.  The returned value is the exit status of the command.
1904%
1905%  The format of the SystemCommand method is:
1906%
1907%      int SystemCommand(const MagickBooleanType asynchronous,
1908%        const MagickBooleanType verbose,const char *command,
1909%        ExceptionInfo *exception)
1910%
1911%  A description of each parameter follows:
1912%
1913%    o asynchronous: a value other than 0 executes the parent program
1914%      concurrently with the new child process.
1915%
1916%    o verbose: a value other than 0 prints the executed command before it is
1917%      invoked.
1918%
1919%    o command: this string is the command to execute.
1920%
1921%    o exception: return any errors here.
1922%
1923*/
1924MagickExport int SystemCommand(const MagickBooleanType asynchronous,
1925  const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
1926{
1927  char
1928    **arguments,
1929    *shell_command;
1930
1931  int
1932    number_arguments,
1933    status;
1934
1935  PolicyDomain
1936    domain;
1937
1938  PolicyRights
1939    rights;
1940
1941  register ssize_t
1942    i;
1943
1944  status=(-1);
1945  arguments=StringToArgv(command,&number_arguments);
1946  if (arguments == (char **) NULL)
1947    return(status);
1948  if (*arguments[1] == '\0')
1949    {
1950      for (i=0; i < (ssize_t) number_arguments; i++)
1951        arguments[i]=DestroyString(arguments[i]);
1952      arguments=(char **) RelinquishMagickMemory(arguments);
1953      return(-1);
1954    }
1955  rights=ExecutePolicyRights;
1956  domain=DelegatePolicyDomain;
1957  if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
1958    {
1959      errno=EPERM;
1960      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1961        "NotAuthorized","`%s'",arguments[1]);
1962      for (i=0; i < (ssize_t) number_arguments; i++)
1963        arguments[i]=DestroyString(arguments[i]);
1964      arguments=(char **) RelinquishMagickMemory(arguments);
1965      return(-1);
1966    }
1967  if (verbose != MagickFalse)
1968    {
1969      (void) FormatLocaleFile(stderr,"%s\n",command);
1970      (void) fflush(stderr);
1971    }
1972  shell_command=(char *) command;
1973  if (asynchronous != MagickFalse)
1974    {
1975      shell_command=AcquireString(command);
1976      (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
1977    }
1978#if defined(MAGICKCORE_POSIX_SUPPORT)
1979#if !defined(MAGICKCORE_HAVE_EXECVP)
1980  status=system(shell_command);
1981#else
1982  if ((asynchronous != MagickFalse) ||
1983      (strpbrk(shell_command,"&;<>|") != (char *) NULL))
1984    status=system(shell_command);
1985  else
1986    {
1987      pid_t
1988        child_pid;
1989
1990      /*
1991        Call application directly rather than from a shell.
1992      */
1993      child_pid=(pid_t) fork();
1994      if (child_pid == (pid_t) -1)
1995        status=system(command);
1996      else
1997        if (child_pid == 0)
1998          {
1999            status=execvp(arguments[1],arguments+1);
2000            _exit(1);
2001          }
2002        else
2003          {
2004            int
2005              child_status;
2006
2007            pid_t
2008              pid;
2009
2010            child_status=0;
2011            pid=(pid_t) waitpid(child_pid,&child_status,0);
2012            if (pid == -1)
2013              status=(-1);
2014            else
2015              {
2016                if (WIFEXITED(child_status) != 0)
2017                  status=WEXITSTATUS(child_status);
2018                else
2019                  if (WIFSIGNALED(child_status))
2020                    status=(-1);
2021              }
2022          }
2023    }
2024#endif
2025#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
2026  status=NTSystemCommand(shell_command);
2027#elif defined(macintosh)
2028  status=MACSystemCommand(shell_command);
2029#elif defined(vms)
2030  status=system(shell_command);
2031#else
2032#  error No suitable system() method.
2033#endif
2034  if (status < 0)
2035    (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
2036      "'%s' (%d)",command,status);
2037  if (shell_command != command)
2038    shell_command=DestroyString(shell_command);
2039  for (i=0; i < (ssize_t) number_arguments; i++)
2040    arguments[i]=DestroyString(arguments[i]);
2041  arguments=(char **) RelinquishMagickMemory(arguments);
2042  return(status);
2043}
2044