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