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"
24
25#if defined(__cplusplus) || defined(c_plusplus)
26extern "C" {
27#endif
28
29#define MagickPathTemplate "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" /* min 6 X's */
30
32 ShredFile(const char *);
33
34static 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)
52static 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
98static 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
124static 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
152static 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__)
170typedef int
171 mode_t;
172#endif
173
174static 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
194static 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
227static 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
346static 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
366static 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
394static 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
414static 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:497
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:1163
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:666
#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 FILE * fopen_utf8(const char *path, const char *mode)
Definition: utility-private.h:124
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 void getcwd_utf8(char *path, size_t extent)
Definition: utility-private.h:152
MagickPrivate MagickBooleanType ShredFile(const char *)
Definition: utility.c:1954
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
static FILE * popen_utf8(const char *command, const char *type)
Definition: utility-private.h:194