]> granicus.if.org Git - imagemagick/blob - magick/utility.c
(no commit message)
[imagemagick] / magick / utility.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
7 %             U   U    T      I    L        I      T     Y Y                  %
8 %             U   U    T      I    L        I      T      Y                   %
9 %             U   U    T      I    L        I      T      Y                   %
10 %              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore Utility Methods                            %
14 %                                                                             %
15 %                             Software Design                                 %
16 %                               John Cristy                                   %
17 %                              January 1993                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-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=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)
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) FormatMagickString(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) FormatMagickString(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(cwd)+strlen(program_name)+1;
1023         program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1024         if (program_name == (char *) NULL)
1025           program_name=program_invocation_name;
1026         else
1027           count=FormatMagickString(program_name,extent,"%s/%s",cwd,
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     wchar_t
1239       *unicode_path;
1240
1241     unicode_path=ConvertUTF8ToUTF16((const unsigned char *) path);
1242     if (unicode_path == (wchar_t *) NULL)
1243       return(MagickFalse);
1244     status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
1245       MagickFalse;
1246     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1247   }
1248 #endif
1249   return(status);
1250 }
1251 \f
1252 /*
1253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254 %                                                                             %
1255 %                                                                             %
1256 %                                                                             %
1257 %   G e t P a t h C o m p o n e n t                                           %
1258 %                                                                             %
1259 %                                                                             %
1260 %                                                                             %
1261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262 %
1263 %  GetPathComponent() returns the parent directory name, filename, basename, or
1264 %  extension of a file path.
1265 %
1266 %  The format of the GetPathComponent function is:
1267 %
1268 %      GetPathComponent(const char *path,PathType type,char *component)
1269 %
1270 %  A description of each parameter follows:
1271 %
1272 %    o path: Specifies a pointer to a character array that contains the
1273 %      file path.
1274 %
1275 %    o type: Specififies which file path component to return.
1276 %
1277 %    o component: the selected file path component is returned here.
1278 %
1279 */
1280 MagickExport void GetPathComponent(const char *path,PathType type,
1281   char *component)
1282 {
1283   char
1284     magick[MaxTextExtent],
1285     *q,
1286     subimage[MaxTextExtent];
1287
1288   register char
1289     *p;
1290
1291   assert(path != (const char *) NULL);
1292   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1293   assert(component != (char *) NULL);
1294   if (*path == '\0')
1295     {
1296       *component='\0';
1297       return;
1298     }
1299   (void) CopyMagickString(component,path,MaxTextExtent);
1300   *magick='\0';
1301 #if defined(__OS2__)
1302   if (path[1] != ":")
1303 #endif
1304   for (p=component; *p != '\0'; p++)
1305   {
1306     if ((*p == '%') && (*(p+1) == '['))
1307       {
1308         /*
1309           Skip over %[...].
1310         */
1311         for (p++; (*p != ']') && (*p != '\0'); p++) ;
1312         if (*p == '\0')
1313           break;
1314       }
1315     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
1316         (IsPathAccessible(path) == MagickFalse))
1317       {
1318         /*
1319           Look for image format specification (e.g. ps3:image).
1320         */
1321         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1322         if (IsMagickConflict(magick) != MagickFalse)
1323           *magick='\0';
1324         else
1325           for (q=component; *q != '\0'; q++)
1326             *q=(*++p);
1327         break;
1328       }
1329   }
1330   *subimage='\0';
1331   p=component;
1332   if (*p != '\0')
1333     p=component+strlen(component)-1;
1334   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1335       (IsPathAccessible(path) == MagickFalse))
1336     {
1337       /*
1338         Look for scene specification (e.g. img0001.pcd[4]).
1339       */
1340       for (q=p-1; q > component; q--)
1341         if (*q == '[')
1342           break;
1343       if (*q == '[')
1344         {
1345           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1346           subimage[p-q-1]='\0';
1347           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1348               (IsGeometry(subimage) == MagickFalse))
1349             *subimage='\0';
1350           else
1351             *q='\0';
1352         }
1353     }
1354   p=component;
1355   if (*p != '\0')
1356     for (p=component+strlen(component)-1; p > component; p--)
1357       if (IsBasenameSeparator(*p) != MagickFalse)
1358         break;
1359   switch (type)
1360   {
1361     case MagickPath:
1362     {
1363       (void) CopyMagickString(component,magick,MaxTextExtent);
1364       break;
1365     }
1366     case RootPath:
1367     {
1368       for (p=component+(strlen(component)-1); p > component; p--)
1369       {
1370         if (IsBasenameSeparator(*p) != MagickFalse)
1371           break;
1372         if (*p == '.')
1373           break;
1374       }
1375       if (*p == '.')
1376         *p='\0';
1377       break;
1378     }
1379     case HeadPath:
1380     {
1381       *p='\0';
1382       break;
1383     }
1384     case TailPath:
1385     {
1386       if (IsBasenameSeparator(*p) != MagickFalse)
1387         (void) CopyMagickMemory((unsigned char *) component,
1388           (const unsigned char *) (p+1),strlen(p+1)+1);
1389       break;
1390     }
1391     case BasePath:
1392     {
1393       if (IsBasenameSeparator(*p) != MagickFalse)
1394         (void) CopyMagickString(component,p+1,MaxTextExtent);
1395       for (p=component+(strlen(component)-1); p > component; p--)
1396         if (*p == '.')
1397           {
1398             *p='\0';
1399             break;
1400           }
1401       break;
1402     }
1403     case ExtensionPath:
1404     {
1405       if (IsBasenameSeparator(*p) != MagickFalse)
1406         (void) CopyMagickString(component,p+1,MaxTextExtent);
1407       p=component;
1408       if (*p != '\0')
1409         for (p=component+strlen(component)-1; p > component; p--)
1410           if (*p == '.')
1411             break;
1412       *component='\0';
1413       if (*p == '.')
1414         (void) CopyMagickString(component,p+1,MaxTextExtent);
1415       break;
1416     }
1417     case SubimagePath:
1418     {
1419       (void) CopyMagickString(component,subimage,MaxTextExtent);
1420       break;
1421     }
1422     case CanonicalPath:
1423     case UndefinedPath:
1424       break;
1425   }
1426 }
1427 \f
1428 /*
1429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 %                                                                             %
1431 %                                                                             %
1432 %                                                                             %
1433 %  G e t P a t h C o m p o n e n t s                                          %
1434 %                                                                             %
1435 %                                                                             %
1436 %                                                                             %
1437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438 %
1439 %  GetPathComponents() returns a list of path components.
1440 %
1441 %  The format of the GetPathComponents method is:
1442 %
1443 %      char **GetPathComponents(const char *path,
1444 %        size_t *number_componenets)
1445 %
1446 %  A description of each parameter follows:
1447 %
1448 %    o path:  Specifies the string to segment into a list.
1449 %
1450 %    o number_components:  return the number of components in the list
1451 %
1452 */
1453 MagickExport char **GetPathComponents(const char *path,
1454   size_t *number_components)
1455 {
1456   char
1457     **components;
1458
1459   register const char
1460     *p,
1461     *q;
1462
1463   register ssize_t
1464     i;
1465
1466   if (path == (char *) NULL)
1467     return((char **) NULL);
1468   *number_components=1;
1469   for (p=path; *p != '\0'; p++)
1470     if (IsBasenameSeparator(*p))
1471       (*number_components)++;
1472   components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1473     sizeof(*components));
1474   if (components == (char **) NULL)
1475     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1476   p=path;
1477   for (i=0; i < (ssize_t) *number_components; i++)
1478   {
1479     for (q=p; *q != '\0'; q++)
1480       if (IsBasenameSeparator(*q))
1481         break;
1482     components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1483       sizeof(**components));
1484     if (components[i] == (char *) NULL)
1485       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1486     (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1487     p=q+1;
1488   }
1489   components[i]=(char *) NULL;
1490   return(components);
1491 }
1492 \f
1493 /*
1494 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1495 %                                                                             %
1496 %                                                                             %
1497 %                                                                             %
1498 %  I s P a t h A c c e s s i b l e                                            %
1499 %                                                                             %
1500 %                                                                             %
1501 %                                                                             %
1502 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1503 %
1504 %  IsPathAccessible() returns MagickTrue if the file as defined by the path is
1505 %  accessible.
1506 %
1507 %  The format of the IsPathAccessible method is:
1508 %
1509 %      MagickBooleanType IsPathAccessible(const char *filename)
1510 %
1511 %  A description of each parameter follows.
1512 %
1513 %    o path:  Specifies a path to a file.
1514 %
1515 */
1516 MagickExport MagickBooleanType IsPathAccessible(const char *path)
1517 {
1518   MagickBooleanType
1519     status;
1520
1521   struct stat
1522     attributes;
1523
1524   if ((path == (const char *) NULL) || (*path == '\0'))
1525     return(MagickFalse);
1526   status=GetPathAttributes(path,&attributes);
1527   if (status == MagickFalse)
1528     return(status);
1529   if (S_ISREG(attributes.st_mode) == 0)
1530     return(MagickFalse);
1531   if (access(path,F_OK) != 0)
1532     return(MagickFalse);
1533   return(MagickTrue);
1534 }
1535 \f
1536 /*
1537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1538 %                                                                             %
1539 %                                                                             %
1540 %                                                                             %
1541 +  I s P a t h D i r e c t o r y                                              %
1542 %                                                                             %
1543 %                                                                             %
1544 %                                                                             %
1545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1546 %
1547 %  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
1548 %  if the path represents a directory otherwise 0.
1549 %
1550 %  The format of the IsPathDirectory method is:
1551 %
1552 %      int IsPathDirectory(const char *path)
1553 %
1554 %  A description of each parameter follows.
1555 %
1556 %   o  path:  The directory path.
1557 %
1558 */
1559 static int IsPathDirectory(const char *path)
1560 {
1561   MagickBooleanType
1562     status;
1563
1564   struct stat
1565     attributes;
1566
1567   if ((path == (const char *) NULL) || (*path == '\0'))
1568     return(MagickFalse);
1569   status=GetPathAttributes(path,&attributes);
1570   if (status == MagickFalse)
1571     return(-1);
1572   if (S_ISDIR(attributes.st_mode) == 0)
1573     return(0);
1574   return(1);
1575 }
1576 \f
1577 /*
1578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1579 %                                                                             %
1580 %                                                                             %
1581 %                                                                             %
1582 %   I s M a g i c k T r u e                                                   %
1583 %                                                                             %
1584 %                                                                             %
1585 %                                                                             %
1586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1587 %
1588 %  IsMagickTrue() returns MagickTrue if the value is "true", "on", "yes" or
1589 %  "1".
1590 %
1591 %  The format of the IsMagickTrue method is:
1592 %
1593 %      MagickBooleanType IsMagickTrue(const char *value)
1594 %
1595 %  A description of each parameter follows:
1596 %
1597 %    o option: either MagickTrue or MagickFalse depending on the value
1598 %      parameter.
1599 %
1600 %    o value: Specifies a pointer to a character array.
1601 %
1602 */
1603 MagickExport MagickBooleanType IsMagickTrue(const char *value)
1604 {
1605   if (value == (const char *) NULL)
1606     return(MagickFalse);
1607   if (LocaleCompare(value,"true") == 0)
1608     return(MagickTrue);
1609   if (LocaleCompare(value,"on") == 0)
1610     return(MagickTrue);
1611   if (LocaleCompare(value,"yes") == 0)
1612     return(MagickTrue);
1613   if (LocaleCompare(value,"1") == 0)
1614     return(MagickTrue);
1615   return(MagickFalse);
1616 }
1617 \f
1618 /*
1619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1620 %                                                                             %
1621 %                                                                             %
1622 %                                                                             %
1623 %   L i s t F i l e s                                                         %
1624 %                                                                             %
1625 %                                                                             %
1626 %                                                                             %
1627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628 %
1629 %  ListFiles() reads the directory specified and returns a list of filenames
1630 %  contained in the directory sorted in ascending alphabetic order.
1631 %
1632 %  The format of the ListFiles function is:
1633 %
1634 %      char **ListFiles(const char *directory,const char *pattern,
1635 %        ssize_t *number_entries)
1636 %
1637 %  A description of each parameter follows:
1638 %
1639 %    o filelist: Method ListFiles returns a list of filenames contained
1640 %      in the directory.  If the directory specified cannot be read or it is
1641 %      a file a NULL list is returned.
1642 %
1643 %    o directory: Specifies a pointer to a text string containing a directory
1644 %      name.
1645 %
1646 %    o pattern: Specifies a pointer to a text string containing a pattern.
1647 %
1648 %    o number_entries:  This integer returns the number of filenames in the
1649 %      list.
1650 %
1651 */
1652
1653 #if defined(__cplusplus) || defined(c_plusplus)
1654 extern "C" {
1655 #endif
1656
1657 static int FileCompare(const void *x,const void *y)
1658 {
1659   register const char
1660     **p,
1661     **q;
1662
1663   p=(const char **) x;
1664   q=(const char **) y;
1665   return(LocaleCompare(*p,*q));
1666 }
1667
1668 #if defined(__cplusplus) || defined(c_plusplus)
1669 }
1670 #endif
1671
1672 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1673   struct dirent **result)
1674 {
1675 #if defined(MAGICKCORE_HAVE_READDIR_R)
1676   return(readdir_r(directory,entry,result));
1677 #else
1678   (void) entry;
1679   errno=0;
1680   *result=readdir(directory);
1681   return(errno);
1682 #endif
1683 }
1684
1685 MagickExport char **ListFiles(const char *directory,const char *pattern,
1686   size_t *number_entries)
1687 {
1688   char
1689     **filelist;
1690
1691   DIR
1692     *current_directory;
1693
1694   struct dirent
1695     *buffer,
1696     *entry;
1697
1698   size_t
1699     max_entries;
1700
1701   /*
1702     Open directory.
1703   */
1704   assert(directory != (const char *) NULL);
1705   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1706   assert(pattern != (const char *) NULL);
1707   assert(number_entries != (size_t *) NULL);
1708   *number_entries=0;
1709   current_directory=opendir(directory);
1710   if (current_directory == (DIR *) NULL)
1711     return((char **) NULL);
1712   /*
1713     Allocate filelist.
1714   */
1715   max_entries=2048;
1716   filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1717     sizeof(*filelist));
1718   if (filelist == (char **) NULL)
1719     {
1720       (void) closedir(current_directory);
1721       return((char **) NULL);
1722     }
1723   /*
1724     Save the current and change to the new directory.
1725   */
1726   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
1727     FILENAME_MAX+1);
1728   if (buffer == (struct dirent *) NULL)
1729     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1730   while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1731          (entry != (struct dirent *) NULL))
1732   {
1733     if (*entry->d_name == '.')
1734       continue;
1735     if ((IsPathDirectory(entry->d_name) > 0) ||
1736 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1737         (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1738 #else
1739         (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1740 #endif
1741       {
1742         if (*number_entries >= max_entries)
1743           {
1744             /*
1745               Extend the file list.
1746             */
1747             max_entries<<=1;
1748             filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1749               max_entries,sizeof(*filelist));
1750             if (filelist == (char **) NULL)
1751               break;
1752           }
1753 #if defined(vms)
1754         {
1755           register char
1756             *p;
1757
1758           p=strchr(entry->d_name,';');
1759           if (p)
1760             *p='\0';
1761           if (*number_entries > 0)
1762             if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1763               continue;
1764         }
1765 #endif
1766         filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1767         (*number_entries)++;
1768       }
1769   }
1770   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1771   (void) closedir(current_directory);
1772   if (filelist == (char **) NULL)
1773     return((char **) NULL);
1774   /*
1775     Sort filelist in ascending order.
1776   */
1777   qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1778     FileCompare);
1779   return(filelist);
1780 }
1781 \f
1782 /*
1783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1784 %                                                                             %
1785 %                                                                             %
1786 %                                                                             %
1787 %   M a g i c k D e l a y                                                     %
1788 %                                                                             %
1789 %                                                                             %
1790 %                                                                             %
1791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1792 %
1793 %  MagickDelay() suspends program execution for the number of milliseconds
1794 %  specified.
1795 %
1796 %  The format of the Delay method is:
1797 %
1798 %      void MagickDelay(const MagickSizeType milliseconds)
1799 %
1800 %  A description of each parameter follows:
1801 %
1802 %    o milliseconds: Specifies the number of milliseconds to delay before
1803 %      returning.
1804 %
1805 */
1806 MagickExport void MagickDelay(const MagickSizeType milliseconds)
1807 {
1808   if (milliseconds == 0)
1809     return;
1810 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
1811   {
1812     struct timespec
1813       timer;
1814
1815     timer.tv_sec=(time_t) (milliseconds/1000);
1816     timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1817     (void) nanosleep(&timer,(struct timespec *) NULL);
1818   }
1819 #elif defined(MAGICKCORE_HAVE_USLEEP)
1820   usleep(1000*milliseconds);
1821 #elif defined(MAGICKCORE_HAVE_SELECT)
1822   {
1823     struct timeval
1824       timer;
1825
1826     timer.tv_sec=(long) milliseconds/1000;
1827     timer.tv_usec=(long) (milliseconds % 1000)*1000;
1828     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1829   }
1830 #elif defined(MAGICKCORE_HAVE_POLL)
1831   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1832 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1833   Sleep((long) milliseconds);
1834 #elif defined(vms)
1835   {
1836     float
1837       timer;
1838
1839     timer=milliseconds/1000.0;
1840     lib$wait(&timer);
1841   }
1842 #elif defined(__BEOS__)
1843   snooze(1000*milliseconds);
1844 #else
1845 # error "Time delay method not defined."
1846 #endif
1847 }
1848 \f
1849 /*
1850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1851 %                                                                             %
1852 %                                                                             %
1853 %                                                                             %
1854 %  M u l t i l i n e C e n s u s                                              %
1855 %                                                                             %
1856 %                                                                             %
1857 %                                                                             %
1858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1859 %
1860 %  MultilineCensus() returns the number of lines within a label.  A line is
1861 %  represented by a \n character.
1862 %
1863 %  The format of the MultilineCenus method is:
1864 %
1865 %      size_t MultilineCensus(const char *label)
1866 %
1867 %  A description of each parameter follows.
1868 %
1869 %   o  label:  This character string is the label.
1870 %
1871 %
1872 */
1873 MagickExport size_t MultilineCensus(const char *label)
1874 {
1875   size_t
1876     number_lines;
1877
1878   /*
1879     Determine the number of lines within this label.
1880   */
1881   if (label == (char *) NULL)
1882     return(0);
1883   for (number_lines=1; *label != '\0'; label++)
1884     if (*label == '\n')
1885       number_lines++;
1886   return(number_lines);
1887 }
1888 \f
1889 /*
1890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1891 %                                                                             %
1892 %                                                                             %
1893 %                                                                             %
1894 %   O p e n M a g i c k S t r e a m                                           %
1895 %                                                                             %
1896 %                                                                             %
1897 %                                                                             %
1898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1899 %
1900 %  OpenMagickStream() opens the file at the specified path and return the
1901 %  associated stream.
1902 %
1903 %  The path of the OpenMagickStream method is:
1904 %
1905 %      FILE *OpenMagickStream(const char *path,const char *mode)
1906 %
1907 %  A description of each parameter follows.
1908 %
1909 %   o  path: the file path.
1910 %
1911 %   o  mode: the file mode.
1912 %
1913 */
1914 MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
1915 {
1916   FILE
1917     *file;
1918
1919   if ((path == (const char *) NULL) || (mode == (const char *) NULL))
1920     {
1921       errno=EINVAL;
1922       return((FILE *) NULL);
1923     }
1924   file=(FILE *) NULL;
1925 #if defined(MAGICKCORE_HAVE__WFOPEN)
1926   {
1927     wchar_t
1928       *unicode_mode,
1929       *unicode_path;
1930
1931     unicode_path=ConvertUTF8ToUTF16((const unsigned char *) path);
1932     if (unicode_path == (wchar_t *) NULL)
1933       return((FILE *) NULL);
1934     unicode_mode=ConvertUTF8ToUTF16((const unsigned char *) mode);
1935     if (unicode_mode == (wchar_t *) NULL)
1936       {
1937         unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1938         return((FILE *) NULL);
1939       }
1940     file=_wfopen(unicode_path,unicode_mode);
1941     unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
1942     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1943   }
1944 #endif
1945   if (file == (FILE *) NULL)
1946     file=fopen(path,mode);
1947   return(file);
1948 }
1949 \f
1950 /*
1951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1952 %                                                                             %
1953 %                                                                             %
1954 %                                                                             %
1955 %   S y s t e m C o m m a n d                                                 %
1956 %                                                                             %
1957 %                                                                             %
1958 %                                                                             %
1959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1960 %
1961 %  SystemCommand() executes the specified command and waits until it
1962 %  terminates.  The returned value is the exit status of the command.
1963 %
1964 %  The format of the SystemCommand method is:
1965 %
1966 %      int SystemCommand(const MagickBooleanType asynchronous,
1967 %        const MagickBooleanType verbose,const char *command,
1968 %        ExceptionInfo *exception)
1969 %
1970 %  A description of each parameter follows:
1971 %
1972 %    o asynchronous: a value other than 0 executes the parent program
1973 %      concurrently with the new child process.
1974 %
1975 %    o verbose: a value other than 0 prints the executed command before it is
1976 %      invoked.
1977 %
1978 %    o command: this string is the command to execute.
1979 %
1980 %    o exception: return any errors here.
1981 %
1982 */
1983 MagickExport int SystemCommand(const MagickBooleanType asynchronous,
1984   const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
1985 {
1986   char
1987     **arguments,
1988     *shell_command;
1989
1990   int
1991     number_arguments,
1992     status;
1993
1994   PolicyDomain
1995     domain;
1996
1997   PolicyRights
1998     rights;
1999
2000   register ssize_t
2001     i;
2002
2003   status=(-1);
2004   arguments=StringToArgv(command,&number_arguments);
2005   if (arguments == (char **) NULL)
2006     return(status);
2007   rights=ExecutePolicyRights;
2008   domain=DelegatePolicyDomain;
2009   if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
2010     {
2011       errno=EPERM;
2012       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
2013         "NotAuthorized","`%s'",arguments[1]);
2014       for (i=0; i < (ssize_t) number_arguments; i++)
2015         arguments[i]=DestroyString(arguments[i]);
2016       arguments=(char **) RelinquishMagickMemory(arguments);
2017       return(-1);
2018     }
2019   if (verbose != MagickFalse)
2020     {
2021       (void) fprintf(stderr,"%s\n",command);
2022       (void) fflush(stderr);
2023     }
2024   shell_command=(char *) command;
2025   if (asynchronous != MagickFalse)
2026     {
2027       shell_command=AcquireString(command);
2028       (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
2029     }
2030 #if defined(MAGICKCORE_POSIX_SUPPORT)
2031 #if !defined(MAGICKCORE_HAVE_EXECVP)
2032   status=system(shell_command);
2033 #else
2034   if ((asynchronous != MagickFalse) || (strspn(shell_command,"&;<>|") == 0))
2035     status=system(shell_command);
2036   else
2037     {
2038       pid_t
2039         child_pid;
2040
2041       /*
2042         Call application directly rather than from a shell.
2043       */
2044       child_pid=fork();
2045       if (child_pid == (pid_t) -1)
2046         status=system(command);
2047       else
2048         if (child_pid == 0)
2049           {
2050             status=execvp(arguments[1],arguments+1);
2051             _exit(1);
2052           }
2053         else
2054           {
2055             int
2056               child_status;
2057
2058             pid_t
2059               pid;
2060
2061             child_status=0;
2062             pid=waitpid(child_pid,&child_status,0);
2063             if (pid == -1)
2064               status=(-1);
2065             else
2066               {
2067                 if (WIFEXITED(child_status) != 0)
2068                   status=WEXITSTATUS(child_status);
2069                 else
2070                   if (WIFSIGNALED(child_status))
2071                     status=(-1);
2072               }
2073           }
2074     }
2075 #endif
2076 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
2077   {
2078     int
2079       mode;
2080
2081     mode=_P_WAIT;
2082     if (asynchronous != MagickFalse)
2083       mode=_P_NOWAIT;
2084     status=spawnvp(mode,arguments[1],(const char **) (arguments+1));
2085   }
2086 #elif defined(macintosh)
2087   status=MACSystemCommand(shell_command);
2088 #elif defined(vms)
2089   status=system(shell_command);
2090 #else
2091 #  error No suitable system() method.
2092 #endif
2093   if (status < 0)
2094     (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
2095       "`%s' (%d)",command,status);
2096   if (shell_command != command)
2097     shell_command=DestroyString(shell_command);
2098   for (i=0; i < (ssize_t) number_arguments; i++)
2099     arguments[i]=DestroyString(arguments[i]);
2100   arguments=(char **) RelinquishMagickMemory(arguments);
2101   return(status);
2102 }