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