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