utility.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
00007 %             U   U    T      I    L        I      T     Y Y                  %
00008 %             U   U    T      I    L        I      T      Y                   %
00009 %             U   U    T      I    L        I      T      Y                   %
00010 %              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
00011 %                                                                             %
00012 %                                                                             %
00013 %                       MagickCore Utility Methods                            %
00014 %                                                                             %
00015 %                             Software Design                                 %
00016 %                               John Cristy                                   %
00017 %                              January 1993                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "magick/studio.h"
00043 #include "magick/property.h"
00044 #include "magick/blob.h"
00045 #include "magick/color.h"
00046 #include "magick/exception.h"
00047 #include "magick/exception-private.h"
00048 #include "magick/geometry.h"
00049 #include "magick/list.h"
00050 #include "magick/log.h"
00051 #include "magick/memory_.h"
00052 #include "magick/option.h"
00053 #include "magick/resource_.h"
00054 #include "magick/semaphore.h"
00055 #include "magick/signature-private.h"
00056 #include "magick/statistic.h"
00057 #include "magick/string_.h"
00058 #include "magick/token.h"
00059 #include "magick/utility.h"
00060 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
00061 #include <mach-o/dyld.h>
00062 #endif
00063 
00064 /*
00065   Static declarations.
00066 */
00067 static const char
00068   Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00069 
00070 /*
00071   Forward declaration.
00072 */
00073 static int
00074   IsPathDirectory(const char *);
00075 
00076 /*
00077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00078 %                                                                             %
00079 %                                                                             %
00080 %                                                                             %
00081 %   A c q u i r e U n i q u e F i l e n a m e                                 %
00082 %                                                                             %
00083 %                                                                             %
00084 %                                                                             %
00085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00086 %
00087 %  AcquireUniqueFilename() replaces the contents of path by a unique path name.
00088 %
00089 %  The format of the AcquireUniqueFilename method is:
00090 %
00091 %      MagickBooleanType AcquireUniqueFilename(char *path)
00092 %
00093 %  A description of each parameter follows.
00094 %
00095 %   o  path:  Specifies a pointer to an array of characters.  The unique path
00096 %      name is returned in this array.
00097 %
00098 */
00099 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
00100 {
00101   int
00102     file;
00103 
00104   file=AcquireUniqueFileResource(path);
00105   if (file == -1)
00106     return(MagickFalse);
00107   file=close(file)-1;
00108   return(MagickTrue);
00109 }
00110 
00111 /*
00112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00113 %                                                                             %
00114 %                                                                             %
00115 %                                                                             %
00116 %   A c q u i r e U n i q u e S ym b o l i c L i n k                          %
00117 %                                                                             %
00118 %                                                                             %
00119 %                                                                             %
00120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00121 %
00122 %  AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified
00123 %  source path and returns MagickTrue on success otherwise MagickFalse.  If the
00124 %  symlink() method fails or is not available, a unique file name is generated
00125 %  and the source file copied to it.  When you are finished with the file, use
00126 %  RelinquishUniqueFilename() to destroy it.
00127 %
00128 %  The format of the AcquireUniqueSymbolicLink method is:
00129 %
00130 %      MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
00131 %        char destination)
00132 %
00133 %  A description of each parameter follows.
00134 %
00135 %   o  source:  the source path.
00136 %
00137 %   o  destination:  the destination path.
00138 %
00139 */
00140 
00141 static inline size_t MagickMin(const size_t x,const size_t y)
00142 {
00143   if (x < y)
00144     return(x);
00145   return(y);
00146 }
00147 
00148 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
00149   char *destination)
00150 {
00151   int
00152     destination_file,
00153     source_file;
00154 
00155   size_t
00156     length,
00157     quantum;
00158 
00159   ssize_t
00160     count;
00161 
00162   struct stat
00163     attributes;
00164 
00165   unsigned char
00166     *buffer;
00167 
00168   assert(source != (const char *) NULL);
00169   assert(destination != (char *) NULL);
00170 #if defined(MAGICKCORE_HAVE_SYMLINK)
00171   (void) AcquireUniqueFilename(destination);
00172   (void) RelinquishUniqueFileResource(destination);
00173   if (*source == *DirectorySeparator)
00174     {
00175       if (symlink(source,destination) == 0)
00176         return(MagickTrue);
00177     }
00178   else
00179     {
00180       char
00181         path[MaxTextExtent];
00182 
00183       *path='\0';
00184       if (getcwd(path,MaxTextExtent) == (char *) NULL)
00185         return(MagickFalse);
00186       (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
00187       (void) ConcatenateMagickString(path,source,MaxTextExtent);
00188       if (symlink(path,destination) == 0)
00189         return(MagickTrue);
00190     }
00191 #endif
00192   destination_file=AcquireUniqueFileResource(destination);
00193   if (destination_file == -1)
00194     return(MagickFalse);
00195   source_file=open(source,O_RDONLY | O_BINARY);
00196   if (source_file == -1)
00197     {
00198       (void) close(destination_file);
00199       (void) RelinquishUniqueFileResource(destination);
00200       return(MagickFalse);
00201     }
00202   quantum=(size_t) MagickMaxBufferExtent;
00203   if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
00204     quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
00205   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
00206   if (buffer == (unsigned char *) NULL)
00207     {
00208       (void) close(source_file);
00209       (void) close(destination_file);
00210       (void) RelinquishUniqueFileResource(destination);
00211       return(MagickFalse);
00212     }
00213   for (length=0; ; )
00214   {
00215     count=(ssize_t) read(source_file,buffer,quantum);
00216     if (count <= 0)
00217       break;
00218     length=(size_t) count;
00219     count=(ssize_t) write(destination_file,buffer,length);
00220     if ((size_t) count != length)
00221       {
00222         (void) close(destination_file);
00223         (void) close(source_file);
00224         buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00225         (void) RelinquishUniqueFileResource(destination);
00226         return(MagickFalse);
00227       }
00228   }
00229   (void) close(destination_file);
00230   (void) close(source_file);
00231   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00232   return(MagickTrue);
00233 }
00234 
00235 /*
00236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00237 %                                                                             %
00238 %                                                                             %
00239 %                                                                             %
00240 %  A p p e n d I m a g e F o r m a t                                          %
00241 %                                                                             %
00242 %                                                                             %
00243 %                                                                             %
00244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00245 %
00246 %  AppendImageFormat() appends the image format type to the filename.  If an
00247 %  extension to the file already exists, it is first removed.
00248 %
00249 %  The format of the AppendImageFormat method is:
00250 %
00251 %      void AppendImageFormat(const char *format,char *filename)
00252 %
00253 %  A description of each parameter follows.
00254 %
00255 %   o  format:  Specifies a pointer to an array of characters.  This the
00256 %      format of the image.
00257 %
00258 %   o  filename:  Specifies a pointer to an array of characters.  The unique
00259 %      file name is returned in this array.
00260 %
00261 */
00262 MagickExport void AppendImageFormat(const char *format,char *filename)
00263 {
00264   char
00265     root[MaxTextExtent];
00266 
00267   assert(format != (char *) NULL);
00268   assert(filename != (char *) NULL);
00269   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00270   if ((*format == '\0') || (*filename == '\0'))
00271     return;
00272   if (LocaleCompare(filename,"-") == 0)
00273     {
00274       char
00275         message[MaxTextExtent];
00276 
00277       (void) FormatMagickString(message,MaxTextExtent,"%s:%s",format,filename);
00278       (void) CopyMagickString(filename,message,MaxTextExtent);
00279       return;
00280     }
00281   GetPathComponent(filename,RootPath,root);
00282   (void) FormatMagickString(filename,MaxTextExtent,"%s.%s",root,format);
00283 }
00284 
00285 /*
00286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00287 %                                                                             %
00288 %                                                                             %
00289 %                                                                             %
00290 %   B a s e 6 4 D e c o d e                                                   %
00291 %                                                                             %
00292 %                                                                             %
00293 %                                                                             %
00294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00295 %
00296 %  Base64Decode() decodes Base64-encoded text and returns its binary
00297 %  equivalent.  NULL is returned if the text is not valid Base64 data, or a
00298 %  memory allocation failure occurs.
00299 %
00300 %  The format of the Base64Decode method is:
00301 %
00302 %      unsigned char *Base64Decode(const char *source,length_t *length)
00303 %
00304 %  A description of each parameter follows:
00305 %
00306 %    o source:  A pointer to a Base64-encoded string.
00307 %
00308 %    o length: the number of bytes decoded.
00309 %
00310 */
00311 MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
00312 {
00313   int
00314     state;
00315 
00316   register const char
00317     *p,
00318     *q;
00319 
00320   register size_t
00321     i;
00322 
00323   unsigned char
00324     *decode;
00325 
00326   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00327   assert(source != (char *) NULL);
00328   assert(length != (size_t *) NULL);
00329   *length=0;
00330   decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
00331     3*sizeof(*decode));
00332   if (decode == (unsigned char *) NULL)
00333     return((unsigned char *) NULL);
00334   i=0;
00335   state=0;
00336   for (p=source; *p != '\0'; p++)
00337   {
00338     if (isspace((int) ((unsigned char) *p)) != 0)
00339       continue;
00340     if (*p == '=')
00341       break;
00342     q=strchr(Base64,*p);
00343     if (q == (char *) NULL)
00344       {
00345         decode=(unsigned char *) RelinquishMagickMemory(decode);
00346         return((unsigned char *) NULL);  /* non-Base64 character */
00347       }
00348     switch (state)
00349     {
00350       case 0:
00351       {
00352         decode[i]=(q-Base64) << 2;
00353         state++;
00354         break;
00355       }
00356       case 1:
00357       {
00358         decode[i++]|=(q-Base64) >> 4;
00359         decode[i]=((q-Base64) & 0x0f) << 4;
00360         state++;
00361         break;
00362       }
00363       case 2:
00364       {
00365         decode[i++]|=(q-Base64) >> 2;
00366         decode[i]=((q-Base64) & 0x03) << 6;
00367         state++;
00368         break;
00369       }
00370       case 3:
00371       {
00372         decode[i++]|=(q-Base64);
00373         state=0;
00374         break;
00375       }
00376     }
00377   }
00378   /*
00379     Verify Base-64 string has proper terminal characters.
00380   */
00381   if (*p != '=')
00382     {
00383       if (state != 0)
00384         {
00385           decode=(unsigned char *) RelinquishMagickMemory(decode);
00386           return((unsigned char *) NULL);
00387         }
00388     }
00389   else
00390     {
00391       p++;
00392       switch (state)
00393       {
00394         case 0:
00395         case 1:
00396         {
00397           /*
00398             Unrecognized '=' character.
00399           */
00400           decode=(unsigned char *) RelinquishMagickMemory(decode);
00401           return((unsigned char *) NULL);
00402         }
00403         case 2:
00404         {
00405           for ( ; *p != '\0'; p++)
00406             if (isspace((int) ((unsigned char) *p)) == 0)
00407               break;
00408           if (*p != '=')
00409             {
00410               decode=(unsigned char *) RelinquishMagickMemory(decode);
00411               return((unsigned char *) NULL);
00412             }
00413           p++;
00414         }
00415         case 3:
00416         {
00417           for ( ; *p != '\0'; p++)
00418             if (isspace((int) ((unsigned char) *p)) == 0)
00419               {
00420                 decode=(unsigned char *) RelinquishMagickMemory(decode);
00421                 return((unsigned char *) NULL);
00422               }
00423           if ((int) decode[i] != 0)
00424             {
00425               decode=(unsigned char *) RelinquishMagickMemory(decode);
00426               return((unsigned char *) NULL);
00427             }
00428         }
00429       }
00430     }
00431   *length=i;
00432   return(decode);
00433 }
00434 
00435 /*
00436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00437 %                                                                             %
00438 %                                                                             %
00439 %                                                                             %
00440 %   B a s e 6 4 E n c o d e                                                   %
00441 %                                                                             %
00442 %                                                                             %
00443 %                                                                             %
00444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00445 %
00446 %  Base64Encode() encodes arbitrary binary data to Base64 encoded format as
00447 %  described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and
00448 %  returns the result as a null-terminated ASCII string.  NULL is returned if
00449 %  a memory allocation failure occurs.
00450 %
00451 %  The format of the Base64Encode method is:
00452 %
00453 %      char *Base64Encode(const unsigned char *blob,const size_t blob_length,
00454 %        size_t *encode_length)
00455 %
00456 %  A description of each parameter follows:
00457 %
00458 %    o blob:  A pointer to binary data to encode.
00459 %
00460 %    o blob_length: the number of bytes to encode.
00461 %
00462 %    o encode_length:  The number of bytes encoded.
00463 %
00464 */
00465 MagickExport char *Base64Encode(const unsigned char *blob,
00466   const size_t blob_length,size_t *encode_length)
00467 {
00468   char
00469     *encode;
00470 
00471   register const unsigned char
00472     *p;
00473 
00474   register size_t
00475     i;
00476 
00477   size_t
00478     remainder;
00479 
00480   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00481   assert(blob != (const unsigned char *) NULL);
00482   assert(blob_length != 0);
00483   assert(encode_length != (size_t *) NULL);
00484   *encode_length=0;
00485   encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
00486   if (encode == (char *) NULL)
00487     return((char *) NULL);
00488   i=0;
00489   for (p=blob; p < (blob+blob_length-2); p+=3)
00490   {
00491     encode[i++]=Base64[(int) (*p >> 2)];
00492     encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
00493     encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
00494     encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
00495   }
00496   remainder=blob_length % 3;
00497   if (remainder != 0)
00498     {
00499       long
00500         j;
00501 
00502       unsigned char
00503         code[3];
00504 
00505       code[0]='\0';
00506       code[1]='\0';
00507       code[2]='\0';
00508       for (j=0; j < (long) remainder; j++)
00509         code[j]=(*p++);
00510       encode[i++]=Base64[(int) (code[0] >> 2)];
00511       encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
00512       if (remainder == 1)
00513         encode[i++]='=';
00514       else
00515         encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
00516       encode[i++]='=';
00517     }
00518   *encode_length=i;
00519   encode[i++]='\0';
00520   return(encode);
00521 }
00522 
00523 /*
00524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00525 %                                                                             %
00526 %                                                                             %
00527 %                                                                             %
00528 %   C h o p P a t h C o m p o n e n t s                                       %
00529 %                                                                             %
00530 %                                                                             %
00531 %                                                                             %
00532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00533 %
00534 %  ChopPathComponents() removes the number of specified file components from a
00535 %  path.
00536 %
00537 %  The format of the ChopPathComponents method is:
00538 %
00539 %      ChopPathComponents(char *path,unsigned long components)
00540 %
00541 %  A description of each parameter follows:
00542 %
00543 %    o path:  The path.
00544 %
00545 %    o components:  The number of components to chop.
00546 %
00547 */
00548 MagickExport void ChopPathComponents(char *path,const unsigned long components)
00549 {
00550   register long
00551     i;
00552 
00553   for (i=0; i < (long) components; i++)
00554     GetPathComponent(path,HeadPath,path);
00555 }
00556 
00557 /*
00558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00559 %                                                                             %
00560 %                                                                             %
00561 %                                                                             %
00562 %   E x p a n d F i l e n a m e                                               %
00563 %                                                                             %
00564 %                                                                             %
00565 %                                                                             %
00566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00567 %
00568 %  ExpandFilename() expands '~' in a path.
00569 %
00570 %  The format of the ExpandFilename function is:
00571 %
00572 %      ExpandFilename(char *path)
00573 %
00574 %  A description of each parameter follows:
00575 %
00576 %    o path: Specifies a pointer to a character array that contains the
00577 %      path.
00578 %
00579 */
00580 MagickExport void ExpandFilename(char *path)
00581 {
00582   char
00583     expand_path[MaxTextExtent];
00584 
00585   if (path == (char *) NULL)
00586     return;
00587   if (*path != '~')
00588     return;
00589   (void) CopyMagickString(expand_path,path,MaxTextExtent);
00590   if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
00591     {
00592       char
00593         *home;
00594 
00595       /*
00596         Substitute ~ with $HOME.
00597       */
00598       (void) CopyMagickString(expand_path,".",MaxTextExtent);
00599       (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00600       home=GetEnvironmentValue("HOME");
00601       if (home == (char *) NULL)
00602         home=GetEnvironmentValue("USERPROFILE");
00603       if (home != (char *) NULL)
00604         {
00605           (void) CopyMagickString(expand_path,home,MaxTextExtent);
00606           (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00607           home=DestroyString(home);
00608         }
00609     }
00610   else
00611     {
00612 #if defined(MAGICKCORE_POSIX_SUPPORT)
00613       char
00614         username[MaxTextExtent];
00615 
00616       register char
00617         *p;
00618 
00619       struct passwd
00620         *entry;
00621 
00622       /*
00623         Substitute ~ with home directory from password file.
00624       */
00625       (void) CopyMagickString(username,path+1,MaxTextExtent);
00626       p=strchr(username,'/');
00627       if (p != (char *) NULL)
00628         *p='\0';
00629       entry=getpwnam(username);
00630       if (entry == (struct passwd *) NULL)
00631         return;
00632       (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
00633       if (p != (char *) NULL)
00634         {
00635           (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
00636           (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
00637         }
00638 #endif
00639     }
00640   (void) CopyMagickString(path,expand_path,MaxTextExtent);
00641 }
00642 
00643 /*
00644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00645 %                                                                             %
00646 %                                                                             %
00647 %                                                                             %
00648 %   E x p a n d F i l e n a m e s                                             %
00649 %                                                                             %
00650 %                                                                             %
00651 %                                                                             %
00652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00653 %
00654 %  ExpandFilenames() checks each argument of the command line vector and
00655 %  expands it if they have a wildcard character.  For example, *.jpg might
00656 %  expand to:  bird.jpg rose.jpg tiki.jpg.
00657 %
00658 %  The format of the ExpandFilenames function is:
00659 %
00660 %      status=ExpandFilenames(int *number_arguments,char ***arguments)
00661 %
00662 %  A description of each parameter follows:
00663 %
00664 %    o number_arguments: Specifies a pointer to an integer describing the
00665 %      number of elements in the argument vector.
00666 %
00667 %    o arguments: Specifies a pointer to a text array containing the command
00668 %      line arguments.
00669 %
00670 */
00671 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
00672   char ***arguments)
00673 {
00674   char
00675     home_directory[MaxTextExtent],
00676     **vector;
00677 
00678   long
00679     count,
00680     parameters;
00681 
00682   register long
00683     i,
00684     j;
00685 
00686   unsigned long
00687     number_files;
00688 
00689   /*
00690     Allocate argument vector.
00691   */
00692   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00693   assert(number_arguments != (int *) NULL);
00694   assert(arguments != (char ***) NULL);
00695   vector=(char **) AcquireQuantumMemory(*number_arguments+1UL,sizeof(*vector));
00696   if (vector == (char **) NULL)
00697     return(MagickFalse);
00698   /*
00699     Expand any wildcard filenames.
00700   */
00701   if (getcwd(home_directory,MaxTextExtent) == (char *) NULL)
00702     return(MagickFalse);
00703   count=0;
00704   for (i=0; i < (long) *number_arguments; i++)
00705   {
00706     char
00707       **filelist,
00708       filename[MaxTextExtent],
00709       magick[MaxTextExtent],
00710       *option,
00711       path[MaxTextExtent],
00712       subimage[MaxTextExtent];
00713 
00714     MagickBooleanType
00715       destroy;
00716 
00717     option=(*arguments)[i];
00718     vector[count++]=ConstantString(option);
00719     destroy=MagickTrue;
00720     parameters=ParseMagickOption(MagickCommandOptions,MagickFalse,option);
00721     if (parameters > 0)
00722       {
00723         /*
00724           Do not expand command option parameters.
00725         */
00726         for (j=0; j < parameters; j++)
00727         {
00728           i++;
00729           if (i == (long) *number_arguments)
00730             break;
00731           option=(*arguments)[i];
00732           vector[count++]=ConstantString(option);
00733         }
00734         continue;
00735       }
00736     if ((*option == '"') || (*option == '\''))
00737       continue;
00738     GetPathComponent(option,TailPath,filename);
00739     if (IsGlob(filename) == MagickFalse)
00740       continue;
00741     GetPathComponent(option,MagickPath,magick);
00742     if ((LocaleCompare(magick,"CAPTION") == 0) ||
00743         (LocaleCompare(magick,"LABEL") == 0) ||
00744         (LocaleCompare(magick,"VID") == 0))
00745       continue;
00746     GetPathComponent(option,HeadPath,path);
00747     GetPathComponent(option,SubimagePath,subimage);
00748     ExpandFilename(path);
00749     filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
00750       &number_files);
00751     if (filelist == (char **) NULL)
00752       continue;
00753     for (j=0; j < (long) number_files; j++)
00754       if (IsPathDirectory(filelist[j]) <= 0)
00755         break;
00756     if (j == (long) number_files)
00757       {
00758         for (j=0; j < (long) number_files; j++)
00759           filelist[j]=DestroyString(filelist[j]);
00760         filelist=(char **) RelinquishMagickMemory(filelist);
00761         continue;
00762       }
00763     /*
00764       Transfer file list to argument vector.
00765     */
00766     vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
00767       count+number_files+1,sizeof(*vector));
00768     if (vector == (char **) NULL)
00769       return(MagickFalse);
00770     for (j=0; j < (long) number_files; j++)
00771     {
00772       (void) CopyMagickString(filename,path,MaxTextExtent);
00773       if (*path != '\0')
00774         (void) ConcatenateMagickString(filename,DirectorySeparator,
00775           MaxTextExtent);
00776       (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
00777       filelist[j]=DestroyString(filelist[j]);
00778       if (strlen(filename) >= MaxTextExtent)
00779         ThrowFatalException(OptionFatalError,"FilenameTruncated");
00780       if (IsPathAccessible(filename) != MagickFalse)
00781         {
00782           char
00783             path[MaxTextExtent];
00784 
00785           *path='\0';
00786           if (*magick != '\0')
00787             {
00788               (void) ConcatenateMagickString(path,magick,MaxTextExtent);
00789               (void) ConcatenateMagickString(path,":",MaxTextExtent);
00790             }
00791           (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00792           if (*subimage != '\0')
00793             {
00794               (void) ConcatenateMagickString(path,"[",MaxTextExtent);
00795               (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
00796               (void) ConcatenateMagickString(path,"]",MaxTextExtent);
00797             }
00798           if (strlen(path) >= MaxTextExtent)
00799             ThrowFatalException(OptionFatalError,"FilenameTruncated");
00800           if (destroy != MagickFalse)
00801             {
00802               count--;
00803               vector[count]=DestroyString(vector[count]);
00804               destroy=MagickFalse;
00805             }
00806           vector[count++]=ConstantString(path);
00807         }
00808     }
00809     filelist=(char **) RelinquishMagickMemory(filelist);
00810   }
00811   vector[count]=(char *) NULL;
00812   if (IsEventLogging() != MagickFalse)
00813     {
00814       char
00815         *command_line;
00816 
00817       command_line=AcquireString(vector[0]);
00818       for (i=1; i < count; i++)
00819       {
00820         (void) ConcatenateString(&command_line," {");
00821         (void) ConcatenateString(&command_line,vector[i]);
00822         (void) ConcatenateString(&command_line,"}");
00823       }
00824       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00825         "Command line: %s",command_line);
00826       command_line=DestroyString(command_line);
00827     }
00828   *number_arguments=(int) count;
00829   *arguments=vector;
00830   return(MagickTrue);
00831 }
00832 
00833 /*
00834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00835 %                                                                             %
00836 %                                                                             %
00837 %                                                                             %
00838 %   G e t E x e c u t i o n P a t h                                           %
00839 %                                                                             %
00840 %                                                                             %
00841 %                                                                             %
00842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00843 %
00844 %  GetExecutionPath() returns the pathname of the executable that started
00845 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
00846 %
00847 %  The format of the GetExecutionPath method is:
00848 %
00849 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00850 %
00851 %  A description of each parameter follows:
00852 %
00853 %    o path: the pathname of the executable that started the process.
00854 %
00855 %    o extent: the maximum extent of the path.
00856 %
00857 */
00858 MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00859 {
00860   char
00861     *cwd;
00862 
00863   *path='\0';
00864   cwd=getcwd(path,(unsigned long) extent);
00865 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK)
00866   {
00867     char
00868       link_path[MaxTextExtent],
00869       real_path[PATH_MAX+1];
00870 
00871     ssize_t
00872       count;
00873 
00874     (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/exe",
00875       (long) getpid());
00876     count=readlink(link_path,real_path,PATH_MAX);
00877     if (count == -1)
00878       {
00879         (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/file",
00880           (long) getpid());
00881         count=readlink(link_path,real_path,PATH_MAX);
00882       }
00883     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
00884       {
00885         real_path[count]='\0';
00886         (void) CopyMagickString(path,real_path,extent);
00887       }
00888   }
00889 #endif
00890 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
00891   {
00892     char
00893       executable_path[PATH_MAX << 1],
00894       real_path[PATH_MAX+1];
00895 
00896     uint32_t
00897       length;
00898 
00899     length=sizeof(executable_path);
00900     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
00901         (realpath(executable_path,real_path) != (char *) NULL))
00902       (void) CopyMagickString(path,real_path,extent);
00903   }
00904 #endif
00905 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
00906   {
00907     const char
00908       *execution_path;
00909 
00910     execution_path=(const char *) getexecname();
00911     if (execution_path != (const char *) NULL)
00912       {
00913         if (*execution_path != *DirectorySeparator)
00914           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
00915         (void) ConcatenateMagickString(path,execution_path,extent);
00916       }
00917   }
00918 #endif
00919 #if defined(__WINDOWS__)
00920   NTGetExecutionPath(path,extent);
00921 #endif
00922   return(IsPathAccessible(path));
00923 }
00924 
00925 /*
00926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00927 %                                                                             %
00928 %                                                                             %
00929 %                                                                             %
00930 %   G e t P a t h A t t r i b u t e s                                         %
00931 %                                                                             %
00932 %                                                                             %
00933 %                                                                             %
00934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00935 %
00936 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
00937 %
00938 %  The path of the GetPathAttributes method is:
00939 %
00940 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
00941 %
00942 %  A description of each parameter follows.
00943 %
00944 %   o  path: the file path.
00945 %
00946 %   o  attributes: the path attributes are returned here.
00947 %
00948 */
00949 
00950 #if defined(MAGICKCORE_HAVE__WFOPEN)
00951 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
00952 {
00953   register const unsigned char
00954     *p;
00955 
00956   if (utf16 != (wchar_t *) NULL)
00957     {
00958       register wchar_t
00959         *q;
00960 
00961       wchar_t
00962         c;
00963 
00964       /*
00965         Convert UTF-8 to UTF-16.
00966       */
00967       q=utf16;
00968       for (p=utf8; *p != '\0'; p++)
00969       {
00970         if ((*p & 0x80) == 0)
00971           *q=(*p);
00972         else
00973           if ((*p & 0xE0) == 0xC0)
00974             {
00975               c=(*p);
00976               *q=(c & 0x1F) << 6;
00977               p++;
00978               if ((*p & 0xC0) != 0x80)
00979                 return(0);
00980               *q|=(*p & 0x3F);
00981             }
00982           else
00983             if ((*p & 0xF0) == 0xE0)
00984               {
00985                 c=(*p);
00986                 *q=c << 12;
00987                 p++;
00988                 if ((*p & 0xC0) != 0x80)
00989                   return(0);
00990                 c=(*p);
00991                 *q|=(c & 0x3F) << 6;
00992                 p++;
00993                 if ((*p & 0xC0) != 0x80)
00994                   return(0);
00995                 *q|=(*p & 0x3F);
00996               }
00997             else
00998               return(0);
00999         q++;
01000       }
01001       *q++='\0';
01002       return(q-utf16);
01003     }
01004   /*
01005     Compute UTF-16 string length.
01006   */
01007   for (p=utf8; *p != '\0'; p++)
01008   {
01009     if ((*p & 0x80) == 0)
01010       ;
01011     else
01012       if ((*p & 0xE0) == 0xC0)
01013         {
01014           p++;
01015           if ((*p & 0xC0) != 0x80)
01016             return(0);
01017         }
01018       else
01019         if ((*p & 0xF0) == 0xE0)
01020           {
01021             p++;
01022             if ((*p & 0xC0) != 0x80)
01023               return(0);
01024             p++;
01025             if ((*p & 0xC0) != 0x80)
01026               return(0);
01027          }
01028        else
01029          return(0);
01030   }
01031   return(p-utf8);
01032 }
01033 
01034 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
01035 {
01036   size_t
01037     length;
01038 
01039   wchar_t
01040     *utf16;
01041 
01042   length=UTF8ToUTF16(source,(wchar_t *) NULL);
01043   if (length == 0)
01044     {
01045       register long
01046         i;
01047 
01048       /*
01049         Not UTF-8, just copy.
01050       */
01051       length=strlen(source);
01052       utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01053       if (utf16 == (wchar_t *) NULL)
01054         return((wchar_t *) NULL);
01055       for (i=0; i <= (long) length; i++)
01056         utf16[i]=source[i];
01057       return(utf16);
01058     }
01059   utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01060   if (utf16 == (wchar_t *) NULL)
01061     return((wchar_t *) NULL);
01062   length=UTF8ToUTF16(source,utf16);
01063   return(utf16);
01064 }
01065 #endif
01066 
01067 MagickExport MagickBooleanType GetPathAttributes(const char *path,
01068   void *attributes)
01069 {
01070   MagickBooleanType
01071     status;
01072 
01073   if (path == (const char *) NULL)
01074     {
01075       errno=EINVAL;
01076       return(MagickFalse);
01077     }
01078 #if !defined(MAGICKCORE_HAVE__WFOPEN)
01079   status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
01080 #else
01081   {
01082     wchar_t
01083       *unicode_path;
01084 
01085     unicode_path=ConvertUTF8ToUTF16(path);
01086     if (unicode_path == (wchar_t *) NULL)
01087       return(MagickFalse);
01088     status=_wstat(unicode_path,(struct _stat *) attributes) == 0 ? MagickTrue :
01089       MagickFalse;
01090     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01091   }
01092 #endif
01093   return(status);
01094 }
01095 
01096 /*
01097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01098 %                                                                             %
01099 %                                                                             %
01100 %                                                                             %
01101 %   G e t P a t h C o m p o n e n t                                           %
01102 %                                                                             %
01103 %                                                                             %
01104 %                                                                             %
01105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01106 %
01107 %  GetPathComponent() returns the parent directory name, filename, basename, or
01108 %  extension of a file path.
01109 %
01110 %  The format of the GetPathComponent function is:
01111 %
01112 %      GetPathComponent(const char *path,PathType type,char *component)
01113 %
01114 %  A description of each parameter follows:
01115 %
01116 %    o path: Specifies a pointer to a character array that contains the
01117 %      file path.
01118 %
01119 %    o type: Specififies which file path component to return.
01120 %
01121 %    o component: the selected file path component is returned here.
01122 %
01123 */
01124 MagickExport void GetPathComponent(const char *path,PathType type,
01125   char *component)
01126 {
01127   char
01128     magick[MaxTextExtent],
01129     *q,
01130     subimage[MaxTextExtent];
01131 
01132   register char
01133     *p;
01134 
01135   assert(path != (const char *) NULL);
01136   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
01137   assert(component != (char *) NULL);
01138   if (*path == '\0')
01139     {
01140       *component='\0';
01141       return;
01142     }
01143   (void) CopyMagickString(component,path,MaxTextExtent);
01144   *magick='\0';
01145   for (p=component; *p != '\0'; p++)
01146     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
01147         (IsPathAccessible(path) == MagickFalse))
01148       {
01149         /*
01150           Look for image format specification (e.g. ps3:image).
01151         */
01152         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
01153         if (IsMagickConflict(magick) != MagickFalse)
01154           *magick='\0';
01155         else
01156           for (q=component; *q != '\0'; q++)
01157             *q=(*++p);
01158         break;
01159       }
01160   *subimage='\0';
01161   p=component;
01162   if (*p != '\0')
01163     p=component+strlen(component)-1;
01164   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
01165       (IsPathAccessible(path) == MagickFalse))
01166     {
01167       /*
01168         Look for scene specification (e.g. img0001.pcd[4]).
01169       */
01170       for (q=p-1; q > component; q--)
01171         if (*q == '[')
01172           break;
01173       if (*q == '[')
01174         {
01175           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
01176           subimage[p-q-1]='\0';
01177           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
01178               (IsGeometry(subimage) == MagickFalse))
01179             *subimage='\0';
01180           else
01181             *q='\0';
01182         }
01183     }
01184   p=component;
01185   if (*p != '\0')
01186     for (p=component+strlen(component)-1; p > component; p--)
01187       if (IsBasenameSeparator(*p) != MagickFalse)
01188         break;
01189   switch (type)
01190   {
01191     case MagickPath:
01192     {
01193       (void) CopyMagickString(component,magick,MaxTextExtent);
01194       break;
01195     }
01196     case RootPath:
01197     {
01198       for (p=component+(strlen(component)-1); p > component; p--)
01199       {
01200         if (IsBasenameSeparator(*p) != MagickFalse)
01201           break;
01202         if (*p == '.')
01203           break;
01204       }
01205       if (*p == '.')
01206         *p='\0';
01207       break;
01208     }
01209     case HeadPath:
01210     {
01211       *p='\0';
01212       break;
01213     }
01214     case TailPath:
01215     {
01216       if (IsBasenameSeparator(*p) != MagickFalse)
01217         (void) CopyMagickMemory((unsigned char *) component,
01218           (const unsigned char *) (p+1),strlen(p+1)+1);
01219       break;
01220     }
01221     case BasePath:
01222     {
01223       if (IsBasenameSeparator(*p) != MagickFalse)
01224         (void) CopyMagickString(component,p+1,MaxTextExtent);
01225       for (p=component+(strlen(component)-1); p