MagickCore  7.1.1-43
Convert, Edit, Or Compose Bitmap Images
utility.c
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"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/geometry.h"
49 #include "MagickCore/image-private.h"
50 #include "MagickCore/list.h"
51 #include "MagickCore/log.h"
52 #include "MagickCore/magick-private.h"
53 #include "MagickCore/memory_.h"
54 #include "MagickCore/nt-base-private.h"
55 #include "MagickCore/option.h"
56 #include "MagickCore/policy.h"
57 #include "MagickCore/random_.h"
58 #include "MagickCore/registry.h"
59 #include "MagickCore/resource_.h"
60 #include "MagickCore/semaphore.h"
61 #include "MagickCore/signature-private.h"
62 #include "MagickCore/statistic.h"
63 #include "MagickCore/string_.h"
64 #include "MagickCore/string-private.h"
65 #include "MagickCore/token.h"
66 #include "MagickCore/token-private.h"
67 #include "MagickCore/utility.h"
68 #include "MagickCore/utility-private.h"
69 #if defined(MAGICKCORE_HAVE_PROCESS_H)
70 #include <process.h>
71 #endif
72 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
73 #include <mach-o/dyld.h>
74 #endif
75 
76 /*
77  Static declarations.
78 */
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 */
111 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
112 {
113  int
114  file;
115 
116  file=AcquireUniqueFileResource(path);
117  if (file == -1)
118  return(MagickFalse);
119  file=close(file)-1;
120  return(MagickTrue);
121 }
122 
123 /*
124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 % %
126 % %
127 % %
128 % A c q u i r e U n i q u e S ym b o l i c L i n k %
129 % %
130 % %
131 % %
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133 %
134 % AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified
135 % source path and returns MagickTrue on success otherwise MagickFalse. If the
136 % symlink() method fails or is not available, a unique file name is generated
137 % and the source file copied to it. When you are finished with the file, use
138 % RelinquishUniqueFileResource() 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 
153 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
154  char *destination)
155 {
156  int
157  destination_file,
158  source_file;
159 
160  MagickBooleanType
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  passes=GetPolicyValue("system:shred");
184  if (passes != (char *) NULL)
185  passes=DestroyString(passes);
186  else
187  {
188  (void) AcquireUniqueFilename(destination);
189  (void) RelinquishUniqueFileResource(destination);
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);
203  (void) ConcatenateMagickString(path,DirectorySeparator,
204  MagickPathExtent);
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+=(ptrdiff_t) 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 */
619 MagickPrivate void ExpandFilename(char *path)
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 environment 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 expand '.*' 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 */
748 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
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 
792  MagickBooleanType
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;
803  parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
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 (IsPathAccessible(option) != MagickFalse)
831  continue;
832  if (*option != '@')
833  {
834  /*
835  Generate file list from wildcard filename (e.g. *.jpg).
836  */
837  GetPathComponent(option,HeadPath,path);
838  GetPathComponent(option,SubimagePath,subimage);
839  ExpandFilename(path);
840  if (*home_directory == '\0')
841  getcwd_utf8(home_directory,MagickPathExtent-1);
842  filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
843  &number_files);
844  }
845  else
846  {
847  char
848  *files;
849 
851  *exception;
852 
853  int
854  length;
855 
856  /*
857  Generate file list from file list (e.g. @filelist.txt).
858  */
859  exception=AcquireExceptionInfo();
860  files=FileToString(option,~0UL,exception);
861  exception=DestroyExceptionInfo(exception);
862  if (files == (char *) NULL)
863  continue;
864  filelist=StringToArgv(files,&length);
865  if (filelist == (char **) NULL)
866  continue;
867  files=DestroyString(files);
868  filelist[0]=DestroyString(filelist[0]);
869  for (j=0; j < (ssize_t) (length-1); j++)
870  filelist[j]=filelist[j+1];
871  number_files=(size_t) length-1;
872  }
873  if (filelist == (char **) NULL)
874  continue;
875  for (j=0; j < (ssize_t) number_files; j++)
876  if (IsPathDirectory(filelist[j]) <= 0)
877  break;
878  if (j == (ssize_t) number_files)
879  {
880  for (j=0; j < (ssize_t) number_files; j++)
881  filelist[j]=DestroyString(filelist[j]);
882  filelist=(char **) RelinquishMagickMemory(filelist);
883  continue;
884  }
885  /*
886  Transfer file list to argument vector.
887  */
888  vector=(char **) ResizeQuantumMemory(vector,(size_t) ((ssize_t)
889  *number_arguments+count+(ssize_t) number_files+1),sizeof(*vector));
890  if (vector == (char **) NULL)
891  {
892  for (j=0; j < (ssize_t) number_files; j++)
893  filelist[j]=DestroyString(filelist[j]);
894  filelist=(char **) RelinquishMagickMemory(filelist);
895  return(MagickFalse);
896  }
897  for (j=0; j < (ssize_t) number_files; j++)
898  {
899  option=filelist[j];
900  parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
901  if (parameters > 0)
902  {
903  ssize_t
904  k;
905 
906  /*
907  Do not expand command option parameters.
908  */
909  vector[count++]=ConstantString(option);
910  for (k=0; k < parameters; k++)
911  {
912  j++;
913  if (j == (ssize_t) number_files)
914  break;
915  option=filelist[j];
916  vector[count++]=ConstantString(option);
917  }
918  continue;
919  }
920  (void) CopyMagickString(filename,path,MagickPathExtent);
921  if (*path != '\0')
922  (void) ConcatenateMagickString(filename,DirectorySeparator,
923  MagickPathExtent);
924  if (filelist[j] != (char *) NULL)
925  (void) ConcatenateMagickString(filename,filelist[j],MagickPathExtent);
926  filelist[j]=DestroyString(filelist[j]);
927  if (strlen(filename) >= (MagickPathExtent-1))
928  ThrowFatalException(OptionFatalError,"FilenameTruncated");
929  if (IsPathDirectory(filename) <= 0)
930  {
931  char
932  file_path[MagickPathExtent];
933 
934  *file_path='\0';
935  if (*magick != '\0')
936  {
937  (void) ConcatenateMagickString(file_path,magick,
938  MagickPathExtent);
939  (void) ConcatenateMagickString(file_path,":",MagickPathExtent);
940  }
941  (void) ConcatenateMagickString(file_path,filename,MagickPathExtent);
942  if (*subimage != '\0')
943  {
944  (void) ConcatenateMagickString(file_path,"[",MagickPathExtent);
945  (void) ConcatenateMagickString(file_path,subimage,
946  MagickPathExtent);
947  (void) ConcatenateMagickString(file_path,"]",MagickPathExtent);
948  }
949  if (strlen(file_path) >= (MagickPathExtent-1))
950  ThrowFatalException(OptionFatalError,"FilenameTruncated");
951  if (destroy != MagickFalse)
952  {
953  count--;
954  vector[count]=DestroyString(vector[count]);
955  destroy=MagickFalse;
956  }
957  vector[count++]=ConstantString(file_path);
958  }
959  }
960  filelist=(char **) RelinquishMagickMemory(filelist);
961  }
962  vector[count]=(char *) NULL;
963  if (IsEventLogging() != MagickFalse)
964  {
965  char
966  *command_line;
967 
968  command_line=AcquireString(vector[0]);
969  for (i=1; i < count; i++)
970  {
971  (void) ConcatenateString(&command_line," {");
972  (void) ConcatenateString(&command_line,vector[i]);
973  (void) ConcatenateString(&command_line,"}");
974  }
975  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
976  "Command line: %s",command_line);
977  command_line=DestroyString(command_line);
978  }
979  *number_arguments=(int) count;
980  *arguments=vector;
981  return(MagickTrue);
982 }
983 
984 /*
985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986 % %
987 % %
988 % %
989 % G e t E x e c u t i o n P a t h %
990 % %
991 % %
992 % %
993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994 %
995 % GetExecutionPath() returns the pathname of the executable that started
996 % the process. On success MagickTrue is returned, otherwise MagickFalse.
997 %
998 % The format of the GetExecutionPath method is:
999 %
1000 % MagickBooleanType GetExecutionPath(char *path,const size_t extent)
1001 %
1002 % A description of each parameter follows:
1003 %
1004 % o path: the pathname of the executable that started the process.
1005 %
1006 % o extent: the maximum extent of the path.
1007 %
1008 */
1009 MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
1010 {
1011  char
1012  *directory;
1013 
1014  *path='\0';
1015  directory=getcwd(path,(unsigned long) extent);
1016  (void) directory;
1017 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
1018  {
1019  char
1020  execution_path[PATH_MAX+1],
1021  link_path[MagickPathExtent];
1022 
1023  ssize_t
1024  count;
1025 
1026  (void) FormatLocaleString(link_path,MagickPathExtent,"/proc/%.20g/exe",
1027  (double) getpid());
1028  count=readlink(link_path,execution_path,PATH_MAX);
1029  if (count == -1)
1030  {
1031  (void) FormatLocaleString(link_path,MagickPathExtent,"/proc/%.20g/file",
1032  (double) getpid());
1033  count=readlink(link_path,execution_path,PATH_MAX);
1034  }
1035  if ((count > 0) && (count <= (ssize_t) PATH_MAX))
1036  {
1037  execution_path[count]='\0';
1038  (void) CopyMagickString(path,execution_path,extent);
1039  }
1040  }
1041 #endif
1042 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
1043  {
1044  char
1045  executable_path[PATH_MAX << 1],
1046  execution_path[PATH_MAX+1];
1047 
1048  uint32_t
1049  length;
1050 
1051  length=sizeof(executable_path);
1052  if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
1053  (realpath(executable_path,execution_path) != (char *) NULL))
1054  (void) CopyMagickString(path,execution_path,extent);
1055  }
1056 #endif
1057 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
1058  {
1059  const char
1060  *execution_path;
1061 
1062  execution_path=(const char *) getexecname();
1063  if (execution_path != (const char *) NULL)
1064  {
1065  if (*execution_path != *DirectorySeparator)
1066  (void) ConcatenateMagickString(path,DirectorySeparator,extent);
1067  (void) ConcatenateMagickString(path,execution_path,extent);
1068  }
1069  }
1070 #endif
1071 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1072  NTGetExecutionPath(path,extent);
1073 #endif
1074 #if defined(__GNU__)
1075  {
1076  char
1077  *program_name;
1078 
1079  ssize_t
1080  count;
1081 
1082  count=0;
1083  program_name=program_invocation_name;
1084  if (*program_invocation_name != '/')
1085  {
1086  size_t
1087  extent;
1088 
1089  extent=strlen(directory)+strlen(program_name)+2;
1090  program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1091  if (program_name == (char *) NULL)
1092  program_name=program_invocation_name;
1093  else
1094  count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1095  program_invocation_name);
1096  }
1097  if (count != -1)
1098  {
1099  char
1100  execution_path[PATH_MAX+1];
1101 
1102  if (realpath(program_name,execution_path) != (char *) NULL)
1103  (void) CopyMagickString(path,execution_path,extent);
1104  }
1105  if (program_name != program_invocation_name)
1106  program_name=(char *) RelinquishMagickMemory(program_name);
1107  }
1108 #endif
1109 #if defined(__OpenBSD__)
1110  {
1111  extern char
1112  *__progname;
1113 
1114  (void) CopyMagickString(path,__progname,extent);
1115  }
1116 #endif
1117  return(IsPathAccessible(path));
1118 }
1119 
1120 /*
1121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1122 % %
1123 % %
1124 % %
1125 % G e t M a g i c k P a g e S i z e %
1126 % %
1127 % %
1128 % %
1129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130 %
1131 % GetMagickPageSize() returns the memory page size.
1132 %
1133 % The format of the GetMagickPageSize method is:
1134 %
1135 % ssize_t GetMagickPageSize()
1136 %
1137 */
1138 MagickPrivate ssize_t GetMagickPageSize(void)
1139 {
1140  static ssize_t
1141  page_size = -1;
1142 
1143  if (page_size > 0)
1144  return(page_size);
1145 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1146  page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1147 #elif defined(MAGICKCORE_HAVE_GETPAGESIZE)
1148  page_size=(ssize_t) getpagesize();
1149 #endif
1150  if (page_size <= 0)
1151  page_size=4096;
1152  return(page_size);
1153 }
1154 
1155 /*
1156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 % %
1158 % %
1159 % %
1160 % G e t P a t h A t t r i b u t e s %
1161 % %
1162 % %
1163 % %
1164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 %
1166 % GetPathAttributes() returns attributes (e.g. size of file) about a path.
1167 %
1168 % The path of the GetPathAttributes method is:
1169 %
1170 % MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1171 %
1172 % A description of each parameter follows.
1173 %
1174 % o path: the file path.
1175 %
1176 % o attributes: the path attributes are returned here.
1177 %
1178 */
1179 MagickExport MagickBooleanType GetPathAttributes(const char *path,
1180  void *attributes)
1181 {
1182  MagickBooleanType
1183  status;
1184 
1185  if (path == (const char *) NULL)
1186  {
1187  errno=EINVAL;
1188  return(MagickFalse);
1189  }
1190  (void) memset(attributes,0,sizeof(struct stat));
1191  status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
1192  MagickFalse;
1193  return(status);
1194 }
1195 
1196 /*
1197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1198 % %
1199 % %
1200 % %
1201 % G e t P a t h C o m p o n e n t %
1202 % %
1203 % %
1204 % %
1205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1206 %
1207 % GetPathComponent() returns the parent directory name, filename, basename, or
1208 % extension of a file path.
1209 %
1210 % The component string pointed to must have at least MagickPathExtent space
1211 % for the results to be stored.
1212 %
1213 % The format of the GetPathComponent function is:
1214 %
1215 % GetPathComponent(const char *path,PathType type,char *component)
1216 %
1217 % A description of each parameter follows:
1218 %
1219 % o path: Specifies a pointer to a character array that contains the
1220 % file path.
1221 %
1222 % o type: Specifies which file path component to return.
1223 %
1224 % o component: the selected file path component is returned here.
1225 %
1226 */
1227 MagickExport void GetPathComponent(const char *path,PathType type,
1228  char *component)
1229 {
1230  char
1231  *q;
1232 
1233  char
1234  *p;
1235 
1236  size_t
1237  magick_length,
1238  subimage_offset,
1239  subimage_length;
1240 
1241  assert(path != (const char *) NULL);
1242  assert(component != (char *) NULL);
1243  if (IsEventLogging() != MagickFalse)
1244  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1245  if (*path == '\0')
1246  {
1247  *component='\0';
1248  return;
1249  }
1250  (void) CopyMagickString(component,path,MagickPathExtent);
1251  subimage_length=0;
1252  subimage_offset=0;
1253  if (type != SubcanonicalPath)
1254  {
1255  p=component+strlen(component)-1;
1256  if ((strlen(component) > 2) && (*p == ']'))
1257  {
1258  q=strrchr(component,'[');
1259  if ((q != (char *) NULL) && ((q == component) || (*(q-1) != ']')) &&
1260  (IsPathAccessible(path) == MagickFalse))
1261  {
1262  /*
1263  Look for scene specification (e.g. img0001.pcd[4]).
1264  */
1265  *p='\0';
1266  if ((IsSceneGeometry(q+1,MagickFalse) == MagickFalse) &&
1267  (IsGeometry(q+1) == MagickFalse))
1268  *p=']';
1269  else
1270  {
1271  subimage_length=(size_t) (p-q);
1272  subimage_offset=(size_t) (q-component+1);
1273  *q='\0';
1274  }
1275  }
1276  }
1277  }
1278  magick_length=0;
1279 #if defined(__OS2__)
1280  if (path[1] != ":")
1281 #endif
1282  for (p=component; *p != '\0'; p++)
1283  {
1284  if ((*p == '%') && (*(p+1) == '['))
1285  {
1286  /*
1287  Skip over %[...].
1288  */
1289  for (p++; (*p != ']') && (*p != '\0'); p++) ;
1290  if (*p == '\0')
1291  break;
1292  }
1293  if ((p != component) && (*p == ':') && (IsPathDirectory(component) < 0) &&
1294  (IsPathAccessible(component) == MagickFalse))
1295  {
1296  /*
1297  Look for image format specification (e.g. ps3:image).
1298  */
1299  *p='\0';
1300  if (IsMagickConflict(component) != MagickFalse)
1301  *p=':';
1302  else
1303  {
1304  magick_length=(size_t) (p-component+1);
1305  for (q=component; *(++p) != '\0'; q++)
1306  *q=(*p);
1307  *q='\0';
1308  }
1309  break;
1310  }
1311  }
1312  p=component;
1313  if (*p != '\0')
1314  for (p=component+strlen(component)-1; p > component; p--)
1315  if (IsBasenameSeparator(*p) != MagickFalse)
1316  break;
1317  switch (type)
1318  {
1319  case MagickPath:
1320  {
1321  if (magick_length != 0)
1322  (void) CopyMagickString(component,path,magick_length);
1323  else
1324  *component='\0';
1325  break;
1326  }
1327  case RootPath:
1328  {
1329  if (*component != '\0')
1330  {
1331  for (p=component+(strlen(component)-1); p > component; p--)
1332  {
1333  if (IsBasenameSeparator(*p) != MagickFalse)
1334  break;
1335  if (*p == '.')
1336  break;
1337  }
1338  if (*p == '.')
1339  *p='\0';
1340  break;
1341  }
1342  magick_fallthrough;
1343  }
1344  case HeadPath:
1345  {
1346  *p='\0';
1347  break;
1348  }
1349  case TailPath:
1350  {
1351  if (IsBasenameSeparator(*p) != MagickFalse)
1352  (void) CopyMagickString(component,p+1,MagickPathExtent);
1353  break;
1354  }
1355  case BasePath:
1356  {
1357  if (IsBasenameSeparator(*p) != MagickFalse)
1358  (void) CopyMagickString(component,p+1,MagickPathExtent);
1359  if (*component != '\0')
1360  for (p=component+(strlen(component)-1); p > component; p--)
1361  if (*p == '.')
1362  {
1363  *p='\0';
1364  break;
1365  }
1366  break;
1367  }
1368  case BasePathSansCompressExtension:
1369  {
1370  char
1371  extension[MagickPathExtent];
1372 
1373  /*
1374  Base path sans any compression extension.
1375  */
1376  GetPathComponent(path,ExtensionPath,extension);
1377  if ((LocaleCompare(extension,"bz2") == 0) ||
1378  (LocaleCompare(extension,"gz") == 0) ||
1379  (LocaleCompare(extension,"svgz") == 0) ||
1380  (LocaleCompare(extension,"wmz") == 0) ||
1381  (LocaleCompare(extension,"Z") == 0))
1382  GetPathComponent(path,BasePath,component);
1383  break;
1384  }
1385  case ExtensionPath:
1386  {
1387  if (IsBasenameSeparator(*p) != MagickFalse)
1388  (void) CopyMagickString(component,p+1,MagickPathExtent);
1389  if (*component != '\0')
1390  for (p=component+strlen(component)-1; p > component; p--)
1391  if (*p == '.')
1392  break;
1393  *component='\0';
1394  if (*p == '.')
1395  (void) CopyMagickString(component,p+1,MagickPathExtent);
1396  break;
1397  }
1398  case SubimagePath:
1399  {
1400  *component='\0';
1401  if ((subimage_length != 0) && (magick_length < subimage_offset))
1402  (void) CopyMagickString(component,path+subimage_offset,subimage_length);
1403  break;
1404  }
1405  case SubcanonicalPath:
1406  case CanonicalPath:
1407  case UndefinedPath:
1408  break;
1409  }
1410 }
1411 
1412 /*
1413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414 % %
1415 % %
1416 % %
1417 % G e t P a t h C o m p o n e n t s %
1418 % %
1419 % %
1420 % %
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 %
1423 % GetPathComponents() returns a list of path components.
1424 %
1425 % The format of the GetPathComponents method is:
1426 %
1427 % char **GetPathComponents(const char *path,
1428 % size_t *number_components)
1429 %
1430 % A description of each parameter follows:
1431 %
1432 % o path: Specifies the string to segment into a list.
1433 %
1434 % o number_components: return the number of components in the list
1435 %
1436 */
1437 MagickPrivate char **GetPathComponents(const char *path,
1438  size_t *number_components)
1439 {
1440  char
1441  **components;
1442 
1443  const char
1444  *p,
1445  *q;
1446 
1447  ssize_t
1448  i;
1449 
1450  if (path == (char *) NULL)
1451  return((char **) NULL);
1452  *number_components=1;
1453  for (p=path; *p != '\0'; p++)
1454  if (IsBasenameSeparator(*p))
1455  (*number_components)++;
1456  components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1457  sizeof(*components));
1458  if (components == (char **) NULL)
1459  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1460  p=path;
1461  for (i=0; i < (ssize_t) *number_components; i++)
1462  {
1463  for (q=p; *q != '\0'; q++)
1464  if (IsBasenameSeparator(*q))
1465  break;
1466  components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MagickPathExtent,
1467  sizeof(**components));
1468  if (components[i] == (char *) NULL)
1469  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1470  (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1471  p=q+1;
1472  }
1473  components[i]=(char *) NULL;
1474  return(components);
1475 }
1476 
1477 /*
1478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1479 % %
1480 % %
1481 % %
1482 % I s P a t h A c c e s s i b l e %
1483 % %
1484 % %
1485 % %
1486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1487 %
1488 % IsPathAccessible() returns MagickTrue if the file as defined by the path is
1489 % accessible.
1490 %
1491 % The format of the IsPathAccessible method is:
1492 %
1493 % MagickBooleanType IsPathAccessible(const char *path)
1494 %
1495 % A description of each parameter follows.
1496 %
1497 % o path: Specifies a path to a file.
1498 %
1499 */
1500 MagickExport MagickBooleanType IsPathAccessible(const char *path)
1501 {
1502  MagickBooleanType
1503  status;
1504 
1505  struct stat
1506  attributes;
1507 
1508  if ((path == (const char *) NULL) || (*path == '\0'))
1509  return(MagickFalse);
1510  if (LocaleCompare(path,"-") == 0)
1511  return(MagickTrue);
1512  status=GetPathAttributes(path,&attributes);
1513  if (status == MagickFalse)
1514  return(status);
1515  if (S_ISREG(attributes.st_mode) == 0)
1516  return(MagickFalse);
1517  if (access_utf8(path,F_OK) != 0)
1518  return(MagickFalse);
1519  return(MagickTrue);
1520 }
1521 
1522 /*
1523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1524 % %
1525 % %
1526 % %
1527 + I s P a t h D i r e c t o r y %
1528 % %
1529 % %
1530 % %
1531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1532 %
1533 % IsPathDirectory() returns -1 if the directory does not exist, 1 is returned
1534 % if the path represents a directory otherwise 0.
1535 %
1536 % The format of the IsPathDirectory method is:
1537 %
1538 % int IsPathDirectory(const char *path)
1539 %
1540 % A description of each parameter follows.
1541 %
1542 % o path: The directory path.
1543 %
1544 */
1545 static int IsPathDirectory(const char *path)
1546 {
1547  MagickBooleanType
1548  status;
1549 
1550  struct stat
1551  attributes;
1552 
1553  if ((path == (const char *) NULL) || (*path == '\0'))
1554  return(MagickFalse);
1555  status=GetPathAttributes(path,&attributes);
1556  if (status == MagickFalse)
1557  return(-1);
1558  if (S_ISDIR(attributes.st_mode) == 0)
1559  return(0);
1560  return(1);
1561 }
1562 
1563 /*
1564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565 % %
1566 % %
1567 % %
1568 % L i s t F i l e s %
1569 % %
1570 % %
1571 % %
1572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573 %
1574 % ListFiles() reads the directory specified and returns a list of filenames
1575 % contained in the directory sorted in ascending alphabetic order.
1576 %
1577 % The format of the ListFiles function is:
1578 %
1579 % char **ListFiles(const char *directory,const char *pattern,
1580 % ssize_t *number_entries)
1581 %
1582 % A description of each parameter follows:
1583 %
1584 % o filelist: Method ListFiles returns a list of filenames contained
1585 % in the directory. If the directory specified cannot be read or it is
1586 % a file a NULL list is returned.
1587 %
1588 % o directory: Specifies a pointer to a text string containing a directory
1589 % name.
1590 %
1591 % o pattern: Specifies a pointer to a text string containing a pattern.
1592 %
1593 % o number_entries: This integer returns the number of filenames in the
1594 % list.
1595 %
1596 */
1597 
1598 #if defined(__cplusplus) || defined(c_plusplus)
1599 extern "C" {
1600 #endif
1601 
1602 static int FileCompare(const void *x,const void *y)
1603 {
1604  const char
1605  **p,
1606  **q;
1607 
1608  p=(const char **) x;
1609  q=(const char **) y;
1610  return(LocaleCompare(*p,*q));
1611 }
1612 
1613 #if defined(__cplusplus) || defined(c_plusplus)
1614 }
1615 #endif
1616 
1617 MagickPrivate char **ListFiles(const char *directory,const char *pattern,
1618  size_t *number_entries)
1619 {
1620  char
1621  **filelist;
1622 
1623  DIR
1624  *current_directory;
1625 
1626  struct dirent
1627  *buffer,
1628  *entry;
1629 
1630  size_t
1631  max_entries;
1632 
1633  /*
1634  Open directory.
1635  */
1636  assert(directory != (const char *) NULL);
1637  assert(pattern != (const char *) NULL);
1638  assert(number_entries != (size_t *) NULL);
1639  if (IsEventLogging() != MagickFalse)
1640  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1641  *number_entries=0;
1642  current_directory=opendir(directory);
1643  if (current_directory == (DIR *) NULL)
1644  return((char **) NULL);
1645  /*
1646  Allocate filelist.
1647  */
1648  max_entries=2048;
1649  filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1650  sizeof(*filelist));
1651  if (filelist == (char **) NULL)
1652  {
1653  (void) closedir(current_directory);
1654  return((char **) NULL);
1655  }
1656  /*
1657  Save the current and change to the new directory.
1658  */
1659  buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
1660  if (buffer == (struct dirent *) NULL)
1661  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1662  while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1663  (entry != (struct dirent *) NULL))
1664  {
1665  if ((LocaleCompare(entry->d_name,".") == 0) ||
1666  (LocaleCompare(entry->d_name,"..") == 0))
1667  continue;
1668  if ((IsPathDirectory(entry->d_name) > 0) ||
1669 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1670  (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1671 #else
1672  (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1673 #endif
1674  {
1675  if (*number_entries >= max_entries)
1676  {
1677  /*
1678  Extend the file list.
1679  */
1680  max_entries<<=1;
1681  filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1682  max_entries,sizeof(*filelist));
1683  if (filelist == (char **) NULL)
1684  break;
1685  }
1686 #if defined(vms)
1687  {
1688  char
1689  *p;
1690 
1691  p=strchr(entry->d_name,';');
1692  if (p)
1693  *p='\0';
1694  if (*number_entries > 0)
1695  if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1696  continue;
1697  }
1698 #endif
1699  filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1700  (*number_entries)++;
1701  }
1702  }
1703  buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1704  (void) closedir(current_directory);
1705  if (filelist == (char **) NULL)
1706  return((char **) NULL);
1707  /*
1708  Sort filelist in ascending order.
1709  */
1710  qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1711  FileCompare);
1712  return(filelist);
1713 }
1714 
1715 /*
1716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717 % %
1718 % %
1719 % %
1720 % M a g i c k D e l a y %
1721 % %
1722 % %
1723 % %
1724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725 %
1726 % MagickDelay() suspends program execution for the number of milliseconds
1727 % specified.
1728 %
1729 % The format of the Delay method is:
1730 %
1731 % void MagickDelay(const MagickSizeType milliseconds)
1732 %
1733 % A description of each parameter follows:
1734 %
1735 % o milliseconds: Specifies the number of milliseconds to delay before
1736 % returning.
1737 %
1738 */
1739 MagickExport void MagickDelay(const MagickSizeType milliseconds)
1740 {
1741  if (milliseconds == 0)
1742  return;
1743 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
1744  {
1745  struct timespec
1746  timer;
1747 
1748  timer.tv_sec=(time_t) (milliseconds/1000);
1749  timer.tv_nsec=(time_t) ((milliseconds % 1000)*1000*1000);
1750  (void) nanosleep(&timer,(struct timespec *) NULL);
1751  }
1752 #elif defined(MAGICKCORE_HAVE_USLEEP)
1753  usleep(1000*milliseconds);
1754 #elif defined(MAGICKCORE_HAVE_SELECT)
1755  {
1756  struct timeval
1757  timer;
1758 
1759  timer.tv_sec=(long) milliseconds/1000;
1760  timer.tv_usec=(long) (milliseconds % 1000)*1000;
1761  (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1762  }
1763 #elif defined(MAGICKCORE_HAVE_POLL)
1764  (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1765 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1766  Sleep((long) milliseconds);
1767 #elif defined(vms)
1768  {
1769  float
1770  timer;
1771 
1772  timer=milliseconds/1000.0;
1773  lib$wait(&timer);
1774  }
1775 #elif defined(__BEOS__)
1776  snooze(1000*milliseconds);
1777 #else
1778  {
1779  clock_t
1780  time_end;
1781 
1782  time_end=clock()+milliseconds*CLOCKS_PER_SEC/1000;
1783  while (clock() < time_end)
1784  {
1785  }
1786  }
1787 #endif
1788 }
1789 
1790 /*
1791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1792 % %
1793 % %
1794 % %
1795 % M u l t i l i n e C e n s u s %
1796 % %
1797 % %
1798 % %
1799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1800 %
1801 % MultilineCensus() returns the number of lines within a label. A line is
1802 % represented by a \n character.
1803 %
1804 % The format of the MultilineCensus method is:
1805 %
1806 % size_t MultilineCensus(const char *label)
1807 %
1808 % A description of each parameter follows.
1809 %
1810 % o label: This character string is the label.
1811 %
1812 */
1813 MagickExport size_t MultilineCensus(const char *label)
1814 {
1815  size_t
1816  number_lines;
1817 
1818  /*
1819  Determine the number of lines within this label.
1820  */
1821  if (label == (char *) NULL)
1822  return(0);
1823  for (number_lines=1; *label != '\0'; label++)
1824  if (*label == '\n')
1825  number_lines++;
1826  return(number_lines);
1827 }
1828 
1829 /*
1830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1831 % %
1832 % %
1833 % %
1834 % S h r e d F i l e %
1835 % %
1836 % %
1837 % %
1838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1839 %
1840 % ShredFile() overwrites the specified file with random data. The overwrite is
1841 % optional and is only required to help keep the contents of the file private.
1842 %
1843 % The format of the ShredFile method is:
1844 %
1845 % MagickBooleanType ShredFile(const char *path)
1846 %
1847 % A description of each parameter follows.
1848 %
1849 % o path: Specifies a path to a file.
1850 %
1851 */
1852 MagickPrivate MagickBooleanType ShredFile(const char *path)
1853 {
1854  int
1855  file,
1856  status;
1857 
1858  MagickSizeType
1859  length;
1860 
1861  RandomInfo
1862  *random_info;
1863 
1864  size_t
1865  quantum;
1866 
1867  ssize_t
1868  i;
1869 
1870  static ssize_t
1871  passes = -1;
1872 
1873  StringInfo
1874  *key;
1875 
1876  struct stat
1877  file_stats;
1878 
1879  if ((path == (const char *) NULL) || (*path == '\0'))
1880  return(MagickFalse);
1881  if (passes == -1)
1882  {
1883  char
1884  *property;
1885 
1886  passes=0;
1887  property=GetEnvironmentValue("MAGICK_SHRED_PASSES");
1888  if (property != (char *) NULL)
1889  {
1890  passes=(ssize_t) StringToInteger(property);
1891  property=DestroyString(property);
1892  }
1893  property=GetPolicyValue("system:shred");
1894  if (property != (char *) NULL)
1895  {
1896  passes=(ssize_t) StringToInteger(property);
1897  property=DestroyString(property);
1898  }
1899  }
1900  if (passes == 0)
1901  return(MagickTrue);
1902  /*
1903  Shred the file.
1904  */
1905  file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
1906  if (file == -1)
1907  return(MagickFalse);
1908  quantum=(size_t) MagickMinBufferExtent;
1909  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1910  quantum=(size_t) MagickMin(file_stats.st_size,MagickMinBufferExtent);
1911  length=(MagickSizeType) file_stats.st_size;
1912  random_info=AcquireRandomInfo();
1913  key=GetRandomKey(random_info,quantum);
1914  for (i=0; i < passes; i++)
1915  {
1916  MagickOffsetType
1917  j;
1918 
1919  ssize_t
1920  count;
1921 
1922  if (lseek(file,0,SEEK_SET) < 0)
1923  break;
1924  for (j=0; j < (MagickOffsetType) length; j+=count)
1925  {
1926  if (i != 0)
1927  SetRandomKey(random_info,quantum,GetStringInfoDatum(key));
1928  count=write(file,GetStringInfoDatum(key),(size_t)
1929  MagickMin((MagickOffsetType) quantum,(MagickOffsetType) length-j));
1930  if (count <= 0)
1931  {
1932  count=0;
1933  if (errno != EINTR)
1934  break;
1935  }
1936  }
1937  if (j < (MagickOffsetType) length)
1938  break;
1939  }
1940  key=DestroyStringInfo(key);
1941  random_info=DestroyRandomInfo(random_info);
1942  status=close(file);
1943  return((status == -1 || i < passes) ? MagickFalse : MagickTrue);
1944 }
_ExceptionInfo
Definition: exception.h:101
_StringInfo
Definition: string_.h:27
_RandomInfo
Definition: random.c:83