]> granicus.if.org Git - imagemagick/blob - MagickCore/utility.c
(no commit message)
[imagemagick] / MagickCore / utility.c
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 \f
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 \f
73 /*
74   Static declarations.
75 */
76 static const char
77   Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
78 \f
79 /*
80   Forward declaration.
81 */
82 static int
83   IsPathDirectory(const char *);
84 \f
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 */
108 MagickExport 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 \f
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
150 static 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
157 MagickExport 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 \f
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 */
271 MagickExport 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 \f
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 */
335 MagickExport 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 \f
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 */
489 MagickExport 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 \f
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 */
572 MagickPrivate 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 \f
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 */
604 MagickPrivate 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 \f
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 events.
703 %
704 %  The returned list should be freed using  DestroyStringList().
705 %
706 %  However the strings in the original pointed to argv are not
707 %  freed  (TO BE CHECKED).  So a copy of the original pointer (and count)
708 %  should be kept separate if they need to be freed later.
709 %
710 %  The format of the ExpandFilenames function is:
711 %
712 %      status=ExpandFilenames(int *number_arguments,char ***arguments)
713 %
714 %  A description of each parameter follows:
715 %
716 %    o number_arguments: Specifies a pointer to an integer describing the
717 %      number of elements in the argument vector.
718 %
719 %    o arguments: Specifies a pointer to a text array containing the command
720 %      line arguments.
721 %
722 */
723 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
724   char ***arguments)
725 {
726   char
727     *directory,
728     home_directory[MaxTextExtent],
729     **vector;
730
731   register ssize_t
732     i,
733     j;
734
735   size_t
736     number_files;
737
738   ssize_t
739     count,
740     parameters;
741
742   /*
743     Allocate argument vector.
744   */
745   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
746   assert(number_arguments != (int *) NULL);
747   assert(arguments != (char ***) NULL);
748   vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
749     sizeof(*vector));
750   if (vector == (char **) NULL)
751     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
752   /*
753     Expand any wildcard filenames.
754   */
755   *home_directory='\0';
756   count=0;
757   for (i=0; i < (ssize_t) *number_arguments; i++)
758   {
759     char
760       **filelist,
761       filename[MaxTextExtent],
762       magick[MaxTextExtent],
763       *option,
764       path[MaxTextExtent],
765       subimage[MaxTextExtent];
766
767     MagickBooleanType
768       destroy;
769
770     option=(*arguments)[i];
771     *magick='\0';
772     *path='\0';
773     *filename='\0';
774     *subimage='\0';
775     vector[count++]=ConstantString(option);
776     destroy=MagickTrue;
777     parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
778     if (parameters > 0)
779       {
780         /*
781           Do not expand command option parameters.
782         */
783         for (j=0; j < parameters; j++)
784         {
785           i++;
786           if (i == (ssize_t) *number_arguments)
787             break;
788           option=(*arguments)[i];
789           vector[count++]=ConstantString(option);
790         }
791         continue;
792       }
793     if ((*option == '"') || (*option == '\''))
794       continue;
795     GetPathComponent(option,TailPath,filename);
796     GetPathComponent(option,MagickPath,magick);
797     if ((LocaleCompare(magick,"CAPTION") == 0) ||
798         (LocaleCompare(magick,"LABEL") == 0) ||
799         (LocaleCompare(magick,"PANGO") == 0) ||
800         (LocaleCompare(magick,"VID") == 0))
801       continue;
802     if ((IsGlob(filename) == MagickFalse) && (*option != '@'))
803       continue;
804     if (*option != '@')
805       {
806         /*
807           Generate file list from wildcard filename (e.g. *.jpg).
808         */
809         GetPathComponent(option,HeadPath,path);
810         GetPathComponent(option,SubimagePath,subimage);
811         ExpandFilename(path);
812         if (*home_directory == '\0')
813           directory=getcwd(home_directory,MaxTextExtent-1);
814         (void) directory;
815         filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
816           &number_files);
817       }
818     else
819       {
820         char
821           *files;
822
823         ExceptionInfo
824           *exception;
825
826         int
827           length;
828
829         /*
830           Generate file list from file list (e.g. @filelist.txt).
831         */
832         exception=AcquireExceptionInfo();
833         files=FileToString(option+1,~0,exception);
834         exception=DestroyExceptionInfo(exception);
835         if (files == (char *) NULL)
836           continue;
837         filelist=StringToArgv(files,&length);
838         if (filelist == (char **) NULL)
839           continue;
840         files=DestroyString(files);
841         filelist[0]=DestroyString(filelist[0]);
842         for (j=0; j < (ssize_t) (length-1); j++)
843           filelist[j]=filelist[j+1];
844         number_files=(size_t) length-1;
845       }
846     if (filelist == (char **) NULL)
847       continue;
848     for (j=0; j < (ssize_t) number_files; j++)
849       if (IsPathDirectory(filelist[j]) <= 0)
850         break;
851     if (j == (ssize_t) number_files)
852       {
853         for (j=0; j < (ssize_t) number_files; j++)
854           filelist[j]=DestroyString(filelist[j]);
855         filelist=(char **) RelinquishMagickMemory(filelist);
856         continue;
857       }
858     /*
859       Transfer file list to argument vector.
860     */
861     vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
862       count+number_files+1,sizeof(*vector));
863     if (vector == (char **) NULL)
864       return(MagickFalse);
865     for (j=0; j < (ssize_t) number_files; j++)
866     {
867       option=filelist[j];
868       parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
869       if (parameters > 0)
870         {
871           ssize_t
872             k;
873
874           /*
875             Do not expand command option parameters.
876           */
877           vector[count++]=ConstantString(option);
878           for (k=0; k < parameters; k++)
879           {
880             j++;
881             if (j == (ssize_t) number_files)
882               break;
883             option=filelist[j];
884             vector[count++]=ConstantString(option);
885           }
886           continue;
887         }
888       (void) CopyMagickString(filename,path,MaxTextExtent);
889       if (*path != '\0')
890         (void) ConcatenateMagickString(filename,DirectorySeparator,
891           MaxTextExtent);
892       (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
893       filelist[j]=DestroyString(filelist[j]);
894       if (strlen(filename) >= (MaxTextExtent-1))
895         ThrowFatalException(OptionFatalError,"FilenameTruncated");
896       if (IsPathDirectory(filename) <= 0)
897         {
898           char
899             path[MaxTextExtent];
900
901           *path='\0';
902           if (*magick != '\0')
903             {
904               (void) ConcatenateMagickString(path,magick,MaxTextExtent);
905               (void) ConcatenateMagickString(path,":",MaxTextExtent);
906             }
907           (void) ConcatenateMagickString(path,filename,MaxTextExtent);
908           if (*subimage != '\0')
909             {
910               (void) ConcatenateMagickString(path,"[",MaxTextExtent);
911               (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
912               (void) ConcatenateMagickString(path,"]",MaxTextExtent);
913             }
914           if (strlen(path) >= (MaxTextExtent-1))
915             ThrowFatalException(OptionFatalError,"FilenameTruncated");
916           if (destroy != MagickFalse)
917             {
918               count--;
919               vector[count]=DestroyString(vector[count]);
920               destroy=MagickFalse;
921             }
922           vector[count++]=ConstantString(path);
923         }
924     }
925     filelist=(char **) RelinquishMagickMemory(filelist);
926   }
927   vector[count]=(char *) NULL;
928   if (IsEventLogging() != MagickFalse)
929     {
930       char
931         *command_line;
932
933       command_line=AcquireString(vector[0]);
934       for (i=1; i < count; i++)
935       {
936         (void) ConcatenateString(&command_line," {");
937         (void) ConcatenateString(&command_line,vector[i]);
938         (void) ConcatenateString(&command_line,"}");
939       }
940       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
941         "Command line: %s",command_line);
942       command_line=DestroyString(command_line);
943     }
944   *number_arguments=(int) count;
945   *arguments=vector;
946   return(MagickTrue);
947 }
948 \f
949 /*
950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951 %                                                                             %
952 %                                                                             %
953 %                                                                             %
954 %   G e t E x e c u t i o n P a t h                                           %
955 %                                                                             %
956 %                                                                             %
957 %                                                                             %
958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
959 %
960 %  GetExecutionPath() returns the pathname of the executable that started
961 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
962 %
963 %  The format of the GetExecutionPath method is:
964 %
965 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
966 %
967 %  A description of each parameter follows:
968 %
969 %    o path: the pathname of the executable that started the process.
970 %
971 %    o extent: the maximum extent of the path.
972 %
973 */
974 MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
975 {
976   char
977     *directory;
978
979   *path='\0';
980   directory=getcwd(path,(unsigned long) extent);
981   (void) directory;
982 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
983   {
984     char
985       link_path[MaxTextExtent],
986       execution_path[PATH_MAX+1];
987
988     ssize_t
989       count;
990
991     (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe",
992       (double) getpid());
993     count=readlink(link_path,execution_path,PATH_MAX);
994     if (count == -1)
995       {
996         (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file",
997           (double) getpid());
998         count=readlink(link_path,execution_path,PATH_MAX);
999       }
1000     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
1001       {
1002         execution_path[count]='\0';
1003         (void) CopyMagickString(path,execution_path,extent);
1004       }
1005   }
1006 #endif
1007 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
1008   {
1009     char
1010       executable_path[PATH_MAX << 1],
1011       execution_path[PATH_MAX+1];
1012
1013     uint32_t
1014       length;
1015
1016     length=sizeof(executable_path);
1017     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
1018         (realpath(executable_path,execution_path) != (char *) NULL))
1019       (void) CopyMagickString(path,execution_path,extent);
1020   }
1021 #endif
1022 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
1023   {
1024     const char
1025       *execution_path;
1026
1027     execution_path=(const char *) getexecname();
1028     if (execution_path != (const char *) NULL)
1029       {
1030         if (*execution_path != *DirectorySeparator)
1031           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
1032         (void) ConcatenateMagickString(path,execution_path,extent);
1033       }
1034   }
1035 #endif
1036 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1037   NTGetExecutionPath(path,extent);
1038 #endif
1039 #if defined(__GNU__)
1040   {
1041     char
1042       *program_name,
1043       *execution_path;
1044
1045     ssize_t
1046       count;
1047
1048     count=0;
1049     execution_path=(char *) NULL;
1050     program_name=program_invocation_name;
1051     if (*program_invocation_name != '/')
1052       {
1053         size_t
1054           extent;
1055
1056         extent=strlen(directory)+strlen(program_name)+2;
1057         program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1058         if (program_name == (char *) NULL)
1059           program_name=program_invocation_name;
1060         else
1061           count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1062             program_invocation_name);
1063       }
1064     if (count != -1)
1065       {
1066         execution_path=realpath(program_name,NULL);
1067         if (execution_path != (char *) NULL)
1068           (void) CopyMagickString(path,execution_path,extent);
1069       }
1070     if (program_name != program_invocation_name)
1071       program_name=(char *) RelinquishMagickMemory(program_name);
1072     execution_path=(char *) RelinquishMagickMemory(execution_path);
1073   }
1074 #endif
1075   return(IsPathAccessible(path));
1076 }
1077 \f
1078 /*
1079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1080 %                                                                             %
1081 %                                                                             %
1082 %                                                                             %
1083 %   G e t M a g i c k P a g e S i z e                                         %
1084 %                                                                             %
1085 %                                                                             %
1086 %                                                                             %
1087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1088 %
1089 %  GetMagickPageSize() returns the memory page size.
1090 %
1091 %  The format of the GetMagickPageSize method is:
1092 %
1093 %      ssize_t GetMagickPageSize()
1094 %
1095 */
1096 MagickPrivate ssize_t GetMagickPageSize(void)
1097 {
1098   static ssize_t
1099     page_size = -1;
1100
1101   if (page_size > 0)
1102     return(page_size);
1103 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1104   page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1105 #else
1106 #if defined(MAGICKCORE_HAVE_GETPAGESIZE)
1107   page_size=(ssize_t) getpagesize();
1108 #endif
1109 #endif
1110   if (page_size <= 0)
1111     page_size=16384;
1112   return(page_size);
1113 }
1114 \f
1115 /*
1116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 %                                                                             %
1118 %                                                                             %
1119 %                                                                             %
1120 %   G e t P a t h A t t r i b u t e s                                         %
1121 %                                                                             %
1122 %                                                                             %
1123 %                                                                             %
1124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1125 %
1126 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
1127 %
1128 %  The path of the GetPathAttributes method is:
1129 %
1130 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1131 %
1132 %  A description of each parameter follows.
1133 %
1134 %   o  path: the file path.
1135 %
1136 %   o  attributes: the path attributes are returned here.
1137 %
1138 */
1139 MagickExport MagickBooleanType GetPathAttributes(const char *path,
1140   void *attributes)
1141 {
1142   MagickBooleanType
1143     status;
1144
1145   if (path == (const char *) NULL)
1146     {
1147       errno=EINVAL;
1148       return(MagickFalse);
1149     }
1150   status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
1151     MagickFalse;
1152   return(status);
1153 }
1154 \f
1155 /*
1156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 %                                                                             %
1158 %                                                                             %
1159 %                                                                             %
1160 %   G e t P a t h C o m p o n e n t                                           %
1161 %                                                                             %
1162 %                                                                             %
1163 %                                                                             %
1164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 %
1166 %  GetPathComponent() returns the parent directory name, filename, basename, or
1167 %  extension of a file path.
1168 %
1169 %  The component string pointed to must have at least MaxTextExtent space
1170 %  for the results to be stored.
1171 %
1172 %  The format of the GetPathComponent function is:
1173 %
1174 %      GetPathComponent(const char *path,PathType type,char *component)
1175 %
1176 %  A description of each parameter follows:
1177 %
1178 %    o path: Specifies a pointer to a character array that contains the
1179 %      file path.
1180 %
1181 %    o type: Specififies which file path component to return.
1182 %
1183 %    o component: the selected file path component is returned here.
1184 %
1185 */
1186 MagickExport void GetPathComponent(const char *path,PathType type,
1187   char *component)
1188 {
1189   char
1190     magick[MaxTextExtent],
1191     *q,
1192     subimage[MaxTextExtent];
1193
1194   register char
1195     *p;
1196
1197   assert(path != (const char *) NULL);
1198   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1199   assert(component != (char *) NULL);
1200   if (*path == '\0')
1201     {
1202       *component='\0';
1203       return;
1204     }
1205   (void) CopyMagickString(component,path,MaxTextExtent);
1206   *magick='\0';
1207 #if defined(__OS2__)
1208   if (path[1] != ":")
1209 #endif
1210   for (p=component; *p != '\0'; p++)
1211   {
1212     if ((*p == '%') && (*(p+1) == '['))
1213       {
1214         /*
1215           Skip over %[...].
1216         */
1217         for (p++; (*p != ']') && (*p != '\0'); p++) ;
1218         if (*p == '\0')
1219           break;
1220       }
1221     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
1222         (IsPathAccessible(path) == MagickFalse))
1223       {
1224         /*
1225           Look for image format specification (e.g. ps3:image).
1226         */
1227         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1228         if (IsMagickConflict(magick) != MagickFalse)
1229           *magick='\0';
1230         else
1231           for (q=component; *q != '\0'; q++)
1232             *q=(*++p);
1233         break;
1234       }
1235   }
1236   *subimage='\0';
1237   p=component;
1238   if (*p != '\0')
1239     p=component+strlen(component)-1;
1240   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1241       (IsPathAccessible(path) == MagickFalse))
1242     {
1243       /*
1244         Look for scene specification (e.g. img0001.pcd[4]).
1245       */
1246       for (q=p-1; q > component; q--)
1247         if (*q == '[')
1248           break;
1249       if (*q == '[')
1250         {
1251           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1252           subimage[p-q-1]='\0';
1253           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1254               (IsGeometry(subimage) == MagickFalse))
1255             *subimage='\0';
1256           else
1257             *q='\0';
1258         }
1259     }
1260   p=component;
1261   if (*p != '\0')
1262     for (p=component+strlen(component)-1; p > component; p--)
1263       if (IsBasenameSeparator(*p) != MagickFalse)
1264         break;
1265   switch (type)
1266   {
1267     case MagickPath:
1268     {
1269       (void) CopyMagickString(component,magick,MaxTextExtent);
1270       break;
1271     }
1272     case RootPath:
1273     {
1274       for (p=component+(strlen(component)-1); p > component; p--)
1275       {
1276         if (IsBasenameSeparator(*p) != MagickFalse)
1277           break;
1278         if (*p == '.')
1279           break;
1280       }
1281       if (*p == '.')
1282         *p='\0';
1283       break;
1284     }
1285     case HeadPath:
1286     {
1287       *p='\0';
1288       break;
1289     }
1290     case TailPath:
1291     {
1292       if (IsBasenameSeparator(*p) != MagickFalse)
1293         (void) CopyMagickMemory((unsigned char *) component,
1294           (const unsigned char *) (p+1),strlen(p+1)+1);
1295       break;
1296     }
1297     case BasePath:
1298     {
1299       if (IsBasenameSeparator(*p) != MagickFalse)
1300         (void) CopyMagickString(component,p+1,MaxTextExtent);
1301       for (p=component+(strlen(component)-1); p > component; p--)
1302         if (*p == '.')
1303           {
1304             *p='\0';
1305             break;
1306           }
1307       break;
1308     }
1309     case ExtensionPath:
1310     {
1311       if (IsBasenameSeparator(*p) != MagickFalse)
1312         (void) CopyMagickString(component,p+1,MaxTextExtent);
1313       p=component;
1314       if (*p != '\0')
1315         for (p=component+strlen(component)-1; p > component; p--)
1316           if (*p == '.')
1317             break;
1318       *component='\0';
1319       if (*p == '.')
1320         (void) CopyMagickString(component,p+1,MaxTextExtent);
1321       break;
1322     }
1323     case SubimagePath:
1324     {
1325       (void) CopyMagickString(component,subimage,MaxTextExtent);
1326       break;
1327     }
1328     case CanonicalPath:
1329     case UndefinedPath:
1330       break;
1331   }
1332 }
1333 \f
1334 /*
1335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1336 %                                                                             %
1337 %                                                                             %
1338 %                                                                             %
1339 %  G e t P a t h C o m p o n e n t s                                          %
1340 %                                                                             %
1341 %                                                                             %
1342 %                                                                             %
1343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1344 %
1345 %  GetPathComponents() returns a list of path components.
1346 %
1347 %  The format of the GetPathComponents method is:
1348 %
1349 %      char **GetPathComponents(const char *path,
1350 %        size_t *number_componenets)
1351 %
1352 %  A description of each parameter follows:
1353 %
1354 %    o path:  Specifies the string to segment into a list.
1355 %
1356 %    o number_components:  return the number of components in the list
1357 %
1358 */
1359 MagickPrivate char **GetPathComponents(const char *path,
1360   size_t *number_components)
1361 {
1362   char
1363     **components;
1364
1365   register const char
1366     *p,
1367     *q;
1368
1369   register ssize_t
1370     i;
1371
1372   if (path == (char *) NULL)
1373     return((char **) NULL);
1374   *number_components=1;
1375   for (p=path; *p != '\0'; p++)
1376     if (IsBasenameSeparator(*p))
1377       (*number_components)++;
1378   components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1379     sizeof(*components));
1380   if (components == (char **) NULL)
1381     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1382   p=path;
1383   for (i=0; i < (ssize_t) *number_components; i++)
1384   {
1385     for (q=p; *q != '\0'; q++)
1386       if (IsBasenameSeparator(*q))
1387         break;
1388     components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1389       sizeof(**components));
1390     if (components[i] == (char *) NULL)
1391       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1392     (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1393     p=q+1;
1394   }
1395   components[i]=(char *) NULL;
1396   return(components);
1397 }
1398 \f
1399 /*
1400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1401 %                                                                             %
1402 %                                                                             %
1403 %                                                                             %
1404 %  I s P a t h A c c e s s i b l e                                            %
1405 %                                                                             %
1406 %                                                                             %
1407 %                                                                             %
1408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1409 %
1410 %  IsPathAccessible() returns MagickTrue if the file as defined by the path is
1411 %  accessible.
1412 %
1413 %  The format of the IsPathAccessible method is:
1414 %
1415 %      MagickBooleanType IsPathAccessible(const char *filename)
1416 %
1417 %  A description of each parameter follows.
1418 %
1419 %    o path:  Specifies a path to a file.
1420 %
1421 */
1422 MagickExport MagickBooleanType IsPathAccessible(const char *path)
1423 {
1424   MagickBooleanType
1425     status;
1426
1427   struct stat
1428     attributes;
1429
1430   if ((path == (const char *) NULL) || (*path == '\0'))
1431     return(MagickFalse);
1432   status=GetPathAttributes(path,&attributes);
1433   if (status == MagickFalse)
1434     return(status);
1435   if (S_ISREG(attributes.st_mode) == 0)
1436     return(MagickFalse);
1437   if (access_utf8(path,F_OK) != 0)
1438     return(MagickFalse);
1439   return(MagickTrue);
1440 }
1441 \f
1442 /*
1443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444 %                                                                             %
1445 %                                                                             %
1446 %                                                                             %
1447 +  I s P a t h D i r e c t o r y                                              %
1448 %                                                                             %
1449 %                                                                             %
1450 %                                                                             %
1451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1452 %
1453 %  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
1454 %  if the path represents a directory otherwise 0.
1455 %
1456 %  The format of the IsPathDirectory method is:
1457 %
1458 %      int IsPathDirectory(const char *path)
1459 %
1460 %  A description of each parameter follows.
1461 %
1462 %   o  path:  The directory path.
1463 %
1464 */
1465 static int IsPathDirectory(const char *path)
1466 {
1467   MagickBooleanType
1468     status;
1469
1470   struct stat
1471     attributes;
1472
1473   if ((path == (const char *) NULL) || (*path == '\0'))
1474     return(MagickFalse);
1475   status=GetPathAttributes(path,&attributes);
1476   if (status == MagickFalse)
1477     return(-1);
1478   if (S_ISDIR(attributes.st_mode) == 0)
1479     return(0);
1480   return(1);
1481 }
1482 \f
1483 /*
1484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1485 %                                                                             %
1486 %                                                                             %
1487 %                                                                             %
1488 %   L i s t F i l e s                                                         %
1489 %                                                                             %
1490 %                                                                             %
1491 %                                                                             %
1492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1493 %
1494 %  ListFiles() reads the directory specified and returns a list of filenames
1495 %  contained in the directory sorted in ascending alphabetic order.
1496 %
1497 %  The format of the ListFiles function is:
1498 %
1499 %      char **ListFiles(const char *directory,const char *pattern,
1500 %        ssize_t *number_entries)
1501 %
1502 %  A description of each parameter follows:
1503 %
1504 %    o filelist: Method ListFiles returns a list of filenames contained
1505 %      in the directory.  If the directory specified cannot be read or it is
1506 %      a file a NULL list is returned.
1507 %
1508 %    o directory: Specifies a pointer to a text string containing a directory
1509 %      name.
1510 %
1511 %    o pattern: Specifies a pointer to a text string containing a pattern.
1512 %
1513 %    o number_entries:  This integer returns the number of filenames in the
1514 %      list.
1515 %
1516 */
1517
1518 #if defined(__cplusplus) || defined(c_plusplus)
1519 extern "C" {
1520 #endif
1521
1522 static int FileCompare(const void *x,const void *y)
1523 {
1524   register const char
1525     **p,
1526     **q;
1527
1528   p=(const char **) x;
1529   q=(const char **) y;
1530   return(LocaleCompare(*p,*q));
1531 }
1532
1533 #if defined(__cplusplus) || defined(c_plusplus)
1534 }
1535 #endif
1536
1537 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1538   struct dirent **result)
1539 {
1540 #if defined(MAGICKCORE_HAVE_READDIR_R)
1541   return(readdir_r(directory,entry,result));
1542 #else
1543   (void) entry;
1544   errno=0;
1545   *result=readdir(directory);
1546   return(errno);
1547 #endif
1548 }
1549
1550 MagickPrivate char **ListFiles(const char *directory,const char *pattern,
1551   size_t *number_entries)
1552 {
1553   char
1554     **filelist;
1555
1556   DIR
1557     *current_directory;
1558
1559   struct dirent
1560     *buffer,
1561     *entry;
1562
1563   size_t
1564     max_entries;
1565
1566   /*
1567     Open directory.
1568   */
1569   assert(directory != (const char *) NULL);
1570   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1571   assert(pattern != (const char *) NULL);
1572   assert(number_entries != (size_t *) NULL);
1573   *number_entries=0;
1574   current_directory=opendir(directory);
1575   if (current_directory == (DIR *) NULL)
1576     return((char **) NULL);
1577   /*
1578     Allocate filelist.
1579   */
1580   max_entries=2048;
1581   filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1582     sizeof(*filelist));
1583   if (filelist == (char **) NULL)
1584     {
1585       (void) closedir(current_directory);
1586       return((char **) NULL);
1587     }
1588   /*
1589     Save the current and change to the new directory.
1590   */
1591   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
1592     FILENAME_MAX+1);
1593   if (buffer == (struct dirent *) NULL)
1594     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1595   while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1596          (entry != (struct dirent *) NULL))
1597   {
1598     if (*entry->d_name == '.')
1599       continue;
1600     if ((IsPathDirectory(entry->d_name) > 0) ||
1601 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1602         (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1603 #else
1604         (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1605 #endif
1606       {
1607         if (*number_entries >= max_entries)
1608           {
1609             /*
1610               Extend the file list.
1611             */
1612             max_entries<<=1;
1613             filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1614               max_entries,sizeof(*filelist));
1615             if (filelist == (char **) NULL)
1616               break;
1617           }
1618 #if defined(vms)
1619         {
1620           register char
1621             *p;
1622
1623           p=strchr(entry->d_name,';');
1624           if (p)
1625             *p='\0';
1626           if (*number_entries > 0)
1627             if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1628               continue;
1629         }
1630 #endif
1631         filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1632         (*number_entries)++;
1633       }
1634   }
1635   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1636   (void) closedir(current_directory);
1637   if (filelist == (char **) NULL)
1638     return((char **) NULL);
1639   /*
1640     Sort filelist in ascending order.
1641   */
1642   qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1643     FileCompare);
1644   return(filelist);
1645 }
1646 \f
1647 /*
1648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1649 %                                                                             %
1650 %                                                                             %
1651 %                                                                             %
1652 %   M a g i c k D e l a y                                                     %
1653 %                                                                             %
1654 %                                                                             %
1655 %                                                                             %
1656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1657 %
1658 %  MagickDelay() suspends program execution for the number of milliseconds
1659 %  specified.
1660 %
1661 %  The format of the Delay method is:
1662 %
1663 %      void MagickDelay(const MagickSizeType milliseconds)
1664 %
1665 %  A description of each parameter follows:
1666 %
1667 %    o milliseconds: Specifies the number of milliseconds to delay before
1668 %      returning.
1669 %
1670 */
1671 MagickPrivate void MagickDelay(const MagickSizeType milliseconds)
1672 {
1673   if (milliseconds == 0)
1674     return;
1675 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
1676   {
1677     struct timespec
1678       timer;
1679
1680     timer.tv_sec=(time_t) (milliseconds/1000);
1681     timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1682     (void) nanosleep(&timer,(struct timespec *) NULL);
1683   }
1684 #elif defined(MAGICKCORE_HAVE_USLEEP)
1685   usleep(1000*milliseconds);
1686 #elif defined(MAGICKCORE_HAVE_SELECT)
1687   {
1688     struct timeval
1689       timer;
1690
1691     timer.tv_sec=(long) milliseconds/1000;
1692     timer.tv_usec=(long) (milliseconds % 1000)*1000;
1693     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1694   }
1695 #elif defined(MAGICKCORE_HAVE_POLL)
1696   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1697 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1698   Sleep((long) milliseconds);
1699 #elif defined(vms)
1700   {
1701     float
1702       timer;
1703
1704     timer=milliseconds/1000.0;
1705     lib$wait(&timer);
1706   }
1707 #elif defined(__BEOS__)
1708   snooze(1000*milliseconds);
1709 #else
1710 # error "Time delay method not defined."
1711 #endif
1712 }
1713 \f
1714 /*
1715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1716 %                                                                             %
1717 %                                                                             %
1718 %                                                                             %
1719 %  M u l t i l i n e C e n s u s                                              %
1720 %                                                                             %
1721 %                                                                             %
1722 %                                                                             %
1723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724 %
1725 %  MultilineCensus() returns the number of lines within a label.  A line is
1726 %  represented by a \n character.
1727 %
1728 %  The format of the MultilineCenus method is:
1729 %
1730 %      size_t MultilineCensus(const char *label)
1731 %
1732 %  A description of each parameter follows.
1733 %
1734 %   o  label:  This character string is the label.
1735 %
1736 */
1737 MagickExport size_t MultilineCensus(const char *label)
1738 {
1739   size_t
1740     number_lines;
1741
1742   /*
1743     Determine the number of lines within this label.
1744   */
1745   if (label == (char *) NULL)
1746     return(0);
1747   for (number_lines=1; *label != '\0'; label++)
1748     if (*label == '\n')
1749       number_lines++;
1750   return(number_lines);
1751 }
1752 \f
1753 /*
1754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1755 %                                                                             %
1756 %                                                                             %
1757 %                                                                             %
1758 %   S y s t e m C o m m a n d                                                 %
1759 %                                                                             %
1760 %                                                                             %
1761 %                                                                             %
1762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 %
1764 %  SystemCommand() executes the specified command and waits until it
1765 %  terminates.  The returned value is the exit status of the command.
1766 %
1767 %  The format of the SystemCommand method is:
1768 %
1769 %      int SystemCommand(const MagickBooleanType asynchronous,
1770 %        const MagickBooleanType verbose,const char *command,
1771 %        ExceptionInfo *exception)
1772 %
1773 %  A description of each parameter follows:
1774 %
1775 %    o asynchronous: a value other than 0 executes the parent program
1776 %      concurrently with the new child process.
1777 %
1778 %    o verbose: a value other than 0 prints the executed command before it is
1779 %      invoked.
1780 %
1781 %    o command: this string is the command to execute.
1782 %
1783 %    o exception: return any errors here.
1784 %
1785 */
1786 MagickExport int SystemCommand(const MagickBooleanType asynchronous,
1787   const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
1788 {
1789   char
1790     **arguments,
1791     *shell_command;
1792
1793   int
1794     number_arguments,
1795     status;
1796
1797   PolicyDomain
1798     domain;
1799
1800   PolicyRights
1801     rights;
1802
1803   register ssize_t
1804     i;
1805
1806   status=(-1);
1807   arguments=StringToArgv(command,&number_arguments);
1808   if (arguments == (char **) NULL)
1809     return(status);
1810   if (*arguments[1] == '\0')
1811     {
1812       for (i=0; i < (ssize_t) number_arguments; i++)
1813         arguments[i]=DestroyString(arguments[i]);
1814       arguments=(char **) RelinquishMagickMemory(arguments);
1815       return(-1);
1816     }
1817   rights=ExecutePolicyRights;
1818   domain=DelegatePolicyDomain;
1819   if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
1820     {
1821       errno=EPERM;
1822       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1823         "NotAuthorized","`%s'",arguments[1]);
1824       for (i=0; i < (ssize_t) number_arguments; i++)
1825         arguments[i]=DestroyString(arguments[i]);
1826       arguments=(char **) RelinquishMagickMemory(arguments);
1827       return(-1);
1828     }
1829   if (verbose != MagickFalse)
1830     {
1831       (void) FormatLocaleFile(stderr,"%s\n",command);
1832       (void) fflush(stderr);
1833     }
1834   shell_command=(char *) command;
1835   if (asynchronous != MagickFalse)
1836     {
1837       shell_command=AcquireString(command);
1838       (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
1839     }
1840 #if defined(MAGICKCORE_POSIX_SUPPORT)
1841 #if !defined(MAGICKCORE_HAVE_EXECVP)
1842   status=system(shell_command);
1843 #else
1844   if ((asynchronous != MagickFalse) ||
1845       (strpbrk(shell_command,"&;<>|") != (char *) NULL))
1846     status=system(shell_command);
1847   else
1848     {
1849       pid_t
1850         child_pid;
1851
1852       /*
1853         Call application directly rather than from a shell.
1854       */
1855       child_pid=(pid_t) fork();
1856       if (child_pid == (pid_t) -1)
1857         status=system(command);
1858       else
1859         if (child_pid == 0)
1860           {
1861             status=execvp(arguments[1],arguments+1);
1862             _exit(1);
1863           }
1864         else
1865           {
1866             int
1867               child_status;
1868
1869             pid_t
1870               pid;
1871
1872             child_status=0;
1873             pid=(pid_t) waitpid(child_pid,&child_status,0);
1874             if (pid == -1)
1875               status=(-1);
1876             else
1877               {
1878                 if (WIFEXITED(child_status) != 0)
1879                   status=WEXITSTATUS(child_status);
1880                 else
1881                   if (WIFSIGNALED(child_status))
1882                     status=(-1);
1883               }
1884           }
1885     }
1886 #endif
1887 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1888   status=NTSystemCommand(shell_command);
1889 #elif defined(macintosh)
1890   status=MACSystemCommand(shell_command);
1891 #elif defined(vms)
1892   status=system(shell_command);
1893 #else
1894 #  error No suitable system() method.
1895 #endif
1896   if (status < 0)
1897     (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
1898       "'%s' (%d)",command,status);
1899   if (shell_command != command)
1900     shell_command=DestroyString(shell_command);
1901   for (i=0; i < (ssize_t) number_arguments; i++)
1902     arguments[i]=DestroyString(arguments[i]);
1903   arguments=(char **) RelinquishMagickMemory(arguments);
1904   return(status);
1905 }