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