00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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/policy.h"
00054 #include "magick/resource_.h"
00055 #include "magick/semaphore.h"
00056 #include "magick/signature-private.h"
00057 #include "magick/statistic.h"
00058 #include "magick/string_.h"
00059 #include "magick/token.h"
00060 #include "magick/utility.h"
00061 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
00062 #include <mach-o/dyld.h>
00063 #endif
00064
00065
00066
00067
00068 static const char
00069 Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00070
00071
00072
00073
00074 static int
00075 IsPathDirectory(const char *);
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
00101 {
00102 int
00103 file;
00104
00105 file=AcquireUniqueFileResource(path);
00106 if (file == -1)
00107 return(MagickFalse);
00108 file=close(file)-1;
00109 return(MagickTrue);
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 static inline size_t MagickMin(const size_t x,const size_t y)
00143 {
00144 if (x < y)
00145 return(x);
00146 return(y);
00147 }
00148
00149 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
00150 char *destination)
00151 {
00152 int
00153 destination_file,
00154 source_file;
00155
00156 size_t
00157 length,
00158 quantum;
00159
00160 ssize_t
00161 count;
00162
00163 struct stat
00164 attributes;
00165
00166 unsigned char
00167 *buffer;
00168
00169 assert(source != (const char *) NULL);
00170 assert(destination != (char *) NULL);
00171 #if defined(MAGICKCORE_HAVE_SYMLINK)
00172 (void) AcquireUniqueFilename(destination);
00173 (void) RelinquishUniqueFileResource(destination);
00174 if (*source == *DirectorySeparator)
00175 {
00176 if (symlink(source,destination) == 0)
00177 return(MagickTrue);
00178 }
00179 else
00180 {
00181 char
00182 path[MaxTextExtent];
00183
00184 *path='\0';
00185 if (getcwd(path,MaxTextExtent) == (char *) NULL)
00186 return(MagickFalse);
00187 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
00188 (void) ConcatenateMagickString(path,source,MaxTextExtent);
00189 if (symlink(path,destination) == 0)
00190 return(MagickTrue);
00191 }
00192 #endif
00193 destination_file=AcquireUniqueFileResource(destination);
00194 if (destination_file == -1)
00195 return(MagickFalse);
00196 source_file=open(source,O_RDONLY | O_BINARY);
00197 if (source_file == -1)
00198 {
00199 (void) close(destination_file);
00200 (void) RelinquishUniqueFileResource(destination);
00201 return(MagickFalse);
00202 }
00203 quantum=(size_t) MagickMaxBufferExtent;
00204 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
00205 quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
00206 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
00207 if (buffer == (unsigned char *) NULL)
00208 {
00209 (void) close(source_file);
00210 (void) close(destination_file);
00211 (void) RelinquishUniqueFileResource(destination);
00212 return(MagickFalse);
00213 }
00214 for (length=0; ; )
00215 {
00216 count=(ssize_t) read(source_file,buffer,quantum);
00217 if (count <= 0)
00218 break;
00219 length=(size_t) count;
00220 count=(ssize_t) write(destination_file,buffer,length);
00221 if ((size_t) count != length)
00222 {
00223 (void) close(destination_file);
00224 (void) close(source_file);
00225 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00226 (void) RelinquishUniqueFileResource(destination);
00227 return(MagickFalse);
00228 }
00229 }
00230 (void) close(destination_file);
00231 (void) close(source_file);
00232 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00233 return(MagickTrue);
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 MagickExport void AppendImageFormat(const char *format,char *filename)
00264 {
00265 char
00266 root[MaxTextExtent];
00267
00268 assert(format != (char *) NULL);
00269 assert(filename != (char *) NULL);
00270 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00271 if ((*format == '\0') || (*filename == '\0'))
00272 return;
00273 if (LocaleCompare(filename,"-") == 0)
00274 {
00275 char
00276 message[MaxTextExtent];
00277
00278 (void) FormatMagickString(message,MaxTextExtent,"%s:%s",format,filename);
00279 (void) CopyMagickString(filename,message,MaxTextExtent);
00280 return;
00281 }
00282 GetPathComponent(filename,RootPath,root);
00283 (void) FormatMagickString(filename,MaxTextExtent,"%s.%s",root,format);
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
00313 {
00314 int
00315 state;
00316
00317 register const char
00318 *p,
00319 *q;
00320
00321 register size_t
00322 i;
00323
00324 unsigned char
00325 *decode;
00326
00327 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00328 assert(source != (char *) NULL);
00329 assert(length != (size_t *) NULL);
00330 *length=0;
00331 decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
00332 3*sizeof(*decode));
00333 if (decode == (unsigned char *) NULL)
00334 return((unsigned char *) NULL);
00335 i=0;
00336 state=0;
00337 for (p=source; *p != '\0'; p++)
00338 {
00339 if (isspace((int) ((unsigned char) *p)) != 0)
00340 continue;
00341 if (*p == '=')
00342 break;
00343 q=strchr(Base64,*p);
00344 if (q == (char *) NULL)
00345 {
00346 decode=(unsigned char *) RelinquishMagickMemory(decode);
00347 return((unsigned char *) NULL);
00348 }
00349 switch (state)
00350 {
00351 case 0:
00352 {
00353 decode[i]=(q-Base64) << 2;
00354 state++;
00355 break;
00356 }
00357 case 1:
00358 {
00359 decode[i++]|=(q-Base64) >> 4;
00360 decode[i]=((q-Base64) & 0x0f) << 4;
00361 state++;
00362 break;
00363 }
00364 case 2:
00365 {
00366 decode[i++]|=(q-Base64) >> 2;
00367 decode[i]=((q-Base64) & 0x03) << 6;
00368 state++;
00369 break;
00370 }
00371 case 3:
00372 {
00373 decode[i++]|=(q-Base64);
00374 state=0;
00375 break;
00376 }
00377 }
00378 }
00379
00380
00381
00382 if (*p != '=')
00383 {
00384 if (state != 0)
00385 {
00386 decode=(unsigned char *) RelinquishMagickMemory(decode);
00387 return((unsigned char *) NULL);
00388 }
00389 }
00390 else
00391 {
00392 p++;
00393 switch (state)
00394 {
00395 case 0:
00396 case 1:
00397 {
00398
00399
00400
00401 decode=(unsigned char *) RelinquishMagickMemory(decode);
00402 return((unsigned char *) NULL);
00403 }
00404 case 2:
00405 {
00406 for ( ; *p != '\0'; p++)
00407 if (isspace((int) ((unsigned char) *p)) == 0)
00408 break;
00409 if (*p != '=')
00410 {
00411 decode=(unsigned char *) RelinquishMagickMemory(decode);
00412 return((unsigned char *) NULL);
00413 }
00414 p++;
00415 }
00416 case 3:
00417 {
00418 for ( ; *p != '\0'; p++)
00419 if (isspace((int) ((unsigned char) *p)) == 0)
00420 {
00421 decode=(unsigned char *) RelinquishMagickMemory(decode);
00422 return((unsigned char *) NULL);
00423 }
00424 if ((int) decode[i] != 0)
00425 {
00426 decode=(unsigned char *) RelinquishMagickMemory(decode);
00427 return((unsigned char *) NULL);
00428 }
00429 }
00430 }
00431 }
00432 *length=i;
00433 return(decode);
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 MagickExport char *Base64Encode(const unsigned char *blob,
00467 const size_t blob_length,size_t *encode_length)
00468 {
00469 char
00470 *encode;
00471
00472 register const unsigned char
00473 *p;
00474
00475 register size_t
00476 i;
00477
00478 size_t
00479 remainder;
00480
00481 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00482 assert(blob != (const unsigned char *) NULL);
00483 assert(blob_length != 0);
00484 assert(encode_length != (size_t *) NULL);
00485 *encode_length=0;
00486 encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
00487 if (encode == (char *) NULL)
00488 return((char *) NULL);
00489 i=0;
00490 for (p=blob; p < (blob+blob_length-2); p+=3)
00491 {
00492 encode[i++]=Base64[(int) (*p >> 2)];
00493 encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
00494 encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
00495 encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
00496 }
00497 remainder=blob_length % 3;
00498 if (remainder != 0)
00499 {
00500 long
00501 j;
00502
00503 unsigned char
00504 code[3];
00505
00506 code[0]='\0';
00507 code[1]='\0';
00508 code[2]='\0';
00509 for (j=0; j < (long) remainder; j++)
00510 code[j]=(*p++);
00511 encode[i++]=Base64[(int) (code[0] >> 2)];
00512 encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
00513 if (remainder == 1)
00514 encode[i++]='=';
00515 else
00516 encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
00517 encode[i++]='=';
00518 }
00519 *encode_length=i;
00520 encode[i++]='\0';
00521 return(encode);
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 MagickExport void ChopPathComponents(char *path,const unsigned long components)
00550 {
00551 register long
00552 i;
00553
00554 for (i=0; i < (long) components; i++)
00555 GetPathComponent(path,HeadPath,path);
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 MagickExport void ExpandFilename(char *path)
00582 {
00583 char
00584 expand_path[MaxTextExtent];
00585
00586 if (path == (char *) NULL)
00587 return;
00588 if (*path != '~')
00589 return;
00590 (void) CopyMagickString(expand_path,path,MaxTextExtent);
00591 if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
00592 {
00593 char
00594 *home;
00595
00596
00597
00598
00599 (void) CopyMagickString(expand_path,".",MaxTextExtent);
00600 (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00601 home=GetEnvironmentValue("HOME");
00602 if (home == (char *) NULL)
00603 home=GetEnvironmentValue("USERPROFILE");
00604 if (home != (char *) NULL)
00605 {
00606 (void) CopyMagickString(expand_path,home,MaxTextExtent);
00607 (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00608 home=DestroyString(home);
00609 }
00610 }
00611 else
00612 {
00613 #if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
00614 char
00615 username[MaxTextExtent];
00616
00617 register char
00618 *p;
00619
00620 struct passwd
00621 *entry;
00622
00623
00624
00625
00626 (void) CopyMagickString(username,path+1,MaxTextExtent);
00627 p=strchr(username,'/');
00628 if (p != (char *) NULL)
00629 *p='\0';
00630 entry=getpwnam(username);
00631 if (entry == (struct passwd *) NULL)
00632 return;
00633 (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
00634 if (p != (char *) NULL)
00635 {
00636 (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
00637 (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
00638 }
00639 #endif
00640 }
00641 (void) CopyMagickString(path,expand_path,MaxTextExtent);
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
00673 char ***arguments)
00674 {
00675 char
00676 *cwd,
00677 home_directory[MaxTextExtent],
00678 **vector;
00679
00680 long
00681 count,
00682 parameters;
00683
00684 register long
00685 i,
00686 j;
00687
00688 unsigned long
00689 number_files;
00690
00691
00692
00693
00694 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00695 assert(number_arguments != (int *) NULL);
00696 assert(arguments != (char ***) NULL);
00697 vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
00698 sizeof(*vector));
00699 if (vector == (char **) NULL)
00700 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00701
00702
00703
00704 *home_directory='\0';
00705 count=0;
00706 for (i=0; i < (long) *number_arguments; i++)
00707 {
00708 char
00709 **filelist,
00710 filename[MaxTextExtent],
00711 magick[MaxTextExtent],
00712 *option,
00713 path[MaxTextExtent],
00714 subimage[MaxTextExtent];
00715
00716 MagickBooleanType
00717 destroy;
00718
00719 option=(*arguments)[i];
00720 *magick='\0';
00721 *path='\0';
00722 *filename='\0';
00723 *subimage='\0';
00724 vector[count++]=ConstantString(option);
00725 destroy=MagickTrue;
00726 parameters=ParseMagickOption(MagickCommandOptions,MagickFalse,option);
00727 if (parameters > 0)
00728 {
00729
00730
00731
00732 for (j=0; j < parameters; j++)
00733 {
00734 i++;
00735 if (i == (long) *number_arguments)
00736 break;
00737 option=(*arguments)[i];
00738 vector[count++]=ConstantString(option);
00739 }
00740 continue;
00741 }
00742 if ((*option == '"') || (*option == '\''))
00743 continue;
00744 GetPathComponent(option,TailPath,filename);
00745 GetPathComponent(option,MagickPath,magick);
00746 if ((LocaleCompare(magick,"CAPTION") == 0) ||
00747 (LocaleCompare(magick,"LABEL") == 0) ||
00748 (LocaleCompare(magick,"VID") == 0))
00749 continue;
00750 if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
00751 continue;
00752 if (*filename != '@')
00753 {
00754
00755
00756
00757 GetPathComponent(option,HeadPath,path);
00758 GetPathComponent(option,SubimagePath,subimage);
00759 ExpandFilename(path);
00760 if (*home_directory == '\0')
00761 cwd=getcwd(home_directory,MaxTextExtent-1);
00762 filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
00763 &number_files);
00764 }
00765 else
00766 {
00767 char
00768 *files;
00769
00770 ExceptionInfo
00771 *exception;
00772
00773 int
00774 number_images;
00775
00776
00777
00778
00779 exception=AcquireExceptionInfo();
00780 files=FileToString(filename+1,~0,exception);
00781 exception=DestroyExceptionInfo(exception);
00782 if (files == (char *) NULL)
00783 continue;
00784 StripString(files);
00785 filelist=StringToArgv(files,&number_images);
00786 files=DestroyString(files);
00787 number_files=(unsigned long) number_images;
00788 if (filelist != (char **) NULL)
00789 {
00790 number_files--;
00791 for (j=0; j < (long) number_files; j++)
00792 filelist[j]=filelist[j+1];
00793 }
00794 }
00795 if (filelist == (char **) NULL)
00796 continue;
00797 for (j=0; j < (long) number_files; j++)
00798 if (IsPathDirectory(filelist[j]) <= 0)
00799 break;
00800 if (j == (long) number_files)
00801 {
00802 for (j=0; j < (long) number_files; j++)
00803 filelist[j]=DestroyString(filelist[j]);
00804 filelist=(char **) RelinquishMagickMemory(filelist);
00805 continue;
00806 }
00807
00808
00809
00810 vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
00811 count+number_files+1,sizeof(*vector));
00812 if (vector == (char **) NULL)
00813 return(MagickFalse);
00814 for (j=0; j < (long) number_files; j++)
00815 {
00816 (void) CopyMagickString(filename,path,MaxTextExtent);
00817 if (*path != '\0')
00818 (void) ConcatenateMagickString(filename,DirectorySeparator,
00819 MaxTextExtent);
00820 (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
00821 filelist[j]=DestroyString(filelist[j]);
00822 if (strlen(filename) >= MaxTextExtent)
00823 ThrowFatalException(OptionFatalError,"FilenameTruncated");
00824 if (IsPathDirectory(filename) == 0)
00825 {
00826 char
00827 path[MaxTextExtent];
00828
00829 *path='\0';
00830 if (*magick != '\0')
00831 {
00832 (void) ConcatenateMagickString(path,magick,MaxTextExtent);
00833 (void) ConcatenateMagickString(path,":",MaxTextExtent);
00834 }
00835 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00836 if (*subimage != '\0')
00837 {
00838 (void) ConcatenateMagickString(path,"[",MaxTextExtent);
00839 (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
00840 (void) ConcatenateMagickString(path,"]",MaxTextExtent);
00841 }
00842 if (strlen(path) >= MaxTextExtent)
00843 ThrowFatalException(OptionFatalError,"FilenameTruncated");
00844 if (destroy != MagickFalse)
00845 {
00846 count--;
00847 vector[count]=DestroyString(vector[count]);
00848 destroy=MagickFalse;
00849 }
00850 vector[count++]=ConstantString(path);
00851 }
00852 }
00853 filelist=(char **) RelinquishMagickMemory(filelist);
00854 }
00855 vector[count]=(char *) NULL;
00856 if (IsEventLogging() != MagickFalse)
00857 {
00858 char
00859 *command_line;
00860
00861 command_line=AcquireString(vector[0]);
00862 for (i=1; i < count; i++)
00863 {
00864 (void) ConcatenateString(&command_line," {");
00865 (void) ConcatenateString(&command_line,vector[i]);
00866 (void) ConcatenateString(&command_line,"}");
00867 }
00868 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00869 "Command line: %s",command_line);
00870 command_line=DestroyString(command_line);
00871 }
00872 *number_arguments=(int) count;
00873 *arguments=vector;
00874 return(MagickTrue);
00875 }
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00903 {
00904 char
00905 *cwd;
00906
00907 *path='\0';
00908 cwd=getcwd(path,(unsigned long) extent);
00909 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
00910 {
00911 char
00912 link_path[MaxTextExtent],
00913 execution_path[PATH_MAX+1];
00914
00915 ssize_t
00916 count;
00917
00918 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/exe",
00919 (long) getpid());
00920 count=readlink(link_path,execution_path,PATH_MAX);
00921 if (count == -1)
00922 {
00923 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/file",
00924 (long) getpid());
00925 count=readlink(link_path,execution_path,PATH_MAX);
00926 }
00927 if ((count > 0) && (count <= (ssize_t) PATH_MAX))
00928 {
00929 execution_path[count]='\0';
00930 (void) CopyMagickString(path,execution_path,extent);
00931 }
00932 }
00933 #endif
00934 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
00935 {
00936 char
00937 executable_path[PATH_MAX << 1],
00938 execution_path[PATH_MAX+1];
00939
00940 uint32_t
00941 length;
00942
00943 length=sizeof(executable_path);
00944 if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
00945 (realpath(executable_path,execution_path) != (char *) NULL))
00946 (void) CopyMagickString(path,execution_path,extent);
00947 }
00948 #endif
00949 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
00950 {
00951 const char
00952 *execution_path;
00953
00954 execution_path=(const char *) getexecname();
00955 if (execution_path != (const char *) NULL)
00956 {
00957 if (*execution_path != *DirectorySeparator)
00958 (void) ConcatenateMagickString(path,DirectorySeparator,extent);
00959 (void) ConcatenateMagickString(path,execution_path,extent);
00960 }
00961 }
00962 #endif
00963 #if defined(__WINDOWS__)
00964 NTGetExecutionPath(path,extent);
00965 #endif
00966 #if defined(__GNU__)
00967 {
00968 char
00969 *program_name,
00970 *execution_path;
00971
00972 long
00973 count;
00974
00975 count=0;
00976 execution_path=(char *) NULL;
00977 program_name=program_invocation_name;
00978 if (*program_invocation_name != '/')
00979 {
00980 size_t
00981 extent;
00982
00983 extent=strlen(cwd)+strlen(program_name)+1;
00984 program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
00985 if (program_name == (char *) NULL)
00986 program_name=program_invocation_name;
00987 else
00988 count=FormatMagickString(program_name,extent,"%s/%s",cwd,
00989 program_invocation_name);
00990 }
00991 if (count != -1)
00992 {
00993 execution_path=realpath(program_name,NULL);
00994 if (execution_path != (char *) NULL)
00995 (void) CopyMagickString(path,execution_path,extent);
00996 }
00997 if (program_name != program_invocation_name)
00998 program_name=(char *) RelinquishMagickMemory(program_name);
00999 execution_path=(char *) RelinquishMagickMemory(execution_path);
01000 }
01001 #endif
01002 return(IsPathAccessible(path));
01003 }
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023 MagickExport long GetMagickPageSize(void)
01024 {
01025 static long
01026 page_size = -1;
01027
01028 if (page_size > 0)
01029 return(page_size);
01030 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
01031 page_size=sysconf(_SC_PAGE_SIZE);
01032 #endif
01033 #if defined(MAGICKCORE_HAVE_GETPAGESIZE)
01034 if (page_size <= 0)
01035 page_size=getpagesize();
01036 #endif
01037 if (page_size <= 0)
01038 page_size=16384;
01039 return(page_size);
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 #if defined(MAGICKCORE_HAVE__WFOPEN)
01068 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
01069 {
01070 register const unsigned char
01071 *p;
01072
01073 if (utf16 != (wchar_t *) NULL)
01074 {
01075 register wchar_t
01076 *q;
01077
01078 wchar_t
01079 c;
01080
01081
01082
01083
01084 q=utf16;
01085 for (p=utf8; *p != '\0'; p++)
01086 {
01087 if ((*p & 0x80) == 0)
01088 *q=(*p);
01089 else
01090 if ((*p & 0xE0) == 0xC0)
01091 {
01092 c=(*p);
01093 *q=(c & 0x1F) << 6;
01094 p++;
01095 if ((*p & 0xC0) != 0x80)
01096 return(0);
01097 *q|=(*p & 0x3F);
01098 }
01099 else
01100 if ((*p & 0xF0) == 0xE0)
01101 {
01102 c=(*p);
01103 *q=c << 12;
01104 p++;
01105 if ((*p & 0xC0) != 0x80)
01106 return(0);
01107 c=(*p);
01108 *q|=(c & 0x3F) << 6;
01109 p++;
01110 if ((*p & 0xC0) != 0x80)
01111 return(0);
01112 *q|=(*p & 0x3F);
01113 }
01114 else
01115 return(0);
01116 q++;
01117 }
01118 *q++='\0';
01119 return(q-utf16);
01120 }
01121
01122
01123
01124 for (p=utf8; *p != '\0'; p++)
01125 {
01126 if ((*p & 0x80) == 0)
01127 ;
01128 else
01129 if ((*p & 0xE0) == 0xC0)
01130 {
01131 p++;
01132 if ((*p & 0xC0) != 0x80)
01133 return(0);
01134 }
01135 else
01136 if ((*p & 0xF0) == 0xE0)
01137 {
01138 p++;
01139 if ((*p & 0xC0) != 0x80)
01140 return(0);
01141 p++;
01142 if ((*p & 0xC0) != 0x80)
01143 return(0);
01144 }
01145 else
01146 return(0);
01147 }
01148 return(p-utf8);
01149 }
01150
01151 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
01152 {
01153 size_t
01154 length;
01155
01156 wchar_t
01157 *utf16;
01158
01159 length=UTF8ToUTF16(source,(wchar_t *) NULL);
01160 if (length == 0)
01161 {
01162 register long
01163 i;
01164
01165
01166
01167
01168 length=strlen(source);
01169 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01170 if (utf16 == (wchar_t *) NULL)
01171 return((wchar_t *) NULL);
01172 for (i=0; i <= (long) length; i++)
01173 utf16[i]=source[i];
01174 return(utf16);
01175 }
01176 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01177 if (utf16 == (wchar_t *) NULL)
01178 return((wchar_t *) NULL);
01179 length=UTF8ToUTF16(source,utf16);
01180 return(utf16);
01181 }
01182 #endif
01183
01184 MagickExport MagickBooleanType GetPathAttributes(const char *path,
01185 void *attributes)
01186 {
01187 MagickBooleanType
01188 status;
01189
01190 if (path == (const char *) NULL)
01191 {
01192 errno=EINVAL;
01193 return(MagickFalse);
01194 }
01195 #if !defined(MAGICKCORE_HAVE__WSTAT)
01196 status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
01197 #else
01198 {
01199 wchar_t
01200 *unicode_path;
01201
01202 unicode_path=ConvertUTF8ToUTF16(path);
01203 if (unicode_path == (wchar_t *) NULL)
01204 return(MagickFalse);
01205 status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
01206 MagickFalse;
01207 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01208 }
01209 #endif
01210 return(status);
01211 }
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 MagickExport void GetPathComponent(const char *path,PathType type,
01242 char *component)
01243 {
01244 char
01245 magick[MaxTextExtent],
01246 *q,
01247 subimage[MaxTextExtent];
01248
01249 register char
01250 *p;
01251
01252 assert(path != (const char *) NULL);
01253 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
01254 assert(component != (char *) NULL);
01255 if (*path == '\0')
01256 {
01257 *component='\0';
01258 return;
01259 }
01260 (void) CopyMagickString(component,path,MaxTextExtent);
01261 *magick='\0';
01262 #if defined(__OS2__)
01263 if (path[1] != ":")
01264 #endif
01265 for (p=component; *p != '\0'; p++)
01266 if ((*p == ':') && (IsPathDirectory(path) < 0) &&
01267 (IsPathAccessible(path) == MagickFalse))
01268 {
01269
01270
01271
01272 (void) CopyMagickString(magick,component,(size_t) (p-component+1));
01273 if (IsMagickConflict(magick) != MagickFalse)
01274 *magick='\0';
01275 else
01276 for (q=component; *q != '\0'; q++)
01277 *q=(*++p);
01278 break;
01279 }
01280 *subimage='\0';
01281 p=component;
01282 if (*p != '\0')
01283 p=component+strlen(component)-1;
01284 if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
01285 (IsPathAccessible(path) == MagickFalse))
01286 {
01287
01288
01289
01290 for (q=p-1; q > component; q--)
01291 if (*q == '[')
01292 break;
01293 if (*q == '[')
01294 {
01295 (void) CopyMagickString(subimage,q+1,MaxTextExtent);
01296 subimage[p-q-1]='\0';
01297 if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
01298 (IsGeometry(subimage) == MagickFalse))
01299 *subimage='\0';
01300 else
01301 *q='\0';
01302 }
01303 }
01304 p=component;
01305 if (*p != '\0')
01306 for (p=component+strlen(component)-1; p > component; p--)
01307 if (IsBasenameSeparator(*p) != MagickFalse)
01308 break;
01309 switch (type)
01310 {
01311 case MagickPath:
01312 {
01313 (void) CopyMagickString(component,magick,MaxTextExtent);
01314 break;
01315 }
01316 case RootPath:
01317 {
01318 for (p=component+(strlen(component)-1); p > component; p--)
01319 {
01320 if (IsBasenameSeparator(*p) != MagickFalse)
01321 break;
01322 if (*p == '.')
01323 break;
01324 }
01325 if (*p == '.')
01326 *p='\0';
01327 break;
01328 }
01329 case HeadPath:
01330 {
01331 *p='\0';
01332 break;
01333 }
01334 case TailPath:
01335 {
01336 if (IsBasenameSeparator(*p) != MagickFalse)
01337 (void) CopyMagickMemory((unsigned char *) component,
01338 (const unsigned char *) (p+1),strlen(p+1)+1);
01339 break;
01340 }
01341 case BasePath:
01342 {
01343 if (IsBasenameSeparator(*p) != MagickFalse)
01344 (void) CopyMagickString(component,p+1,MaxTextExtent);
01345 for (p=component+(strlen(component)-1); p > component; p--)
01346 if (*p == '.')
01347 {
01348 *p='\0';
01349 break;
01350 }
01351 break;
01352 }
01353 case ExtensionPath:
01354 {
01355 if (IsBasenameSeparator(*p) != MagickFalse)
01356 (void) CopyMagickString(component,p+1,MaxTextExtent);
01357 p=component;
01358 if (*p != '\0')
01359 for (p=component+strlen(component)-1; p > component; p--)
01360 if (*p == '.')
01361 break;
01362 *component='\0';
01363 if (*p == '.')
01364 (void) CopyMagickString(component,p+1,MaxTextExtent);
01365 break;
01366 }
01367 case SubimagePath:
01368 {
01369 (void) CopyMagickString(component,subimage,MaxTextExtent);
01370 break;
01371 }
01372 case CanonicalPath:
01373 case UndefinedPath:
01374 break;
01375 }
01376 }
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403 MagickExport char **GetPathComponents(const char *path,
01404 unsigned long *number_components)
01405 {
01406 char
01407 **components;
01408
01409 register const char
01410 *p,
01411 *q;
01412
01413 register long
01414 i;
01415
01416 if (path == (char *) NULL)
01417 return((char **) NULL);
01418 *number_components=1;
01419 for (p=path; *p != '\0'; p++)
01420 if (IsBasenameSeparator(*p))
01421 (*number_components)++;
01422 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
01423 sizeof(*components));
01424 if (components == (char **) NULL)
01425 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01426 p=path;
01427 for (i=0; i < (long) *number_components; i++)
01428 {
01429 for (q=p; *q != '\0'; q++)
01430 if (IsBasenameSeparator(*q))
01431 break;
01432 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
01433 sizeof(*components));
01434 if (components[i] == (char *) NULL)
01435 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01436 (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
01437 p=q+1;
01438 }
01439 components[i]=(char *) NULL;
01440 return(components);
01441 }
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466 MagickExport MagickBooleanType IsPathAccessible(const char *path)
01467 {
01468 MagickBooleanType
01469 status;
01470
01471 struct stat
01472 attributes;
01473
01474 if ((path == (const char *) NULL) || (*path == '\0'))
01475 return(MagickFalse);
01476 status=GetPathAttributes(path,&attributes);
01477 if (status == MagickFalse)
01478 return(status);
01479 if (S_ISREG(attributes.st_mode) == 0)
01480 return(MagickFalse);
01481 if (access(path,F_OK) != 0)
01482 return(MagickFalse);
01483 return(MagickTrue);
01484 }
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509 static int IsPathDirectory(const char *path)
01510 {
01511 MagickBooleanType
01512 status;
01513
01514 struct stat
01515 attributes;
01516
01517 if ((path == (const char *) NULL) || (*path == '\0'))
01518 return(MagickFalse);
01519 status=GetPathAttributes(path,&attributes);
01520 if (status == MagickFalse)
01521 return(-1);
01522 if (S_ISDIR(attributes.st_mode) == 0)
01523 return(0);
01524 return(1);
01525 }
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553 MagickExport MagickBooleanType IsMagickTrue(const char *value)
01554 {
01555 if (value == (const char *) NULL)
01556 return(MagickFalse);
01557 if (LocaleCompare(value,"true") == 0)
01558 return(MagickTrue);
01559 if (LocaleCompare(value,"on") == 0)
01560 return(MagickTrue);
01561 if (LocaleCompare(value,"yes") == 0)
01562 return(MagickTrue);
01563 if (LocaleCompare(value,"1") == 0)
01564 return(MagickTrue);
01565 return(MagickFalse);
01566 }
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 #if defined(__cplusplus) || defined(c_plusplus)
01604 extern "C" {
01605 #endif
01606
01607 static int FileCompare(const void *x,const void *y)
01608 {
01609 register const char
01610 **p,
01611 **q;
01612
01613 p=(const char **) x;
01614 q=(const char **) y;
01615 return(LocaleCompare(*p,*q));
01616 }
01617
01618 #if defined(__cplusplus) || defined(c_plusplus)
01619 }
01620 #endif
01621
01622 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
01623 struct dirent **result)
01624 {
01625 #if defined(MAGICKCORE_HAVE_READDIR_R)
01626 return(readdir_r(directory,entry,result));
01627 #else
01628 (void) entry;
01629 errno=0;
01630 *result=readdir(directory);
01631 return(errno);
01632 #endif
01633 }
01634
01635 MagickExport char **ListFiles(const char *directory,const char *pattern,
01636 unsigned long *number_entries)
01637 {
01638 char
01639 **filelist;
01640
01641 DIR
01642 *current_directory;
01643
01644 struct dirent
01645 *buffer,
01646 *entry;
01647
01648 unsigned long
01649 max_entries;
01650
01651
01652
01653
01654 assert(directory != (const char *) NULL);
01655 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
01656 assert(pattern != (const char *) NULL);
01657 assert(number_entries != (unsigned long *) NULL);
01658 *number_entries=0;
01659 current_directory=opendir(directory);
01660 if (current_directory == (DIR *) NULL)
01661 return((char **) NULL);
01662
01663
01664
01665 max_entries=2048;
01666 filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
01667 sizeof(*filelist));
01668 if (filelist == (char **) NULL)
01669 {
01670 (void) closedir(current_directory);
01671 return((char **) NULL);
01672 }
01673
01674
01675
01676 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
01677 if (buffer == (struct dirent *) NULL)
01678 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01679 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
01680 (entry != (struct dirent *) NULL))
01681 {
01682 if (*entry->d_name == '.')
01683 continue;
01684 if ((IsPathDirectory(entry->d_name) > 0) ||
01685 #if defined(__WINDOWS__)
01686 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
01687 #else
01688 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
01689 #endif
01690 {
01691 if (*number_entries >= max_entries)
01692 {
01693
01694
01695
01696 max_entries<<=1;
01697 filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
01698 max_entries,sizeof(*filelist));
01699 if (filelist == (char **) NULL)
01700 break;
01701 }
01702 #if defined(vms)
01703 {
01704 register char
01705 *p;
01706
01707 p=strchr(entry->d_name,';');
01708 if (p)
01709 *p='\0';
01710 if (*number_entries > 0)
01711 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
01712 continue;
01713 }
01714 #endif
01715 filelist[*number_entries]=(char *) AcquireString(entry->d_name);
01716 if (IsPathDirectory(entry->d_name) > 0)
01717 (void) ConcatenateMagickString(filelist[*number_entries],
01718 DirectorySeparator,MaxTextExtent);
01719 (*number_entries)++;
01720 }
01721 }
01722 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
01723 (void) closedir(current_directory);
01724 if (filelist == (char **) NULL)
01725 return((char **) NULL);
01726
01727
01728
01729 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
01730 FileCompare);
01731 return(filelist);
01732 }
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758 MagickExport unsigned long MultilineCensus(const char *label)
01759 {
01760 unsigned long
01761 number_lines;
01762
01763
01764
01765
01766 if (label == (char *) NULL)
01767 return(0);
01768 for (number_lines=1; *label != '\0'; label++)
01769 if (*label == '\n')
01770 number_lines++;
01771 return(number_lines);
01772 }
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799 MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
01800 {
01801 FILE
01802 *file;
01803
01804 if ((path == (const char *) NULL) || (mode == (const char *) NULL))
01805 {
01806 errno=EINVAL;
01807 return((FILE *) NULL);
01808 }
01809 file=(FILE *) NULL;
01810 #if defined(MAGICKCORE_HAVE__WFOPEN)
01811 {
01812 wchar_t
01813 *unicode_mode,
01814 *unicode_path;
01815
01816 unicode_path=ConvertUTF8ToUTF16(path);
01817 if (unicode_path == (wchar_t *) NULL)
01818 return((FILE *) NULL);
01819 unicode_mode=ConvertUTF8ToUTF16(mode);
01820 if (unicode_mode == (wchar_t *) NULL)
01821 {
01822 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01823 return((FILE *) NULL);
01824 }
01825 file=_wfopen(unicode_path,unicode_mode);
01826 unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
01827 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01828 }
01829 #endif
01830 if (file == (FILE *) NULL)
01831 file=fopen(path,mode);
01832 return(file);
01833 }
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864 MagickExport int SystemCommand(const MagickBooleanType verbose,
01865 const char *command,ExceptionInfo *exception)
01866 {
01867 char
01868 **arguments;
01869
01870 int
01871 number_arguments,
01872 status;
01873
01874 PolicyDomain
01875 domain;
01876
01877 PolicyRights
01878 rights;
01879
01880 register long
01881 i;
01882
01883 status=(-1);
01884 arguments=StringToArgv(command,&number_arguments);
01885 if (arguments == (char **) NULL)
01886 return(status);
01887 domain=DelegatePolicyDomain;
01888 rights=ExecutePolicyRights;
01889 if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
01890 {
01891 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
01892 "NotAuthorized","`%s'",arguments[1]);
01893 for (i=0; i < number_arguments; i++)
01894 arguments[i]=DestroyString(arguments[i]);
01895 arguments=(char **) RelinquishMagickMemory(arguments);
01896 return(-1);
01897 }
01898 if (verbose != MagickFalse)
01899 {
01900 (void) fprintf(stderr,"%s\n",command);
01901 (void) fflush(stderr);
01902 }
01903 #if defined(MAGICKCORE_POSIX_SUPPORT)
01904 #if !defined(MAGICKCORE_HAVE_EXECVP)
01905 status=system(command);
01906 #else
01907 if (strspn(command,"&;<>|") == 0)
01908 status=system(command);
01909 else
01910 {
01911 pid_t
01912 child_pid;
01913
01914
01915
01916
01917 child_pid=fork();
01918 if (child_pid == (pid_t) -1)
01919 status=system(command);
01920 else
01921 if (child_pid == 0)
01922 {
01923 status=execvp(arguments[1],arguments+1);
01924 _exit(1);
01925 }
01926 else
01927 {
01928 int
01929 child_status;
01930
01931 pid_t
01932 pid;
01933
01934 child_status=0;
01935 pid=waitpid(child_pid,&child_status,0);
01936 if (pid == -1)
01937 status=(-1);
01938 else
01939 {
01940 if (WIFEXITED(child_status) != 0)
01941 status=WEXITSTATUS(child_status);
01942 else
01943 if (WIFSIGNALED(child_status))
01944 status=(-1);
01945 }
01946 }
01947 }
01948 #endif
01949 #elif defined(__WINDOWS__)
01950 status=NTSystemCommand(command);
01951 #elif defined(macintosh)
01952 status=MACSystemCommand(command);
01953 #elif defined(vms)
01954 status=system(command);
01955 #else
01956 # error No suitable system() method.
01957 #endif
01958 if (status < 0)
01959 {
01960 char
01961 *message;
01962
01963 message=GetExceptionMessage(errno);
01964 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
01965 "`%s': %s",command,message);
01966 message=DestroyString(message);
01967 }
01968 for (i=0; i < number_arguments; i++)
01969 arguments[i]=DestroyString(arguments[i]);
01970 arguments=(char **) RelinquishMagickMemory(arguments);
01971 return(status);
01972 }