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