]> 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       (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
898       filelist[j]=DestroyString(filelist[j]);
899       if (strlen(filename) >= (MaxTextExtent-1))
900         ThrowFatalException(OptionFatalError,"FilenameTruncated");
901       if (IsPathDirectory(filename) <= 0)
902         {
903           char
904             path[MaxTextExtent];
905
906           *path='\0';
907           if (*magick != '\0')
908             {
909               (void) ConcatenateMagickString(path,magick,MaxTextExtent);
910               (void) ConcatenateMagickString(path,":",MaxTextExtent);
911             }
912           (void) ConcatenateMagickString(path,filename,MaxTextExtent);
913           if (*subimage != '\0')
914             {
915               (void) ConcatenateMagickString(path,"[",MaxTextExtent);
916               (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
917               (void) ConcatenateMagickString(path,"]",MaxTextExtent);
918             }
919           if (strlen(path) >= (MaxTextExtent-1))
920             ThrowFatalException(OptionFatalError,"FilenameTruncated");
921           if (destroy != MagickFalse)
922             {
923               count--;
924               vector[count]=DestroyString(vector[count]);
925               destroy=MagickFalse;
926             }
927           vector[count++]=ConstantString(path);
928         }
929     }
930     filelist=(char **) RelinquishMagickMemory(filelist);
931   }
932   vector[count]=(char *) NULL;
933   if (IsEventLogging() != MagickFalse)
934     {
935       char
936         *command_line;
937
938       command_line=AcquireString(vector[0]);
939       for (i=1; i < count; i++)
940       {
941         (void) ConcatenateString(&command_line," {");
942         (void) ConcatenateString(&command_line,vector[i]);
943         (void) ConcatenateString(&command_line,"}");
944       }
945       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
946         "Command line: %s",command_line);
947       command_line=DestroyString(command_line);
948     }
949   *number_arguments=(int) count;
950   *arguments=vector;
951   return(MagickTrue);
952 }
953 \f
954 /*
955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
956 %                                                                             %
957 %                                                                             %
958 %                                                                             %
959 %   G e t E x e c u t i o n P a t h                                           %
960 %                                                                             %
961 %                                                                             %
962 %                                                                             %
963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964 %
965 %  GetExecutionPath() returns the pathname of the executable that started
966 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
967 %
968 %  The format of the GetExecutionPath method is:
969 %
970 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
971 %
972 %  A description of each parameter follows:
973 %
974 %    o path: the pathname of the executable that started the process.
975 %
976 %    o extent: the maximum extent of the path.
977 %
978 */
979 MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
980 {
981   char
982     *directory;
983
984   *path='\0';
985   directory=getcwd(path,(unsigned long) extent);
986   (void) directory;
987 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
988   {
989     char
990       link_path[MaxTextExtent],
991       execution_path[PATH_MAX+1];
992
993     ssize_t
994       count;
995
996     (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe",
997       (double) getpid());
998     count=readlink(link_path,execution_path,PATH_MAX);
999     if (count == -1)
1000       {
1001         (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file",
1002           (double) getpid());
1003         count=readlink(link_path,execution_path,PATH_MAX);
1004       }
1005     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
1006       {
1007         execution_path[count]='\0';
1008         (void) CopyMagickString(path,execution_path,extent);
1009       }
1010   }
1011 #endif
1012 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
1013   {
1014     char
1015       executable_path[PATH_MAX << 1],
1016       execution_path[PATH_MAX+1];
1017
1018     uint32_t
1019       length;
1020
1021     length=sizeof(executable_path);
1022     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
1023         (realpath(executable_path,execution_path) != (char *) NULL))
1024       (void) CopyMagickString(path,execution_path,extent);
1025   }
1026 #endif
1027 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
1028   {
1029     const char
1030       *execution_path;
1031
1032     execution_path=(const char *) getexecname();
1033     if (execution_path != (const char *) NULL)
1034       {
1035         if (*execution_path != *DirectorySeparator)
1036           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
1037         (void) ConcatenateMagickString(path,execution_path,extent);
1038       }
1039   }
1040 #endif
1041 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1042   NTGetExecutionPath(path,extent);
1043 #endif
1044 #if defined(__GNU__)
1045   {
1046     char
1047       *program_name,
1048       *execution_path;
1049
1050     ssize_t
1051       count;
1052
1053     count=0;
1054     execution_path=(char *) NULL;
1055     program_name=program_invocation_name;
1056     if (*program_invocation_name != '/')
1057       {
1058         size_t
1059           extent;
1060
1061         extent=strlen(directory)+strlen(program_name)+2;
1062         program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1063         if (program_name == (char *) NULL)
1064           program_name=program_invocation_name;
1065         else
1066           count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1067             program_invocation_name);
1068       }
1069     if (count != -1)
1070       {
1071         execution_path=realpath(program_name,NULL);
1072         if (execution_path != (char *) NULL)
1073           (void) CopyMagickString(path,execution_path,extent);
1074       }
1075     if (program_name != program_invocation_name)
1076       program_name=(char *) RelinquishMagickMemory(program_name);
1077     execution_path=(char *) RelinquishMagickMemory(execution_path);
1078   }
1079 #endif
1080 #if defined(__OpenBSD__)
1081   {
1082     extern char
1083       *__progname;
1084
1085     (void) CopyMagickString(path,__progname,extent);
1086   }
1087 #endif
1088   return(IsPathAccessible(path));
1089 }
1090 \f
1091 /*
1092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1093 %                                                                             %
1094 %                                                                             %
1095 %                                                                             %
1096 %   G e t M a g i c k P a g e S i z e                                         %
1097 %                                                                             %
1098 %                                                                             %
1099 %                                                                             %
1100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1101 %
1102 %  GetMagickPageSize() returns the memory page size.
1103 %
1104 %  The format of the GetMagickPageSize method is:
1105 %
1106 %      ssize_t GetMagickPageSize()
1107 %
1108 */
1109 MagickPrivate ssize_t GetMagickPageSize(void)
1110 {
1111   static ssize_t
1112     page_size = -1;
1113
1114   if (page_size > 0)
1115     return(page_size);
1116 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1117   page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1118 #else
1119 #if defined(MAGICKCORE_HAVE_GETPAGESIZE)
1120   page_size=(ssize_t) getpagesize();
1121 #endif
1122 #endif
1123   if (page_size <= 0)
1124     page_size=16384;
1125   return(page_size);
1126 }
1127 \f
1128 /*
1129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130 %                                                                             %
1131 %                                                                             %
1132 %                                                                             %
1133 %   G e t P a t h A t t r i b u t e s                                         %
1134 %                                                                             %
1135 %                                                                             %
1136 %                                                                             %
1137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1138 %
1139 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
1140 %
1141 %  The path of the GetPathAttributes method is:
1142 %
1143 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1144 %
1145 %  A description of each parameter follows.
1146 %
1147 %   o  path: the file path.
1148 %
1149 %   o  attributes: the path attributes are returned here.
1150 %
1151 */
1152 MagickExport MagickBooleanType GetPathAttributes(const char *path,
1153   void *attributes)
1154 {
1155   MagickBooleanType
1156     status;
1157
1158   if (path == (const char *) NULL)
1159     {
1160       errno=EINVAL;
1161       return(MagickFalse);
1162     }
1163   status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
1164     MagickFalse;
1165   return(status);
1166 }
1167 \f
1168 /*
1169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1170 %                                                                             %
1171 %                                                                             %
1172 %                                                                             %
1173 %   G e t P a t h C o m p o n e n t                                           %
1174 %                                                                             %
1175 %                                                                             %
1176 %                                                                             %
1177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1178 %
1179 %  GetPathComponent() returns the parent directory name, filename, basename, or
1180 %  extension of a file path.
1181 %
1182 %  The component string pointed to must have at least MaxTextExtent space
1183 %  for the results to be stored.
1184 %
1185 %  The format of the GetPathComponent function is:
1186 %
1187 %      GetPathComponent(const char *path,PathType type,char *component)
1188 %
1189 %  A description of each parameter follows:
1190 %
1191 %    o path: Specifies a pointer to a character array that contains the
1192 %      file path.
1193 %
1194 %    o type: Specififies which file path component to return.
1195 %
1196 %    o component: the selected file path component is returned here.
1197 %
1198 */
1199 MagickExport void GetPathComponent(const char *path,PathType type,
1200   char *component)
1201 {
1202   char
1203     magick[MaxTextExtent],
1204     *q,
1205     subimage[MaxTextExtent];
1206
1207   register char
1208     *p;
1209
1210   assert(path != (const char *) NULL);
1211   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1212   assert(component != (char *) NULL);
1213   if (*path == '\0')
1214     {
1215       *component='\0';
1216       return;
1217     }
1218   (void) CopyMagickString(component,path,MaxTextExtent);
1219   *magick='\0';
1220 #if defined(__OS2__)
1221   if (path[1] != ":")
1222 #endif
1223   for (p=component; *p != '\0'; p++)
1224   {
1225     if ((*p == '%') && (*(p+1) == '['))
1226       {
1227         /*
1228           Skip over %[...].
1229         */
1230         for (p++; (*p != ']') && (*p != '\0'); p++) ;
1231         if (*p == '\0')
1232           break;
1233       }
1234     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
1235         (IsPathAccessible(path) == MagickFalse))
1236       {
1237         /*
1238           Look for image format specification (e.g. ps3:image).
1239         */
1240         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1241         if (IsMagickConflict(magick) != MagickFalse)
1242           *magick='\0';
1243         else
1244           for (q=component; *q != '\0'; q++)
1245             *q=(*++p);
1246         break;
1247       }
1248   }
1249   *subimage='\0';
1250   p=component;
1251   if (*p != '\0')
1252     p=component+strlen(component)-1;
1253   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1254       (IsPathAccessible(path) == MagickFalse))
1255     {
1256       /*
1257         Look for scene specification (e.g. img0001.pcd[4]).
1258       */
1259       for (q=p-1; q > component; q--)
1260         if (*q == '[')
1261           break;
1262       if (*q == '[')
1263         {
1264           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1265           subimage[p-q-1]='\0';
1266           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1267               (IsGeometry(subimage) == MagickFalse))
1268             *subimage='\0';
1269           else
1270             *q='\0';
1271         }
1272     }
1273   p=component;
1274   if (*p != '\0')
1275     for (p=component+strlen(component)-1; p > component; p--)
1276       if (IsBasenameSeparator(*p) != MagickFalse)
1277         break;
1278   switch (type)
1279   {
1280     case MagickPath:
1281     {
1282       (void) CopyMagickString(component,magick,MaxTextExtent);
1283       break;
1284     }
1285     case RootPath:
1286     {
1287       for (p=component+(strlen(component)-1); p > component; p--)
1288       {
1289         if (IsBasenameSeparator(*p) != MagickFalse)
1290           break;
1291         if (*p == '.')
1292           break;
1293       }
1294       if (*p == '.')
1295         *p='\0';
1296       break;
1297     }
1298     case HeadPath:
1299     {
1300       *p='\0';
1301       break;
1302     }
1303     case TailPath:
1304     {
1305       if (IsBasenameSeparator(*p) != MagickFalse)
1306         (void) CopyMagickMemory((unsigned char *) component,
1307           (const unsigned char *) (p+1),strlen(p+1)+1);
1308       break;
1309     }
1310     case BasePath:
1311     {
1312       if (IsBasenameSeparator(*p) != MagickFalse)
1313         (void) CopyMagickString(component,p+1,MaxTextExtent);
1314       for (p=component+(strlen(component)-1); p > component; p--)
1315         if (*p == '.')
1316           {
1317             *p='\0';
1318             break;
1319           }
1320       break;
1321     }
1322     case ExtensionPath:
1323     {
1324       if (IsBasenameSeparator(*p) != MagickFalse)
1325         (void) CopyMagickString(component,p+1,MaxTextExtent);
1326       p=component;
1327       if (*p != '\0')
1328         for (p=component+strlen(component)-1; p > component; p--)
1329           if (*p == '.')
1330             break;
1331       *component='\0';
1332       if (*p == '.')
1333         (void) CopyMagickString(component,p+1,MaxTextExtent);
1334       break;
1335     }
1336     case SubimagePath:
1337     {
1338       (void) CopyMagickString(component,subimage,MaxTextExtent);
1339       break;
1340     }
1341     case CanonicalPath:
1342     case UndefinedPath:
1343       break;
1344   }
1345 }
1346 \f
1347 /*
1348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1349 %                                                                             %
1350 %                                                                             %
1351 %                                                                             %
1352 %  G e t P a t h C o m p o n e n t s                                          %
1353 %                                                                             %
1354 %                                                                             %
1355 %                                                                             %
1356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1357 %
1358 %  GetPathComponents() returns a list of path components.
1359 %
1360 %  The format of the GetPathComponents method is:
1361 %
1362 %      char **GetPathComponents(const char *path,
1363 %        size_t *number_componenets)
1364 %
1365 %  A description of each parameter follows:
1366 %
1367 %    o path:  Specifies the string to segment into a list.
1368 %
1369 %    o number_components:  return the number of components in the list
1370 %
1371 */
1372 MagickPrivate char **GetPathComponents(const char *path,
1373   size_t *number_components)
1374 {
1375   char
1376     **components;
1377
1378   register const char
1379     *p,
1380     *q;
1381
1382   register ssize_t
1383     i;
1384
1385   if (path == (char *) NULL)
1386     return((char **) NULL);
1387   *number_components=1;
1388   for (p=path; *p != '\0'; p++)
1389     if (IsBasenameSeparator(*p))
1390       (*number_components)++;
1391   components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1392     sizeof(*components));
1393   if (components == (char **) NULL)
1394     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1395   p=path;
1396   for (i=0; i < (ssize_t) *number_components; i++)
1397   {
1398     for (q=p; *q != '\0'; q++)
1399       if (IsBasenameSeparator(*q))
1400         break;
1401     components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1402       sizeof(**components));
1403     if (components[i] == (char *) NULL)
1404       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1405     (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1406     p=q+1;
1407   }
1408   components[i]=(char *) NULL;
1409   return(components);
1410 }
1411 \f
1412 /*
1413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414 %                                                                             %
1415 %                                                                             %
1416 %                                                                             %
1417 %  I s P a t h A c c e s s i b l e                                            %
1418 %                                                                             %
1419 %                                                                             %
1420 %                                                                             %
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 %
1423 %  IsPathAccessible() returns MagickTrue if the file as defined by the path is
1424 %  accessible.
1425 %
1426 %  The format of the IsPathAccessible method is:
1427 %
1428 %      MagickBooleanType IsPathAccessible(const char *path)
1429 %
1430 %  A description of each parameter follows.
1431 %
1432 %    o path:  Specifies a path to a file.
1433 %
1434 */
1435 MagickExport MagickBooleanType IsPathAccessible(const char *path)
1436 {
1437   MagickBooleanType
1438     status;
1439
1440   struct stat
1441     attributes;
1442
1443   if ((path == (const char *) NULL) || (*path == '\0'))
1444     return(MagickFalse);
1445   status=GetPathAttributes(path,&attributes);
1446   if (status == MagickFalse)
1447     return(status);
1448   if (S_ISREG(attributes.st_mode) == 0)
1449     return(MagickFalse);
1450   if (access_utf8(path,F_OK) != 0)
1451     return(MagickFalse);
1452   return(MagickTrue);
1453 }
1454 \f
1455 /*
1456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1457 %                                                                             %
1458 %                                                                             %
1459 %                                                                             %
1460 +  I s P a t h D i r e c t o r y                                              %
1461 %                                                                             %
1462 %                                                                             %
1463 %                                                                             %
1464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465 %
1466 %  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
1467 %  if the path represents a directory otherwise 0.
1468 %
1469 %  The format of the IsPathDirectory method is:
1470 %
1471 %      int IsPathDirectory(const char *path)
1472 %
1473 %  A description of each parameter follows.
1474 %
1475 %   o  path:  The directory path.
1476 %
1477 */
1478 static int IsPathDirectory(const char *path)
1479 {
1480   MagickBooleanType
1481     status;
1482
1483   struct stat
1484     attributes;
1485
1486   if ((path == (const char *) NULL) || (*path == '\0'))
1487     return(MagickFalse);
1488   status=GetPathAttributes(path,&attributes);
1489   if (status == MagickFalse)
1490     return(-1);
1491   if (S_ISDIR(attributes.st_mode) == 0)
1492     return(0);
1493   return(1);
1494 }
1495 \f
1496 /*
1497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1498 %                                                                             %
1499 %                                                                             %
1500 %                                                                             %
1501 %   L i s t F i l e s                                                         %
1502 %                                                                             %
1503 %                                                                             %
1504 %                                                                             %
1505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1506 %
1507 %  ListFiles() reads the directory specified and returns a list of filenames
1508 %  contained in the directory sorted in ascending alphabetic order.
1509 %
1510 %  The format of the ListFiles function is:
1511 %
1512 %      char **ListFiles(const char *directory,const char *pattern,
1513 %        ssize_t *number_entries)
1514 %
1515 %  A description of each parameter follows:
1516 %
1517 %    o filelist: Method ListFiles returns a list of filenames contained
1518 %      in the directory.  If the directory specified cannot be read or it is
1519 %      a file a NULL list is returned.
1520 %
1521 %    o directory: Specifies a pointer to a text string containing a directory
1522 %      name.
1523 %
1524 %    o pattern: Specifies a pointer to a text string containing a pattern.
1525 %
1526 %    o number_entries:  This integer returns the number of filenames in the
1527 %      list.
1528 %
1529 */
1530
1531 #if defined(__cplusplus) || defined(c_plusplus)
1532 extern "C" {
1533 #endif
1534
1535 static int FileCompare(const void *x,const void *y)
1536 {
1537   register const char
1538     **p,
1539     **q;
1540
1541   p=(const char **) x;
1542   q=(const char **) y;
1543   return(LocaleCompare(*p,*q));
1544 }
1545
1546 #if defined(__cplusplus) || defined(c_plusplus)
1547 }
1548 #endif
1549
1550 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1551   struct dirent **result)
1552 {
1553 #if defined(MAGICKCORE_HAVE_READDIR_R)
1554   return(readdir_r(directory,entry,result));
1555 #else
1556   (void) entry;
1557   errno=0;
1558   *result=readdir(directory);
1559   return(errno);
1560 #endif
1561 }
1562
1563 MagickPrivate char **ListFiles(const char *directory,const char *pattern,
1564   size_t *number_entries)
1565 {
1566   char
1567     **filelist;
1568
1569   DIR
1570     *current_directory;
1571
1572   struct dirent
1573     *buffer,
1574     *entry;
1575
1576   size_t
1577     max_entries;
1578
1579   /*
1580     Open directory.
1581   */
1582   assert(directory != (const char *) NULL);
1583   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1584   assert(pattern != (const char *) NULL);
1585   assert(number_entries != (size_t *) NULL);
1586   *number_entries=0;
1587   current_directory=opendir(directory);
1588   if (current_directory == (DIR *) NULL)
1589     return((char **) NULL);
1590   /*
1591     Allocate filelist.
1592   */
1593   max_entries=2048;
1594   filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1595     sizeof(*filelist));
1596   if (filelist == (char **) NULL)
1597     {
1598       (void) closedir(current_directory);
1599       return((char **) NULL);
1600     }
1601   /*
1602     Save the current and change to the new directory.
1603   */
1604   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
1605     FILENAME_MAX+1);
1606   if (buffer == (struct dirent *) NULL)
1607     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1608   while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1609          (entry != (struct dirent *) NULL))
1610   {
1611     if (*entry->d_name == '.')
1612       continue;
1613     if ((IsPathDirectory(entry->d_name) > 0) ||
1614 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1615         (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1616 #else
1617         (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1618 #endif
1619       {
1620         if (*number_entries >= max_entries)
1621           {
1622             /*
1623               Extend the file list.
1624             */
1625             max_entries<<=1;
1626             filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1627               max_entries,sizeof(*filelist));
1628             if (filelist == (char **) NULL)
1629               break;
1630           }
1631 #if defined(vms)
1632         {
1633           register char
1634             *p;
1635
1636           p=strchr(entry->d_name,';');
1637           if (p)
1638             *p='\0';
1639           if (*number_entries > 0)
1640             if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1641               continue;
1642         }
1643 #endif
1644         filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1645         (*number_entries)++;
1646       }
1647   }
1648   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1649   (void) closedir(current_directory);
1650   if (filelist == (char **) NULL)
1651     return((char **) NULL);
1652   /*
1653     Sort filelist in ascending order.
1654   */
1655   qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1656     FileCompare);
1657   return(filelist);
1658 }
1659 \f
1660 /*
1661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1662 %                                                                             %
1663 %                                                                             %
1664 %                                                                             %
1665 %   M a g i c k D e l a y                                                     %
1666 %                                                                             %
1667 %                                                                             %
1668 %                                                                             %
1669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1670 %
1671 %  MagickDelay() suspends program execution for the number of milliseconds
1672 %  specified.
1673 %
1674 %  The format of the Delay method is:
1675 %
1676 %      void MagickDelay(const MagickSizeType milliseconds)
1677 %
1678 %  A description of each parameter follows:
1679 %
1680 %    o milliseconds: Specifies the number of milliseconds to delay before
1681 %      returning.
1682 %
1683 */
1684 MagickPrivate void MagickDelay(const MagickSizeType milliseconds)
1685 {
1686   if (milliseconds == 0)
1687     return;
1688 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
1689   {
1690     struct timespec
1691       timer;
1692
1693     timer.tv_sec=(time_t) (milliseconds/1000);
1694     timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1695     (void) nanosleep(&timer,(struct timespec *) NULL);
1696   }
1697 #elif defined(MAGICKCORE_HAVE_USLEEP)
1698   usleep(1000*milliseconds);
1699 #elif defined(MAGICKCORE_HAVE_SELECT)
1700   {
1701     struct timeval
1702       timer;
1703
1704     timer.tv_sec=(long) milliseconds/1000;
1705     timer.tv_usec=(long) (milliseconds % 1000)*1000;
1706     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1707   }
1708 #elif defined(MAGICKCORE_HAVE_POLL)
1709   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1710 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1711   Sleep((long) milliseconds);
1712 #elif defined(vms)
1713   {
1714     float
1715       timer;
1716
1717     timer=milliseconds/1000.0;
1718     lib$wait(&timer);
1719   }
1720 #elif defined(__BEOS__)
1721   snooze(1000*milliseconds);
1722 #else
1723 # error "Time delay method not defined."
1724 #endif
1725 }
1726 \f
1727 /*
1728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1729 %                                                                             %
1730 %                                                                             %
1731 %                                                                             %
1732 %  M u l t i l i n e C e n s u s                                              %
1733 %                                                                             %
1734 %                                                                             %
1735 %                                                                             %
1736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1737 %
1738 %  MultilineCensus() returns the number of lines within a label.  A line is
1739 %  represented by a \n character.
1740 %
1741 %  The format of the MultilineCenus method is:
1742 %
1743 %      size_t MultilineCensus(const char *label)
1744 %
1745 %  A description of each parameter follows.
1746 %
1747 %   o  label:  This character string is the label.
1748 %
1749 */
1750 MagickExport size_t MultilineCensus(const char *label)
1751 {
1752   size_t
1753     number_lines;
1754
1755   /*
1756     Determine the number of lines within this label.
1757   */
1758   if (label == (char *) NULL)
1759     return(0);
1760   for (number_lines=1; *label != '\0'; label++)
1761     if (*label == '\n')
1762       number_lines++;
1763   return(number_lines);
1764 }
1765 \f
1766 /*
1767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1768 %                                                                             %
1769 %                                                                             %
1770 %                                                                             %
1771 %   S h r e a d F i l e                                                       %
1772 %                                                                             %
1773 %                                                                             %
1774 %                                                                             %
1775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1776 %
1777 %  ShredFile() overwrites the specified file with zeros or random data and then
1778 %  removes it.  The overwrite is optional and is only required to help keep
1779 %  the contents of the file private.  On the first pass, the file is zeroed.
1780 %  For subsequent passes, random data is written.
1781 %
1782 %  The format of the ShredFile method is:
1783 %
1784 %      MagickBooleanType ShredFile(const char *path)
1785 %
1786 %  A description of each parameter follows.
1787 %
1788 %    o path:  Specifies a path to a file.
1789 %
1790 */
1791 MagickPrivate MagickBooleanType ShredFile(const char *path)
1792 {
1793   char
1794     *passes;
1795
1796   ExceptionInfo
1797     *exception;
1798
1799   int
1800     file,
1801     status;
1802
1803   MagickSizeType
1804     length;
1805
1806   register ssize_t
1807     i;
1808
1809   size_t
1810     quantum;
1811
1812   struct stat
1813     file_stats;
1814
1815   if ((path == (const char *) NULL) || (*path == '\0'))
1816     return(MagickFalse);
1817   exception=AcquireExceptionInfo();
1818   passes=(char *) GetImageRegistry(StringRegistryType,"shred-passes",exception);
1819   exception=DestroyExceptionInfo(exception);
1820   if (passes == (char *) NULL)
1821     passes=GetEnvironmentValue("MAGICK_SHRED_PASSES");
1822   if (passes == (char *) NULL)
1823     {
1824       /*
1825         Don't shred the file, just remove it.
1826       */
1827       status=remove_utf8(path);
1828       if (status == -1)
1829         return(MagickFalse);
1830       return(MagickTrue);
1831     }
1832   file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
1833   if (file == -1)
1834     {
1835       /*
1836         Don't shred the file, just remove it.
1837       */
1838       status=remove_utf8(path);
1839       return(MagickFalse);
1840     }
1841   /*
1842     Shred the file.
1843   */
1844   quantum=(size_t) MagickMaxBufferExtent;
1845   if ((fstat(file,&file_stats) == 0) && (file_stats.st_size != 0))
1846     quantum=(size_t) MagickMin((MagickSizeType) file_stats.st_size,
1847       MagickMaxBufferExtent);
1848   length=(MagickSizeType) file_stats.st_size;
1849   for (i=0; i < (ssize_t) StringToInteger(passes); i++)
1850   {
1851     RandomInfo
1852       *random_info;
1853
1854     register MagickOffsetType
1855       j;
1856
1857     ssize_t
1858       count;
1859
1860     if (lseek(file,0,SEEK_SET) < 0)
1861       break;
1862     random_info=AcquireRandomInfo();
1863     for (j=0; j < (MagickOffsetType) length; j+=count)
1864     {
1865       StringInfo
1866         *key;
1867
1868       key=GetRandomKey(random_info,quantum);
1869       if (i == 0)
1870         ResetStringInfo(key);  /* zero on first pass */
1871       count=write(file,GetStringInfoDatum(key),(size_t)
1872         MagickMin(quantum,length-j));
1873       key=DestroyStringInfo(key);
1874       if (count <= 0)
1875         {
1876           count=0;
1877           if (errno != EINTR)
1878             break;
1879         }
1880     }
1881     random_info=DestroyRandomInfo(random_info);
1882     if (j < (MagickOffsetType) length)
1883       break;
1884   }
1885   status=close(file);
1886   status=remove_utf8(path);
1887   if (status == -1)
1888     return(MagickFalse);
1889   return(i < (ssize_t) StringToInteger(passes) ? MagickFalse : MagickTrue);
1890 }
1891 \f
1892 /*
1893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1894 %                                                                             %
1895 %                                                                             %
1896 %                                                                             %
1897 %   S y s t e m C o m m a n d                                                 %
1898 %                                                                             %
1899 %                                                                             %
1900 %                                                                             %
1901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1902 %
1903 %  SystemCommand() executes the specified command and waits until it
1904 %  terminates.  The returned value is the exit status of the command.
1905 %
1906 %  The format of the SystemCommand method is:
1907 %
1908 %      int SystemCommand(const MagickBooleanType asynchronous,
1909 %        const MagickBooleanType verbose,const char *command,
1910 %        ExceptionInfo *exception)
1911 %
1912 %  A description of each parameter follows:
1913 %
1914 %    o asynchronous: a value other than 0 executes the parent program
1915 %      concurrently with the new child process.
1916 %
1917 %    o verbose: a value other than 0 prints the executed command before it is
1918 %      invoked.
1919 %
1920 %    o command: this string is the command to execute.
1921 %
1922 %    o exception: return any errors here.
1923 %
1924 */
1925 MagickExport int SystemCommand(const MagickBooleanType asynchronous,
1926   const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
1927 {
1928   char
1929     **arguments,
1930     *shell_command;
1931
1932   int
1933     number_arguments,
1934     status;
1935
1936   PolicyDomain
1937     domain;
1938
1939   PolicyRights
1940     rights;
1941
1942   register ssize_t
1943     i;
1944
1945   status=(-1);
1946   arguments=StringToArgv(command,&number_arguments);
1947   if (arguments == (char **) NULL)
1948     return(status);
1949   if (*arguments[1] == '\0')
1950     {
1951       for (i=0; i < (ssize_t) number_arguments; i++)
1952         arguments[i]=DestroyString(arguments[i]);
1953       arguments=(char **) RelinquishMagickMemory(arguments);
1954       return(-1);
1955     }
1956   rights=ExecutePolicyRights;
1957   domain=DelegatePolicyDomain;
1958   if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
1959     {
1960       errno=EPERM;
1961       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1962         "NotAuthorized","`%s'",arguments[1]);
1963       for (i=0; i < (ssize_t) number_arguments; i++)
1964         arguments[i]=DestroyString(arguments[i]);
1965       arguments=(char **) RelinquishMagickMemory(arguments);
1966       return(-1);
1967     }
1968   if (verbose != MagickFalse)
1969     {
1970       (void) FormatLocaleFile(stderr,"%s\n",command);
1971       (void) fflush(stderr);
1972     }
1973   shell_command=(char *) command;
1974   if (asynchronous != MagickFalse)
1975     {
1976       shell_command=AcquireString(command);
1977       (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
1978     }
1979 #if defined(MAGICKCORE_POSIX_SUPPORT)
1980 #if !defined(MAGICKCORE_HAVE_EXECVP)
1981   status=system(shell_command);
1982 #else
1983   if ((asynchronous != MagickFalse) ||
1984       (strpbrk(shell_command,"&;<>|") != (char *) NULL))
1985     status=system(shell_command);
1986   else
1987     {
1988       pid_t
1989         child_pid;
1990
1991       /*
1992         Call application directly rather than from a shell.
1993       */
1994       child_pid=(pid_t) fork();
1995       if (child_pid == (pid_t) -1)
1996         status=system(command);
1997       else
1998         if (child_pid == 0)
1999           {
2000             status=execvp(arguments[1],arguments+1);
2001             _exit(1);
2002           }
2003         else
2004           {
2005             int
2006               child_status;
2007
2008             pid_t
2009               pid;
2010
2011             child_status=0;
2012             pid=(pid_t) waitpid(child_pid,&child_status,0);
2013             if (pid == -1)
2014               status=(-1);
2015             else
2016               {
2017                 if (WIFEXITED(child_status) != 0)
2018                   status=WEXITSTATUS(child_status);
2019                 else
2020                   if (WIFSIGNALED(child_status))
2021                     status=(-1);
2022               }
2023           }
2024     }
2025 #endif
2026 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
2027   status=NTSystemCommand(shell_command);
2028 #elif defined(macintosh)
2029   status=MACSystemCommand(shell_command);
2030 #elif defined(vms)
2031   status=system(shell_command);
2032 #else
2033 #  error No suitable system() method.
2034 #endif
2035   if (status < 0)
2036     (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
2037       "'%s' (%d)",command,status);
2038   if (shell_command != command)
2039     shell_command=DestroyString(shell_command);
2040   for (i=0; i < (ssize_t) number_arguments; i++)
2041     arguments[i]=DestroyString(arguments[i]);
2042   arguments=(char **) RelinquishMagickMemory(arguments);
2043   return(status);
2044 }