]> granicus.if.org Git - imagemagick/blob - MagickCore/utility.c
(no commit message)
[imagemagick] / MagickCore / utility.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
7 %             U   U    T      I    L        I      T     Y Y                  %
8 %             U   U    T      I    L        I      T      Y                   %
9 %             U   U    T      I    L        I      T      Y                   %
10 %              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore Utility Methods                            %
14 %                                                                             %
15 %                             Software Design                                 %
16 %                               John Cristy                                   %
17 %                              January 1993                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/property.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/color.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/geometry.h"
49 #include "MagickCore/list.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/memory_.h"
52 #include "MagickCore/option.h"
53 #include "MagickCore/policy.h"
54 #include "MagickCore/resource_.h"
55 #include "MagickCore/semaphore.h"
56 #include "MagickCore/signature-private.h"
57 #include "MagickCore/statistic.h"
58 #include "MagickCore/string_.h"
59 #include "MagickCore/token.h"
60 #include "MagickCore/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) FormatLocaleString(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) FormatLocaleString(filename,MaxTextExtent,"%s.%s.%s",root,format,
297         extension);
298       return;
299     }
300   GetPathComponent(filename,RootPath,root);
301   (void) FormatLocaleString(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=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
745     if (parameters > 0)
746       {
747         /*
748           Do not expand command option parameters.
749         */
750         for (j=0; j < parameters; j++)
751         {
752           i++;
753           if (i == (ssize_t) *number_arguments)
754             break;
755           option=(*arguments)[i];
756           vector[count++]=ConstantString(option);
757         }
758         continue;
759       }
760     if ((*option == '"') || (*option == '\''))
761       continue;
762     GetPathComponent(option,TailPath,filename);
763     GetPathComponent(option,MagickPath,magick);
764     if ((LocaleCompare(magick,"CAPTION") == 0) ||
765         (LocaleCompare(magick,"LABEL") == 0) ||
766         (LocaleCompare(magick,"VID") == 0))
767       continue;
768     if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
769       continue;
770     if (*filename != '@')
771       {
772         /*
773           Generate file list from wildcard filename (e.g. *.jpg).
774         */
775         GetPathComponent(option,HeadPath,path);
776         GetPathComponent(option,SubimagePath,subimage);
777         ExpandFilename(path);
778         if (*home_directory == '\0')
779           directory=getcwd(home_directory,MaxTextExtent-1);
780         (void) directory;
781         filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
782           &number_files);
783       }
784     else
785       {
786         char
787           *files;
788
789         ExceptionInfo
790           *exception;
791
792         int
793           length;
794
795         /*
796           Generate file list from file list (e.g. @filelist.txt).
797         */
798         exception=AcquireExceptionInfo();
799         files=FileToString(filename+1,~0,exception);
800         exception=DestroyExceptionInfo(exception);
801         if (files == (char *) NULL)
802           continue;
803         filelist=StringToArgv(files,&length);
804         if (filelist == (char **) NULL)
805           continue;
806         files=DestroyString(files);
807         filelist[0]=DestroyString(filelist[0]);
808         for (j=0; j < (ssize_t) (length-1); j++)
809           filelist[j]=filelist[j+1];
810         number_files=(size_t) length-1;
811       }
812     if (filelist == (char **) NULL)
813       continue;
814     for (j=0; j < (ssize_t) number_files; j++)
815       if (IsPathDirectory(filelist[j]) <= 0)
816         break;
817     if (j == (ssize_t) number_files)
818       {
819         for (j=0; j < (ssize_t) number_files; j++)
820           filelist[j]=DestroyString(filelist[j]);
821         filelist=(char **) RelinquishMagickMemory(filelist);
822         continue;
823       }
824     /*
825       Transfer file list to argument vector.
826     */
827     vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
828       count+number_files+1,sizeof(*vector));
829     if (vector == (char **) NULL)
830       return(MagickFalse);
831     for (j=0; j < (ssize_t) number_files; j++)
832     {
833       option=filelist[j];
834       parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
835       if (parameters > 0)
836         {
837           ssize_t
838             k;
839
840           /*
841             Do not expand command option parameters.
842           */
843           vector[count++]=ConstantString(option);
844           for (k=0; k < parameters; k++)
845           {
846             j++;
847             if (j == (ssize_t) number_files)
848               break;
849             option=filelist[j];
850             vector[count++]=ConstantString(option);
851           }
852           continue;
853         }
854       (void) CopyMagickString(filename,path,MaxTextExtent);
855       if (*path != '\0')
856         (void) ConcatenateMagickString(filename,DirectorySeparator,
857           MaxTextExtent);
858       (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
859       filelist[j]=DestroyString(filelist[j]);
860       if (strlen(filename) >= (MaxTextExtent-1))
861         ThrowFatalException(OptionFatalError,"FilenameTruncated");
862       if (IsPathDirectory(filename) <= 0)
863         {
864           char
865             path[MaxTextExtent];
866
867           *path='\0';
868           if (*magick != '\0')
869             {
870               (void) ConcatenateMagickString(path,magick,MaxTextExtent);
871               (void) ConcatenateMagickString(path,":",MaxTextExtent);
872             }
873           (void) ConcatenateMagickString(path,filename,MaxTextExtent);
874           if (*subimage != '\0')
875             {
876               (void) ConcatenateMagickString(path,"[",MaxTextExtent);
877               (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
878               (void) ConcatenateMagickString(path,"]",MaxTextExtent);
879             }
880           if (strlen(path) >= (MaxTextExtent-1))
881             ThrowFatalException(OptionFatalError,"FilenameTruncated");
882           if (destroy != MagickFalse)
883             {
884               count--;
885               vector[count]=DestroyString(vector[count]);
886               destroy=MagickFalse;
887             }
888           vector[count++]=ConstantString(path);
889         }
890     }
891     filelist=(char **) RelinquishMagickMemory(filelist);
892   }
893   vector[count]=(char *) NULL;
894   if (IsEventLogging() != MagickFalse)
895     {
896       char
897         *command_line;
898
899       command_line=AcquireString(vector[0]);
900       for (i=1; i < count; i++)
901       {
902         (void) ConcatenateString(&command_line," {");
903         (void) ConcatenateString(&command_line,vector[i]);
904         (void) ConcatenateString(&command_line,"}");
905       }
906       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
907         "Command line: %s",command_line);
908       command_line=DestroyString(command_line);
909     }
910   *number_arguments=(int) count;
911   *arguments=vector;
912   return(MagickTrue);
913 }
914 \f
915 /*
916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917 %                                                                             %
918 %                                                                             %
919 %                                                                             %
920 %   G e t E x e c u t i o n P a t h                                           %
921 %                                                                             %
922 %                                                                             %
923 %                                                                             %
924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
925 %
926 %  GetExecutionPath() returns the pathname of the executable that started
927 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
928 %
929 %  The format of the GetExecutionPath method is:
930 %
931 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
932 %
933 %  A description of each parameter follows:
934 %
935 %    o path: the pathname of the executable that started the process.
936 %
937 %    o extent: the maximum extent of the path.
938 %
939 */
940 MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
941 {
942   char
943     *directory;
944
945   *path='\0';
946   directory=getcwd(path,(unsigned long) extent);
947   (void) directory;
948 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
949   {
950     char
951       link_path[MaxTextExtent],
952       execution_path[PATH_MAX+1];
953
954     ssize_t
955       count;
956
957     (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe",
958       (double) getpid());
959     count=readlink(link_path,execution_path,PATH_MAX);
960     if (count == -1)
961       {
962         (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file",
963           (double) getpid());
964         count=readlink(link_path,execution_path,PATH_MAX);
965       }
966     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
967       {
968         execution_path[count]='\0';
969         (void) CopyMagickString(path,execution_path,extent);
970       }
971   }
972 #endif
973 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
974   {
975     char
976       executable_path[PATH_MAX << 1],
977       execution_path[PATH_MAX+1];
978
979     uint32_t
980       length;
981
982     length=sizeof(executable_path);
983     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
984         (realpath(executable_path,execution_path) != (char *) NULL))
985       (void) CopyMagickString(path,execution_path,extent);
986   }
987 #endif
988 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
989   {
990     const char
991       *execution_path;
992
993     execution_path=(const char *) getexecname();
994     if (execution_path != (const char *) NULL)
995       {
996         if (*execution_path != *DirectorySeparator)
997           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
998         (void) ConcatenateMagickString(path,execution_path,extent);
999       }
1000   }
1001 #endif
1002 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1003   NTGetExecutionPath(path,extent);
1004 #endif
1005 #if defined(__GNU__)
1006   {
1007     char
1008       *program_name,
1009       *execution_path;
1010
1011     ssize_t
1012       count;
1013
1014     count=0;
1015     execution_path=(char *) NULL;
1016     program_name=program_invocation_name;
1017     if (*program_invocation_name != '/')
1018       {
1019         size_t
1020           extent;
1021
1022         extent=strlen(directory)+strlen(program_name)+2;
1023         program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1024         if (program_name == (char *) NULL)
1025           program_name=program_invocation_name;
1026         else
1027           count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1028             program_invocation_name);
1029       }
1030     if (count != -1)
1031       {
1032         execution_path=realpath(program_name,NULL);
1033         if (execution_path != (char *) NULL)
1034           (void) CopyMagickString(path,execution_path,extent);
1035       }
1036     if (program_name != program_invocation_name)
1037       program_name=(char *) RelinquishMagickMemory(program_name);
1038     execution_path=(char *) RelinquishMagickMemory(execution_path);
1039   }
1040 #endif
1041   return(IsPathAccessible(path));
1042 }
1043 \f
1044 /*
1045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046 %                                                                             %
1047 %                                                                             %
1048 %                                                                             %
1049 %   G e t M a g i c k P a g e S i z e                                         %
1050 %                                                                             %
1051 %                                                                             %
1052 %                                                                             %
1053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054 %
1055 %  GetMagickPageSize() returns the memory page size.
1056 %
1057 %  The format of the GetMagickPageSize method is:
1058 %
1059 %      ssize_t GetMagickPageSize()
1060 %
1061 */
1062 MagickExport ssize_t GetMagickPageSize(void)
1063 {
1064   static ssize_t
1065     page_size = -1;
1066
1067   if (page_size > 0)
1068     return(page_size);
1069 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1070   page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1071 #else
1072 #if defined(MAGICKCORE_HAVE_GETPAGESIZE)
1073   page_size=(ssize_t) getpagesize();
1074 #endif
1075 #endif
1076   if (page_size <= 0)
1077     page_size=16384;
1078   return(page_size);
1079 }
1080 \f
1081 /*
1082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1083 %                                                                             %
1084 %                                                                             %
1085 %                                                                             %
1086 %   G e t P a t h A t t r i b u t e s                                         %
1087 %                                                                             %
1088 %                                                                             %
1089 %                                                                             %
1090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091 %
1092 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
1093 %
1094 %  The path of the GetPathAttributes method is:
1095 %
1096 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1097 %
1098 %  A description of each parameter follows.
1099 %
1100 %   o  path: the file path.
1101 %
1102 %   o  attributes: the path attributes are returned here.
1103 %
1104 */
1105
1106 #if defined(MAGICKCORE_HAVE__WFOPEN)
1107 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
1108 {
1109   register const unsigned char
1110     *p;
1111
1112   if (utf16 != (wchar_t *) NULL)
1113     {
1114       register wchar_t
1115         *q;
1116
1117       wchar_t
1118         c;
1119
1120       /*
1121         Convert UTF-8 to UTF-16.
1122       */
1123       q=utf16;
1124       for (p=utf8; *p != '\0'; p++)
1125       {
1126         if ((*p & 0x80) == 0)
1127           *q=(*p);
1128         else
1129           if ((*p & 0xE0) == 0xC0)
1130             {
1131               c=(*p);
1132               *q=(c & 0x1F) << 6;
1133               p++;
1134               if ((*p & 0xC0) != 0x80)
1135                 return(0);
1136               *q|=(*p & 0x3F);
1137             }
1138           else
1139             if ((*p & 0xF0) == 0xE0)
1140               {
1141                 c=(*p);
1142                 *q=c << 12;
1143                 p++;
1144                 if ((*p & 0xC0) != 0x80)
1145                   return(0);
1146                 c=(*p);
1147                 *q|=(c & 0x3F) << 6;
1148                 p++;
1149                 if ((*p & 0xC0) != 0x80)
1150                   return(0);
1151                 *q|=(*p & 0x3F);
1152               }
1153             else
1154               return(0);
1155         q++;
1156       }
1157       *q++='\0';
1158       return(q-utf16);
1159     }
1160   /*
1161     Compute UTF-16 string length.
1162   */
1163   for (p=utf8; *p != '\0'; p++)
1164   {
1165     if ((*p & 0x80) == 0)
1166       ;
1167     else
1168       if ((*p & 0xE0) == 0xC0)
1169         {
1170           p++;
1171           if ((*p & 0xC0) != 0x80)
1172             return(0);
1173         }
1174       else
1175         if ((*p & 0xF0) == 0xE0)
1176           {
1177             p++;
1178             if ((*p & 0xC0) != 0x80)
1179               return(0);
1180             p++;
1181             if ((*p & 0xC0) != 0x80)
1182               return(0);
1183          }
1184        else
1185          return(0);
1186   }
1187   return(p-utf8);
1188 }
1189
1190 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
1191 {
1192   size_t
1193     length;
1194
1195   wchar_t
1196     *utf16;
1197
1198   length=UTF8ToUTF16(source,(wchar_t *) NULL);
1199   if (length == 0)
1200     {
1201       register ssize_t
1202         i;
1203
1204       /*
1205         Not UTF-8, just copy.
1206       */
1207       length=strlen((const char *) source);
1208       utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
1209       if (utf16 == (wchar_t *) NULL)
1210         return((wchar_t *) NULL);
1211       for (i=0; i <= (ssize_t) length; i++)
1212         utf16[i]=source[i];
1213       return(utf16);
1214     }
1215   utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
1216   if (utf16 == (wchar_t *) NULL)
1217     return((wchar_t *) NULL);
1218   length=UTF8ToUTF16(source,utf16);
1219   return(utf16);
1220 }
1221 #endif
1222
1223 MagickExport MagickBooleanType GetPathAttributes(const char *path,
1224   void *attributes)
1225 {
1226   MagickBooleanType
1227     status;
1228
1229   if (path == (const char *) NULL)
1230     {
1231       errno=EINVAL;
1232       return(MagickFalse);
1233     }
1234 #if !defined(MAGICKCORE_HAVE__WSTAT)
1235   status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
1236 #else
1237   {
1238     int
1239       count;
1240
1241     wchar_t
1242       *unicode_path;
1243
1244     count=MultiByteToWideChar(CP_ACP,0,path,-1,NULL,0);
1245     unicode_path=(wchar_t *) AcquireQuantumMemory(count,sizeof(*unicode_path));
1246     if (unicode_path == (wchar_t *) NULL)
1247       return(MagickFalse);
1248     status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
1249       MagickFalse;
1250     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1251   }
1252 #endif
1253   return(status);
1254 }
1255 \f
1256 /*
1257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258 %                                                                             %
1259 %                                                                             %
1260 %                                                                             %
1261 %   G e t P a t h C o m p o n e n t                                           %
1262 %                                                                             %
1263 %                                                                             %
1264 %                                                                             %
1265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1266 %
1267 %  GetPathComponent() returns the parent directory name, filename, basename, or
1268 %  extension of a file path.
1269 %
1270 %  The format of the GetPathComponent function is:
1271 %
1272 %      GetPathComponent(const char *path,PathType type,char *component)
1273 %
1274 %  A description of each parameter follows:
1275 %
1276 %    o path: Specifies a pointer to a character array that contains the
1277 %      file path.
1278 %
1279 %    o type: Specififies which file path component to return.
1280 %
1281 %    o component: the selected file path component is returned here.
1282 %
1283 */
1284 MagickExport void GetPathComponent(const char *path,PathType type,
1285   char *component)
1286 {
1287   char
1288     magick[MaxTextExtent],
1289     *q,
1290     subimage[MaxTextExtent];
1291
1292   register char
1293     *p;
1294
1295   assert(path != (const char *) NULL);
1296   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1297   assert(component != (char *) NULL);
1298   if (*path == '\0')
1299     {
1300       *component='\0';
1301       return;
1302     }
1303   (void) CopyMagickString(component,path,MaxTextExtent);
1304   *magick='\0';
1305   *subimage='\0';
1306   p=component;
1307   if (*p != '\0')
1308     p=component+strlen(component)-1;
1309   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1310       (IsPathAccessible(path) == MagickFalse))
1311     {
1312       /*
1313         Look for scene specification (e.g. img0001.pcd[4]).
1314       */
1315       for (q=p-1; q > component; q--)
1316         if (*q == '[')
1317           break;
1318       if (*q == '[')
1319         {
1320           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1321           subimage[p-q-1]='\0';
1322           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1323               (IsGeometry(subimage) == MagickFalse))
1324             *subimage='\0';
1325           else
1326             *q='\0';
1327         }
1328     }
1329 #if defined(__OS2__)
1330   if (path[1] != ':')
1331 #endif
1332   for (p=component; *p != '\0'; p++)
1333   {
1334     if ((*p == '%') && (*(p+1) == '['))
1335       {
1336         /*
1337           Skip over %[...].
1338         */
1339         for (p++; (*p != ']') && (*p != '\0'); p++) ;
1340         if (*p == '\0')
1341           break;
1342       }
1343     if ((*p == ':') && (IsPathDirectory(component) < 0) &&
1344         (IsPathAccessible(component) == MagickFalse))
1345       {
1346         /*
1347           Look for image format specification (e.g. ps3:image).
1348         */
1349         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1350         if (IsMagickConflict(magick) != MagickFalse)
1351           *magick='\0';
1352         else
1353           for (q=component; *q != '\0'; q++)
1354             *q=(*++p);
1355         break;
1356       }
1357   }
1358   p=component;
1359   if (*p != '\0')
1360     for (p=component+strlen(component)-1; p > component; p--)
1361       if (IsBasenameSeparator(*p) != MagickFalse)
1362         break;
1363   switch (type)
1364   {
1365     case MagickPath:
1366     {
1367       (void) CopyMagickString(component,magick,MaxTextExtent);
1368       break;
1369     }
1370     case RootPath:
1371     {
1372       for (p=component+(strlen(component)-1); p > component; p--)
1373       {
1374         if (IsBasenameSeparator(*p) != MagickFalse)
1375           break;
1376         if (*p == '.')
1377           break;
1378       }
1379       if (*p == '.')
1380         *p='\0';
1381       break;
1382     }
1383     case HeadPath:
1384     {
1385       *p='\0';
1386       break;
1387     }
1388     case TailPath:
1389     {
1390       if (IsBasenameSeparator(*p) != MagickFalse)
1391         (void) CopyMagickMemory((unsigned char *) component,
1392           (const unsigned char *) (p+1),strlen(p+1)+1);
1393       break;
1394     }
1395     case BasePath:
1396     {
1397       if (IsBasenameSeparator(*p) != MagickFalse)
1398         (void) CopyMagickString(component,p+1,MaxTextExtent);
1399       for (p=component+(strlen(component)-1); p > component; p--)
1400         if (*p == '.')
1401           {
1402             *p='\0';
1403             break;
1404           }
1405       break;
1406     }
1407     case ExtensionPath:
1408     {
1409       if (IsBasenameSeparator(*p) != MagickFalse)
1410         (void) CopyMagickString(component,p+1,MaxTextExtent);
1411       p=component;
1412       if (*p != '\0')
1413         for (p=component+strlen(component)-1; p > component; p--)
1414           if (*p == '.')
1415             break;
1416       *component='\0';
1417       if (*p == '.')
1418         (void) CopyMagickString(component,p+1,MaxTextExtent);
1419       break;
1420     }
1421     case SubimagePath:
1422     {
1423       (void) CopyMagickString(component,subimage,MaxTextExtent);
1424       break;
1425     }
1426     case CanonicalPath:
1427     case UndefinedPath:
1428       break;
1429   }
1430 }
1431 \f
1432 /*
1433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1434 %                                                                             %
1435 %                                                                             %
1436 %                                                                             %
1437 %  G e t P a t h C o m p o n e n t s                                          %
1438 %                                                                             %
1439 %                                                                             %
1440 %                                                                             %
1441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1442 %
1443 %  GetPathComponents() returns a list of path components.
1444 %
1445 %  The format of the GetPathComponents method is:
1446 %
1447 %      char **GetPathComponents(const char *path,
1448 %        size_t *number_componenets)
1449 %
1450 %  A description of each parameter follows:
1451 %
1452 %    o path:  Specifies the string to segment into a list.
1453 %
1454 %    o number_components:  return the number of components in the list
1455 %
1456 */
1457 MagickExport char **GetPathComponents(const char *path,
1458   size_t *number_components)
1459 {
1460   char
1461     **components;
1462
1463   register const char
1464     *p,
1465     *q;
1466
1467   register ssize_t
1468     i;
1469
1470   if (path == (char *) NULL)
1471     return((char **) NULL);
1472   *number_components=1;
1473   for (p=path; *p != '\0'; p++)
1474     if (IsBasenameSeparator(*p))
1475       (*number_components)++;
1476   components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1477     sizeof(*components));
1478   if (components == (char **) NULL)
1479     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1480   p=path;
1481   for (i=0; i < (ssize_t) *number_components; i++)
1482   {
1483     for (q=p; *q != '\0'; q++)
1484       if (IsBasenameSeparator(*q))
1485         break;
1486     components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1487       sizeof(**components));
1488     if (components[i] == (char *) NULL)
1489       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1490     (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1491     p=q+1;
1492   }
1493   components[i]=(char *) NULL;
1494   return(components);
1495 }
1496 \f
1497 /*
1498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1499 %                                                                             %
1500 %                                                                             %
1501 %                                                                             %
1502 %  I s P a t h A c c e s s i b l e                                            %
1503 %                                                                             %
1504 %                                                                             %
1505 %                                                                             %
1506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1507 %
1508 %  IsPathAccessible() returns MagickTrue if the file as defined by the path is
1509 %  accessible.
1510 %
1511 %  The format of the IsPathAccessible method is:
1512 %
1513 %      MagickBooleanType IsPathAccessible(const char *filename)
1514 %
1515 %  A description of each parameter follows.
1516 %
1517 %    o path:  Specifies a path to a file.
1518 %
1519 */
1520 MagickExport MagickBooleanType IsPathAccessible(const char *path)
1521 {
1522   MagickBooleanType
1523     status;
1524
1525   struct stat
1526     attributes;
1527
1528   if ((path == (const char *) NULL) || (*path == '\0'))
1529     return(MagickFalse);
1530   status=GetPathAttributes(path,&attributes);
1531   if (status == MagickFalse)
1532     return(status);
1533   if (S_ISREG(attributes.st_mode) == 0)
1534     return(MagickFalse);
1535   if (access(path,F_OK) != 0)
1536     return(MagickFalse);
1537   return(MagickTrue);
1538 }
1539 \f
1540 /*
1541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1542 %                                                                             %
1543 %                                                                             %
1544 %                                                                             %
1545 +  I s P a t h D i r e c t o r y                                              %
1546 %                                                                             %
1547 %                                                                             %
1548 %                                                                             %
1549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1550 %
1551 %  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
1552 %  if the path represents a directory otherwise 0.
1553 %
1554 %  The format of the IsPathDirectory method is:
1555 %
1556 %      int IsPathDirectory(const char *path)
1557 %
1558 %  A description of each parameter follows.
1559 %
1560 %   o  path:  The directory path.
1561 %
1562 */
1563 static int IsPathDirectory(const char *path)
1564 {
1565   MagickBooleanType
1566     status;
1567
1568   struct stat
1569     attributes;
1570
1571   if ((path == (const char *) NULL) || (*path == '\0'))
1572     return(MagickFalse);
1573   status=GetPathAttributes(path,&attributes);
1574   if (status == MagickFalse)
1575     return(-1);
1576   if (S_ISDIR(attributes.st_mode) == 0)
1577     return(0);
1578   return(1);
1579 }
1580 \f
1581 /*
1582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1583 %                                                                             %
1584 %                                                                             %
1585 %                                                                             %
1586 %   I s M a g i c k T r u e                                                   %
1587 %                                                                             %
1588 %                                                                             %
1589 %                                                                             %
1590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1591 %
1592 %  IsMagickTrue() returns MagickTrue if the value is "true", "on", "yes" or
1593 %  "1".
1594 %
1595 %  The format of the IsMagickTrue method is:
1596 %
1597 %      MagickBooleanType IsMagickTrue(const char *value)
1598 %
1599 %  A description of each parameter follows:
1600 %
1601 %    o option: either MagickTrue or MagickFalse depending on the value
1602 %      parameter.
1603 %
1604 %    o value: Specifies a pointer to a character array.
1605 %
1606 */
1607 MagickExport MagickBooleanType IsMagickTrue(const char *value)
1608 {
1609   if (value == (const char *) NULL)
1610     return(MagickFalse);
1611   if (LocaleCompare(value,"true") == 0)
1612     return(MagickTrue);
1613   if (LocaleCompare(value,"on") == 0)
1614     return(MagickTrue);
1615   if (LocaleCompare(value,"yes") == 0)
1616     return(MagickTrue);
1617   if (LocaleCompare(value,"1") == 0)
1618     return(MagickTrue);
1619   return(MagickFalse);
1620 }
1621 \f
1622 /*
1623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1624 %                                                                             %
1625 %                                                                             %
1626 %                                                                             %
1627 %   L i s t F i l e s                                                         %
1628 %                                                                             %
1629 %                                                                             %
1630 %                                                                             %
1631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1632 %
1633 %  ListFiles() reads the directory specified and returns a list of filenames
1634 %  contained in the directory sorted in ascending alphabetic order.
1635 %
1636 %  The format of the ListFiles function is:
1637 %
1638 %      char **ListFiles(const char *directory,const char *pattern,
1639 %        ssize_t *number_entries)
1640 %
1641 %  A description of each parameter follows:
1642 %
1643 %    o filelist: Method ListFiles returns a list of filenames contained
1644 %      in the directory.  If the directory specified cannot be read or it is
1645 %      a file a NULL list is returned.
1646 %
1647 %    o directory: Specifies a pointer to a text string containing a directory
1648 %      name.
1649 %
1650 %    o pattern: Specifies a pointer to a text string containing a pattern.
1651 %
1652 %    o number_entries:  This integer returns the number of filenames in the
1653 %      list.
1654 %
1655 */
1656
1657 #if defined(__cplusplus) || defined(c_plusplus)
1658 extern "C" {
1659 #endif
1660
1661 static int FileCompare(const void *x,const void *y)
1662 {
1663   register const char
1664     **p,
1665     **q;
1666
1667   p=(const char **) x;
1668   q=(const char **) y;
1669   return(LocaleCompare(*p,*q));
1670 }
1671
1672 #if defined(__cplusplus) || defined(c_plusplus)
1673 }
1674 #endif
1675
1676 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1677   struct dirent **result)
1678 {
1679 #if defined(MAGICKCORE_HAVE_READDIR_R)
1680   return(readdir_r(directory,entry,result));
1681 #else
1682   (void) entry;
1683   errno=0;
1684   *result=readdir(directory);
1685   return(errno);
1686 #endif
1687 }
1688
1689 MagickExport char **ListFiles(const char *directory,const char *pattern,
1690   size_t *number_entries)
1691 {
1692   char
1693     **filelist;
1694
1695   DIR
1696     *current_directory;
1697
1698   struct dirent
1699     *buffer,
1700     *entry;
1701
1702   size_t
1703     max_entries;
1704
1705   /*
1706     Open directory.
1707   */
1708   assert(directory != (const char *) NULL);
1709   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1710   assert(pattern != (const char *) NULL);
1711   assert(number_entries != (size_t *) NULL);
1712   *number_entries=0;
1713   current_directory=opendir(directory);
1714   if (current_directory == (DIR *) NULL)
1715     return((char **) NULL);
1716   /*
1717     Allocate filelist.
1718   */
1719   max_entries=2048;
1720   filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1721     sizeof(*filelist));
1722   if (filelist == (char **) NULL)
1723     {
1724       (void) closedir(current_directory);
1725       return((char **) NULL);
1726     }
1727   /*
1728     Save the current and change to the new directory.
1729   */
1730   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
1731     FILENAME_MAX+1);
1732   if (buffer == (struct dirent *) NULL)
1733     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1734   while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1735          (entry != (struct dirent *) NULL))
1736   {
1737     if (*entry->d_name == '.')
1738       continue;
1739     if ((IsPathDirectory(entry->d_name) > 0) ||
1740 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1741         (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1742 #else
1743         (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1744 #endif
1745       {
1746         if (*number_entries >= max_entries)
1747           {
1748             /*
1749               Extend the file list.
1750             */
1751             max_entries<<=1;
1752             filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1753               max_entries,sizeof(*filelist));
1754             if (filelist == (char **) NULL)
1755               break;
1756           }
1757 #if defined(vms)
1758         {
1759           register char
1760             *p;
1761
1762           p=strchr(entry->d_name,';');
1763           if (p)
1764             *p='\0';
1765           if (*number_entries > 0)
1766             if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1767               continue;
1768         }
1769 #endif
1770         filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1771         (*number_entries)++;
1772       }
1773   }
1774   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1775   (void) closedir(current_directory);
1776   if (filelist == (char **) NULL)
1777     return((char **) NULL);
1778   /*
1779     Sort filelist in ascending order.
1780   */
1781   qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1782     FileCompare);
1783   return(filelist);
1784 }
1785 \f
1786 /*
1787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1788 %                                                                             %
1789 %                                                                             %
1790 %                                                                             %
1791 %   M a g i c k D e l a y                                                     %
1792 %                                                                             %
1793 %                                                                             %
1794 %                                                                             %
1795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1796 %
1797 %  MagickDelay() suspends program execution for the number of milliseconds
1798 %  specified.
1799 %
1800 %  The format of the Delay method is:
1801 %
1802 %      void MagickDelay(const MagickSizeType milliseconds)
1803 %
1804 %  A description of each parameter follows:
1805 %
1806 %    o milliseconds: Specifies the number of milliseconds to delay before
1807 %      returning.
1808 %
1809 */
1810 MagickExport void MagickDelay(const MagickSizeType milliseconds)
1811 {
1812   if (milliseconds == 0)
1813     return;
1814 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
1815   {
1816     struct timespec
1817       timer;
1818
1819     timer.tv_sec=(time_t) (milliseconds/1000);
1820     timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1821     (void) nanosleep(&timer,(struct timespec *) NULL);
1822   }
1823 #elif defined(MAGICKCORE_HAVE_USLEEP)
1824   usleep(1000*milliseconds);
1825 #elif defined(MAGICKCORE_HAVE_SELECT)
1826   {
1827     struct timeval
1828       timer;
1829
1830     timer.tv_sec=(long) milliseconds/1000;
1831     timer.tv_usec=(long) (milliseconds % 1000)*1000;
1832     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1833   }
1834 #elif defined(MAGICKCORE_HAVE_POLL)
1835   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1836 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1837   Sleep((long) milliseconds);
1838 #elif defined(vms)
1839   {
1840     float
1841       timer;
1842
1843     timer=milliseconds/1000.0;
1844     lib$wait(&timer);
1845   }
1846 #elif defined(__BEOS__)
1847   snooze(1000*milliseconds);
1848 #else
1849 # error "Time delay method not defined."
1850 #endif
1851 }
1852 \f
1853 /*
1854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1855 %                                                                             %
1856 %                                                                             %
1857 %                                                                             %
1858 %  M u l t i l i n e C e n s u s                                              %
1859 %                                                                             %
1860 %                                                                             %
1861 %                                                                             %
1862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1863 %
1864 %  MultilineCensus() returns the number of lines within a label.  A line is
1865 %  represented by a \n character.
1866 %
1867 %  The format of the MultilineCenus method is:
1868 %
1869 %      size_t MultilineCensus(const char *label)
1870 %
1871 %  A description of each parameter follows.
1872 %
1873 %   o  label:  This character string is the label.
1874 %
1875 %
1876 */
1877 MagickExport size_t MultilineCensus(const char *label)
1878 {
1879   size_t
1880     number_lines;
1881
1882   /*
1883     Determine the number of lines within this label.
1884   */
1885   if (label == (char *) NULL)
1886     return(0);
1887   for (number_lines=1; *label != '\0'; label++)
1888     if (*label == '\n')
1889       number_lines++;
1890   return(number_lines);
1891 }
1892 \f
1893 /*
1894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1895 %                                                                             %
1896 %                                                                             %
1897 %                                                                             %
1898 %   O p e n M a g i c k S t r e a m                                           %
1899 %                                                                             %
1900 %                                                                             %
1901 %                                                                             %
1902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1903 %
1904 %  OpenMagickStream() opens the file at the specified path and return the
1905 %  associated stream.
1906 %
1907 %  The path of the OpenMagickStream method is:
1908 %
1909 %      FILE *OpenMagickStream(const char *path,const char *mode)
1910 %
1911 %  A description of each parameter follows.
1912 %
1913 %   o  path: the file path.
1914 %
1915 %   o  mode: the file mode.
1916 %
1917 */
1918 MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
1919 {
1920   FILE
1921     *file;
1922
1923   if ((path == (const char *) NULL) || (mode == (const char *) NULL))
1924     {
1925       errno=EINVAL;
1926       return((FILE *) NULL);
1927     }
1928   file=(FILE *) NULL;
1929 #if defined(MAGICKCORE_HAVE__WFOPEN)
1930   {
1931     int
1932       count;
1933
1934     wchar_t
1935       *unicode_mode,
1936       *unicode_path;
1937
1938     count=MultiByteToWideChar(CP_ACP,0,path,-1,NULL,0);
1939     unicode_path=(wchar_t *) AcquireQuantumMemory(count,sizeof(*unicode_path));
1940     if (unicode_path == (wchar_t *) NULL)
1941       return((FILE *) NULL);
1942     count=MultiByteToWideChar(CP_ACP,0,mode,-1,NULL,0);
1943     unicode_mode=(wchar_t *) AcquireQuantumMemory(count,sizeof(*unicode_mode));
1944     if (unicode_mode == (wchar_t *) NULL)
1945       {
1946         unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1947         return((FILE *) NULL);
1948       }
1949     file=_wfopen(unicode_path,unicode_mode);
1950     unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
1951     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1952   }
1953 #endif
1954   if (file == (FILE *) NULL)
1955     file=fopen(path,mode);
1956   return(file);
1957 }
1958 \f
1959 /*
1960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1961 %                                                                             %
1962 %                                                                             %
1963 %                                                                             %
1964 %   S y s t e m C o m m a n d                                                 %
1965 %                                                                             %
1966 %                                                                             %
1967 %                                                                             %
1968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1969 %
1970 %  SystemCommand() executes the specified command and waits until it
1971 %  terminates.  The returned value is the exit status of the command.
1972 %
1973 %  The format of the SystemCommand method is:
1974 %
1975 %      int SystemCommand(const MagickBooleanType asynchronous,
1976 %        const MagickBooleanType verbose,const char *command,
1977 %        ExceptionInfo *exception)
1978 %
1979 %  A description of each parameter follows:
1980 %
1981 %    o asynchronous: a value other than 0 executes the parent program
1982 %      concurrently with the new child process.
1983 %
1984 %    o verbose: a value other than 0 prints the executed command before it is
1985 %      invoked.
1986 %
1987 %    o command: this string is the command to execute.
1988 %
1989 %    o exception: return any errors here.
1990 %
1991 */
1992 MagickExport int SystemCommand(const MagickBooleanType asynchronous,
1993   const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
1994 {
1995   char
1996     **arguments,
1997     *shell_command;
1998
1999   int
2000     number_arguments,
2001     status;
2002
2003   PolicyDomain
2004     domain;
2005
2006   PolicyRights
2007     rights;
2008
2009   register ssize_t
2010     i;
2011
2012   status=(-1);
2013   arguments=StringToArgv(command,&number_arguments);
2014   if (arguments == (char **) NULL)
2015     return(status);
2016   rights=ExecutePolicyRights;
2017   domain=DelegatePolicyDomain;
2018   if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
2019     {
2020       errno=EPERM;
2021       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2022         "NotAuthorized","`%s'",arguments[1]);
2023       for (i=0; i < (ssize_t) number_arguments; i++)
2024         arguments[i]=DestroyString(arguments[i]);
2025       arguments=(char **) RelinquishMagickMemory(arguments);
2026       return(-1);
2027     }
2028   if (verbose != MagickFalse)
2029     {
2030       (void) FormatLocaleFile(stderr,"%s\n",command);
2031       (void) fflush(stderr);
2032     }
2033   shell_command=(char *) command;
2034   if (asynchronous != MagickFalse)
2035     {
2036       shell_command=AcquireString(command);
2037       (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
2038     }
2039 #if defined(MAGICKCORE_POSIX_SUPPORT)
2040 #if !defined(MAGICKCORE_HAVE_EXECVP)
2041   status=system(shell_command);
2042 #else
2043   if ((asynchronous != MagickFalse) || (strspn(shell_command,"&;<>|") == 0))
2044     status=system(shell_command);
2045   else
2046     {
2047       pid_t
2048         child_pid;
2049
2050       /*
2051         Call application directly rather than from a shell.
2052       */
2053       child_pid=fork();
2054       if (child_pid == (pid_t) -1)
2055         status=system(command);
2056       else
2057         if (child_pid == 0)
2058           {
2059             status=execvp(arguments[1],arguments+1);
2060             _exit(1);
2061           }
2062         else
2063           {
2064             int
2065               child_status;
2066
2067             pid_t
2068               pid;
2069
2070             child_status=0;
2071             pid=waitpid(child_pid,&child_status,0);
2072             if (pid == -1)
2073               status=(-1);
2074             else
2075               {
2076                 if (WIFEXITED(child_status) != 0)
2077                   status=WEXITSTATUS(child_status);
2078                 else
2079                   if (WIFSIGNALED(child_status))
2080                     status=(-1);
2081               }
2082           }
2083     }
2084 #endif
2085 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
2086   {
2087     int
2088       mode;
2089
2090     mode=_P_WAIT;
2091     if (asynchronous != MagickFalse)
2092       mode=_P_NOWAIT;
2093     status=spawnvp(mode,arguments[1],(const char **) (arguments+1));
2094   }
2095 #elif defined(macintosh)
2096   status=MACSystemCommand(shell_command);
2097 #elif defined(vms)
2098   status=system(shell_command);
2099 #else
2100 #  error No suitable system() method.
2101 #endif
2102   if (status < 0)
2103     (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
2104       "`%s' (%d)",command,status);
2105   if (shell_command != command)
2106     shell_command=DestroyString(shell_command);
2107   for (i=0; i < (ssize_t) number_arguments; i++)
2108     arguments[i]=DestroyString(arguments[i]);
2109   arguments=(char **) RelinquishMagickMemory(arguments);
2110   return(status);
2111 }