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