MagickCore  6.9.12-77
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 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  }
1340  case HeadPath:
1341  {
1342  *p='\0';
1343  break;
1344  }
1345  case TailPath:
1346  {
1347  if (IsBasenameSeparator(*p) != MagickFalse)
1348  (void) CopyMagickString(component,p+1,MagickPathExtent);
1349  break;
1350  }
1351  case BasePath:
1352  {
1353  if (IsBasenameSeparator(*p) != MagickFalse)
1354  (void) CopyMagickString(component,p+1,MagickPathExtent);
1355  if (*component != '\0')
1356  for (p=component+(strlen(component)-1); p > component; p--)
1357  if (*p == '.')
1358  {
1359  *p='\0';
1360  break;
1361  }
1362  break;
1363  }
1364  case BasePathSansCompressExtension:
1365  {
1366  char
1367  extension[MagickPathExtent];
1368 
1369  /*
1370  Base path sans any compression extension.
1371  */
1372  GetPathComponent(path,ExtensionPath,extension);
1373  if ((LocaleCompare(extension,"bz2") == 0) ||
1374  (LocaleCompare(extension,"gz") == 0) ||
1375  (LocaleCompare(extension,"svgz") == 0) ||
1376  (LocaleCompare(extension,"wmz") == 0) ||
1377  (LocaleCompare(extension,"Z") == 0))
1378  GetPathComponent(path,BasePath,component);
1379  break;
1380  }
1381  case ExtensionPath:
1382  {
1383  if (IsBasenameSeparator(*p) != MagickFalse)
1384  (void) CopyMagickString(component,p+1,MagickPathExtent);
1385  if (*component != '\0')
1386  for (p=component+strlen(component)-1; p > component; p--)
1387  if (*p == '.')
1388  break;
1389  *component='\0';
1390  if (*p == '.')
1391  (void) CopyMagickString(component,p+1,MagickPathExtent);
1392  break;
1393  }
1394  case SubimagePath:
1395  {
1396  *component='\0';
1397  if ((subimage_length != 0) && (magick_length < subimage_offset))
1398  (void) CopyMagickString(component,path+subimage_offset,subimage_length);
1399  break;
1400  }
1401  case SubcanonicalPath:
1402  case CanonicalPath:
1403  case UndefinedPath:
1404  break;
1405  }
1406 }
1407 
1408 /*
1409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1410 % %
1411 % %
1412 % %
1413 % G e t P a t h C o m p o n e n t s %
1414 % %
1415 % %
1416 % %
1417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1418 %
1419 % GetPathComponents() returns a list of path components.
1420 %
1421 % The format of the GetPathComponents method is:
1422 %
1423 % char **GetPathComponents(const char *path,
1424 % size_t *number_components)
1425 %
1426 % A description of each parameter follows:
1427 %
1428 % o path: Specifies the string to segment into a list.
1429 %
1430 % o number_components: return the number of components in the list
1431 %
1432 */
1433 MagickExport char **GetPathComponents(const char *path,
1434  size_t *number_components)
1435 {
1436  char
1437  **components;
1438 
1439  const char
1440  *p,
1441  *q;
1442 
1443  ssize_t
1444  i;
1445 
1446  if (path == (char *) NULL)
1447  return((char **) NULL);
1448  *number_components=1;
1449  for (p=path; *p != '\0'; p++)
1450  if (IsBasenameSeparator(*p))
1451  (*number_components)++;
1452  components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1453  sizeof(*components));
1454  if (components == (char **) NULL)
1455  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1456  p=path;
1457  for (i=0; i < (ssize_t) *number_components; i++)
1458  {
1459  for (q=p; *q != '\0'; q++)
1460  if (IsBasenameSeparator(*q))
1461  break;
1462  components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1463  sizeof(**components));
1464  if (components[i] == (char *) NULL)
1465  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1466  (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1467  p=q+1;
1468  }
1469  components[i]=(char *) NULL;
1470  return(components);
1471 }
1472 
1473 /*
1474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1475 % %
1476 % %
1477 % %
1478 % I s P a t h A c c e s s i b l e %
1479 % %
1480 % %
1481 % %
1482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483 %
1484 % IsPathAccessible() returns MagickTrue if the file as defined by the path is
1485 % accessible.
1486 %
1487 % The format of the IsPathAccessible method is:
1488 %
1489 % MagickBooleanType IsPathAccessible(const char *path)
1490 %
1491 % A description of each parameter follows.
1492 %
1493 % o path: Specifies a path to a file.
1494 %
1495 */
1496 MagickExport MagickBooleanType IsPathAccessible(const char *path)
1497 {
1498  MagickBooleanType
1499  status;
1500 
1501  struct stat
1502  attributes;
1503 
1504  if ((path == (const char *) NULL) || (*path == '\0'))
1505  return(MagickFalse);
1506  if (LocaleCompare(path,"-") == 0)
1507  return(MagickTrue);
1508  status=GetPathAttributes(path,&attributes);
1509  if (status == MagickFalse)
1510  return(status);
1511  if (S_ISREG(attributes.st_mode) == 0)
1512  return(MagickFalse);
1513  if (access_utf8(path,F_OK) != 0)
1514  return(MagickFalse);
1515  return(MagickTrue);
1516 }
1517 
1518 /*
1519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1520 % %
1521 % %
1522 % %
1523 + I s P a t h D i r e c t o r y %
1524 % %
1525 % %
1526 % %
1527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528 %
1529 % IsPathDirectory() returns -1 if the directory does not exist, 1 is returned
1530 % if the path represents a directory otherwise 0.
1531 %
1532 % The format of the IsPathDirectory method is:
1533 %
1534 % int IsPathDirectory(const char *path)
1535 %
1536 % A description of each parameter follows.
1537 %
1538 % o path: The directory path.
1539 %
1540 */
1541 static int IsPathDirectory(const char *path)
1542 {
1543  MagickBooleanType
1544  status;
1545 
1546  struct stat
1547  attributes;
1548 
1549  if ((path == (const char *) NULL) || (*path == '\0'))
1550  return(MagickFalse);
1551  status=GetPathAttributes(path,&attributes);
1552  if (status == MagickFalse)
1553  return(-1);
1554  if (S_ISDIR(attributes.st_mode) == 0)
1555  return(0);
1556  return(1);
1557 }
1558 
1559 /*
1560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1561 % %
1562 % %
1563 % %
1564 % L i s t F i l e s %
1565 % %
1566 % %
1567 % %
1568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1569 %
1570 % ListFiles() reads the directory specified and returns a list of filenames
1571 % contained in the directory sorted in ascending alphabetic order.
1572 %
1573 % The format of the ListFiles function is:
1574 %
1575 % char **ListFiles(const char *directory,const char *pattern,
1576 % ssize_t *number_entries)
1577 %
1578 % A description of each parameter follows:
1579 %
1580 % o filelist: Method ListFiles returns a list of filenames contained
1581 % in the directory. If the directory specified cannot be read or it is
1582 % a file a NULL list is returned.
1583 %
1584 % o directory: Specifies a pointer to a text string containing a directory
1585 % name.
1586 %
1587 % o pattern: Specifies a pointer to a text string containing a pattern.
1588 %
1589 % o number_entries: This integer returns the number of filenames in the
1590 % list.
1591 %
1592 */
1593 
1594 #if defined(__cplusplus) || defined(c_plusplus)
1595 extern "C" {
1596 #endif
1597 
1598 static int FileCompare(const void *x,const void *y)
1599 {
1600  const char
1601  **p,
1602  **q;
1603 
1604  p=(const char **) x;
1605  q=(const char **) y;
1606  return(LocaleCompare(*p,*q));
1607 }
1608 
1609 #if defined(__cplusplus) || defined(c_plusplus)
1610 }
1611 #endif
1612 
1613 MagickExport char **ListFiles(const char *directory,const char *pattern,
1614  size_t *number_entries)
1615 {
1616  char
1617  **filelist;
1618 
1619  DIR
1620  *current_directory;
1621 
1622  struct dirent
1623  *buffer,
1624  *entry;
1625 
1626  size_t
1627  max_entries;
1628 
1629  /*
1630  Open directory.
1631  */
1632  assert(directory != (const char *) NULL);
1633  assert(pattern != (const char *) NULL);
1634  assert(number_entries != (size_t *) NULL);
1635  if (IsEventLogging() != MagickFalse)
1636  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1637  *number_entries=0;
1638  current_directory=opendir(directory);
1639  if (current_directory == (DIR *) NULL)
1640  return((char **) NULL);
1641  /*
1642  Allocate filelist.
1643  */
1644  max_entries=2048;
1645  filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1646  sizeof(*filelist));
1647  if (filelist == (char **) NULL)
1648  {
1649  (void) closedir(current_directory);
1650  return((char **) NULL);
1651  }
1652  /*
1653  Save the current and change to the new directory.
1654  */
1655  buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
1656  if (buffer == (struct dirent *) NULL)
1657  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1658  while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1659  (entry != (struct dirent *) NULL))
1660  {
1661  if ((LocaleCompare(entry->d_name,".") == 0) ||
1662  (LocaleCompare(entry->d_name,"..") == 0))
1663  continue;
1664  if ((IsPathDirectory(entry->d_name) > 0) ||
1665 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1666  (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1667 #else
1668  (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1669 #endif
1670  {
1671  if (*number_entries >= max_entries)
1672  {
1673  /*
1674  Extend the file list.
1675  */
1676  max_entries<<=1;
1677  filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1678  max_entries,sizeof(*filelist));
1679  if (filelist == (char **) NULL)
1680  break;
1681  }
1682 #if defined(vms)
1683  {
1684  char
1685  *p;
1686 
1687  p=strchr(entry->d_name,';');
1688  if (p)
1689  *p='\0';
1690  if (*number_entries > 0)
1691  if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1692  continue;
1693  }
1694 #endif
1695  filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1696  (*number_entries)++;
1697  }
1698  }
1699  buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1700  (void) closedir(current_directory);
1701  if (filelist == (char **) NULL)
1702  return((char **) NULL);
1703  /*
1704  Sort filelist in ascending order.
1705  */
1706  qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1707  FileCompare);
1708  return(filelist);
1709 }
1710 
1711 /*
1712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1713 % %
1714 % %
1715 % %
1716 % M a g i c k D e l a y %
1717 % %
1718 % %
1719 % %
1720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1721 %
1722 % MagickDelay() suspends program execution for the number of milliseconds
1723 % specified.
1724 %
1725 % The format of the Delay method is:
1726 %
1727 % void MagickDelay(const MagickSizeType milliseconds)
1728 %
1729 % A description of each parameter follows:
1730 %
1731 % o milliseconds: Specifies the number of milliseconds to delay before
1732 % returning.
1733 %
1734 */
1735 MagickExport void MagickDelay(const MagickSizeType milliseconds)
1736 {
1737  if (milliseconds == 0)
1738  return;
1739 #if defined(MAGICKCORE_HAVE_NANOSLEEP)
1740  {
1741  struct timespec
1742  timer;
1743 
1744  timer.tv_sec=(time_t) (milliseconds/1000);
1745  timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1746  (void) nanosleep(&timer,(struct timespec *) NULL);
1747  }
1748 #elif defined(MAGICKCORE_HAVE_USLEEP)
1749  usleep(1000*milliseconds);
1750 #elif defined(MAGICKCORE_HAVE_SELECT)
1751  {
1752  struct timeval
1753  timer;
1754 
1755  timer.tv_sec=(long) milliseconds/1000;
1756  timer.tv_usec=(long) (milliseconds % 1000)*1000;
1757  (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1758  }
1759 #elif defined(MAGICKCORE_HAVE_POLL)
1760  (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1761 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1762  Sleep((long) milliseconds);
1763 #elif defined(vms)
1764  {
1765  float
1766  timer;
1767 
1768  timer=milliseconds/1000.0;
1769  lib$wait(&timer);
1770  }
1771 #elif defined(__BEOS__)
1772  snooze(1000*milliseconds);
1773 #else
1774  {
1775  clock_t
1776  time_end;
1777 
1778  time_end=clock()+milliseconds*CLOCKS_PER_SEC/1000;
1779  while (clock() < time_end)
1780  {
1781  }
1782  }
1783 #endif
1784 }
1785 
1786 /*
1787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1788 % %
1789 % %
1790 % %
1791 % M u l t i l i n e C e n s u s %
1792 % %
1793 % %
1794 % %
1795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1796 %
1797 % MultilineCensus() returns the number of lines within a label. A line is
1798 % represented by a \n character.
1799 %
1800 % The format of the MultilineCensus method is:
1801 %
1802 % size_t MultilineCensus(const char *label)
1803 %
1804 % A description of each parameter follows.
1805 %
1806 % o label: This character string is the label.
1807 %
1808 %
1809 */
1810 MagickExport size_t MultilineCensus(const char *label)
1811 {
1812  size_t
1813  number_lines;
1814 
1815  /*
1816  Determine the number of lines within this label.
1817  */
1818  if (label == (char *) NULL)
1819  return(0);
1820  for (number_lines=1; *label != '\0'; label++)
1821  if (*label == '\n')
1822  number_lines++;
1823  return(number_lines);
1824 }
1825 
1826 /*
1827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1828 % %
1829 % %
1830 % %
1831 % S h r e d F i l e %
1832 % %
1833 % %
1834 % %
1835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1836 %
1837 % ShredFile() overwrites the specified file with random data. The overwrite
1838 % is optional and is only required to help keep the contents of the file
1839 % private.
1840 %
1841 % The format of the ShredFile method is:
1842 %
1843 % MagickBooleanType ShredFile(const char *path)
1844 %
1845 % A description of each parameter follows.
1846 %
1847 % o path: Specifies a path to a file.
1848 %
1849 */
1850 MagickPrivate MagickBooleanType ShredFile(const char *path)
1851 {
1852  int
1853  file,
1854  status;
1855 
1856  MagickSizeType
1857  length;
1858 
1859  RandomInfo
1860  *random_info;
1861 
1862  size_t
1863  quantum;
1864 
1865  ssize_t
1866  i;
1867 
1868  static ssize_t
1869  passes = -1;
1870 
1871  StringInfo
1872  *key;
1873 
1874  struct stat
1875  file_stats;
1876 
1877  if ((path == (const char *) NULL) || (*path == '\0'))
1878  return(MagickFalse);
1879  if (passes == -1)
1880  {
1881  char
1882  *property;
1883 
1884  passes=0;
1885  property=GetEnvironmentValue("MAGICK_SHRED_PASSES");
1886  if (property != (char *) NULL)
1887  {
1888  passes=(ssize_t) StringToInteger(property);
1889  property=DestroyString(property);
1890  }
1891  property=GetPolicyValue("system:shred");
1892  if (property != (char *) NULL)
1893  {
1894  passes=(ssize_t) StringToInteger(property);
1895  property=DestroyString(property);
1896  }
1897  }
1898  if (passes == 0)
1899  return(MagickTrue);
1900  file=open_utf8(path,O_WRONLY | O_EXCL | O_BINARY,S_MODE);
1901  if (file == -1)
1902  return(MagickFalse);
1903  /*
1904  Shred the file.
1905  */
1906  quantum=(size_t) MagickMinBufferExtent;
1907  if ((fstat(file,&file_stats) == 0) && (file_stats.st_size > 0))
1908  quantum=(size_t) MagickMin(file_stats.st_size,MagickMinBufferExtent);
1909  length=(MagickSizeType) file_stats.st_size;
1910  random_info=AcquireRandomInfo();
1911  key=GetRandomKey(random_info,quantum);
1912  for (i=0; i < passes; i++)
1913  {
1914  MagickOffsetType
1915  j;
1916 
1917  ssize_t
1918  count;
1919 
1920  if (lseek(file,0,SEEK_SET) < 0)
1921  break;
1922  for (j=0; j < (MagickOffsetType) length; j+=count)
1923  {
1924  if (i != 0)
1925  SetRandomKey(random_info,quantum,GetStringInfoDatum(key));
1926  count=write(file,GetStringInfoDatum(key),(size_t)
1927  MagickMin((MagickSizeType) quantum,length-j));
1928  if (count <= 0)
1929  {
1930  count=0;
1931  if (errno != EINTR)
1932  break;
1933  }
1934  }
1935  if (j < (MagickOffsetType) length)
1936  break;
1937  }
1938  key=DestroyStringInfo(key);
1939  random_info=DestroyRandomInfo(random_info);
1940  status=close(file);
1941  return((status == -1 || i < passes) ? MagickFalse : MagickTrue);
1942 }
Definition: mac.h:53
Definition: mac.h:41