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