MagickCore  6.9.11-60
Convert, Edit, Or Compose Bitmap Images
utility-private.h
Go to the documentation of this file.
1 /*
2  Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization
3  dedicated to making software imaging solutions freely available.
4 
5  You may not use this file except in compliance with the License. You may
6  obtain a copy of the License at
7 
8  https://imagemagick.org/script/license.php
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 
16  MagickCore private utility methods.
17 */
18 #ifndef MAGICKCORE_UTILITY_PRIVATE_H
19 #define MAGICKCORE_UTILITY_PRIVATE_H
20 
21 #include "magick/memory_.h"
22 #include "magick/nt-base.h"
23 #include "magick/nt-base-private.h"
24 
25 #if defined(__cplusplus) || defined(c_plusplus)
26 extern "C" {
27 #endif
28 
29 #define MagickPathTemplate "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" /* min 6 X's */
30 
32  ShredFile(const char *);
33 
34 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
35  struct dirent **result)
36 {
37 #if defined(MAGICKCORE_HAVE_READDIR_R)
38  return(readdir_r(directory,entry,result));
39 #else
40  (void) entry;
41  errno=0;
42  *result=readdir(directory);
43  return(errno);
44 #endif
45 }
46 
47 /*
48  Windows UTF8 compatibility methods.
49 */
50 
51 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
52 static inline wchar_t *create_wchar_path(const char *utf8)
53 {
54  int
55  count;
56 
57  wchar_t
58  *wideChar;
59 
60  count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);
61  if ((count > MAX_PATH) && (NTLongPathsEnabled() == MagickFalse))
62  {
63  char
64  buffer[MaxTextExtent];
65 
66  wchar_t
67  shortPath[MAX_PATH],
68  *longPath;
69 
70  (void) FormatLocaleString(buffer,MaxTextExtent,"\\\\?\\%s",utf8);
71  count+=4;
72  longPath=(wchar_t *) AcquireQuantumMemory(count,sizeof(*longPath));
73  if (longPath == (wchar_t *) NULL)
74  return((wchar_t *) NULL);
75  count=MultiByteToWideChar(CP_UTF8,0,buffer,-1,longPath,count);
76  if (count != 0)
77  count=GetShortPathNameW(longPath,shortPath,MAX_PATH);
78  longPath=(wchar_t *) RelinquishMagickMemory(longPath);
79  if ((count < 5) || (count >= MAX_PATH))
80  return((wchar_t *) NULL);
81  wideChar=(wchar_t *) AcquireQuantumMemory(count-3,sizeof(*wideChar));
82  wcscpy(wideChar,shortPath+4);
83  return(wideChar);
84  }
85  wideChar=(wchar_t *) AcquireQuantumMemory(count,sizeof(*wideChar));
86  if (wideChar == (wchar_t *) NULL)
87  return((wchar_t *) NULL);
88  count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,wideChar,count);
89  if (count == 0)
90  {
91  wideChar=(wchar_t *) RelinquishMagickMemory(wideChar);
92  return((wchar_t *) NULL);
93  }
94  return(wideChar);
95 }
96 #endif
97 
98 static inline int access_utf8(const char *path,int mode)
99 {
100 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
101  return(access(path,mode));
102 #else
103  int
104  status;
105 
106  wchar_t
107  *path_wide;
108 
109  path_wide=create_wchar_path(path);
110  if (path_wide == (wchar_t *) NULL)
111  return(-1);
112  status=_waccess(path_wide,mode);
113  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
114  return(status);
115 #endif
116 }
117 
118 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__)
119 #define close_utf8 _close
120 #else
121 #define close_utf8 close
122 #endif
123 
124 static inline FILE *fopen_utf8(const char *path,const char *mode)
125 {
126 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
127  return(fopen(path,mode));
128 #else
129  FILE
130  *file;
131 
132  wchar_t
133  *mode_wide,
134  *path_wide;
135 
136  path_wide=create_wchar_path(path);
137  if (path_wide == (wchar_t *) NULL)
138  return((FILE *) NULL);
139  mode_wide=create_wchar_path(mode);
140  if (mode_wide == (wchar_t *) NULL)
141  {
142  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
143  return((FILE *) NULL);
144  }
145  file=_wfopen(path_wide,mode_wide);
146  mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
147  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
148  return(file);
149 #endif
150 }
151 
152 static inline void getcwd_utf8(char *path,size_t extent)
153 {
154 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
155  char
156  *directory;
157 
158  directory=getcwd(path,extent);
159  (void) directory;
160 #else
161  wchar_t
162  wide_path[MaxTextExtent];
163 
164  (void) _wgetcwd(wide_path,MaxTextExtent-1);
165  (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
166 #endif
167 }
168 
169 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__)
170 typedef int
171  mode_t;
172 #endif
173 
174 static inline int open_utf8(const char *path,int flags,mode_t mode)
175 {
176 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
177  return(open(path,flags,mode));
178 #else
179  int
180  status;
181 
182  wchar_t
183  *path_wide;
184 
185  path_wide=create_wchar_path(path);
186  if (path_wide == (wchar_t *) NULL)
187  return(-1);
188  status=_wopen(path_wide,flags,mode);
189  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
190  return(status);
191 #endif
192 }
193 
194 static inline FILE *popen_utf8(const char *command,const char *type)
195 {
196 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
197  return(popen(command,type));
198 #else
199  FILE
200  *file;
201 
202  int
203  length;
204 
205  wchar_t
206  *command_wide,
207  type_wide[5];
208 
209  file=(FILE *) NULL;
210  length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
211  if (length == 0)
212  return(file);
213  length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
214  if (length == 0)
215  return(file);
216  command_wide=(wchar_t *) AcquireQuantumMemory(length,sizeof(*command_wide));
217  if (command_wide == (wchar_t *) NULL)
218  return(file);
219  length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
220  if (length != 0)
221  file=_wpopen(command_wide,type_wide);
222  command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
223  return(file);
224 #endif
225 }
226 
227 static inline char *realpath_utf8(const char *path)
228 {
229 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
230 #if defined(MAGICKCORE_HAVE_REALPATH)
231  return(realpath(path,(char *) NULL));
232 #else
233  return(AcquireString(path));
234 #endif
235 #else
236  char
237  *real_path;
238 
239  DWORD
240  final_path_length,
241  full_path_length;
242 
243  HANDLE
244  file_handle;
245 
246  int
247  length,
248  utf8_length,
249 
250  wchar_t
251  *clean_path,
252  *final_path,
253  *full_path,
254  *wide_path;
255 
256  /*
257  Convert UTF-8 to UTF-16.
258  */
259  if (path == (const char *) NULL)
260  return((char *) NULL);
261  length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
262  if (length <= 0)
263  return((char *) NULL);
264  wide_path=(wchar_t *) AcquireQuantumMeory(length,sizeof(wchar_t));
265  if (wide_path == (wchar_t *) NULL)
266  return((char *) NULL);
267  MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
268  /*
269  Normalize syntactically.
270  */
271  full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
272  if (full_path_length == 0)
273  {
274  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
275  return((char *) NULL);
276  }
277  full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
278  if (full_path == (wchar_t *) NULL);
279  {
280  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
281  return((char *) NULL);
282  }
283  GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
284  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
285  /*
286  Open the file/directory to resolve symlinks.
287  */
288  file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
289  FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
290  FILE_FLAG_BACKUP_SEMANTICS,NULL);
291  if (file_handle == INVALID_HANDLE_VALUE)
292  {
293  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
294  return((char *) NULL);
295  }
296  /*
297  Resolve final canonical path.
298  */
299  final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
300  FILE_NAME_NORMALIZED);
301  if (final_path_length == 0)
302  {
303  CloseHandle(file_handle);
304  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
305  return((char *) NULL);
306  }
307  final_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
308  sizeof(wchar_t));
309  if (final_path == (wchar_t *) NULL)
310  {
311  CloseHandle(file_handle);
312  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
313  return((char *) NULL);
314  }
315  GetFinalPathNameByHandleW(file_handle,final_path,final_path_length,
316  FILE_NAME_NORMALIZED);
317  CloseHandle(file_handle);
318  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
319  /*
320  Remove \\?\ prefix for POSIX-like behavior.
321  */
322  clean_path=final_path;
323  if (wcsncmp(final_path,L"\\\\?\\",4) == 0)
324  clean_path=final_path+4;
325  /*
326  Convert UTF-16 to UTF-8.
327  */
328  utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
329  if (utf8_length <= 0)
330  {
331  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
332  return NULL;
333  }
334  real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
335  if (real_path == (char *) NULL)
336  {
337  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
338  return NULL;
339  }
340  WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
341  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
342  return(real_path);
343 #endif
344 }
345 
346 static inline int remove_utf8(const char *path)
347 {
348 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
349  return(unlink(path));
350 #else
351  int
352  status;
353 
354  wchar_t
355  *path_wide;
356 
357  path_wide=create_wchar_path(path);
358  if (path_wide == (wchar_t *) NULL)
359  return(-1);
360  status=_wremove(path_wide);
361  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
362  return(status);
363 #endif
364 }
365 
366 static inline int rename_utf8(const char *source,const char *destination)
367 {
368 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
369  return(rename(source,destination));
370 #else
371  int
372  status;
373 
374  wchar_t
375  *destination_wide,
376  *source_wide;
377 
378  source_wide=create_wchar_path(source);
379  if (source_wide == (wchar_t *) NULL)
380  return(-1);
381  destination_wide=create_wchar_path(destination);
382  if (destination_wide == (wchar_t *) NULL)
383  {
384  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
385  return(-1);
386  }
387  status=_wrename(source_wide,destination_wide);
388  destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
389  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
390  return(status);
391 #endif
392 }
393 
394 static inline int stat_utf8(const char *path,struct stat *attributes)
395 {
396 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
397  return(stat(path,attributes));
398 #else
399  int
400  status;
401 
402  wchar_t
403  *path_wide;
404 
405  path_wide=create_wchar_path(path);
406  if (path_wide == (WCHAR *) NULL)
407  return(-1);
408  status=wstat(path_wide,attributes);
409  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
410  return(status);
411 #endif
412 }
413 
414 static inline MagickBooleanType is_symlink_utf8(const char *path)
415 {
416 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
417 #if defined(MAGICKCORE_POSIX_SUPPORT)
418  struct stat
419  status;
420 
421  if (lstat(path,&status) == -1)
422  return(MagickFalse);
423  return(S_ISLNK(status.st_mode) != 0 ? MagickTrue : MagickFalse);
424 #else
425  return(MagickFalse);
426 #endif
427 #else
428  return(NTIsSymlinkWide(path));
429 #endif
430 }
431 
432 
433 #if defined(__cplusplus) || defined(c_plusplus)
434 }
435 #endif
436 
437 #endif
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:498
MagickExport struct dirent * readdir(DIR *)
MagickBooleanType
Definition: magick-type.h:203
@ MagickFalse
Definition: magick-type.h:204
@ MagickTrue
Definition: magick-type.h:205
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1209
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:667
#define MagickPrivate
Definition: method-attribute.h:81
#define MaxTextExtent
Definition: method-attribute.h:89
MagickExport char * AcquireString(const char *source)
Definition: string.c:126
Definition: mac.h:42
Definition: mac.h:54
static int open_utf8(const char *path, int flags, mode_t mode)
Definition: utility-private.h:174
static int MagickReadDirectory(DIR *directory, struct dirent *entry, struct dirent **result)
Definition: utility-private.h:34
static int remove_utf8(const char *path)
Definition: utility-private.h:346
static char * realpath_utf8(const char *path)
Definition: utility-private.h:227
static int access_utf8(const char *path, int mode)
Definition: utility-private.h:98
static int stat_utf8(const char *path, struct stat *attributes)
Definition: utility-private.h:394
static FILE * popen_utf8(const char *command, const char *type)
Definition: utility-private.h:194
static FILE * fopen_utf8(const char *path, const char *mode)
Definition: utility-private.h:124
static void getcwd_utf8(char *path, size_t extent)
Definition: utility-private.h:152
MagickPrivate MagickBooleanType ShredFile(const char *)
Definition: utility.c:1962
static int rename_utf8(const char *source, const char *destination)
Definition: utility-private.h:366
static MagickBooleanType is_symlink_utf8(const char *path)
Definition: utility-private.h:414