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