MagickCore  6.9.10
Convert, Edit, Or Compose Bitmap Images
utility-private.h
Go to the documentation of this file.
1 /*
2  Copyright 1999-2019 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.
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)
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)
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__) || defined(__MINGW32__)
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__) || defined(__MINGW32__)
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__) || defined(__MINGW32__)
197  return(popen(command,type));
198 #else
199  FILE
200  *file;
201 
202  wchar_t
203  *type_wide,
204  *command_wide;
205 
206  command_wide=create_wchar_path(command);
207  if (command_wide == (wchar_t *) NULL)
208  return((FILE *) NULL);
209  type_wide=create_wchar_path(type);
210  if (type_wide == (wchar_t *) NULL)
211  {
212  command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
213  return((FILE *) NULL);
214  }
215  file=_wpopen(command_wide,type_wide);
216  type_wide=(wchar_t *) RelinquishMagickMemory(type_wide);
217  command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
218  return(file);
219 #endif
220 }
221 
222 static inline char *realpath_utf8(const char *path)
223 {
224 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
225 #if defined(MAGICKCORE_HAVE_REALPATH)
226  return(realpath(path,(char *) NULL));
227 #else
228  return(AcquireString(path));
229 #endif
230 #else
231  char
232  *real_path;
233 
234  DWORD
235  final_path_length,
236  full_path_length;
237 
238  HANDLE
239  file_handle;
240 
241  int
242  length,
243  utf8_length,
244 
245  wchar_t
246  *clean_path,
247  *final_path,
248  *full_path,
249  *wide_path;
250 
251  /*
252  Convert UTF-8 to UTF-16.
253  */
254  if (path == (const char *) NULL)
255  return((char *) NULL);
256  length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
257  if (length <= 0)
258  return((char *) NULL);
259  wide_path=(wchar_t *) AcquireQuantumMeory(length,sizeof(wchar_t));
260  if (wide_path == (wchar_t *) NULL)
261  return((char *) NULL);
262  MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
263  /*
264  Normalize syntactically.
265  */
266  full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
267  if (full_path_length == 0)
268  {
269  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
270  return((char *) NULL);
271  }
272  full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
273  if (full_path == (wchar_t *) NULL);
274  {
275  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
276  return((char *) NULL);
277  }
278  GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
279  wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
280  /*
281  Open the file/directory to resolve symlinks.
282  */
283  file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
284  FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
285  FILE_FLAG_BACKUP_SEMANTICS,NULL);
286  if (file_handle == INVALID_HANDLE_VALUE)
287  {
288  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
289  return((char *) NULL);
290  }
291  /*
292  Resolve final canonical path.
293  */
294  final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
295  FILE_NAME_NORMALIZED);
296  if (final_path_length == 0)
297  {
298  CloseHandle(file_handle);
299  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
300  return((char *) NULL);
301  }
302  final_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
303  sizeof(wchar_t));
304  if (final_path == (wchar_t *) NULL)
305  {
306  CloseHandle(file_handle);
307  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
308  return((char *) NULL);
309  }
310  GetFinalPathNameByHandleW(file_handle,final_path,final_path_length,
311  FILE_NAME_NORMALIZED);
312  CloseHandle(file_handle);
313  full_path=(wchar_t *) RelinquishMagickMemory(full_path);
314  /*
315  Remove \\?\ prefix for POSIX-like behavior.
316  */
317  clean_path=final_path;
318  if (wcsncmp(final_path,L"\\\\?\\",4) == 0)
319  clean_path=final_path+4;
320  /*
321  Convert UTF-16 to UTF-8.
322  */
323  utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
324  if (utf8_length <= 0)
325  {
326  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
327  return NULL;
328  }
329  real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
330  if (real_path == (char *) NULL)
331  {
332  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
333  return NULL;
334  }
335  WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
336  final_path=(wchar_t *) RelinquishMagickMemory(final_path);
337  return(real_path);
338 #endif
339 }
340 
341 static inline int remove_utf8(const char *path)
342 {
343 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__)
344  return(unlink(path));
345 #else
346  int
347  status;
348 
349  wchar_t
350  *path_wide;
351 
352  path_wide=create_wchar_path(path);
353  if (path_wide == (wchar_t *) NULL)
354  return(-1);
355  status=_wremove(path_wide);
356  path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
357  return(status);
358 #endif
359 }
360 
361 static inline int rename_utf8(const char *source,const char *destination)
362 {
363 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__)
364  return(rename(source,destination));
365 #else
366  int
367  status;
368 
369  wchar_t
370  *destination_wide,
371  *source_wide;
372 
373  source_wide=create_wchar_path(source);
374  if (source_wide == (wchar_t *) NULL)
375  return(-1);
376  destination_wide=create_wchar_path(destination);
377  if (destination_wide == (wchar_t *) NULL)
378  {
379  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
380  return(-1);
381  }
382  status=_wrename(source_wide,destination_wide);
383  destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
384  source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
385  return(status);
386 #endif
387 }
388 
389 static inline int stat_utf8(const char *path,struct stat *attributes)
390 {
391 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__)
392  return(stat(path,attributes));
393 #else
394  int
395  status;
396 
397  wchar_t
398  *path_wide;
399 
400  path_wide=create_wchar_path(path);
401  if (path_wide == (WCHAR *) NULL)
402  return(-1);
403  status=wstat(path_wide,attributes);
404  path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
405  return(status);
406 #endif
407 }
408 
409 static inline MagickBooleanType is_symlink_utf8(const char *path)
410 {
411 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
412 #if 1
413  struct stat
414  status;
415 
416  if (lstat(path,&status) == -1)
417  return(MagickFalse);
418  return(S_ISLNK(status.st_mode) != 0 ? MagickTrue : MagickFalse);
419 #else
420  return(MagickFalse);
421 #endif
422 #else
423  return(NTIsSymlinkWide(path));
424 #endif
425 }
426 
427 
428 #if defined(__cplusplus) || defined(c_plusplus)
429 }
430 #endif
431 
432 #endif
static FILE * popen_utf8(const char *command, const char *type)
Definition: utility-private.h:194
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:502
static void getcwd_utf8(char *path, size_t extent)
Definition: utility-private.h:152
char * path
Definition: type.h:56
Definition: mac.h:53
Definition: mac.h:41
static int stat_utf8(const char *path, struct stat *attributes)
Definition: utility-private.h:389
MagickBooleanType
Definition: magick-type.h:191
MagickExport char * AcquireString(const char *source)
Definition: string.c:126
static int remove_utf8(const char *path)
Definition: utility-private.h:341
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:547
static FILE * fopen_utf8(const char *path, const char *mode)
Definition: utility-private.h:124
#define MaxTextExtent
Definition: method-attribute.h:89
Definition: magick-type.h:194
static int open_utf8(const char *path, int flags, mode_t mode)
Definition: utility-private.h:174
MagickPrivate MagickBooleanType ShredFile(const char *)
Definition: utility.c:1933
Definition: magick-type.h:193
MagickExport struct dirent * readdir(DIR *)
static MagickBooleanType is_symlink_utf8(const char *path)
Definition: utility-private.h:409
static int rename_utf8(const char *source, const char *destination)
Definition: utility-private.h:361
static int access_utf8(const char *path, int mode)
Definition: utility-private.h:98
static int MagickReadDirectory(DIR *directory, struct dirent *entry, struct dirent **result)
Definition: utility-private.h:34
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1086
#define MagickPrivate
Definition: method-attribute.h:81
static char * realpath_utf8(const char *path)
Definition: utility-private.h:222