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