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