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