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
150#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__)
151#define close_utf8 _close
152#else
153#define close_utf8 close
154#endif
155
156static inline FILE *fopen_utf8(const char *path,const char *mode)
157{
158#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
159 return(fopen(path,mode));
160#else
161 FILE
162 *file;
163
164 wchar_t
165 *mode_wide,
166 *path_wide;
167
168 path_wide=create_wchar_path(path);
169 if (path_wide == (wchar_t *) NULL)
170 return((FILE *) NULL);
171 mode_wide=create_wchar_mode(mode);
172 if (mode_wide == (wchar_t *) NULL)
173 {
174 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
175 return((FILE *) NULL);
176 }
177 file=_wfopen(path_wide,mode_wide);
178 mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
179 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
180 return(file);
181#endif
182}
183
184static inline MagickBooleanType is_symlink_utf8(const char *path)
185{
186#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
187#if defined(MAGICKCORE_POSIX_SUPPORT)
188 struct stat
189 status;
190
191 if (lstat(path,&status) == -1)
192 return(MagickFalse);
193 return(S_ISLNK(status.st_mode) != 0 ? MagickTrue : MagickFalse);
194#else
195 return(MagickFalse);
196#endif
197#else
198 return(NTIsSymlinkWide(path));
199#endif
200}
201
202static inline void getcwd_utf8(char *path,size_t extent)
203{
204#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
205 char
206 *directory;
207
208 directory=getcwd(path,extent);
209 (void) directory;
210#else
211 wchar_t
212 wide_path[MagickPathExtent];
213
214 (void) _wgetcwd(wide_path,MagickPathExtent-1);
215 (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
216#endif
217}
218
219#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__)
220typedef int
221 mode_t;
222#endif
223
224static inline int open_utf8(const char *path,int flags,mode_t mode)
225{
226#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
227 return(open(path,flags,mode));
228#else
229 int
230 status;
231
232 wchar_t
233 *path_wide;
234
235 path_wide=create_wchar_path(path);
236 if (path_wide == (wchar_t *) NULL)
237 return(-1);
238 /* O_NOINHERIT specifies that the file is not inherited by child processes */
239 status=_wopen(path_wide,flags | O_NOINHERIT,mode);
240 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
241 return(status);
242#endif
243}
244
245static inline FILE *popen_utf8(const char *command,const char *type)
246{
247#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
248 return(popen(command,type));
249#else
250 FILE
251 *file;
252
253 int
254 length;
255
256 wchar_t
257 *command_wide,
258 type_wide[5];
259
260 file=(FILE *) NULL;
261 length=MultiByteToWideChar(CP_UTF8,0,type,-1,type_wide,5);
262 if (length == 0)
263 return(file);
264 length=MultiByteToWideChar(CP_UTF8,0,command,-1,NULL,0);
265 if (length == 0)
266 return(file);
267 command_wide=(wchar_t *) AcquireQuantumMemory((size_t) length,
268 sizeof(*command_wide));
269 if (command_wide == (wchar_t *) NULL)
270 return(file);
271 length=MultiByteToWideChar(CP_UTF8,0,command,-1,command_wide,length);
272 if (length != 0)
273 file=_wpopen(command_wide,type_wide);
274 command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
275 return(file);
276#endif
277}
278
279static inline char *realpath_utf8(const char *path)
280{
281#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
282#if defined(MAGICKCORE_HAVE_REALPATH)
283 return(realpath(path,(char *) NULL));
284#else
285 return(AcquireString(path));
286#endif
287#else
288 char
289 *real_path;
290
291 DWORD
292 final_path_length,
293 full_path_length;
294
295 HANDLE
296 file_handle;
297
298 int
299 length,
300 utf8_length;
301
302 wchar_t
303 *clean_path,
304 *full_path,
305 *wide_path;
306
307 /*
308 Convert UTF-8 to UTF-16.
309 */
310 if (path == (const char *) NULL)
311 return((char *) NULL);
312 length=MultiByteToWideChar(CP_UTF8,0,path,-1,NULL,0);
313 if (length <= 0)
314 return((char *) NULL);
315 wide_path=(wchar_t *) AcquireQuantumMemory(length,sizeof(wchar_t));
316 if (wide_path == (wchar_t *) NULL)
317 return((char *) NULL);
318 MultiByteToWideChar(CP_UTF8,0,path,-1,wide_path,length);
319 /*
320 Normalize syntactically.
321 */
322 full_path_length=GetFullPathNameW(wide_path,0,NULL,NULL);
323 if (full_path_length == 0)
324 {
325 wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
326 return((char *) NULL);
327 }
328 full_path=(wchar_t *) AcquireQuantumMemory(full_path_length,sizeof(wchar_t));
329 if (full_path == (wchar_t *) NULL)
330 {
331 wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
332 return((char *) NULL);
333 }
334 GetFullPathNameW(wide_path,full_path_length,full_path,NULL);
335 wide_path=(wchar_t *) RelinquishMagickMemory(wide_path);
336 /*
337 Open the file/directory to resolve symlinks.
338 */
339 file_handle=CreateFileW(full_path,GENERIC_READ,FILE_SHARE_READ |
340 FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,
341 FILE_FLAG_BACKUP_SEMANTICS,NULL);
342 if (file_handle != INVALID_HANDLE_VALUE)
343 {
344 /*
345 Resolve final canonical path.
346 */
347 final_path_length=GetFinalPathNameByHandleW(file_handle,NULL,0,
348 FILE_NAME_NORMALIZED);
349 if (final_path_length == 0)
350 {
351 CloseHandle(file_handle);
352 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
353 return((char *) NULL);
354 }
355 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
356 full_path=(wchar_t *) AcquireQuantumMemory(final_path_length,
357 sizeof(wchar_t));
358 if (full_path == (wchar_t *) NULL)
359 {
360 CloseHandle(file_handle);
361 return((char *) NULL);
362 }
363 GetFinalPathNameByHandleW(file_handle,full_path,final_path_length,
364 FILE_NAME_NORMALIZED);
365 CloseHandle(file_handle);
366 }
367 /*
368 Remove \\?\ prefix for POSIX-like behavior.
369 */
370 clean_path=full_path;
371 if (wcsncmp(full_path,L"\\\\?\\",4) == 0)
372 clean_path=full_path+4;
373 /*
374 Convert UTF-16 to UTF-8.
375 */
376 utf8_length=WideCharToMultiByte(CP_UTF8,0,clean_path,-1,NULL,0,NULL,NULL);
377 if (utf8_length <= 0)
378 {
379 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
380 return NULL;
381 }
382 real_path=(char *) AcquireQuantumMemory(utf8_length,sizeof(char));
383 if (real_path == (char *) NULL)
384 {
385 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
386 return NULL;
387 }
388 WideCharToMultiByte(CP_UTF8,0,clean_path,-1,real_path,utf8_length,NULL,NULL);
389 full_path=(wchar_t *) RelinquishMagickMemory(full_path);
390 return(real_path);
391#endif
392}
393
394static inline int remove_utf8(const char *path)
395{
396#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
397 return(unlink(path));
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_t *) NULL)
407 return(-1);
408 status=_wremove(path_wide);
409 path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
410 return(status);
411#endif
412}
413
414static inline int rename_utf8(const char *source,const char *destination)
415{
416#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
417 return(rename(source,destination));
418#else
419 int
420 status;
421
422 wchar_t
423 *destination_wide,
424 *source_wide;
425
426 source_wide=create_wchar_path(source);
427 if (source_wide == (wchar_t *) NULL)
428 return(-1);
429 destination_wide=create_wchar_path(destination);
430 if (destination_wide == (wchar_t *) NULL)
431 {
432 source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
433 return(-1);
434 }
435 status=_wrename(source_wide,destination_wide);
436 destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
437 source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
438 return(status);
439#endif
440}
441
442static inline int set_file_timestamp(const char *path,struct stat *attributes)
443{
444 int
445 status;
446
447#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
448#if defined(MAGICKCORE_HAVE_UTIMENSAT)
449#if defined(__APPLE__) || defined(__NetBSD__)
450#define st_atim st_atimespec
451#define st_ctim st_ctimespec
452#define st_mtim st_mtimespec
453#endif
454
455 struct timespec
456 timestamp[2];
457
458 timestamp[0].tv_sec=attributes->st_atim.tv_sec;
459 timestamp[0].tv_nsec=attributes->st_atim.tv_nsec;
460 timestamp[1].tv_sec=attributes->st_mtim.tv_sec;
461 timestamp[1].tv_nsec=attributes->st_mtim.tv_nsec;
462 status=utimensat(AT_FDCWD,path,timestamp,0);
463#else
464 struct utimbuf
465 timestamp;
466
467 timestamp.actime=attributes->st_atime;
468 timestamp.modtime=attributes->st_mtime;
469 status=utime(path,&timestamp);
470#endif
471#else
472 HANDLE
473 handle;
474
475 wchar_t
476 *path_wide;
477
478 status=(-1);
479 path_wide=create_wchar_path(path);
480 if (path_wide == (WCHAR *) NULL)
481 return(status);
482 handle=CreateFileW(path_wide,FILE_WRITE_ATTRIBUTES,FILE_SHARE_WRITE |
483 FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
484 if (handle != (HANDLE) NULL)
485 {
486 FILETIME
487 creation_time,
488 last_access_time,
489 last_write_time;
490
491 ULARGE_INTEGER
492 date_time;
493
494 date_time.QuadPart=(ULONGLONG) (attributes->st_ctime*10000000LL)+
495 116444736000000000LL;
496 creation_time.dwLowDateTime=date_time.LowPart;
497 creation_time.dwHighDateTime=date_time.HighPart;
498 date_time.QuadPart=(ULONGLONG) (attributes->st_atime*10000000LL)+
499 116444736000000000LL;
500 last_access_time.dwLowDateTime=date_time.LowPart;
501 last_access_time.dwHighDateTime=date_time.HighPart;
502 date_time.QuadPart=(ULONGLONG) (attributes->st_mtime*10000000LL)+
503 116444736000000000LL;
504 last_write_time.dwLowDateTime=date_time.LowPart;
505 last_write_time.dwHighDateTime=date_time.HighPart;
506 status=SetFileTime(handle,&creation_time,&last_access_time,&last_write_time);
507 CloseHandle(handle);
508 status=0;
509 }
510 path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
511#endif
512 return(status);
513}
514
515static inline int stat_utf8(const char *path,struct stat *attributes)
516{
517#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
518 return(stat(path,attributes));
519#else
520 int
521 status;
522
523 wchar_t
524 *path_wide;
525
526 path_wide=create_wchar_path(path);
527 if (path_wide == (WCHAR *) NULL)
528 return(-1);
529 status=_wstati64(path_wide,attributes);
530 path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
531 return(status);
532#endif
533}
534
535#if defined(__cplusplus) || defined(c_plusplus)
536}
537#endif
538
539#endif