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