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