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