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 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__)
117 #define close_utf8 _close
118 #else
119 #define close_utf8 close
120 #endif
121 
122 static inline FILE *fopen_utf8(const char *path,const char *mode)
123 {
124 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
125  return(fopen(path,mode));
126 #else
127  FILE
128  *file;
129 
130  wchar_t
131  *mode_wide,
132  *path_wide;
133 
134  path_wide=create_wchar_path(path);
135  if (path_wide == (wchar_t *) NULL)
136  return((FILE *) NULL);
137  mode_wide=create_wchar_path(mode);
138  if (mode_wide == (wchar_t *) NULL)
139  {
140  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
141  return((FILE *) NULL);
142  }
143  file=_wfopen(path_wide,mode_wide);
144  mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
145  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
146  return(file);
147 #endif
148 }
149 
150 static inline void getcwd_utf8(char *path,size_t extent)
151 {
152 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
153  char
154  *directory;
155 
156  directory=getcwd(path,extent);
157  (void) directory;
158 #else
159  wchar_t
160  wide_path[MaxTextExtent];
161 
162  (void) _wgetcwd(wide_path,MaxTextExtent-1);
163  (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
164 #endif
165 }
166 
167 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__)
168 typedef int
169  mode_t;
170 #endif
171 
172 static inline int open_utf8(const char *path,int flags,mode_t mode)
173 {
174 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
175  return(open(path,flags,mode));
176 #else
177  int
178  status;
179 
180  wchar_t
181  *path_wide;
182 
183  path_wide=create_wchar_path(path);
184  if (path_wide == (wchar_t *) NULL)
185  return(-1);
186  status=_wopen(path_wide,flags,mode);
187  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
188  return(status);
189 #endif
190 }
191 
192 static inline FILE *popen_utf8(const char *command,const char *type)
193 {
194 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
195  return(popen(command,type));
196 #else
197  FILE
198  *file;
199 
200  int
201  length;
202 
203  wchar_t
204  *command_wide,
205  type_wide[5];
206 
207  file=(FILE *) NULL;
208  length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
209  if (length == 0)
210  return(file);
211  length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
212  if (length == 0)
213  return(file);
214  command_wide=(wchar_t *) AcquireQuantumMemory(length,sizeof(*command_wide));
215  if (command_wide == (wchar_t *) NULL)
216  return(file);
217  length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
218  if (length != 0)
219  file=_wpopen(command_wide,type_wide);
220  command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
221  return(file);
222 #endif
223 }
224 
225 static inline char *realpath_utf8(const char *path)
226 {
227 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
228 #if defined(MAGICKCORE_HAVE_REALPATH)
229  return(realpath(path,(char *) NULL));
230 #else
231  return(AcquireString(path));
232 #endif
233 #else
234  char
235  *real_path;
236 
237  DWORD
238  final_path_length,
239  full_path_length;
240 
241  HANDLE
242  file_handle;
243 
244  int
245  length,
246  utf8_length,
247 
248  wchar_t
249  *clean_path,
250  *final_path,
251  *full_path,
252  *wide_path;
253 
254  /*
255  Convert UTF-8 to UTF-16.
256  */
257  if (path == (const char *) NULL)
258  return((char *) NULL);
259  length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
260  if (length <= 0)
261  return((char *) NULL);
262  wide_path=(wchar_t *) AcquireQuantumMeory(length,sizeof(wchar_t));
263  if (wide_path == (wchar_t *) NULL)
264  return((char *) NULL);
265  MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
266  /*
267  Normalize syntactically.
268  */
269  full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
270  if (full_path_length == 0)
271  {
272  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
273  return((char *) NULL);
274  }
275  full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
276  if (full_path == (wchar_t *) NULL);
277  {
278  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
279  return((char *) NULL);
280  }
281  GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
282  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
283  /*
284  Open the file/directory to resolve symlinks.
285  */
286  file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
287  FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
288  FILE_FLAG_BACKUP_SEMANTICS,NULL);
289  if (file_handle == INVALID_HANDLE_VALUE)
290  {
291  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
292  return((char *) NULL);
293  }
294  /*
295  Resolve final canonical path.
296  */
297  final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
298  FILE_NAME_NORMALIZED);
299  if (final_path_length == 0)
300  {
301  CloseHandle(file_handle);
302  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
303  return((char *) NULL);
304  }
305  final_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
306  sizeof(wchar_t));
307  if (final_path == (wchar_t *) NULL)
308  {
309  CloseHandle(file_handle);
310  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
311  return((char *) NULL);
312  }
313  GetFinalPathNameByHandleW(file_handle,final_path,final_path_length,
314  FILE_NAME_NORMALIZED);
315  CloseHandle(file_handle);
316  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
317  /*
318  Remove \\?\ prefix for POSIX-like behavior.
319  */
320  clean_path=final_path;
321  if (wcsncmp(final_path,L"\\\\?\\",4) == 0)
322  clean_path=final_path+4;
323  /*
324  Convert UTF-16 to UTF-8.
325  */
326  utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
327  if (utf8_length <= 0)
328  {
329  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
330  return NULL;
331  }
332  real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
333  if (real_path == (char *) NULL)
334  {
335  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
336  return NULL;
337  }
338  WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
339  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
340  return(real_path);
341 #endif
342 }
343 
344 static inline int remove_utf8(const char *path)
345 {
346 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
347  return(unlink(path));
348 #else
349  int
350  status;
351 
352  wchar_t
353  *path_wide;
354 
355  path_wide=create_wchar_path(path);
356  if (path_wide == (wchar_t *) NULL)
357  return(-1);
358  status=_wremove(path_wide);
359  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
360  return(status);
361 #endif
362 }
363 
364 static inline int rename_utf8(const char *source,const char *destination)
365 {
366 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
367  return(rename(source,destination));
368 #else
369  int
370  status;
371 
372  wchar_t
373  *destination_wide,
374  *source_wide;
375 
376  source_wide=create_wchar_path(source);
377  if (source_wide == (wchar_t *) NULL)
378  return(-1);
379  destination_wide=create_wchar_path(destination);
380  if (destination_wide == (wchar_t *) NULL)
381  {
382  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
383  return(-1);
384  }
385  status=_wrename(source_wide,destination_wide);
386  destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
387  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
388  return(status);
389 #endif
390 }
391 
392 static inline int stat_utf8(const char *path,struct stat *attributes)
393 {
394 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
395  return(stat(path,attributes));
396 #else
397  int
398  status;
399 
400  wchar_t
401  *path_wide;
402 
403  path_wide=create_wchar_path(path);
404  if (path_wide == (WCHAR *) NULL)
405  return(-1);
406  status=wstat(path_wide,attributes);
407  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
408  return(status);
409 #endif
410 }
411 
412 #if defined(__cplusplus) || defined(c_plusplus)
413 }
414 #endif
415 
416 #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:172
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:344
static char * realpath_utf8(const char *path)
Definition: utility-private.h:225
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:392
static FILE * popen_utf8(const char *command, const char *type)
Definition: utility-private.h:192
static FILE * fopen_utf8(const char *path, const char *mode)
Definition: utility-private.h:122
static void getcwd_utf8(char *path, size_t extent)
Definition: utility-private.h:150
MagickPrivate MagickBooleanType ShredFile(const char *)
Definition: utility.c:1844
static int rename_utf8(const char *source, const char *destination)
Definition: utility-private.h:364