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