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 
30  ShredFile(const char *);
31 
32 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
33  struct dirent **result)
34 {
35 #if defined(MAGICKCORE_HAVE_READDIR_R)
36  return(readdir_r(directory,entry,result));
37 #else
38  (void) entry;
39  errno=0;
40  *result=readdir(directory);
41  return(errno);
42 #endif
43 }
44 
45 /*
46  Windows UTF8 compatibility methods.
47 */
48 
49 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
50 static inline wchar_t *create_wchar_path(const char *utf8)
51 {
52  int
53  count;
54 
55  wchar_t
56  *wideChar;
57 
58  count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);
59  if ((count > MAX_PATH) && (NTLongPathsEnabled() == MagickFalse))
60  {
61  char
62  buffer[MaxTextExtent];
63 
64  wchar_t
65  shortPath[MAX_PATH],
66  *longPath;
67 
68  (void) FormatLocaleString(buffer,MaxTextExtent,"\\\\?\\%s",utf8);
69  count+=4;
70  longPath=(wchar_t *) AcquireQuantumMemory(count,sizeof(*longPath));
71  if (longPath == (wchar_t *) NULL)
72  return((wchar_t *) NULL);
73  count=MultiByteToWideChar(CP_UTF8,0,buffer,-1,longPath,count);
74  if (count != 0)
75  count=GetShortPathNameW(longPath,shortPath,MAX_PATH);
76  longPath=(wchar_t *) RelinquishMagickMemory(longPath);
77  if ((count < 5) || (count >= MAX_PATH))
78  return((wchar_t *) NULL);
79  wideChar=(wchar_t *) AcquireQuantumMemory(count-3,sizeof(*wideChar));
80  wcscpy(wideChar,shortPath+4);
81  return(wideChar);
82  }
83  wideChar=(wchar_t *) AcquireQuantumMemory(count,sizeof(*wideChar));
84  if (wideChar == (wchar_t *) NULL)
85  return((wchar_t *) NULL);
86  count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,wideChar,count);
87  if (count == 0)
88  {
89  wideChar=(wchar_t *) RelinquishMagickMemory(wideChar);
90  return((wchar_t *) NULL);
91  }
92  return(wideChar);
93 }
94 #endif
95 
96 static inline int access_utf8(const char *path,int mode)
97 {
98 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
99  return(access(path,mode));
100 #else
101  int
102  status;
103 
104  wchar_t
105  *path_wide;
106 
107  path_wide=create_wchar_path(path);
108  if (path_wide == (wchar_t *) NULL)
109  return(-1);
110  status=_waccess(path_wide,mode);
111  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
112  return(status);
113 #endif
114 }
115 
116 static inline FILE *fopen_utf8(const char *path,const char *mode)
117 {
118 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
119  return(fopen(path,mode));
120 #else
121  FILE
122  *file;
123 
124  wchar_t
125  *mode_wide,
126  *path_wide;
127 
128  path_wide=create_wchar_path(path);
129  if (path_wide == (wchar_t *) NULL)
130  return((FILE *) NULL);
131  mode_wide=create_wchar_path(mode);
132  if (mode_wide == (wchar_t *) NULL)
133  {
134  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
135  return((FILE *) NULL);
136  }
137  file=_wfopen(path_wide,mode_wide);
138  mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
139  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
140  return(file);
141 #endif
142 }
143 
144 static inline void getcwd_utf8(char *path,size_t extent)
145 {
146 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
147  char
148  *directory;
149 
150  directory=getcwd(path,extent);
151  (void) directory;
152 #else
153  wchar_t
154  wide_path[MaxTextExtent];
155 
156  (void) _wgetcwd(wide_path,MaxTextExtent-1);
157  (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
158 #endif
159 }
160 
161 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__)
162 typedef int
163  mode_t;
164 #endif
165 
166 static inline int open_utf8(const char *path,int flags,mode_t mode)
167 {
168 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
169  return(open(path,flags,mode));
170 #else
171  int
172  status;
173 
174  wchar_t
175  *path_wide;
176 
177  path_wide=create_wchar_path(path);
178  if (path_wide == (wchar_t *) NULL)
179  return(-1);
180  status=_wopen(path_wide,flags,mode);
181  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
182  return(status);
183 #endif
184 }
185 
186 static inline FILE *popen_utf8(const char *command,const char *type)
187 {
188 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
189  return(popen(command,type));
190 #else
191  FILE
192  *file;
193 
194  int
195  length;
196 
197  wchar_t
198  *command_wide,
199  type_wide[5];
200 
201  file=(FILE *) NULL;
202  length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
203  if (length == 0)
204  return(file);
205  length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
206  if (length == 0)
207  return(file);
208  command_wide=(wchar_t *) AcquireQuantumMemory(length,sizeof(*command_wide));
209  if (command_wide == (wchar_t *) NULL)
210  return(file);
211  length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
212  if (length != 0)
213  file=_wpopen(command_wide,type_wide);
214  command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
215  return(file);
216 #endif
217 }
218 
219 static inline char *realpath_utf8(const char *path)
220 {
221 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
222 #if defined(MAGICKCORE_HAVE_REALPATH)
223  return(realpath(path,(char *) NULL));
224 #else
225  return(AcquireString(path));
226 #endif
227 #else
228  char
229  *real_path;
230 
231  DWORD
232  final_path_length,
233  full_path_length;
234 
235  HANDLE
236  file_handle;
237 
238  int
239  length,
240  utf8_length,
241 
242  wchar_t
243  *clean_path,
244  *final_path,
245  *full_path,
246  *wide_path;
247 
248  /*
249  Convert UTF-8 to UTF-16.
250  */
251  if (path == (const char *) NULL)
252  return((char *) NULL);
253  length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
254  if (length <= 0)
255  return((char *) NULL);
256  wide_path=(wchar_t *) AcquireQuantumMeory(length,sizeof(wchar_t));
257  if (wide_path == (wchar_t *) NULL)
258  return((char *) NULL);
259  MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
260  /*
261  Normalize syntactically.
262  */
263  full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
264  if (full_path_length == 0)
265  {
266  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
267  return((char *) NULL);
268  }
269  full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
270  if (full_path == (wchar_t *) NULL);
271  {
272  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
273  return((char *) NULL);
274  }
275  GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
276  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
277  /*
278  Open the file/directory to resolve symlinks.
279  */
280  file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
281  FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
282  FILE_FLAG_BACKUP_SEMANTICS,NULL);
283  if (file_handle == INVALID_HANDLE_VALUE)
284  {
285  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
286  return((char *) NULL);
287  }
288  /*
289  Resolve final canonical path.
290  */
291  final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
292  FILE_NAME_NORMALIZED);
293  if (final_path_length == 0)
294  {
295  CloseHandle(file_handle);
296  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
297  return((char *) NULL);
298  }
299  final_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
300  sizeof(wchar_t));
301  if (final_path == (wchar_t *) NULL)
302  {
303  CloseHandle(file_handle);
304  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
305  return((char *) NULL);
306  }
307  GetFinalPathNameByHandleW(file_handle,final_path,final_path_length,
308  FILE_NAME_NORMALIZED);
309  CloseHandle(file_handle);
310  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
311  /*
312  Remove \\?\ prefix for POSIX-like behavior.
313  */
314  clean_path=final_path;
315  if (wcsncmp(final_path,L"\\\\?\\",4) == 0)
316  clean_path=final_path+4;
317  /*
318  Convert UTF-16 to UTF-8.
319  */
320  utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
321  if (utf8_length <= 0)
322  {
323  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
324  return NULL;
325  }
326  real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
327  if (real_path == (char *) NULL)
328  {
329  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
330  return NULL;
331  }
332  WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
333  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
334  return(real_path);
335 #endif
336 }
337 
338 static inline int remove_utf8(const char *path)
339 {
340 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
341  return(unlink(path));
342 #else
343  int
344  status;
345 
346  wchar_t
347  *path_wide;
348 
349  path_wide=create_wchar_path(path);
350  if (path_wide == (wchar_t *) NULL)
351  return(-1);
352  status=_wremove(path_wide);
353  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
354  return(status);
355 #endif
356 }
357 
358 static inline int rename_utf8(const char *source,const char *destination)
359 {
360 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
361  return(rename(source,destination));
362 #else
363  int
364  status;
365 
366  wchar_t
367  *destination_wide,
368  *source_wide;
369 
370  source_wide=create_wchar_path(source);
371  if (source_wide == (wchar_t *) NULL)
372  return(-1);
373  destination_wide=create_wchar_path(destination);
374  if (destination_wide == (wchar_t *) NULL)
375  {
376  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
377  return(-1);
378  }
379  status=_wrename(source_wide,destination_wide);
380  destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
381  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
382  return(status);
383 #endif
384 }
385 
386 static inline int stat_utf8(const char *path,struct stat *attributes)
387 {
388 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
389  return(stat(path,attributes));
390 #else
391  int
392  status;
393 
394  wchar_t
395  *path_wide;
396 
397  path_wide=create_wchar_path(path);
398  if (path_wide == (WCHAR *) NULL)
399  return(-1);
400  status=wstat(path_wide,attributes);
401  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
402  return(status);
403 #endif
404 }
405 
406 #if defined(__cplusplus) || defined(c_plusplus)
407 }
408 #endif
409 
410 #endif
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:497
MagickExport struct dirent * readdir(DIR *)
MagickBooleanType
Definition: magick-type.h:203
@ MagickFalse
Definition: magick-type.h:204
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1162
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:665
#define MagickPrivate
Definition: method-attribute.h:81
#define MaxTextExtent
Definition: method-attribute.h:89
MagickExport char * AcquireString(const char *source)
Definition: string.c:125
Definition: mac.h:42
Definition: mac.h:54
static int open_utf8(const char *path, int flags, mode_t mode)
Definition: utility-private.h:166
static int MagickReadDirectory(DIR *directory, struct dirent *entry, struct dirent **result)
Definition: utility-private.h:32
static int remove_utf8(const char *path)
Definition: utility-private.h:338
static char * realpath_utf8(const char *path)
Definition: utility-private.h:219
static int access_utf8(const char *path, int mode)
Definition: utility-private.h:96
static int stat_utf8(const char *path, struct stat *attributes)
Definition: utility-private.h:386
static FILE * popen_utf8(const char *command, const char *type)
Definition: utility-private.h:186
static FILE * fopen_utf8(const char *path, const char *mode)
Definition: utility-private.h:116
static void getcwd_utf8(char *path, size_t extent)
Definition: utility-private.h:144
MagickPrivate MagickBooleanType ShredFile(const char *)
Definition: utility.c:1836
static int rename_utf8(const char *source, const char *destination)
Definition: utility-private.h:358