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