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