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_PROCESS_H)
00062 #include <process.h>
00063 #endif
00064 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
00065 #include <mach-o/dyld.h>
00066 #endif
00067
00068
00069
00070
00071 static const char
00072 Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00073
00074
00075
00076
00077 static int
00078 IsPathDirectory(const char *);
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
00104 {
00105 int
00106 file;
00107
00108 file=AcquireUniqueFileResource(path);
00109 if (file == -1)
00110 return(MagickFalse);
00111 file=close(file)-1;
00112 return(MagickTrue);
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
00143
00144
00145 static inline size_t MagickMin(const size_t x,const size_t y)
00146 {
00147 if (x < y)
00148 return(x);
00149 return(y);
00150 }
00151
00152 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
00153 char *destination)
00154 {
00155 int
00156 destination_file,
00157 source_file;
00158
00159 size_t
00160 length,
00161 quantum;
00162
00163 ssize_t
00164 count;
00165
00166 struct stat
00167 attributes;
00168
00169 unsigned char
00170 *buffer;
00171
00172 assert(source != (const char *) NULL);
00173 assert(destination != (char *) NULL);
00174 #if defined(MAGICKCORE_HAVE_SYMLINK)
00175 (void) AcquireUniqueFilename(destination);
00176 (void) RelinquishUniqueFileResource(destination);
00177 if (*source == *DirectorySeparator)
00178 {
00179 if (symlink(source,destination) == 0)
00180 return(MagickTrue);
00181 }
00182 else
00183 {
00184 char
00185 path[MaxTextExtent];
00186
00187 *path='\0';
00188 if (getcwd(path,MaxTextExtent) == (char *) NULL)
00189 return(MagickFalse);
00190 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
00191 (void) ConcatenateMagickString(path,source,MaxTextExtent);
00192 if (symlink(path,destination) == 0)
00193 return(MagickTrue);
00194 }
00195 #endif
00196 destination_file=AcquireUniqueFileResource(destination);
00197 if (destination_file == -1)
00198 return(MagickFalse);
00199 source_file=open(source,O_RDONLY | O_BINARY);
00200 if (source_file == -1)
00201 {
00202 (void) close(destination_file);
00203 (void) RelinquishUniqueFileResource(destination);
00204 return(MagickFalse);
00205 }
00206 quantum=(size_t) MagickMaxBufferExtent;
00207 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
00208 quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
00209 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
00210 if (buffer == (unsigned char *) NULL)
00211 {
00212 (void) close(source_file);
00213 (void) close(destination_file);
00214 (void) RelinquishUniqueFileResource(destination);
00215 return(MagickFalse);
00216 }
00217 for (length=0; ; )
00218 {
00219 count=(ssize_t) read(source_file,buffer,quantum);
00220 if (count <= 0)
00221 break;
00222 length=(size_t) count;
00223 count=(ssize_t) write(destination_file,buffer,length);
00224 if ((size_t) count != length)
00225 {
00226 (void) close(destination_file);
00227 (void) close(source_file);
00228 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00229 (void) RelinquishUniqueFileResource(destination);
00230 return(MagickFalse);
00231 }
00232 }
00233 (void) close(destination_file);
00234 (void) close(source_file);
00235 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00236 return(MagickTrue);
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
00264
00265
00266 MagickExport void AppendImageFormat(const char *format,char *filename)
00267 {
00268 char
00269 root[MaxTextExtent];
00270
00271 assert(format != (char *) NULL);
00272 assert(filename != (char *) NULL);
00273 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00274 if ((*format == '\0') || (*filename == '\0'))
00275 return;
00276 if (LocaleCompare(filename,"-") == 0)
00277 {
00278 char
00279 message[MaxTextExtent];
00280
00281 (void) FormatMagickString(message,MaxTextExtent,"%s:%s",format,filename);
00282 (void) CopyMagickString(filename,message,MaxTextExtent);
00283 return;
00284 }
00285 GetPathComponent(filename,RootPath,root);
00286 (void) FormatMagickString(filename,MaxTextExtent,"%s.%s",root,format);
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
00313
00314
00315 MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
00316 {
00317 int
00318 state;
00319
00320 register const char
00321 *p,
00322 *q;
00323
00324 register size_t
00325 i;
00326
00327 unsigned char
00328 *decode;
00329
00330 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00331 assert(source != (char *) NULL);
00332 assert(length != (size_t *) NULL);
00333 *length=0;
00334 decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
00335 3*sizeof(*decode));
00336 if (decode == (unsigned char *) NULL)
00337 return((unsigned char *) NULL);
00338 i=0;
00339 state=0;
00340 for (p=source; *p != '\0'; p++)
00341 {
00342 if (isspace((int) ((unsigned char) *p)) != 0)
00343 continue;
00344 if (*p == '=')
00345 break;
00346 q=strchr(Base64,*p);
00347 if (q == (char *) NULL)
00348 {
00349 decode=(unsigned char *) RelinquishMagickMemory(decode);
00350 return((unsigned char *) NULL);
00351 }
00352 switch (state)
00353 {
00354 case 0:
00355 {
00356 decode[i]=(q-Base64) << 2;
00357 state++;
00358 break;
00359 }
00360 case 1:
00361 {
00362 decode[i++]|=(q-Base64) >> 4;
00363 decode[i]=((q-Base64) & 0x0f) << 4;
00364 state++;
00365 break;
00366 }
00367 case 2:
00368 {
00369 decode[i++]|=(q-Base64) >> 2;
00370 decode[i]=((q-Base64) & 0x03) << 6;
00371 state++;
00372 break;
00373 }
00374 case 3:
00375 {
00376 decode[i++]|=(q-Base64);
00377 state=0;
00378 break;
00379 }
00380 }
00381 }
00382
00383
00384
00385 if (*p != '=')
00386 {
00387 if (state != 0)
00388 {
00389 decode=(unsigned char *) RelinquishMagickMemory(decode);
00390 return((unsigned char *) NULL);
00391 }
00392 }
00393 else
00394 {
00395 p++;
00396 switch (state)
00397 {
00398 case 0:
00399 case 1:
00400 {
00401
00402
00403
00404 decode=(unsigned char *) RelinquishMagickMemory(decode);
00405 return((unsigned char *) NULL);
00406 }
00407 case 2:
00408 {
00409 for ( ; *p != '\0'; p++)
00410 if (isspace((int) ((unsigned char) *p)) == 0)
00411 break;
00412 if (*p != '=')
00413 {
00414 decode=(unsigned char *) RelinquishMagickMemory(decode);
00415 return((unsigned char *) NULL);
00416 }
00417 p++;
00418 }
00419 case 3:
00420 {
00421 for ( ; *p != '\0'; p++)
00422 if (isspace((int) ((unsigned char) *p)) == 0)
00423 {
00424 decode=(unsigned char *) RelinquishMagickMemory(decode);
00425 return((unsigned char *) NULL);
00426 }
00427 if ((int) decode[i] != 0)
00428 {
00429 decode=(unsigned char *) RelinquishMagickMemory(decode);
00430 return((unsigned char *) NULL);
00431 }
00432 }
00433 }
00434 }
00435 *length=i;
00436 return(decode);
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
00467
00468
00469 MagickExport char *Base64Encode(const unsigned char *blob,
00470 const size_t blob_length,size_t *encode_length)
00471 {
00472 char
00473 *encode;
00474
00475 register const unsigned char
00476 *p;
00477
00478 register size_t
00479 i;
00480
00481 size_t
00482 remainder;
00483
00484 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00485 assert(blob != (const unsigned char *) NULL);
00486 assert(blob_length != 0);
00487 assert(encode_length != (size_t *) NULL);
00488 *encode_length=0;
00489 encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
00490 if (encode == (char *) NULL)
00491 return((char *) NULL);
00492 i=0;
00493 for (p=blob; p < (blob+blob_length-2); p+=3)
00494 {
00495 encode[i++]=Base64[(int) (*p >> 2)];
00496 encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
00497 encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
00498 encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
00499 }
00500 remainder=blob_length % 3;
00501 if (remainder != 0)
00502 {
00503 long
00504 j;
00505
00506 unsigned char
00507 code[3];
00508
00509 code[0]='\0';
00510 code[1]='\0';
00511 code[2]='\0';
00512 for (j=0; j < (long) remainder; j++)
00513 code[j]=(*p++);
00514 encode[i++]=Base64[(int) (code[0] >> 2)];
00515 encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
00516 if (remainder == 1)
00517 encode[i++]='=';
00518 else
00519 encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
00520 encode[i++]='=';
00521 }
00522 *encode_length=i;
00523 encode[i++]='\0';
00524 return(encode);
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
00550
00551
00552 MagickExport void ChopPathComponents(char *path,const unsigned long components)
00553 {
00554 register long
00555 i;
00556
00557 for (i=0; i < (long) components; i++)
00558 GetPathComponent(path,HeadPath,path);
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 MagickExport void ExpandFilename(char *path)
00585 {
00586 char
00587 expand_path[MaxTextExtent];
00588
00589 if (path == (char *) NULL)
00590 return;
00591 if (*path != '~')
00592 return;
00593 (void) CopyMagickString(expand_path,path,MaxTextExtent);
00594 if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
00595 {
00596 char
00597 *home;
00598
00599
00600
00601
00602 (void) CopyMagickString(expand_path,".",MaxTextExtent);
00603 (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00604 home=GetEnvironmentValue("HOME");
00605 if (home == (char *) NULL)
00606 home=GetEnvironmentValue("USERPROFILE");
00607 if (home != (char *) NULL)
00608 {
00609 (void) CopyMagickString(expand_path,home,MaxTextExtent);
00610 (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00611 home=DestroyString(home);
00612 }
00613 }
00614 else
00615 {
00616 #if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
00617 char
00618 username[MaxTextExtent];
00619
00620 register char
00621 *p;
00622
00623 struct passwd
00624 *entry;
00625
00626
00627
00628
00629 (void) CopyMagickString(username,path+1,MaxTextExtent);
00630 p=strchr(username,'/');
00631 if (p != (char *) NULL)
00632 *p='\0';
00633 entry=getpwnam(username);
00634 if (entry == (struct passwd *) NULL)
00635 return;
00636 (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
00637 if (p != (char *) NULL)
00638 {
00639 (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
00640 (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
00641 }
00642 #endif
00643 }
00644 (void) CopyMagickString(path,expand_path,MaxTextExtent);
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
00673
00674
00675 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
00676 char ***arguments)
00677 {
00678 char
00679 *cwd,
00680 home_directory[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
00696
00697 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00698 assert(number_arguments != (int *) NULL);
00699 assert(arguments != (char ***) NULL);
00700 vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
00701 sizeof(*vector));
00702 if (vector == (char **) NULL)
00703 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00704
00705
00706
00707 *home_directory='\0';
00708 count=0;
00709 for (i=0; i < (long) *number_arguments; i++)
00710 {
00711 char
00712 **filelist,
00713 filename[MaxTextExtent],
00714 magick[MaxTextExtent],
00715 *option,
00716 path[MaxTextExtent],
00717 subimage[MaxTextExtent];
00718
00719 MagickBooleanType
00720 destroy;
00721
00722 option=(*arguments)[i];
00723 *magick='\0';
00724 *path='\0';
00725 *filename='\0';
00726 *subimage='\0';
00727 vector[count++]=ConstantString(option);
00728 destroy=MagickTrue;
00729 parameters=ParseMagickOption(MagickCommandOptions,MagickFalse,option);
00730 if (parameters > 0)
00731 {
00732
00733
00734
00735 for (j=0; j < parameters; j++)
00736 {
00737 i++;
00738 if (i == (long) *number_arguments)
00739 break;
00740 option=(*arguments)[i];
00741 vector[count++]=ConstantString(option);
00742 }
00743 continue;
00744 }
00745 if ((*option == '"') || (*option == '\''))
00746 continue;
00747 GetPathComponent(option,TailPath,filename);
00748 GetPathComponent(option,MagickPath,magick);
00749 if ((LocaleCompare(magick,"CAPTION") == 0) ||
00750 (LocaleCompare(magick,"LABEL") == 0) ||
00751 (LocaleCompare(magick,"VID") == 0))
00752 continue;
00753 if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
00754 continue;
00755 if (*filename != '@')
00756 {
00757
00758
00759
00760 GetPathComponent(option,HeadPath,path);
00761 GetPathComponent(option,SubimagePath,subimage);
00762 ExpandFilename(path);
00763 if (*home_directory == '\0')
00764 cwd=getcwd(home_directory,MaxTextExtent-1);
00765 filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
00766 &number_files);
00767 }
00768 else
00769 {
00770 char
00771 *files;
00772
00773 ExceptionInfo
00774 *exception;
00775
00776 int
00777 number_images;
00778
00779
00780
00781
00782 exception=AcquireExceptionInfo();
00783 files=FileToString(filename+1,~0,exception);
00784 exception=DestroyExceptionInfo(exception);
00785 if (files == (char *) NULL)
00786 continue;
00787 StripString(files);
00788 filelist=StringToArgv(files,&number_images);
00789 files=DestroyString(files);
00790 number_files=(unsigned long) number_images;
00791 if (filelist != (char **) NULL)
00792 {
00793 number_files--;
00794 for (j=0; j < (long) number_files; j++)
00795 filelist[j]=filelist[j+1];
00796 }
00797 }
00798 if (filelist == (char **) NULL)
00799 continue;
00800 for (j=0; j < (long) number_files; j++)
00801 if (IsPathDirectory(filelist[j]) <= 0)
00802 break;
00803 if (j == (long) number_files)
00804 {
00805 for (j=0; j < (long) number_files; j++)
00806 filelist[j]=DestroyString(filelist[j]);
00807 filelist=(char **) RelinquishMagickMemory(filelist);
00808 continue;
00809 }
00810
00811
00812
00813 vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
00814 count+number_files+1,sizeof(*vector));
00815 if (vector == (char **) NULL)
00816 return(MagickFalse);
00817 for (j=0; j < (long) number_files; j++)
00818 {
00819 (void) CopyMagickString(filename,path,MaxTextExtent);
00820 if (*path != '\0')
00821 (void) ConcatenateMagickString(filename,DirectorySeparator,
00822 MaxTextExtent);
00823 (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
00824 filelist[j]=DestroyString(filelist[j]);
00825 if (strlen(filename) >= MaxTextExtent)
00826 ThrowFatalException(OptionFatalError,"FilenameTruncated");
00827 if (IsPathDirectory(filename) == 0)
00828 {
00829 char
00830 path[MaxTextExtent];
00831
00832 *path='\0';
00833 if (*magick != '\0')
00834 {
00835 (void) ConcatenateMagickString(path,magick,MaxTextExtent);
00836 (void) ConcatenateMagickString(path,":",MaxTextExtent);
00837 }
00838 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00839 if (*subimage != '\0')
00840 {
00841 (void) ConcatenateMagickString(path,"[",MaxTextExtent);
00842 (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
00843 (void) ConcatenateMagickString(path,"]",MaxTextExtent);
00844 }
00845 if (strlen(path) >= MaxTextExtent)
00846 ThrowFatalException(OptionFatalError,"FilenameTruncated");
00847 if (destroy != MagickFalse)
00848 {
00849 count--;
00850 vector[count]=DestroyString(vector[count]);
00851 destroy=MagickFalse;
00852 }
00853 vector[count++]=ConstantString(path);
00854 }
00855 }
00856 filelist=(char **) RelinquishMagickMemory(filelist);
00857 }
00858 vector[count]=(char *) NULL;
00859 if (IsEventLogging() != MagickFalse)
00860 {
00861 char
00862 *command_line;
00863
00864 command_line=AcquireString(vector[0]);
00865 for (i=1; i < count; i++)
00866 {
00867 (void) ConcatenateString(&command_line," {");
00868 (void) ConcatenateString(&command_line,vector[i]);
00869 (void) ConcatenateString(&command_line,"}");
00870 }
00871 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00872 "Command line: %s",command_line);
00873 command_line=DestroyString(command_line);
00874 }
00875 *number_arguments=(int) count;
00876 *arguments=vector;
00877 return(MagickTrue);
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
00903
00904
00905 MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00906 {
00907 char
00908 *cwd;
00909
00910 *path='\0';
00911 cwd=getcwd(path,(unsigned long) extent);
00912 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
00913 {
00914 char
00915 link_path[MaxTextExtent],
00916 execution_path[PATH_MAX+1];
00917
00918 ssize_t
00919 count;
00920
00921 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/exe",
00922 (long) getpid());
00923 count=readlink(link_path,execution_path,PATH_MAX);
00924 if (count == -1)
00925 {
00926 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/file",
00927 (long) getpid());
00928 count=readlink(link_path,execution_path,PATH_MAX);
00929 }
00930 if ((count > 0) && (count <= (ssize_t) PATH_MAX))
00931 {
00932 execution_path[count]='\0';
00933 (void) CopyMagickString(path,execution_path,extent);
00934 }
00935 }
00936 #endif
00937 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
00938 {
00939 char
00940 executable_path[PATH_MAX << 1],
00941 execution_path[PATH_MAX+1];
00942
00943 uint32_t
00944 length;
00945
00946 length=sizeof(executable_path);
00947 if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
00948 (realpath(executable_path,execution_path) != (char *) NULL))
00949 (void) CopyMagickString(path,execution_path,extent);
00950 }
00951 #endif
00952 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
00953 {
00954 const char
00955 *execution_path;
00956
00957 execution_path=(const char *) getexecname();
00958 if (execution_path != (const char *) NULL)
00959 {
00960 if (*execution_path != *DirectorySeparator)
00961 (void) ConcatenateMagickString(path,DirectorySeparator,extent);
00962 (void) ConcatenateMagickString(path,execution_path,extent);
00963 }
00964 }
00965 #endif
00966 #if defined(__WINDOWS__)
00967 NTGetExecutionPath(path,extent);
00968 #endif
00969 #if defined(__GNU__)
00970 {
00971 char
00972 *program_name,
00973 *execution_path;
00974
00975 long
00976 count;
00977
00978 count=0;
00979 execution_path=(char *) NULL;
00980 program_name=program_invocation_name;
00981 if (*program_invocation_name != '/')
00982 {
00983 size_t
00984 extent;
00985
00986 extent=strlen(cwd)+strlen(program_name)+1;
00987 program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
00988 if (program_name == (char *) NULL)
00989 program_name=program_invocation_name;
00990 else
00991 count=FormatMagickString(program_name,extent,"%s/%s",cwd,
00992 program_invocation_name);
00993 }
00994 if (count != -1)
00995 {
00996 execution_path=realpath(program_name,NULL);
00997 if (execution_path != (char *) NULL)
00998 (void) CopyMagickString(path,execution_path,extent);
00999 }
01000 if (program_name != program_invocation_name)
01001 program_name=(char *) RelinquishMagickMemory(program_name);
01002 execution_path=(char *) RelinquishMagickMemory(execution_path);
01003 }
01004 #endif
01005 return(IsPathAccessible(path));
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 MagickExport long GetMagickPageSize(void)
01027 {
01028 static long
01029 page_size = -1;
01030
01031 if (page_size > 0)
01032 return(page_size);
01033 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
01034 page_size=sysconf(_SC_PAGE_SIZE);
01035 #else
01036 #if defined(MAGICKCORE_HAVE_GETPAGESIZE)
01037 page_size=getpagesize();
01038 #endif
01039 #endif
01040 if (page_size <= 0)
01041 page_size=16384;
01042 return(page_size);
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
01068
01069
01070 #if defined(MAGICKCORE_HAVE__WFOPEN)
01071 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
01072 {
01073 register const unsigned char
01074 *p;
01075
01076 if (utf16 != (wchar_t *) NULL)
01077 {
01078 register wchar_t
01079 *q;
01080
01081 wchar_t
01082 c;
01083
01084
01085
01086
01087 q=utf16;
01088 for (p=utf8; *p != '\0'; p++)
01089 {
01090 if ((*p & 0x80) == 0)
01091 *q=(*p);
01092 else
01093 if ((*p & 0xE0) == 0xC0)
01094 {
01095 c=(*p);
01096 *q=(c & 0x1F) << 6;
01097 p++;
01098 if ((*p & 0xC0) != 0x80)
01099 return(0);
01100 *q|=(*p & 0x3F);
01101 }
01102 else
01103 if ((*p & 0xF0) == 0xE0)
01104 {
01105 c=(*p);
01106 *q=c << 12;
01107 p++;
01108 if ((*p & 0xC0) != 0x80)
01109 return(0);
01110 c=(*p);
01111 *q|=(c & 0x3F) << 6;
01112 p++;
01113 if ((*p & 0xC0) != 0x80)
01114 return(0);
01115 *q|=(*p & 0x3F);
01116 }
01117 else
01118 return(0);
01119 q++;
01120 }
01121 *q++='\0';
01122 return(q-utf16);
01123 }
01124
01125
01126
01127 for (p=utf8; *p != '\0'; p++)
01128 {
01129 if ((*p & 0x80) == 0)
01130 ;
01131 else
01132 if ((*p & 0xE0) == 0xC0)
01133 {
01134 p++;
01135 if ((*p & 0xC0) != 0x80)
01136 return(0);
01137 }
01138 else
01139 if ((*p & 0xF0) == 0xE0)
01140 {
01141 p++;
01142 if ((*p & 0xC0) != 0x80)
01143 return(0);
01144 p++;
01145 if ((*p & 0xC0) != 0x80)
01146 return(0);
01147 }
01148 else
01149 return(0);
01150 }
01151 return(p-utf8);
01152 }
01153
01154 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
01155 {
01156 size_t
01157 length;
01158
01159 wchar_t
01160 *utf16;
01161
01162 length=UTF8ToUTF16(source,(wchar_t *) NULL);
01163 if (length == 0)
01164 {
01165 register long
01166 i;
01167
01168
01169
01170
01171 length=strlen(source);
01172 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01173 if (utf16 == (wchar_t *) NULL)
01174 return((wchar_t *) NULL);
01175 for (i=0; i <= (long) length; i++)
01176 utf16[i]=source[i];
01177 return(utf16);
01178 }
01179 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01180 if (utf16 == (wchar_t *) NULL)
01181 return((wchar_t *) NULL);
01182 length=UTF8ToUTF16(source,utf16);
01183 return(utf16);
01184 }
01185 #endif
01186
01187 MagickExport MagickBooleanType GetPathAttributes(const char *path,
01188 void *attributes)
01189 {
01190 MagickBooleanType
01191 status;
01192
01193 if (path == (const char *) NULL)
01194 {
01195 errno=EINVAL;
01196 return(MagickFalse);
01197 }
01198 #if !defined(MAGICKCORE_HAVE__WSTAT)
01199 status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
01200 #else
01201 {
01202 wchar_t
01203 *unicode_path;
01204
01205 unicode_path=ConvertUTF8ToUTF16(path);
01206 if (unicode_path == (wchar_t *) NULL)
01207 return(MagickFalse);
01208 status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
01209 MagickFalse;
01210 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01211 }
01212 #endif
01213 return(status);
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
01242
01243
01244 MagickExport void GetPathComponent(const char *path,PathType type,
01245 char *component)
01246 {
01247 char
01248 magick[MaxTextExtent],
01249 *q,
01250 subimage[MaxTextExtent];
01251
01252 register char
01253 *p;
01254
01255 assert(path != (const char *) NULL);
01256 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
01257 assert(component != (char *) NULL);
01258 if (*path == '\0')
01259 {
01260 *component='\0';
01261 return;
01262 }
01263 (void) CopyMagickString(component,path,MaxTextExtent);
01264 *magick='\0';
01265 #if defined(__OS2__)
01266 if (path[1] != ":")
01267 #endif
01268 for (p=component; *p != '\0'; p++)
01269 if ((*p == ':') && (IsPathDirectory(path) < 0) &&
01270 (IsPathAccessible(path) == MagickFalse))
01271 {
01272
01273
01274
01275 (void) CopyMagickString(magick,component,(size_t) (p-component+1));
01276 if (IsMagickConflict(magick) != MagickFalse)
01277 *magick='\0';
01278 else
01279 for (q=component; *q != '\0'; q++)
01280 *q=(*++p);
01281 break;
01282 }
01283 *subimage='\0';
01284 p=component;
01285 if (*p != '\0')
01286 p=component+strlen(component)-1;
01287 if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
01288 (IsPathAccessible(path) == MagickFalse))
01289 {
01290
01291
01292
01293 for (q=p-1; q > component; q--)
01294 if (*q == '[')
01295 break;
01296 if (*q == '[')
01297 {
01298 (void) CopyMagickString(subimage,q+1,MaxTextExtent);
01299 subimage[p-q-1]='\0';
01300 if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
01301 (IsGeometry(subimage) == MagickFalse))
01302 *subimage='\0';
01303 else
01304 *q='\0';
01305 }
01306 }
01307 p=component;
01308 if (*p != '\0')
01309 for (p=component+strlen(component)-1; p > component; p--)
01310 if (IsBasenameSeparator(*p) != MagickFalse)
01311 break;
01312 switch (type)
01313 {
01314 case MagickPath:
01315 {
01316 (void) CopyMagickString(component,magick,MaxTextExtent);
01317 break;
01318 }
01319 case RootPath:
01320 {
01321 for (p=component+(strlen(component)-1); p > component; p--)
01322 {
01323 if (IsBasenameSeparator(*p) != MagickFalse)
01324 break;
01325 if (*p == '.')
01326 break;
01327 }
01328 if (*p == '.')
01329 *p='\0';
01330 break;
01331 }
01332 case HeadPath:
01333 {
01334 *p='\0';
01335 break;
01336 }
01337 case TailPath:
01338 {
01339 if (IsBasenameSeparator(*p) != MagickFalse)
01340 (void) CopyMagickMemory((unsigned char *) component,
01341 (const unsigned char *) (p+1),strlen(p+1)+1);
01342 break;
01343 }
01344 case BasePath:
01345 {
01346 if (IsBasenameSeparator(*p) != MagickFalse)
01347 (void) CopyMagickString(component,p+1,MaxTextExtent);
01348 for (p=component+(strlen(component)-1); p > component; p--)
01349 if (*p == '.')
01350 {
01351 *p='\0';
01352 break;
01353 }
01354 break;
01355 }
01356 case ExtensionPath:
01357 {
01358 if (IsBasenameSeparator(*p) != MagickFalse)
01359 (void) CopyMagickString(component,p+1,MaxTextExtent);
01360 p=component;
01361 if (*p != '\0')
01362 for (p=component+strlen(component)-1; p > component; p--)
01363 if (*p == '.')
01364 break;
01365 *component='\0';
01366 if (*p == '.')
01367 (void) CopyMagickString(component,p+1,MaxTextExtent);
01368 break;
01369 }
01370 case SubimagePath:
01371 {
01372 (void) CopyMagickString(component,subimage,MaxTextExtent);
01373 break;
01374 }
01375 case CanonicalPath:
01376 case UndefinedPath:
01377 break;
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
01404
01405
01406 MagickExport char **GetPathComponents(const char *path,
01407 unsigned long *number_components)
01408 {
01409 char
01410 **components;
01411
01412 register const char
01413 *p,
01414 *q;
01415
01416 register long
01417 i;
01418
01419 if (path == (char *) NULL)
01420 return((char **) NULL);
01421 *number_components=1;
01422 for (p=path; *p != '\0'; p++)
01423 if (IsBasenameSeparator(*p))
01424 (*number_components)++;
01425 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
01426 sizeof(*components));
01427 if (components == (char **) NULL)
01428 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01429 p=path;
01430 for (i=0; i < (long) *number_components; i++)
01431 {
01432 for (q=p; *q != '\0'; q++)
01433 if (IsBasenameSeparator(*q))
01434 break;
01435 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
01436 sizeof(*components));
01437 if (components[i] == (char *) NULL)
01438 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01439 (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
01440 p=q+1;
01441 }
01442 components[i]=(char *) NULL;
01443 return(components);
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 MagickExport MagickBooleanType IsPathAccessible(const char *path)
01470 {
01471 MagickBooleanType
01472 status;
01473
01474 struct stat
01475 attributes;
01476
01477 if ((path == (const char *) NULL) || (*path == '\0'))
01478 return(MagickFalse);
01479 status=GetPathAttributes(path,&attributes);
01480 if (status == MagickFalse)
01481 return(status);
01482 if (S_ISREG(attributes.st_mode) == 0)
01483 return(MagickFalse);
01484 if (access(path,F_OK) != 0)
01485 return(MagickFalse);
01486 return(MagickTrue);
01487 }
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512 static int IsPathDirectory(const char *path)
01513 {
01514 MagickBooleanType
01515 status;
01516
01517 struct stat
01518 attributes;
01519
01520 if ((path == (const char *) NULL) || (*path == '\0'))
01521 return(MagickFalse);
01522 status=GetPathAttributes(path,&attributes);
01523 if (status == MagickFalse)
01524 return(-1);
01525 if (S_ISDIR(attributes.st_mode) == 0)
01526 return(0);
01527 return(1);
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
01554
01555
01556 MagickExport MagickBooleanType IsMagickTrue(const char *value)
01557 {
01558 if (value == (const char *) NULL)
01559 return(MagickFalse);
01560 if (LocaleCompare(value,"true") == 0)
01561 return(MagickTrue);
01562 if (LocaleCompare(value,"on") == 0)
01563 return(MagickTrue);
01564 if (LocaleCompare(value,"yes") == 0)
01565 return(MagickTrue);
01566 if (LocaleCompare(value,"1") == 0)
01567 return(MagickTrue);
01568 return(MagickFalse);
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
01604
01605
01606 #if defined(__cplusplus) || defined(c_plusplus)
01607 extern "C" {
01608 #endif
01609
01610 static int FileCompare(const void *x,const void *y)
01611 {
01612 register const char
01613 **p,
01614 **q;
01615
01616 p=(const char **) x;
01617 q=(const char **) y;
01618 return(LocaleCompare(*p,*q));
01619 }
01620
01621 #if defined(__cplusplus) || defined(c_plusplus)
01622 }
01623 #endif
01624
01625 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
01626 struct dirent **result)
01627 {
01628 #if defined(MAGICKCORE_HAVE_READDIR_R)
01629 return(readdir_r(directory,entry,result));
01630 #else
01631 (void) entry;
01632 errno=0;
01633 *result=readdir(directory);
01634 return(errno);
01635 #endif
01636 }
01637
01638 MagickExport char **ListFiles(const char *directory,const char *pattern,
01639 unsigned long *number_entries)
01640 {
01641 char
01642 **filelist;
01643
01644 DIR
01645 *current_directory;
01646
01647 struct dirent
01648 *buffer,
01649 *entry;
01650
01651 unsigned long
01652 max_entries;
01653
01654
01655
01656
01657 assert(directory != (const char *) NULL);
01658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
01659 assert(pattern != (const char *) NULL);
01660 assert(number_entries != (unsigned long *) NULL);
01661 *number_entries=0;
01662 current_directory=opendir(directory);
01663 if (current_directory == (DIR *) NULL)
01664 return((char **) NULL);
01665
01666
01667
01668 max_entries=2048;
01669 filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
01670 sizeof(*filelist));
01671 if (filelist == (char **) NULL)
01672 {
01673 (void) closedir(current_directory);
01674 return((char **) NULL);
01675 }
01676
01677
01678
01679 buffer=(struct dirent *) AcquireAlignedMemory(1,sizeof(*buffer)+FILENAME_MAX+1);
01680 if (buffer == (struct dirent *) NULL)
01681 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01682 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
01683 (entry != (struct dirent *) NULL))
01684 {
01685 if (*entry->d_name == '.')
01686 continue;
01687 if ((IsPathDirectory(entry->d_name) > 0) ||
01688 #if defined(__WINDOWS__)
01689 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
01690 #else
01691 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
01692 #endif
01693 {
01694 if (*number_entries >= max_entries)
01695 {
01696
01697
01698
01699 max_entries<<=1;
01700 filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
01701 max_entries,sizeof(*filelist));
01702 if (filelist == (char **) NULL)
01703 break;
01704 }
01705 #if defined(vms)
01706 {
01707 register char
01708 *p;
01709
01710 p=strchr(entry->d_name,';');
01711 if (p)
01712 *p='\0';
01713 if (*number_entries > 0)
01714 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
01715 continue;
01716 }
01717 #endif
01718 filelist[*number_entries]=(char *) AcquireString(entry->d_name);
01719 if (IsPathDirectory(entry->d_name) > 0)
01720 (void) ConcatenateMagickString(filelist[*number_entries],
01721 DirectorySeparator,MaxTextExtent);
01722 (*number_entries)++;
01723 }
01724 }
01725 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
01726 (void) closedir(current_directory);
01727 if (filelist == (char **) NULL)
01728 return((char **) NULL);
01729
01730
01731
01732 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
01733 FileCompare);
01734 return(filelist);
01735 }
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761 MagickExport unsigned long MultilineCensus(const char *label)
01762 {
01763 unsigned long
01764 number_lines;
01765
01766
01767
01768
01769 if (label == (char *) NULL)
01770 return(0);
01771 for (number_lines=1; *label != '\0'; label++)
01772 if (*label == '\n')
01773 number_lines++;
01774 return(number_lines);
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
01800
01801
01802 MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
01803 {
01804 FILE
01805 *file;
01806
01807 if ((path == (const char *) NULL) || (mode == (const char *) NULL))
01808 {
01809 errno=EINVAL;
01810 return((FILE *) NULL);
01811 }
01812 file=(FILE *) NULL;
01813 #if defined(MAGICKCORE_HAVE__WFOPEN)
01814 {
01815 wchar_t
01816 *unicode_mode,
01817 *unicode_path;
01818
01819 unicode_path=ConvertUTF8ToUTF16(path);
01820 if (unicode_path == (wchar_t *) NULL)
01821 return((FILE *) NULL);
01822 unicode_mode=ConvertUTF8ToUTF16(mode);
01823 if (unicode_mode == (wchar_t *) NULL)
01824 {
01825 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01826 return((FILE *) NULL);
01827 }
01828 file=_wfopen(unicode_path,unicode_mode);
01829 unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
01830 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01831 }
01832 #endif
01833 if (file == (FILE *) NULL)
01834 file=fopen(path,mode);
01835 return(file);
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
01865
01866
01867
01868
01869
01870
01871 MagickExport int SystemCommand(const MagickBooleanType asynchronous,
01872 const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
01873 {
01874 char
01875 **arguments,
01876 *shell_command;
01877
01878 int
01879 number_arguments,
01880 status;
01881
01882 PolicyDomain
01883 domain;
01884
01885 PolicyRights
01886 rights;
01887
01888 register long
01889 i;
01890
01891 status=(-1);
01892 arguments=StringToArgv(command,&number_arguments);
01893 if (arguments == (char **) NULL)
01894 return(status);
01895 rights=ExecutePolicyRights;
01896 domain=DelegatePolicyDomain;
01897 if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
01898 {
01899 errno=EPERM;
01900 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
01901 "NotAuthorized","`%s'",arguments[1]);
01902 for (i=0; i < number_arguments; i++)
01903 arguments[i]=DestroyString(arguments[i]);
01904 arguments=(char **) RelinquishMagickMemory(arguments);
01905 return(-1);
01906 }
01907 if (verbose != MagickFalse)
01908 {
01909 (void) fprintf(stderr,"%s\n",command);
01910 (void) fflush(stderr);
01911 }
01912 shell_command=(char *) command;
01913 if (asynchronous != MagickFalse)
01914 {
01915 shell_command=AcquireString(command);
01916 (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
01917 }
01918 #if defined(MAGICKCORE_POSIX_SUPPORT)
01919 #if !defined(MAGICKCORE_HAVE_EXECVP)
01920 status=system(shell_command);
01921 #else
01922 if ((asynchronous != MagickFalse) || (strspn(shell_command,"&;<>|") == 0))
01923 status=system(shell_command);
01924 else
01925 {
01926 pid_t
01927 child_pid;
01928
01929
01930
01931
01932 child_pid=fork();
01933 if (child_pid == (pid_t) -1)
01934 status=system(command);
01935 else
01936 if (child_pid == 0)
01937 {
01938 status=execvp(arguments[1],arguments+1);
01939 _exit(1);
01940 }
01941 else
01942 {
01943 int
01944 child_status;
01945
01946 pid_t
01947 pid;
01948
01949 child_status=0;
01950 pid=waitpid(child_pid,&child_status,0);
01951 if (pid == -1)
01952 status=(-1);
01953 else
01954 {
01955 if (WIFEXITED(child_status) != 0)
01956 status=WEXITSTATUS(child_status);
01957 else
01958 if (WIFSIGNALED(child_status))
01959 status=(-1);
01960 }
01961 }
01962 }
01963 #endif
01964 #elif defined(__WINDOWS__)
01965 {
01966 int
01967 mode;
01968
01969 mode=_P_WAIT;
01970 if (asynchronous != MagickFalse)
01971 mode=_P_NOWAIT;
01972 status=spawnvp(mode,arguments[1],arguments+1);
01973 }
01974 #elif defined(macintosh)
01975 status=MACSystemCommand(shell_command);
01976 #elif defined(vms)
01977 status=system(shell_command);
01978 #else
01979 # error No suitable system() method.
01980 #endif
01981 if (status < 0)
01982 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
01983 "`%s' (%d)",command,status);
01984 if (shell_command != command)
01985 shell_command=DestroyString(shell_command);
01986 for (i=0; i < number_arguments; i++)
01987 arguments[i]=DestroyString(arguments[i]);
01988 arguments=(char **) RelinquishMagickMemory(arguments);
01989 return(status);
01990 }