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-2008 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 *argc,char ***argv)
00661 %
00662 %  A description of each parameter follows:
00663 %
00664 %    o argc: Specifies a pointer to an integer describing the number of
00665 %      elements in the argument vector.
00666 %
00667 %    o argv: Specifies a pointer to a text array containing the command line
00668 %      arguments.
00669 %
00670 */
00671 MagickExport MagickBooleanType ExpandFilenames(int *argc,char ***argv)
00672 {
00673   char
00674     **filelist,
00675     filename[MaxTextExtent],
00676     home_directory[MaxTextExtent],
00677     magick[MaxTextExtent],
00678     *option,
00679     path[MaxTextExtent],
00680     subimage[MaxTextExtent],
00681     **vector;
00682 
00683   long
00684     count,
00685     parameters;
00686 
00687   register long
00688     i,
00689     j;
00690 
00691   unsigned long
00692     number_files;
00693 
00694   /*
00695     Allocate argument vector.
00696   */
00697   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00698   assert(argc != (int *) NULL);
00699   assert(argv != (char ***) NULL);
00700   vector=(char **) AcquireQuantumMemory(*argc+1UL,sizeof(*vector));
00701   if (vector == (char **) NULL)
00702     return(MagickFalse);
00703   /*
00704     Expand any wildcard filenames.
00705   */
00706   if (getcwd(home_directory,MaxTextExtent) == (char *) NULL)
00707     return(MagickFalse);
00708   count=0;
00709   for (i=0; i < (long) *argc; i++)
00710   {
00711     option=(*argv)[i];
00712     vector[count++]=ConstantString(option);
00713     parameters=ParseMagickOption(MagickCommandOptions,MagickFalse,option);
00714     if (parameters > 0)
00715       {
00716         /*
00717           Do not expand command option parameters.
00718         */
00719         for (j=0; j < parameters; j++)
00720         {
00721           i++;
00722           if (i == (long) *argc)
00723             break;
00724           option=(*argv)[i];
00725           vector[count++]=ConstantString(option);
00726         }
00727         continue;
00728       }
00729     if ((*option == '"') || (*option == '\''))
00730       continue;
00731     GetPathComponent(option,TailPath,filename);
00732     if (IsGlob(filename) == MagickFalse)
00733       continue;
00734     GetPathComponent(option,MagickPath,magick);
00735     if ((LocaleCompare(magick,"CAPTION") == 0) ||
00736         (LocaleCompare(magick,"LABEL") == 0) ||
00737         (LocaleCompare(magick,"VID") == 0))
00738       continue;
00739     GetPathComponent(option,HeadPath,path);
00740     GetPathComponent(option,SubimagePath,subimage);
00741     ExpandFilename(path);
00742     filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
00743       &number_files);
00744     if (filelist == (char **) NULL)
00745       continue;
00746     for (j=0; j < (long) number_files; j++)
00747       if (IsPathDirectory(filelist[j]) <= 0)
00748         break;
00749     if (j == (long) number_files)
00750       {
00751         for (j=0; j < (long) number_files; j++)
00752           filelist[j]=DestroyString(filelist[j]);
00753         filelist=(char **) RelinquishMagickMemory(filelist);
00754         continue;
00755       }
00756     /*
00757       Transfer file list to argument vector.
00758     */
00759     vector=(char **) ResizeQuantumMemory(vector,(size_t) *argc+count+
00760       number_files+1,sizeof(*vector));
00761     if (vector == (char **) NULL)
00762       return(MagickFalse);
00763     count--;
00764     for (j=0; j < (long) number_files; j++)
00765     {
00766       (void) CopyMagickString(filename,path,MaxTextExtent);
00767       if (*path != '\0')
00768         (void) ConcatenateMagickString(filename,DirectorySeparator,
00769           MaxTextExtent);
00770       (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
00771       filelist[j]=DestroyString(filelist[j]);
00772       if (IsPathAccessible(filename) != MagickFalse)
00773         {
00774           char
00775             path[MaxTextExtent];
00776 
00777           *path='\0';
00778           if (*magick != '\0')
00779             {
00780               (void) ConcatenateMagickString(path,magick,MaxTextExtent);
00781               (void) ConcatenateMagickString(path,":",MaxTextExtent);
00782             }
00783           (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00784           if (*subimage != '\0')
00785             {
00786               (void) ConcatenateMagickString(path,"[",MaxTextExtent);
00787               (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
00788               (void) ConcatenateMagickString(path,"]",MaxTextExtent);
00789             }
00790           vector[count++]=ConstantString(path);
00791         }
00792     }
00793     filelist=(char **) RelinquishMagickMemory(filelist);
00794   }
00795   vector[count]=(char *) NULL;
00796   if (IsEventLogging() != MagickFalse)
00797     {
00798       char
00799         *command_line;
00800 
00801       command_line=AcquireString(vector[0]);
00802       for (i=1; i < count; i++)
00803       {
00804         (void) ConcatenateString(&command_line," {");
00805         (void) ConcatenateString(&command_line,vector[i]);
00806         (void) ConcatenateString(&command_line,"}");
00807       }
00808       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00809         "Command line: %s",command_line);
00810       command_line=DestroyString(command_line);
00811     }
00812   *argc=(int) count;
00813   *argv=vector;
00814   return(MagickTrue);
00815 }
00816 
00817 /*
00818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00819 %                                                                             %
00820 %                                                                             %
00821 %                                                                             %
00822 %   G e t E x e c u t i o n P a t h                                           %
00823 %                                                                             %
00824 %                                                                             %
00825 %                                                                             %
00826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00827 %
00828 %  GetExecutionPath() returns the pathname of the executable that started
00829 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
00830 %
00831 %  The format of the GetExecutionPath method is:
00832 %
00833 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00834 %
00835 %  A description of each parameter follows:
00836 %
00837 %    o path: the pathname of the executable that started the process.
00838 %
00839 %    o extent: the maximum extent of the path.
00840 %
00841 */
00842 MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00843 {
00844   *path='\0';
00845   (void) getcwd(path,(unsigned long) extent);
00846 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK)
00847   {
00848     char
00849       link_path[MaxTextExtent],
00850       real_path[PATH_MAX+1];
00851 
00852     ssize_t
00853       count;
00854 
00855     (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/exe",
00856       (long) getpid());
00857     count=readlink(link_path,real_path,PATH_MAX);
00858     if (count == -1)
00859       {
00860         (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/file",
00861           (long) getpid());
00862         count=readlink(link_path,real_path,PATH_MAX);
00863       }
00864     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
00865       {
00866         real_path[count]='\0';
00867         (void) CopyMagickString(path,real_path,extent);
00868       }
00869   }
00870 #endif
00871 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
00872   {
00873     char
00874       executable_path[PATH_MAX << 1],
00875       real_path[PATH_MAX+1];
00876 
00877     uint32_t
00878       length;
00879 
00880     length=sizeof(executable_path);
00881     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
00882         (realpath(executable_path,real_path) != (char *) NULL))
00883       (void) CopyMagickString(path,real_path,extent);
00884   }
00885 #endif
00886 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
00887   {
00888     const char
00889       *execution_path;
00890 
00891     execution_path=(const char *) getexecname();
00892     if (execution_path != (const char *) NULL)
00893       {
00894         if (*execution_path != *DirectorySeparator)
00895           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
00896         (void) ConcatenateMagickString(path,execution_path,extent);
00897       }
00898   }
00899 #endif
00900 #if defined(__WINDOWS__)
00901   NTGetExecutionPath(path,extent);
00902 #endif
00903   return(IsPathAccessible(path));
00904 }
00905 
00906 /*
00907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00908 %                                                                             %
00909 %                                                                             %
00910 %                                                                             %
00911 %   G e t P a t h A t t r i b u t e s                                         %
00912 %                                                                             %
00913 %                                                                             %
00914 %                                                                             %
00915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00916 %
00917 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
00918 %
00919 %  The path of the GetPathAttributes method is:
00920 %
00921 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
00922 %
00923 %  A description of each parameter follows.
00924 %
00925 %   o  path: the file path.
00926 %
00927 %   o  attributes: the path attributes are returned here.
00928 %
00929 */
00930 
00931 #if defined(MAGICKCORE_HAVE__WFOPEN)
00932 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
00933 {
00934   register const unsigned char
00935     *p;
00936 
00937   if (utf16 != (wchar_t *) NULL)
00938     {
00939       register wchar_t
00940         *q;
00941 
00942       wchar_t
00943         c;
00944 
00945       /*
00946         Convert UTF-8 to UTF-16.
00947       */
00948       q=utf16;
00949       for (p=utf8; *p != '\0'; p++)
00950       {
00951         if ((*p & 0x80) == 0)
00952           *q=(*p);
00953         else
00954           if ((*p & 0xE0) == 0xC0)
00955             {
00956               c=(*p);
00957               *q=(c & 0x1F) << 6;
00958               p++;
00959               if ((*p & 0xC0) != 0x80)
00960                 return(0);
00961               *q|=(*p & 0x3F);
00962             }
00963           else
00964             if ((*p & 0xF0) == 0xE0)
00965               {
00966                 c=(*p);
00967                 *q=c << 12;
00968                 p++;
00969                 if ((*p & 0xC0) != 0x80)
00970                   return(0);
00971                 c=(*p);
00972                 *q|=(c & 0x3F) << 6;
00973                 p++;
00974                 if ((*p & 0xC0) != 0x80)
00975                   return(0);
00976                 *q|=(*p & 0x3F);
00977               }
00978             else
00979               return(0);
00980         q++;
00981       }
00982       *q++='\0';
00983       return(q-utf16);
00984     }
00985   /*
00986     Compute UTF-16 string length.
00987   */
00988   for (p=utf8; *p != '\0'; p++)
00989   {
00990     if ((*p & 0x80) == 0)
00991       ;
00992     else
00993       if ((*p & 0xE0) == 0xC0)
00994         {
00995           p++;
00996           if ((*p & 0xC0) != 0x80)
00997             return(0);
00998         }
00999       else
01000         if ((*p & 0xF0) == 0xE0)
01001           {
01002             p++;
01003             if ((*p & 0xC0) != 0x80)
01004               return(0);
01005             p++;
01006             if ((*p & 0xC0) != 0x80)
01007               return(0);
01008          }
01009        else
01010          return(0);
01011   }
01012   return(p-utf8);
01013 }
01014 
01015 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
01016 {
01017   size_t
01018     length;
01019 
01020   wchar_t
01021     *utf16;
01022 
01023   length=UTF8ToUTF16(source,(wchar_t *) NULL);
01024   if (length == 0)
01025     {
01026       register long
01027         i;
01028 
01029       /*
01030         Not UTF-8, just copy.
01031       */
01032       length=strlen(source);
01033       utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01034       if (utf16 == (wchar_t *) NULL)
01035         return((wchar_t *) NULL);
01036       for (i=0; i <= (long) length; i++)
01037         utf16[i]=source[i];
01038       return(utf16);
01039     }
01040   utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01041   if (utf16 == (wchar_t *) NULL)
01042     return((wchar_t *) NULL);
01043   length=UTF8ToUTF16(source,utf16);
01044   return(utf16);
01045 }
01046 #endif
01047 
01048 MagickExport MagickBooleanType GetPathAttributes(const char *path,
01049   void *attributes)
01050 {
01051   MagickBooleanType
01052     status;
01053 
01054   if (path == (const char *) NULL)
01055     {
01056       errno=EINVAL;
01057       return(MagickFalse);
01058     }
01059 #if !defined(MAGICKCORE_HAVE__WFOPEN)
01060   status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
01061 #else
01062   {
01063     wchar_t
01064       *unicode_path;
01065 
01066     unicode_path=ConvertUTF8ToUTF16(path);
01067     if (unicode_path == (wchar_t *) NULL)
01068       return(MagickFalse);
01069     status=_wstat(unicode_path,(struct _stat *) attributes) == 0 ? MagickTrue :
01070       MagickFalse;
01071     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01072   }
01073 #endif
01074   return(status);
01075 }
01076 
01077 /*
01078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01079 %                                                                             %
01080 %                                                                             %
01081 %                                                                             %
01082 %   G e t P a t h C o m p o n e n t                                           %
01083 %                                                                             %
01084 %                                                                             %
01085 %                                                                             %
01086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01087 %
01088 %  GetPathComponent() returns the parent directory name, filename, basename, or
01089 %  extension of a file path.
01090 %
01091 %  The format of the GetPathComponent function is:
01092 %
01093 %      GetPathComponent(const char *path,PathType type,char *component)
01094 %
01095 %  A description of each parameter follows:
01096 %
01097 %    o path: Specifies a pointer to a character array that contains the
01098 %      file path.
01099 %
01100 %    o type: Specififies which file path component to return.
01101 %
01102 %    o component: the selected file path component is returned here.
01103 %
01104 */
01105 MagickExport void GetPathComponent(const char *path,PathType type,
01106   char *component)
01107 {
01108   char
01109     magick[MaxTextExtent],
01110     *q,
01111     subimage[MaxTextExtent];
01112 
01113   register char
01114     *p;
01115 
01116   assert(path != (const char *) NULL);
01117   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
01118   assert(component != (char *) NULL);
01119   if (*path == '\0')
01120     {
01121       *component='\0';
01122       return;
01123     }
01124   (void) CopyMagickString(component,path,MaxTextExtent);
01125   *magick='\0';
01126   for (p=component; *p != '\0'; p++)
01127     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
01128         (IsPathAccessible(path) == MagickFalse))
01129       {
01130         /*
01131           Look for image format specification (e.g. ps3:image).
01132         */
01133         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
01134         if (IsMagickConflict(magick) != MagickFalse)
01135           *magick='\0';
01136         else
01137           for (q=component; *q != '\0'; q++)
01138             *q=(*++p);
01139         break;
01140       }
01141   *subimage='\0';
01142   p=component;
01143   if (*p != '\0')
01144     p=component+strlen(component)-1;
01145   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
01146       (IsPathAccessible(path) == MagickFalse))
01147     {
01148       /*
01149         Look for scene specification (e.g. img0001.pcd[4]).
01150       */
01151       for (q=p-1; q > component; q--)
01152         if (*q == '[')
01153           break;
01154       if (*q == '[')
01155         {
01156           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
01157           subimage[p-q-1]='\0';
01158           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
01159               (IsGeometry(subimage) == MagickFalse))
01160             *subimage='\0';
01161           else
01162             *q='\0';
01163         }
01164     }
01165   p=component;
01166   if (*p != '\0')
01167     for (p=component+strlen(component)-1; p > component; p--)
01168       if (IsBasenameSeparator(*p) != MagickFalse)
01169         break;
01170   switch (type)
01171   {
01172     case MagickPath:
01173     {
01174       (void) CopyMagickString(component,magick,MaxTextExtent);
01175       break;
01176     }
01177     case RootPath:
01178     {
01179       for (p=component+(strlen(component)-1); p > component; p--)
01180       {
01181         if (IsBasenameSeparator(*p) != MagickFalse)
01182           break;
01183         if (*p == '.')
01184           break;
01185       }
01186       if (*p == '.')
01187         *p='\0';
01188       break;
01189     }
01190     case HeadPath:
01191     {
01192       *p='\0';
01193       break;
01194     }
01195     case TailPath:
01196     {
01197       if (IsBasenameSeparator(*p) != MagickFalse)
01198         (void) CopyMagickMemory((unsigned char *) component,
01199           (const unsigned char *) (p+1),strlen(p+1)+1);
01200       break;
01201     }
01202     case BasePath:
01203     {
01204       if (IsBasenameSeparator(*p) != MagickFalse)
01205         (void) CopyMagickString(component,p+1,MaxTextExtent);
01206       for (p=component+(strlen(component)-1); p > component; p--)
01207         if (*p == '.')
01208           {
01209             *p='\0';
01210             break;
01211           }
01212       break;
01213     }
01214     case ExtensionPath:
01215     {
01216       if (IsBasenameSeparator(*p) != MagickFalse)
01217         (void) CopyMagickString(component,p+1,MaxTextExtent);
01218       p=component;
01219       if (*p != '\0')
01220         for (p=component+strlen(component)-1; p > component; p--)
01221           if (*p == '.')
01222             break;
01223       *component='\0';
01224       if (*p == '.')
01225         (void) CopyMagickString(component,p+1,MaxTextExtent);
01226       break;
01227     }
01228     case SubimagePath:
01229     {
01230       (void) CopyMagickString(component,subimage,