MagickCore 7.1.1-43
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
utility-private.h
1/*
2 Copyright @ 1999 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 "MagickCore/memory_.h"
22#include "MagickCore/nt-base.h"
23#include "MagickCore/nt-base-private.h"
24#if defined(MAGICKCORE_HAVE_UTIME_H)
25#include <utime.h>
26#endif
27
28#if defined(__cplusplus) || defined(c_plusplus)
29extern "C" {
30#endif
31
32extern MagickPrivate char
33 **GetPathComponents(const char *,size_t *),
34 **ListFiles(const char *,const char *,size_t *);
35
36extern MagickPrivate MagickBooleanType
37 GetExecutionPath(char *,const size_t),
38 ShredFile(const char *);
39
40extern MagickPrivate ssize_t
41 GetMagickPageSize(void);
42
43extern MagickPrivate void
44 ChopPathComponents(char *,const size_t),
45 ExpandFilename(char *);
46
47static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
48 struct dirent **result)
49{
50 (void) entry;
51 errno=0;
52 *result=readdir(directory);
53 return(errno);
54}
55
56/*
57 Windows UTF8 compatibility methods.
58*/
59
60#if defined(MAGICKCORE_WINDOWS_SUPPORT)
61static inline wchar_t *create_wchar_path(const char *utf8)
62{
63 int
64 count;
65
66 wchar_t
67 *wide;
68
69 count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);
70 if ((count > MAX_PATH) && (strncmp(utf8,"\\\\?\\",4) != 0) &&
71 (NTLongPathsEnabled() == MagickFalse))
72 {
73 char
74 buffer[MagickPathExtent];
75
76 wchar_t
77 shortPath[MAX_PATH],
78 *longPath;
79
80 (void) FormatLocaleString(buffer,MagickPathExtent,"\\\\?\\%s",utf8);
81 count+=4;
82 longPath=(wchar_t *) NTAcquireQuantumMemory((size_t) count,
83 sizeof(*longPath));
84 if (longPath == (wchar_t *) NULL)
85 return((wchar_t *) NULL);
86 count=MultiByteToWideChar(CP_UTF8,0,buffer,-1,longPath,count);
87 if (count != 0)
88 count=(int) GetShortPathNameW(longPath,shortPath,MAX_PATH);
89 longPath=(wchar_t *) RelinquishMagickMemory(longPath);
90 if ((count < 5) || (count >= MAX_PATH))
91 return((wchar_t *) NULL);
92 wide=(wchar_t *) NTAcquireQuantumMemory((size_t) count-3,sizeof(*wide));
93 wcscpy(wide,shortPath+4);
94 return(wide);
95 }
96 wide=(wchar_t *) NTAcquireQuantumMemory((size_t) count,sizeof(*wide));
97 if ((wide != (wchar_t *) NULL) &&
98 (MultiByteToWideChar(CP_UTF8,0,utf8,-1,wide,count) == 0))
99 wide=(wchar_t *) RelinquishMagickMemory(wide);
100 return(wide);
101}
102
103static inline wchar_t *create_wchar_mode(const char *mode)
104{
105 int
106 count;
107
108 wchar_t
109 *wide;
110
111 count=MultiByteToWideChar(CP_UTF8,0,mode,-1,NULL,0);
112 wide=(wchar_t *) AcquireQuantumMemory((size_t) count+1,
113 sizeof(*wide));
114 if (wide == (wchar_t *) NULL)
115 return((wchar_t *) NULL);
116 if (MultiByteToWideChar(CP_UTF8,0,mode,-1,wide,count) == 0)
117 {
118 wide=(wchar_t *) RelinquishMagickMemory(wide);
119 return((wchar_t *) NULL);
120 }
121 /* Specifies that the file is not inherited by child processes */
122 wide[count] = L'\0';
123 wide[count-1] = L'N';
124 return(wide);
125}
126#endif
127
128static inline int access_utf8(const char *path,int mode)
129{
130 if (path == (const char *) NULL)
131 return(-1);
132#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
133 return(access(path,mode));
134#else
135 int
136 status;
137
138 wchar_t
139 *path_wide;
140
141 path_wide=create_wchar_path(path);
142 if (path_wide == (wchar_t *) NULL)
143 return(-1);
144 status=_waccess(path_wide,mode);
145 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
146 return(status);
147#endif
148}
149
150static inline FILE *fopen_utf8(const char *path,const char *mode)
151{
152#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
153 return(fopen(path,mode));
154#else
155 FILE
156 *file;
157
158 wchar_t
159 *mode_wide,
160 *path_wide;
161
162 path_wide=create_wchar_path(path);
163 if (path_wide == (wchar_t *) NULL)
164 return((FILE *) NULL);
165 mode_wide=create_wchar_mode(mode);
166 if (mode_wide == (wchar_t *) NULL)
167 {
168 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
169 return((FILE *) NULL);
170 }
171 file=_wfopen(path_wide,mode_wide);
172 mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
173 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
174 return(file);
175#endif
176}
177
178static inline void getcwd_utf8(char *path,size_t extent)
179{
180#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
181 char
182 *directory;
183
184 directory=getcwd(path,extent);
185 (void) directory;
186#else
187 wchar_t
188 wide_path[MagickPathExtent];
189
190 (void) _wgetcwd(wide_path,MagickPathExtent-1);
191 (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
192#endif
193}
194
195#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__)
196typedef int
197 mode_t;
198#endif
199
200static inline int open_utf8(const char *path,int flags,mode_t mode)
201{
202#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
203 return(open(path,flags,mode));
204#else
205 int
206 status;
207
208 wchar_t
209 *path_wide;
210
211 path_wide=create_wchar_path(path);
212 if (path_wide == (wchar_t *) NULL)
213 return(-1);
214 /* O_NOINHERIT specifies that the file is not inherited by child processes */
215 status=_wopen(path_wide,flags | O_NOINHERIT,mode);
216 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
217 return(status);
218#endif
219}
220
221static inline FILE *popen_utf8(const char *command,const char *type)
222{
223#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
224 return(popen(command,type));
225#else
226 FILE
227 *file;
228
229 int
230 length;
231
232 wchar_t
233 *command_wide,
234 type_wide[5];
235
236 file=(FILE *) NULL;
237 length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
238 if (length == 0)
239 return(file);
240 length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
241 if (length == 0)
242 return(file);
243 command_wide=(wchar_t *) AcquireQuantumMemory((size_t) length,
244 sizeof(*command_wide));
245 if (command_wide == (wchar_t *) NULL)
246 return(file);
247 length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
248 if (length != 0)
249 file=_wpopen(command_wide,type_wide);
250 command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
251 return(file);
252#endif
253}
254
255static inline char *realpath_utf8(const char *path)
256{
257#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
258#if defined(MAGICKCORE_HAVE_REALPATH)
259 return(realpath(path,(char *) NULL));
260#else
261 return(AcquireString(path));
262#endif
263#else
264 char
265 *real_path;
266
267 DWORD
268 final_path_length,
269 full_path_length;
270
271 HANDLE
272 file_handle;
273
274 int
275 length,
276 utf8_length;
277
278 wchar_t
279 *clean_path,
280 *full_path,
281 *wide_path;
282
283 /*
284 Convert UTF-8 to UTF-16.
285 */
286 if (path == (const char *) NULL)
287 return((char *) NULL);
288 length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
289 if (length <= 0)
290 return((char *) NULL);
291 wide_path=(wchar_t *) AcquireQuantumMemory(length,sizeof(wchar_t));
292 if (wide_path == (wchar_t *) NULL)
293 return((char *) NULL);
294 MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
295 /*
296 Normalize syntactically.
297 */
298 full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
299 if (full_path_length == 0)
300 {
301 wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
302 return((char *) NULL);
303 }
304 full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
305 if (full_path == (wchar_t *) NULL)
306 {
307 wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
308 return((char *) NULL);
309 }
310 GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
311 wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
312 /*
313 Open the file/directory to resolve symlinks.
314 */
315 file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
316 FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
317 FILE_FLAG_BACKUP_SEMANTICS,NULL);
318 if (file_handle != INVALID_HANDLE_VALUE)
319 {
320 /*
321 Resolve final canonical path.
322 */
323 final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
324 FILE_NAME_NORMALIZED);
325 if (final_path_length == 0)
326 {
327 CloseHandle(file_handle);
328 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
329 return((char *) NULL);
330 }
331 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
332 full_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
333 sizeof(wchar_t));
334 if (full_path == (wchar_t *) NULL)
335 {
336 CloseHandle(file_handle);
337 return((char *) NULL);
338 }
339 GetFinalPathNameByHandleW(file_handle,full_path,final_path_length,
340 FILE_NAME_NORMALIZED);
341 CloseHandle(file_handle);
342 }
343 /*
344 Remove \\?\ prefix for POSIX-like behavior.
345 */
346 clean_path=full_path;
347 if (wcsncmp(full_path,L"\\\\?\\",4) == 0)
348 clean_path=full_path+4;
349 /*
350 Convert UTF-16 to UTF-8.
351 */
352 utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
353 if (utf8_length <= 0)
354 {
355 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
356 return NULL;
357 }
358 real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
359 if (real_path == (char *) NULL)
360 {
361 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
362 return NULL;
363 }
364 WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
365 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
366 return(real_path);
367#endif
368}
369
370static inline int remove_utf8(const char *path)
371{
372#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
373 return(unlink(path));
374#else
375 int
376 status;
377
378 wchar_t
379 *path_wide;
380
381 path_wide=create_wchar_path(path);
382 if (path_wide == (wchar_t *) NULL)
383 return(-1);
384 status=_wremove(path_wide);
385 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
386 return(status);
387#endif
388}
389
390static inline int rename_utf8(const char *source,const char *destination)
391{
392#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
393 return(rename(source,destination));
394#else
395 int
396 status;
397
398 wchar_t
399 *destination_wide,
400 *source_wide;
401
402 source_wide=create_wchar_path(source);
403 if (source_wide == (wchar_t *) NULL)
404 return(-1);
405 destination_wide=create_wchar_path(destination);
406 if (destination_wide == (wchar_t *) NULL)
407 {
408 source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
409 return(-1);
410 }
411 status=_wrename(source_wide,destination_wide);
412 destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
413 source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
414 return(status);
415#endif
416}
417
418static inline int set_file_timestamp(const char *path,struct stat *attributes)
419{
420 int
421 status;
422
423#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
424#if defined(MAGICKCORE_HAVE_UTIMENSAT)
425#if defined(__APPLE__) || defined(__NetBSD__)
426#define st_atim st_atimespec
427#define st_ctim st_ctimespec
428#define st_mtim st_mtimespec
429#endif
430
431 struct timespec
432 timestamp[2];
433
434 timestamp[0].tv_sec=attributes->st_atim.tv_sec;
435 timestamp[0].tv_nsec=attributes->st_atim.tv_nsec;
436 timestamp[1].tv_sec=attributes->st_mtim.tv_sec;
437 timestamp[1].tv_nsec=attributes->st_mtim.tv_nsec;
438 status=utimensat(AT_FDCWD,path,timestamp,0);
439#else
440 struct utimbuf
441 timestamp;
442
443 timestamp.actime=attributes->st_atime;
444 timestamp.modtime=attributes->st_mtime;
445 status=utime(path,&timestamp);
446#endif
447#else
448 HANDLE
449 handle;
450
451 wchar_t
452 *path_wide;
453
454 status=(-1);
455 path_wide=create_wchar_path(path);
456 if (path_wide == (WCHAR *) NULL)
457 return(status);
458 handle=CreateFileW(path_wide,FILE_WRITE_ATTRIBUTES,FILE_SHARE_WRITE |
459 FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
460 if (handle != (HANDLE) NULL)
461 {
462 FILETIME
463 creation_time,
464 last_access_time,
465 last_write_time;
466
467 ULARGE_INTEGER
468 date_time;
469
470 date_time.QuadPart=(ULONGLONG) (attributes->st_ctime*10000000LL)+
471 116444736000000000LL;
472 creation_time.dwLowDateTime=date_time.LowPart;
473 creation_time.dwHighDateTime=date_time.HighPart;
474 date_time.QuadPart=(ULONGLONG) (attributes->st_atime*10000000LL)+
475 116444736000000000LL;
476 last_access_time.dwLowDateTime=date_time.LowPart;
477 last_access_time.dwHighDateTime=date_time.HighPart;
478 date_time.QuadPart=(ULONGLONG) (attributes->st_mtime*10000000LL)+
479 116444736000000000LL;
480 last_write_time.dwLowDateTime=date_time.LowPart;
481 last_write_time.dwHighDateTime=date_time.HighPart;
482 status=SetFileTime(handle,&creation_time,&last_access_time,&last_write_time);
483 CloseHandle(handle);
484 status=0;
485 }
486 path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
487#endif
488 return(status);
489}
490
491static inline int stat_utf8(const char *path,struct stat *attributes)
492{
493#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
494 return(stat(path,attributes));
495#else
496 int
497 status;
498
499 wchar_t
500 *path_wide;
501
502 path_wide=create_wchar_path(path);
503 if (path_wide == (WCHAR *) NULL)
504 return(-1);
505 status=_wstati64(path_wide,attributes);
506 path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
507 return(status);
508#endif
509}
510
511#if defined(__cplusplus) || defined(c_plusplus)
512}
513#endif
514
515#endif