1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% U U TTTTT IIIII L IIIII TTTTT Y Y % 7% U U T I L I T Y Y % 8% U U T I L I T Y % 9% U U T I L I T Y % 10% UUU T IIIII LLLLL IIIII T Y % 11% % 12% % 13% MagickCore Utility Methods % 14% % 15% Software Design % 16% Cristy % 17% January 1993 % 18% % 19% % 20% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21% dedicated to making software imaging solutions freely available. % 22% % 23% You may not use this file except in compliance with the License. You may % 24% obtain a copy of the License at % 25% % 26% http://www.imagemagick.org/script/license.php % 27% % 28% Unless required by applicable law or agreed to in writing, software % 29% distributed under the License is distributed on an "AS IS" BASIS, % 30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31% See the License for the specific language governing permissions and % 32% limitations under the License. % 33% % 34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35% 36% 37*/ 38 39/* 40 Include declarations. 41*/ 42#include "MagickCore/studio.h" 43#include "MagickCore/property.h" 44#include "MagickCore/blob.h" 45#include "MagickCore/color.h" 46#include "MagickCore/exception.h" 47#include "MagickCore/exception-private.h" 48#include "MagickCore/geometry.h" 49#include "MagickCore/image-private.h" 50#include "MagickCore/list.h" 51#include "MagickCore/log.h" 52#include "MagickCore/magick-private.h" 53#include "MagickCore/memory_.h" 54#include "MagickCore/nt-base-private.h" 55#include "MagickCore/option.h" 56#include "MagickCore/policy.h" 57#include "MagickCore/random_.h" 58#include "MagickCore/registry.h" 59#include "MagickCore/resource_.h" 60#include "MagickCore/semaphore.h" 61#include "MagickCore/signature-private.h" 62#include "MagickCore/statistic.h" 63#include "MagickCore/string_.h" 64#include "MagickCore/string-private.h" 65#include "MagickCore/token.h" 66#include "MagickCore/token-private.h" 67#include "MagickCore/utility.h" 68#include "MagickCore/utility-private.h" 69#if defined(MAGICKCORE_HAVE_PROCESS_H) 70#include <process.h> 71#endif 72#if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H) 73#include <mach-o/dyld.h> 74#endif 75 76/* 77 Static declarations. 78*/ 79static const char 80 Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 81 82/* 83 Forward declaration. 84*/ 85static int 86 IsPathDirectory(const char *); 87 88/* 89%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 90% % 91% % 92% % 93% A c q u i r e U n i q u e F i l e n a m e % 94% % 95% % 96% % 97%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 98% 99% AcquireUniqueFilename() replaces the contents of path by a unique path name. 100% 101% The format of the AcquireUniqueFilename method is: 102% 103% MagickBooleanType AcquireUniqueFilename(char *path) 104% 105% A description of each parameter follows. 106% 107% o path: Specifies a pointer to an array of characters. The unique path 108% name is returned in this array. 109% 110*/ 111MagickExport MagickBooleanType AcquireUniqueFilename(char *path) 112{ 113 int 114 file; 115 116 file=AcquireUniqueFileResource(path); 117 if (file == -1) 118 return(MagickFalse); 119 file=close(file)-1; 120 return(MagickTrue); 121} 122 123/* 124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 125% % 126% % 127% % 128% A c q u i r e U n i q u e S ym b o l i c L i n k % 129% % 130% % 131% % 132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 133% 134% AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified 135% source path and returns MagickTrue on success otherwise MagickFalse. If the 136% symlink() method fails or is not available, a unique file name is generated 137% and the source file copied to it. When you are finished with the file, use 138% RelinquishUniqueFilename() to destroy it. 139% 140% The format of the AcquireUniqueSymbolicLink method is: 141% 142% MagickBooleanType AcquireUniqueSymbolicLink(const char *source, 143% char destination) 144% 145% A description of each parameter follows. 146% 147% o source: the source path. 148% 149% o destination: the destination path. 150% 151*/ 152 153MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source, 154 char *destination) 155{ 156 int 157 destination_file, 158 source_file; 159 160 size_t 161 length, 162 quantum; 163 164 ssize_t 165 count; 166 167 struct stat 168 attributes; 169 170 unsigned char 171 *buffer; 172 173 assert(source != (const char *) NULL); 174 assert(destination != (char *) NULL); 175#if defined(MAGICKCORE_HAVE_SYMLINK) 176 (void) AcquireUniqueFilename(destination); 177 (void) RelinquishUniqueFileResource(destination); 178 if (*source == *DirectorySeparator) 179 { 180 if (symlink(source,destination) == 0) 181 return(MagickTrue); 182 } 183 else 184 { 185 char 186 path[MagickPathExtent]; 187 188 *path='\0'; 189 if (getcwd(path,MagickPathExtent) == (char *) NULL) 190 return(MagickFalse); 191 (void) ConcatenateMagickString(path,DirectorySeparator,MagickPathExtent); 192 (void) ConcatenateMagickString(path,source,MagickPathExtent); 193 if (symlink(path,destination) == 0) 194 return(MagickTrue); 195 } 196#endif 197 destination_file=AcquireUniqueFileResource(destination); 198 if (destination_file == -1) 199 return(MagickFalse); 200 source_file=open_utf8(source,O_RDONLY | O_BINARY,0); 201 if (source_file == -1) 202 { 203 (void) close(destination_file); 204 (void) RelinquishUniqueFileResource(destination); 205 return(MagickFalse); 206 } 207 quantum=(size_t) MagickMaxBufferExtent; 208 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size > 0)) 209 quantum=(size_t) MagickMin(attributes.st_size,MagickMaxBufferExtent); 210 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer)); 211 if (buffer == (unsigned char *) NULL) 212 { 213 (void) close(source_file); 214 (void) close(destination_file); 215 (void) RelinquishUniqueFileResource(destination); 216 return(MagickFalse); 217 } 218 for (length=0; ; ) 219 { 220 count=(ssize_t) read(source_file,buffer,quantum); 221 if (count <= 0) 222 break; 223 length=(size_t) count; 224 count=(ssize_t) write(destination_file,buffer,length); 225 if ((size_t) count != length) 226 { 227 (void) close(destination_file); 228 (void) close(source_file); 229 buffer=(unsigned char *) RelinquishMagickMemory(buffer); 230 (void) RelinquishUniqueFileResource(destination); 231 return(MagickFalse); 232 } 233 } 234 (void) close(destination_file); 235 (void) close(source_file); 236 buffer=(unsigned char *) RelinquishMagickMemory(buffer); 237 return(MagickTrue); 238} 239 240/* 241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 242% % 243% % 244% % 245% A p p e n d I m a g e F o r m a t % 246% % 247% % 248% % 249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 250% 251% AppendImageFormat() appends the image format type to the filename. If an 252% extension to the file already exists, it is first removed. 253% 254% The format of the AppendImageFormat method is: 255% 256% void AppendImageFormat(const char *format,char *filename) 257% 258% A description of each parameter follows. 259% 260% o format: Specifies a pointer to an array of characters. This the 261% format of the image. 262% 263% o filename: Specifies a pointer to an array of characters. The unique 264% file name is returned in this array. 265% 266*/ 267MagickExport void AppendImageFormat(const char *format,char *filename) 268{ 269 char 270 extension[MagickPathExtent], 271 root[MagickPathExtent]; 272 273 assert(format != (char *) NULL); 274 assert(filename != (char *) NULL); 275 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename); 276 if ((*format == '\0') || (*filename == '\0')) 277 return; 278 if (LocaleCompare(filename,"-") == 0) 279 { 280 char 281 message[MagickPathExtent]; 282 283 (void) FormatLocaleString(message,MagickPathExtent,"%s:%s",format, 284 filename); 285 (void) CopyMagickString(filename,message,MagickPathExtent); 286 return; 287 } 288 GetPathComponent(filename,ExtensionPath,extension); 289 if ((LocaleCompare(extension,"Z") == 0) || 290 (LocaleCompare(extension,"bz2") == 0) || 291 (LocaleCompare(extension,"gz") == 0) || 292 (LocaleCompare(extension,"wmz") == 0) || 293 (LocaleCompare(extension,"svgz") == 0)) 294 { 295 GetPathComponent(filename,RootPath,root); 296 (void) CopyMagickString(filename,root,MagickPathExtent); 297 GetPathComponent(filename,RootPath,root); 298 (void) FormatLocaleString(filename,MagickPathExtent,"%s.%s.%s",root, 299 format,extension); 300 return; 301 } 302 GetPathComponent(filename,RootPath,root); 303 (void) FormatLocaleString(filename,MagickPathExtent,"%s.%s",root,format); 304} 305 306/* 307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 308% % 309% % 310% % 311% B a s e 6 4 D e c o d e % 312% % 313% % 314% % 315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 316% 317% Base64Decode() decodes Base64-encoded text and returns its binary 318% equivalent. NULL is returned if the text is not valid Base64 data, or a 319% memory allocation failure occurs. 320% 321% The format of the Base64Decode method is: 322% 323% unsigned char *Base64Decode(const char *source,length_t *length) 324% 325% A description of each parameter follows: 326% 327% o source: A pointer to a Base64-encoded string. 328% 329% o length: the number of bytes decoded. 330% 331*/ 332MagickExport unsigned char *Base64Decode(const char *source,size_t *length) 333{ 334 int 335 state; 336 337 register const char 338 *p, 339 *q; 340 341 register size_t 342 i; 343 344 unsigned char 345 *decode; 346 347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 348 assert(source != (char *) NULL); 349 assert(length != (size_t *) NULL); 350 *length=0; 351 decode=(unsigned char *) AcquireQuantumMemory((strlen(source)+3)/4, 352 3*sizeof(*decode)); 353 if (decode == (unsigned char *) NULL) 354 return((unsigned char *) NULL); 355 i=0; 356 state=0; 357 for (p=source; *p != '\0'; p++) 358 { 359 if (isspace((int) ((unsigned char) *p)) != 0) 360 continue; 361 if (*p == '=') 362 break; 363 q=strchr(Base64,*p); 364 if (q == (char *) NULL) 365 { 366 decode=(unsigned char *) RelinquishMagickMemory(decode); 367 return((unsigned char *) NULL); /* non-Base64 character */ 368 } 369 switch (state) 370 { 371 case 0: 372 { 373 decode[i]=(q-Base64) << 2; 374 state++; 375 break; 376 } 377 case 1: 378 { 379 decode[i++]|=(q-Base64) >> 4; 380 decode[i]=((q-Base64) & 0x0f) << 4; 381 state++; 382 break; 383 } 384 case 2: 385 { 386 decode[i++]|=(q-Base64) >> 2; 387 decode[i]=((q-Base64) & 0x03) << 6; 388 state++; 389 break; 390 } 391 case 3: 392 { 393 decode[i++]|=(q-Base64); 394 state=0; 395 break; 396 } 397 } 398 } 399 /* 400 Verify Base-64 string has proper terminal characters. 401 */ 402 if (*p != '=') 403 { 404 if (state != 0) 405 { 406 decode=(unsigned char *) RelinquishMagickMemory(decode); 407 return((unsigned char *) NULL); 408 } 409 } 410 else 411 { 412 p++; 413 switch (state) 414 { 415 case 0: 416 case 1: 417 { 418 /* 419 Unrecognized '=' character. 420 */ 421 decode=(unsigned char *) RelinquishMagickMemory(decode); 422 return((unsigned char *) NULL); 423 } 424 case 2: 425 { 426 for ( ; *p != '\0'; p++) 427 if (isspace((int) ((unsigned char) *p)) == 0) 428 break; 429 if (*p != '=') 430 { 431 decode=(unsigned char *) RelinquishMagickMemory(decode); 432 return((unsigned char *) NULL); 433 } 434 p++; 435 } 436 case 3: 437 { 438 for ( ; *p != '\0'; p++) 439 if (isspace((int) ((unsigned char) *p)) == 0) 440 { 441 decode=(unsigned char *) RelinquishMagickMemory(decode); 442 return((unsigned char *) NULL); 443 } 444 if ((int) decode[i] != 0) 445 { 446 decode=(unsigned char *) RelinquishMagickMemory(decode); 447 return((unsigned char *) NULL); 448 } 449 break; 450 } 451 } 452 } 453 *length=i; 454 return(decode); 455} 456 457/* 458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 459% % 460% % 461% % 462% B a s e 6 4 E n c o d e % 463% % 464% % 465% % 466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 467% 468% Base64Encode() encodes arbitrary binary data to Base64 encoded format as 469% described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and 470% returns the result as a null-terminated ASCII string. NULL is returned if 471% a memory allocation failure occurs. 472% 473% The format of the Base64Encode method is: 474% 475% char *Base64Encode(const unsigned char *blob,const size_t blob_length, 476% size_t *encode_length) 477% 478% A description of each parameter follows: 479% 480% o blob: A pointer to binary data to encode. 481% 482% o blob_length: the number of bytes to encode. 483% 484% o encode_length: The number of bytes encoded. 485% 486*/ 487MagickExport char *Base64Encode(const unsigned char *blob, 488 const size_t blob_length,size_t *encode_length) 489{ 490 char 491 *encode; 492 493 register const unsigned char 494 *p; 495 496 register size_t 497 i; 498 499 size_t 500 remainder; 501 502 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 503 assert(blob != (const unsigned char *) NULL); 504 assert(blob_length != 0); 505 assert(encode_length != (size_t *) NULL); 506 *encode_length=0; 507 encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode)); 508 if (encode == (char *) NULL) 509 return((char *) NULL); 510 i=0; 511 for (p=blob; p < (blob+blob_length-2); p+=3) 512 { 513 encode[i++]=Base64[(int) (*p >> 2)]; 514 encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))]; 515 encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))]; 516 encode[i++]=Base64[(int) (*(p+2) & 0x3f)]; 517 } 518 remainder=blob_length % 3; 519 if (remainder != 0) 520 { 521 ssize_t 522 j; 523 524 unsigned char 525 code[3]; 526 527 code[0]='\0'; 528 code[1]='\0'; 529 code[2]='\0'; 530 for (j=0; j < (ssize_t) remainder; j++) 531 code[j]=(*p++); 532 encode[i++]=Base64[(int) (code[0] >> 2)]; 533 encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))]; 534 if (remainder == 1) 535 encode[i++]='='; 536 else 537 encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))]; 538 encode[i++]='='; 539 } 540 *encode_length=i; 541 encode[i++]='\0'; 542 return(encode); 543} 544 545/* 546%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 547% % 548% % 549% % 550% C h o p P a t h C o m p o n e n t s % 551% % 552% % 553% % 554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 555% 556% ChopPathComponents() removes the number of specified file components from a 557% path. 558% 559% The format of the ChopPathComponents method is: 560% 561% ChopPathComponents(char *path,size_t components) 562% 563% A description of each parameter follows: 564% 565% o path: The path. 566% 567% o components: The number of components to chop. 568% 569*/ 570MagickPrivate void ChopPathComponents(char *path,const size_t components) 571{ 572 register ssize_t 573 i; 574 575 for (i=0; i < (ssize_t) components; i++) 576 GetPathComponent(path,HeadPath,path); 577} 578 579/* 580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 581% % 582% % 583% % 584% E x p a n d F i l e n a m e % 585% % 586% % 587% % 588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 589% 590% ExpandFilename() expands '~' in a path. 591% 592% The format of the ExpandFilename function is: 593% 594% ExpandFilename(char *path) 595% 596% A description of each parameter follows: 597% 598% o path: Specifies a pointer to a character array that contains the 599% path. 600% 601*/ 602MagickPrivate void ExpandFilename(char *path) 603{ 604 char 605 expand_path[MagickPathExtent]; 606 607 if (path == (char *) NULL) 608 return; 609 if (*path != '~') 610 return; 611 (void) CopyMagickString(expand_path,path,MagickPathExtent); 612 if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0')) 613 { 614 char 615 *home; 616 617 /* 618 Substitute ~ with $HOME. 619 */ 620 (void) CopyMagickString(expand_path,".",MagickPathExtent); 621 (void) ConcatenateMagickString(expand_path,path+1,MagickPathExtent); 622 home=GetEnvironmentValue("HOME"); 623 if (home == (char *) NULL) 624 home=GetEnvironmentValue("USERPROFILE"); 625 if (home != (char *) NULL) 626 { 627 (void) CopyMagickString(expand_path,home,MagickPathExtent); 628 (void) ConcatenateMagickString(expand_path,path+1,MagickPathExtent); 629 home=DestroyString(home); 630 } 631 } 632 else 633 { 634#if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__) 635 char 636 username[MagickPathExtent]; 637 638 register char 639 *p; 640 641 struct passwd 642 *entry; 643 644 /* 645 Substitute ~ with home directory from password file. 646 */ 647 (void) CopyMagickString(username,path+1,MagickPathExtent); 648 p=strchr(username,'/'); 649 if (p != (char *) NULL) 650 *p='\0'; 651 entry=getpwnam(username); 652 if (entry == (struct passwd *) NULL) 653 return; 654 (void) CopyMagickString(expand_path,entry->pw_dir,MagickPathExtent); 655 if (p != (char *) NULL) 656 { 657 (void) ConcatenateMagickString(expand_path,"/",MagickPathExtent); 658 (void) ConcatenateMagickString(expand_path,p+1,MagickPathExtent); 659 } 660#endif 661 } 662 (void) CopyMagickString(path,expand_path,MagickPathExtent); 663} 664 665/* 666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 667% % 668% % 669% % 670% E x p a n d F i l e n a m e s % 671% % 672% % 673% % 674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 675% 676% ExpandFilenames() checks each argument of the given argument array, and 677% expands it if they have a wildcard character. 678% 679% Any coder prefix (EG: 'coder:filename') or read modifier postfix (EG: 680% 'filename[...]') are ignored during the file the expansion, but will be 681% included in the final argument. If no filename matching the meta-character 682% 'glob' is found the original argument is returned. 683% 684% For example, an argument of '*.gif[20x20]' will be replaced by the list 685% 'abc.gif[20x20]', 'foobar.gif[20x20]', 'xyzzy.gif[20x20]' 686% if such filenames exist, (in the current directory in this case). 687% 688% Meta-characters handled... 689% @ read a list of filenames (no further expansion performed) 690% ~ At start of filename expands to HOME environemtn variable 691% * matches any string including an empty string 692% ? matches by any single character 693% 694% WARNING: filenames starting with '.' (hidden files in a UNIX file system) 695% will never be expanded. Attempting to epand '.*' will produce no change. 696% 697% Expansion is ignored for coders "label:" "caption:" "pango:" and "vid:". 698% Which provide their own '@' meta-character handling. 699% 700% You can see the results of the expansion using "Configure" log events. 701% 702% The returned list should be freed using DestroyStringList(). 703% 704% However the strings in the original pointed to argv are not 705% freed (TO BE CHECKED). So a copy of the original pointer (and count) 706% should be kept separate if they need to be freed later. 707% 708% The format of the ExpandFilenames function is: 709% 710% status=ExpandFilenames(int *number_arguments,char ***arguments) 711% 712% A description of each parameter follows: 713% 714% o number_arguments: Specifies a pointer to an integer describing the 715% number of elements in the argument vector. 716% 717% o arguments: Specifies a pointer to a text array containing the command 718% line arguments. 719% 720*/ 721MagickExport MagickBooleanType ExpandFilenames(int *number_arguments, 722 char ***arguments) 723{ 724 char 725 home_directory[MagickPathExtent], 726 **vector; 727 728 register ssize_t 729 i, 730 j; 731 732 size_t 733 number_files; 734 735 ssize_t 736 count, 737 parameters; 738 739 /* 740 Allocate argument vector. 741 */ 742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 743 assert(number_arguments != (int *) NULL); 744 assert(arguments != (char ***) NULL); 745 vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1), 746 sizeof(*vector)); 747 if (vector == (char **) NULL) 748 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 749 /* 750 Expand any wildcard filenames. 751 */ 752 *home_directory='\0'; 753 count=0; 754 for (i=0; i < (ssize_t) *number_arguments; i++) 755 { 756 char 757 **filelist, 758 filename[MagickPathExtent], 759 magick[MagickPathExtent], 760 *option, 761 path[MagickPathExtent], 762 subimage[MagickPathExtent]; 763 764 MagickBooleanType 765 destroy; 766 767 option=(*arguments)[i]; 768 *magick='\0'; 769 *path='\0'; 770 *filename='\0'; 771 *subimage='\0'; 772 number_files=0; 773 vector[count++]=ConstantString(option); 774 destroy=MagickTrue; 775 parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option); 776 if (parameters > 0) 777 { 778 /* 779 Do not expand command option parameters. 780 */ 781 for (j=0; j < parameters; j++) 782 { 783 i++; 784 if (i == (ssize_t) *number_arguments) 785 break; 786 option=(*arguments)[i]; 787 vector[count++]=ConstantString(option); 788 } 789 continue; 790 } 791 if ((*option == '"') || (*option == '\'')) 792 continue; 793 GetPathComponent(option,TailPath,filename); 794 GetPathComponent(option,MagickPath,magick); 795 if ((LocaleCompare(magick,"CAPTION") == 0) || 796 (LocaleCompare(magick,"LABEL") == 0) || 797 (LocaleCompare(magick,"PANGO") == 0) || 798 (LocaleCompare(magick,"VID") == 0)) 799 continue; 800 if ((IsGlob(filename) == MagickFalse) && (*option != '@')) 801 continue; 802 if (*option != '@') 803 { 804 /* 805 Generate file list from wildcard filename (e.g. *.jpg). 806 */ 807 GetPathComponent(option,HeadPath,path); 808 GetPathComponent(option,SubimagePath,subimage); 809 ExpandFilename(path); 810 if (*home_directory == '\0') 811 getcwd_utf8(home_directory,MagickPathExtent-1); 812 filelist=ListFiles(*path == '\0' ? home_directory : path,filename, 813 &number_files); 814 } 815 else 816 { 817 char 818 *files; 819 820 ExceptionInfo 821 *exception; 822 823 int 824 length; 825 826 /* 827 Generate file list from file list (e.g. @filelist.txt). 828 */ 829 exception=AcquireExceptionInfo(); 830 files=FileToString(option+1,~0UL,exception); 831 exception=DestroyExceptionInfo(exception); 832 if (files == (char *) NULL) 833 continue; 834 filelist=StringToArgv(files,&length); 835 if (filelist == (char **) NULL) 836 continue; 837 files=DestroyString(files); 838 filelist[0]=DestroyString(filelist[0]); 839 for (j=0; j < (ssize_t) (length-1); j++) 840 filelist[j]=filelist[j+1]; 841 number_files=(size_t) length-1; 842 } 843 if (filelist == (char **) NULL) 844 continue; 845 for (j=0; j < (ssize_t) number_files; j++) 846 if (IsPathDirectory(filelist[j]) <= 0) 847 break; 848 if (j == (ssize_t) number_files) 849 { 850 for (j=0; j < (ssize_t) number_files; j++) 851 filelist[j]=DestroyString(filelist[j]); 852 filelist=(char **) RelinquishMagickMemory(filelist); 853 continue; 854 } 855 /* 856 Transfer file list to argument vector. 857 */ 858 vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+ 859 count+number_files+1,sizeof(*vector)); 860 if (vector == (char **) NULL) 861 { 862 for (j=0; j < (ssize_t) number_files; j++) 863 filelist[j]=DestroyString(filelist[j]); 864 filelist=(char **) RelinquishMagickMemory(filelist); 865 return(MagickFalse); 866 } 867 for (j=0; j < (ssize_t) number_files; j++) 868 { 869 option=filelist[j]; 870 parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option); 871 if (parameters > 0) 872 { 873 ssize_t 874 k; 875 876 /* 877 Do not expand command option parameters. 878 */ 879 vector[count++]=ConstantString(option); 880 for (k=0; k < parameters; k++) 881 { 882 j++; 883 if (j == (ssize_t) number_files) 884 break; 885 option=filelist[j]; 886 vector[count++]=ConstantString(option); 887 } 888 continue; 889 } 890 (void) CopyMagickString(filename,path,MagickPathExtent); 891 if (*path != '\0') 892 (void) ConcatenateMagickString(filename,DirectorySeparator, 893 MagickPathExtent); 894 if (filelist[j] != (char *) NULL) 895 (void) ConcatenateMagickString(filename,filelist[j],MagickPathExtent); 896 filelist[j]=DestroyString(filelist[j]); 897 if (strlen(filename) >= (MagickPathExtent-1)) 898 ThrowFatalException(OptionFatalError,"FilenameTruncated"); 899 if (IsPathDirectory(filename) <= 0) 900 { 901 char 902 path[MagickPathExtent]; 903 904 *path='\0'; 905 if (*magick != '\0') 906 { 907 (void) ConcatenateMagickString(path,magick,MagickPathExtent); 908 (void) ConcatenateMagickString(path,":",MagickPathExtent); 909 } 910 (void) ConcatenateMagickString(path,filename,MagickPathExtent); 911 if (*subimage != '\0') 912 { 913 (void) ConcatenateMagickString(path,"[",MagickPathExtent); 914 (void) ConcatenateMagickString(path,subimage,MagickPathExtent); 915 (void) ConcatenateMagickString(path,"]",MagickPathExtent); 916 } 917 if (strlen(path) >= (MagickPathExtent-1)) 918 ThrowFatalException(OptionFatalError,"FilenameTruncated"); 919 if (destroy != MagickFalse) 920 { 921 count--; 922 vector[count]=DestroyString(vector[count]); 923 destroy=MagickFalse; 924 } 925 vector[count++]=ConstantString(path); 926 } 927 } 928 filelist=(char **) RelinquishMagickMemory(filelist); 929 } 930 vector[count]=(char *) NULL; 931 if (IsEventLogging() != MagickFalse) 932 { 933 char 934 *command_line; 935 936 command_line=AcquireString(vector[0]); 937 for (i=1; i < count; i++) 938 { 939 (void) ConcatenateString(&command_line," {"); 940 (void) ConcatenateString(&command_line,vector[i]); 941 (void) ConcatenateString(&command_line,"}"); 942 } 943 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), 944 "Command line: %s",command_line); 945 command_line=DestroyString(command_line); 946 } 947 *number_arguments=(int) count; 948 *arguments=vector; 949 return(MagickTrue); 950} 951 952/* 953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 954% % 955% % 956% % 957% G e t E x e c u t i o n P a t h % 958% % 959% % 960% % 961%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 962% 963% GetExecutionPath() returns the pathname of the executable that started 964% the process. On success MagickTrue is returned, otherwise MagickFalse. 965% 966% The format of the GetExecutionPath method is: 967% 968% MagickBooleanType GetExecutionPath(char *path,const size_t extent) 969% 970% A description of each parameter follows: 971% 972% o path: the pathname of the executable that started the process. 973% 974% o extent: the maximum extent of the path. 975% 976*/ 977MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent) 978{ 979 char 980 *directory; 981 982 *path='\0'; 983 directory=getcwd(path,(unsigned long) extent); 984 (void) directory; 985#if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX) 986 { 987 char 988 execution_path[PATH_MAX+1], 989 link_path[MagickPathExtent]; 990 991 ssize_t 992 count; 993 994 (void) FormatLocaleString(link_path,MagickPathExtent,"/proc/%.20g/exe", 995 (double) getpid()); 996 count=readlink(link_path,execution_path,PATH_MAX); 997 if (count == -1) 998 { 999 (void) FormatLocaleString(link_path,MagickPathExtent,"/proc/%.20g/file", 1000 (double) getpid()); 1001 count=readlink(link_path,execution_path,PATH_MAX); 1002 } 1003 if ((count > 0) && (count <= (ssize_t) PATH_MAX)) 1004 { 1005 execution_path[count]='\0'; 1006 (void) CopyMagickString(path,execution_path,extent); 1007 } 1008 } 1009#endif 1010#if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH) 1011 { 1012 char 1013 executable_path[PATH_MAX << 1], 1014 execution_path[PATH_MAX+1]; 1015 1016 uint32_t 1017 length; 1018 1019 length=sizeof(executable_path); 1020 if ((_NSGetExecutablePath(executable_path,&length) == 0) && 1021 (realpath(executable_path,execution_path) != (char *) NULL)) 1022 (void) CopyMagickString(path,execution_path,extent); 1023 } 1024#endif 1025#if defined(MAGICKCORE_HAVE_GETEXECNAME) 1026 { 1027 const char 1028 *execution_path; 1029 1030 execution_path=(const char *) getexecname(); 1031 if (execution_path != (const char *) NULL) 1032 { 1033 if (*execution_path != *DirectorySeparator) 1034 (void) ConcatenateMagickString(path,DirectorySeparator,extent); 1035 (void) ConcatenateMagickString(path,execution_path,extent); 1036 } 1037 } 1038#endif 1039#if defined(MAGICKCORE_WINDOWS_SUPPORT) 1040 NTGetExecutionPath(path,extent); 1041#endif 1042#if defined(__GNU__) 1043 { 1044 char 1045 *program_name, 1046 *execution_path; 1047 1048 ssize_t 1049 count; 1050 1051 count=0; 1052 execution_path=(char *) NULL; 1053 program_name=program_invocation_name; 1054 if (*program_invocation_name != '/') 1055 { 1056 size_t 1057 extent; 1058 1059 extent=strlen(directory)+strlen(program_name)+2; 1060 program_name=AcquireQuantumMemory(extent,sizeof(*program_name)); 1061 if (program_name == (char *) NULL) 1062 program_name=program_invocation_name; 1063 else 1064 count=FormatLocaleString(program_name,extent,"%s/%s",directory, 1065 program_invocation_name); 1066 } 1067 if (count != -1) 1068 { 1069 execution_path=realpath(program_name,NULL); 1070 if (execution_path != (char *) NULL) 1071 (void) CopyMagickString(path,execution_path,extent); 1072 } 1073 if (program_name != program_invocation_name) 1074 program_name=(char *) RelinquishMagickMemory(program_name); 1075 execution_path=(char *) RelinquishMagickMemory(execution_path); 1076 } 1077#endif 1078#if defined(__OpenBSD__) 1079 { 1080 extern char 1081 *__progname; 1082 1083 (void) CopyMagickString(path,__progname,extent); 1084 } 1085#endif 1086 return(IsPathAccessible(path)); 1087} 1088 1089/* 1090%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1091% % 1092% % 1093% % 1094% G e t M a g i c k P a g e S i z e % 1095% % 1096% % 1097% % 1098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1099% 1100% GetMagickPageSize() returns the memory page size. 1101% 1102% The format of the GetMagickPageSize method is: 1103% 1104% ssize_t GetMagickPageSize() 1105% 1106*/ 1107MagickPrivate ssize_t GetMagickPageSize(void) 1108{ 1109 static ssize_t 1110 page_size = -1; 1111 1112 if (page_size > 0) 1113 return(page_size); 1114#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) 1115 page_size=(ssize_t) sysconf(_SC_PAGE_SIZE); 1116#else 1117#if defined(MAGICKCORE_HAVE_GETPAGESIZE) 1118 page_size=(ssize_t) getpagesize(); 1119#endif 1120#endif 1121 if (page_size <= 0) 1122 page_size=16384; 1123 return(page_size); 1124} 1125 1126/* 1127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1128% % 1129% % 1130% % 1131% G e t P a t h A t t r i b u t e s % 1132% % 1133% % 1134% % 1135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1136% 1137% GetPathAttributes() returns attributes (e.g. size of file) about a path. 1138% 1139% The path of the GetPathAttributes method is: 1140% 1141% MagickBooleanType GetPathAttributes(const char *path,void *attributes) 1142% 1143% A description of each parameter follows. 1144% 1145% o path: the file path. 1146% 1147% o attributes: the path attributes are returned here. 1148% 1149*/ 1150MagickExport MagickBooleanType GetPathAttributes(const char *path, 1151 void *attributes) 1152{ 1153 MagickBooleanType 1154 status; 1155 1156 if (path == (const char *) NULL) 1157 { 1158 errno=EINVAL; 1159 return(MagickFalse); 1160 } 1161 (void) ResetMagickMemory(attributes,0,sizeof(struct stat)); 1162 status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue : 1163 MagickFalse; 1164 return(status); 1165} 1166 1167/* 1168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1169% % 1170% % 1171% % 1172% G e t P a t h C o m p o n e n t % 1173% % 1174% % 1175% % 1176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1177% 1178% GetPathComponent() returns the parent directory name, filename, basename, or 1179% extension of a file path. 1180% 1181% The component string pointed to must have at least MagickPathExtent space 1182% for the results to be stored. 1183% 1184% The format of the GetPathComponent function is: 1185% 1186% GetPathComponent(const char *path,PathType type,char *component) 1187% 1188% A description of each parameter follows: 1189% 1190% o path: Specifies a pointer to a character array that contains the 1191% file path. 1192% 1193% o type: Specififies which file path component to return. 1194% 1195% o component: the selected file path component is returned here. 1196% 1197*/ 1198MagickExport void GetPathComponent(const char *path,PathType type, 1199 char *component) 1200{ 1201 char 1202 *q; 1203 1204 register char 1205 *p; 1206 1207 size_t 1208 magick_length, 1209 subimage_offset, 1210 subimage_length; 1211 1212 assert(path != (const char *) NULL); 1213 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path); 1214 assert(component != (char *) NULL); 1215 if (*path == '\0') 1216 { 1217 *component='\0'; 1218 return; 1219 } 1220 (void) CopyMagickString(component,path,MagickPathExtent); 1221 magick_length=0; 1222#if defined(__OS2__) 1223 if (path[1] != ":") 1224#endif 1225 for (p=component; *p != '\0'; p++) 1226 { 1227 if ((*p == '%') && (*(p+1) == '[')) 1228 { 1229 /* 1230 Skip over %[...]. 1231 */ 1232 for (p++; (*p != ']') && (*p != '\0'); p++) ; 1233 if (*p == '\0') 1234 break; 1235 } 1236 if ((*p == ':') && (IsPathDirectory(path) < 0) && 1237 (IsPathAccessible(path) == MagickFalse)) 1238 { 1239 /* 1240 Look for image format specification (e.g. ps3:image). 1241 */ 1242 *p='\0'; 1243 if (IsMagickConflict(component) != MagickFalse) 1244 *p=':'; 1245 else 1246 { 1247 magick_length=(size_t) (p-component+1); 1248 for (q=component; *(++p) != '\0'; q++) 1249 *q=(*p); 1250 *q='\0'; 1251 } 1252 break; 1253 } 1254 } 1255 subimage_length=0; 1256 subimage_offset=0; 1257 p=component; 1258 if (*p != '\0') 1259 p=component+strlen(component)-1; 1260 if ((*p == ']') && (strchr(component,'[') != (char *) NULL) && 1261 (IsPathAccessible(path) == MagickFalse)) 1262 { 1263 /* 1264 Look for scene specification (e.g. img0001.pcd[4]). 1265 */ 1266 for (q=p-1; q > component; q--) 1267 if (*q == '[') 1268 break; 1269 if (*q == '[') 1270 { 1271 *p='\0'; 1272 if ((IsSceneGeometry(q+1,MagickFalse) == MagickFalse) && 1273 (IsGeometry(q+1) == MagickFalse)) 1274 *p=']'; 1275 else 1276 { 1277 subimage_length=(size_t) (p-q); 1278 subimage_offset=magick_length+1+(size_t) (q-component); 1279 *q='\0'; 1280 } 1281 } 1282 } 1283 p=component; 1284 if (*p != '\0') 1285 for (p=component+strlen(component)-1; p > component; p--) 1286 if (IsBasenameSeparator(*p) != MagickFalse) 1287 break; 1288 switch (type) 1289 { 1290 case MagickPath: 1291 { 1292 if (magick_length != 0) 1293 (void) CopyMagickString(component,path,magick_length); 1294 else 1295 *component='\0'; 1296 break; 1297 } 1298 case RootPath: 1299 { 1300 for (p=component+(strlen(component)-1); p > component; p--) 1301 { 1302 if (IsBasenameSeparator(*p) != MagickFalse) 1303 break; 1304 if (*p == '.') 1305 break; 1306 } 1307 if (*p == '.') 1308 *p='\0'; 1309 break; 1310 } 1311 case HeadPath: 1312 { 1313 *p='\0'; 1314 break; 1315 } 1316 case TailPath: 1317 { 1318 if (IsBasenameSeparator(*p) != MagickFalse) 1319 (void) CopyMagickMemory((unsigned char *) component, 1320 (const unsigned char *) (p+1),strlen(p+1)+1); 1321 break; 1322 } 1323 case BasePath: 1324 { 1325 if (IsBasenameSeparator(*p) != MagickFalse) 1326 (void) CopyMagickString(component,p+1,MagickPathExtent); 1327 for (p=component+(strlen(component)-1); p > component; p--) 1328 if (*p == '.') 1329 { 1330 *p='\0'; 1331 break; 1332 } 1333 break; 1334 } 1335 case ExtensionPath: 1336 { 1337 if (IsBasenameSeparator(*p) != MagickFalse) 1338 (void) CopyMagickString(component,p+1,MagickPathExtent); 1339 p=component; 1340 if (*p != '\0') 1341 for (p=component+strlen(component)-1; p > component; p--) 1342 if (*p == '.') 1343 break; 1344 *component='\0'; 1345 if (*p == '.') 1346 (void) CopyMagickString(component,p+1,MagickPathExtent); 1347 break; 1348 } 1349 case SubimagePath: 1350 { 1351 if (subimage_length != 0) 1352 (void) CopyMagickString(component,path+subimage_offset,subimage_length); 1353 else 1354 *component = '\0'; 1355 break; 1356 } 1357 case CanonicalPath: 1358 case UndefinedPath: 1359 break; 1360 } 1361} 1362 1363/* 1364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1365% % 1366% % 1367% % 1368% G e t P a t h C o m p o n e n t s % 1369% % 1370% % 1371% % 1372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1373% 1374% GetPathComponents() returns a list of path components. 1375% 1376% The format of the GetPathComponents method is: 1377% 1378% char **GetPathComponents(const char *path, 1379% size_t *number_componenets) 1380% 1381% A description of each parameter follows: 1382% 1383% o path: Specifies the string to segment into a list. 1384% 1385% o number_components: return the number of components in the list 1386% 1387*/ 1388MagickPrivate char **GetPathComponents(const char *path, 1389 size_t *number_components) 1390{ 1391 char 1392 **components; 1393 1394 register const char 1395 *p, 1396 *q; 1397 1398 register ssize_t 1399 i; 1400 1401 if (path == (char *) NULL) 1402 return((char **) NULL); 1403 *number_components=1; 1404 for (p=path; *p != '\0'; p++) 1405 if (IsBasenameSeparator(*p)) 1406 (*number_components)++; 1407 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL, 1408 sizeof(*components)); 1409 if (components == (char **) NULL) 1410 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 1411 p=path; 1412 for (i=0; i < (ssize_t) *number_components; i++) 1413 { 1414 for (q=p; *q != '\0'; q++) 1415 if (IsBasenameSeparator(*q)) 1416 break; 1417 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MagickPathExtent, 1418 sizeof(**components)); 1419 if (components[i] == (char *) NULL) 1420 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 1421 (void) CopyMagickString(components[i],p,(size_t) (q-p+1)); 1422 p=q+1; 1423 } 1424 components[i]=(char *) NULL; 1425 return(components); 1426} 1427 1428/* 1429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1430% % 1431% % 1432% % 1433% I s P a t h A c c e s s i b l e % 1434% % 1435% % 1436% % 1437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1438% 1439% IsPathAccessible() returns MagickTrue if the file as defined by the path is 1440% accessible. 1441% 1442% The format of the IsPathAccessible method is: 1443% 1444% MagickBooleanType IsPathAccessible(const char *path) 1445% 1446% A description of each parameter follows. 1447% 1448% o path: Specifies a path to a file. 1449% 1450*/ 1451MagickExport MagickBooleanType IsPathAccessible(const char *path) 1452{ 1453 MagickBooleanType 1454 status; 1455 1456 struct stat 1457 attributes; 1458 1459 if ((path == (const char *) NULL) || (*path == '\0')) 1460 return(MagickFalse); 1461 if (LocaleCompare(path,"-") == 0) 1462 return(MagickTrue); 1463 status=GetPathAttributes(path,&attributes); 1464 if (status == MagickFalse) 1465 return(status); 1466 if (S_ISREG(attributes.st_mode) == 0) 1467 return(MagickFalse); 1468 if (access_utf8(path,F_OK) != 0) 1469 return(MagickFalse); 1470 return(MagickTrue); 1471} 1472 1473/* 1474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1475% % 1476% % 1477% % 1478+ I s P a t h D i r e c t o r y % 1479% % 1480% % 1481% % 1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1483% 1484% IsPathDirectory() returns -1 if the directory does not exist, 1 is returned 1485% if the path represents a directory otherwise 0. 1486% 1487% The format of the IsPathDirectory method is: 1488% 1489% int IsPathDirectory(const char *path) 1490% 1491% A description of each parameter follows. 1492% 1493% o path: The directory path. 1494% 1495*/ 1496static int IsPathDirectory(const char *path) 1497{ 1498 MagickBooleanType 1499 status; 1500 1501 struct stat 1502 attributes; 1503 1504 if ((path == (const char *) NULL) || (*path == '\0')) 1505 return(MagickFalse); 1506 status=GetPathAttributes(path,&attributes); 1507 if (status == MagickFalse) 1508 return(-1); 1509 if (S_ISDIR(attributes.st_mode) == 0) 1510 return(0); 1511 return(1); 1512} 1513 1514/* 1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1516% % 1517% % 1518% % 1519% L i s t F i l e s % 1520% % 1521% % 1522% % 1523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1524% 1525% ListFiles() reads the directory specified and returns a list of filenames 1526% contained in the directory sorted in ascending alphabetic order. 1527% 1528% The format of the ListFiles function is: 1529% 1530% char **ListFiles(const char *directory,const char *pattern, 1531% ssize_t *number_entries) 1532% 1533% A description of each parameter follows: 1534% 1535% o filelist: Method ListFiles returns a list of filenames contained 1536% in the directory. If the directory specified cannot be read or it is 1537% a file a NULL list is returned. 1538% 1539% o directory: Specifies a pointer to a text string containing a directory 1540% name. 1541% 1542% o pattern: Specifies a pointer to a text string containing a pattern. 1543% 1544% o number_entries: This integer returns the number of filenames in the 1545% list. 1546% 1547*/ 1548 1549#if defined(__cplusplus) || defined(c_plusplus) 1550extern "C" { 1551#endif 1552 1553static int FileCompare(const void *x,const void *y) 1554{ 1555 register const char 1556 **p, 1557 **q; 1558 1559 p=(const char **) x; 1560 q=(const char **) y; 1561 return(LocaleCompare(*p,*q)); 1562} 1563 1564#if defined(__cplusplus) || defined(c_plusplus) 1565} 1566#endif 1567 1568static inline int MagickReadDirectory(DIR *directory,struct dirent *entry, 1569 struct dirent **result) 1570{ 1571#if defined(MAGICKCORE_HAVE_READDIR_R) 1572 return(readdir_r(directory,entry,result)); 1573#else 1574 (void) entry; 1575 errno=0; 1576 *result=readdir(directory); 1577 return(errno); 1578#endif 1579} 1580 1581MagickPrivate char **ListFiles(const char *directory,const char *pattern, 1582 size_t *number_entries) 1583{ 1584 char 1585 **filelist; 1586 1587 DIR 1588 *current_directory; 1589 1590 struct dirent 1591 *buffer, 1592 *entry; 1593 1594 size_t 1595 max_entries; 1596 1597 /* 1598 Open directory. 1599 */ 1600 assert(directory != (const char *) NULL); 1601 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory); 1602 assert(pattern != (const char *) NULL); 1603 assert(number_entries != (size_t *) NULL); 1604 *number_entries=0; 1605 current_directory=opendir(directory); 1606 if (current_directory == (DIR *) NULL) 1607 return((char **) NULL); 1608 /* 1609 Allocate filelist. 1610 */ 1611 max_entries=2048; 1612 filelist=(char **) AcquireQuantumMemory((size_t) max_entries, 1613 sizeof(*filelist)); 1614 if (filelist == (char **) NULL) 1615 { 1616 (void) closedir(current_directory); 1617 return((char **) NULL); 1618 } 1619 /* 1620 Save the current and change to the new directory. 1621 */ 1622 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1); 1623 if (buffer == (struct dirent *) NULL) 1624 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 1625 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) && 1626 (entry != (struct dirent *) NULL)) 1627 { 1628 if (*entry->d_name == '.') 1629 continue; 1630 if ((IsPathDirectory(entry->d_name) > 0) || 1631#if defined(MAGICKCORE_WINDOWS_SUPPORT) 1632 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse)) 1633#else 1634 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse)) 1635#endif 1636 { 1637 if (*number_entries >= max_entries) 1638 { 1639 /* 1640 Extend the file list. 1641 */ 1642 max_entries<<=1; 1643 filelist=(char **) ResizeQuantumMemory(filelist,(size_t) 1644 max_entries,sizeof(*filelist)); 1645 if (filelist == (char **) NULL) 1646 break; 1647 } 1648#if defined(vms) 1649 { 1650 register char 1651 *p; 1652 1653 p=strchr(entry->d_name,';'); 1654 if (p) 1655 *p='\0'; 1656 if (*number_entries > 0) 1657 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0) 1658 continue; 1659 } 1660#endif 1661 filelist[*number_entries]=(char *) AcquireString(entry->d_name); 1662 (*number_entries)++; 1663 } 1664 } 1665 buffer=(struct dirent *) RelinquishMagickMemory(buffer); 1666 (void) closedir(current_directory); 1667 if (filelist == (char **) NULL) 1668 return((char **) NULL); 1669 /* 1670 Sort filelist in ascending order. 1671 */ 1672 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist), 1673 FileCompare); 1674 return(filelist); 1675} 1676 1677/* 1678%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1679% % 1680% % 1681% % 1682% M a g i c k D e l a y % 1683% % 1684% % 1685% % 1686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1687% 1688% MagickDelay() suspends program execution for the number of milliseconds 1689% specified. 1690% 1691% The format of the Delay method is: 1692% 1693% void MagickDelay(const MagickSizeType milliseconds) 1694% 1695% A description of each parameter follows: 1696% 1697% o milliseconds: Specifies the number of milliseconds to delay before 1698% returning. 1699% 1700*/ 1701MagickExport void MagickDelay(const MagickSizeType milliseconds) 1702{ 1703 if (milliseconds == 0) 1704 return; 1705#if defined(MAGICKCORE_HAVE_NANOSLEEP) 1706 { 1707 struct timespec 1708 timer; 1709 1710 timer.tv_sec=(time_t) (milliseconds/1000); 1711 timer.tv_nsec=(milliseconds % 1000)*1000*1000; 1712 (void) nanosleep(&timer,(struct timespec *) NULL); 1713 } 1714#elif defined(MAGICKCORE_HAVE_USLEEP) 1715 usleep(1000*milliseconds); 1716#elif defined(MAGICKCORE_HAVE_SELECT) 1717 { 1718 struct timeval 1719 timer; 1720 1721 timer.tv_sec=(long) milliseconds/1000; 1722 timer.tv_usec=(long) (milliseconds % 1000)*1000; 1723 (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer); 1724 } 1725#elif defined(MAGICKCORE_HAVE_POLL) 1726 (void) poll((struct pollfd *) NULL,0,(int) milliseconds); 1727#elif defined(MAGICKCORE_WINDOWS_SUPPORT) 1728 Sleep((long) milliseconds); 1729#elif defined(vms) 1730 { 1731 float 1732 timer; 1733 1734 timer=milliseconds/1000.0; 1735 lib$wait(&timer); 1736 } 1737#elif defined(__BEOS__) 1738 snooze(1000*milliseconds); 1739#else 1740# error "Time delay method not defined." 1741#endif 1742} 1743 1744/* 1745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1746% % 1747% % 1748% % 1749% M u l t i l i n e C e n s u s % 1750% % 1751% % 1752% % 1753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1754% 1755% MultilineCensus() returns the number of lines within a label. A line is 1756% represented by a \n character. 1757% 1758% The format of the MultilineCenus method is: 1759% 1760% size_t MultilineCensus(const char *label) 1761% 1762% A description of each parameter follows. 1763% 1764% o label: This character string is the label. 1765% 1766*/ 1767MagickExport size_t MultilineCensus(const char *label) 1768{ 1769 size_t 1770 number_lines; 1771 1772 /* 1773 Determine the number of lines within this label. 1774 */ 1775 if (label == (char *) NULL) 1776 return(0); 1777 for (number_lines=1; *label != '\0'; label++) 1778 if (*label == '\n') 1779 number_lines++; 1780 return(number_lines); 1781} 1782 1783/* 1784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1785% % 1786% % 1787% % 1788% S h r e d F i l e % 1789% % 1790% % 1791% % 1792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1793% 1794% ShredFile() overwrites the specified file with zeros or random data and then 1795% removes it. The overwrite is optional and is only required to help keep 1796% the contents of the file private. On the first pass, the file is zeroed. 1797% For subsequent passes, random data is written. 1798% 1799% The format of the ShredFile method is: 1800% 1801% MagickBooleanType ShredFile(const char *path) 1802% 1803% A description of each parameter follows. 1804% 1805% o path: Specifies a path to a file. 1806% 1807*/ 1808MagickPrivate MagickBooleanType ShredFile(const char *path) 1809{ 1810 char 1811 *passes; 1812 1813 int 1814 file, 1815 status; 1816 1817 MagickSizeType 1818 length; 1819 1820 register ssize_t 1821 i; 1822 1823 size_t 1824 quantum; 1825 1826 struct stat 1827 file_stats; 1828 1829 if ((path == (const char *) NULL) || (*path == '\0')) 1830 return(MagickFalse); 1831 passes=GetEnvironmentValue("MAGICK_SHRED_PASSES"); 1832 if (passes == (char *) NULL) 1833 { 1834 /* 1835 Don't shred the file, just remove it. 1836 */ 1837 status=remove_utf8(path); 1838 if (status == -1) 1839 { 1840 (void) LogMagickEvent(ExceptionEvent,GetMagickModule(), 1841 "Failed to remove: %s",path); 1842 return(MagickFalse); 1843 } 1844 return(MagickTrue); 1845 } 1846 file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE); 1847 if (file == -1) 1848 { 1849 /* 1850 Don't shred the file, just remove it. 1851 */ 1852 passes=DestroyString(passes); 1853 status=remove_utf8(path); 1854 if (status == -1) 1855 (void) LogMagickEvent(ExceptionEvent,GetMagickModule(), 1856 "Failed to remove: %s",path); 1857 return(MagickFalse); 1858 } 1859 /* 1860 Shred the file. 1861 */ 1862 quantum=(size_t) MagickMaxBufferExtent; 1863 if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0)) 1864 quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent); 1865 length=(MagickSizeType) file_stats.st_size; 1866 for (i=0; i < (ssize_t) StringToInteger(passes); i++) 1867 { 1868 RandomInfo 1869 *random_info; 1870 1871 register MagickOffsetType 1872 j; 1873 1874 ssize_t 1875 count; 1876 1877 if (lseek(file,0,SEEK_SET) < 0) 1878 break; 1879 random_info=AcquireRandomInfo(); 1880 for (j=0; j < (MagickOffsetType) length; j+=count) 1881 { 1882 StringInfo 1883 *key; 1884 1885 key=GetRandomKey(random_info,quantum); 1886 if (i == 0) 1887 ResetStringInfo(key); /* zero on first pass */ 1888 count=write(file,GetStringInfoDatum(key),(size_t) 1889 MagickMin(quantum,length-j)); 1890 key=DestroyStringInfo(key); 1891 if (count <= 0) 1892 { 1893 count=0; 1894 if (errno != EINTR) 1895 break; 1896 } 1897 } 1898 random_info=DestroyRandomInfo(random_info); 1899 if (j < (MagickOffsetType) length) 1900 break; 1901 } 1902 status=close(file); 1903 status=remove_utf8(path); 1904 if (status != -1) 1905 status=StringToInteger(passes); 1906 passes=DestroyString(passes); 1907 return((status == -1 || i < (ssize_t) status) ? MagickFalse : MagickTrue); 1908} 1909