1/*
2  Copyright 1999-2016 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.
6  obtain a copy of the License at
7
8    http://www.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
25#if defined(__cplusplus) || defined(c_plusplus)
26extern "C" {
27#endif
28
29extern MagickPrivate char
30  **GetPathComponents(const char *,size_t *),
31  **ListFiles(const char *,const char *,size_t *);
32
33extern MagickPrivate MagickBooleanType
34  GetExecutionPath(char *,const size_t),
35  ShredFile(const char *);
36
37extern MagickPrivate ssize_t
38  GetMagickPageSize(void);
39
40extern MagickPrivate void
41  ChopPathComponents(char *,const size_t),
42  ExpandFilename(char *);
43
44/*
45  Windows UTF8 compatibility methods.
46*/
47
48#if defined(MAGICKCORE_WINDOWS_SUPPORT)
49static inline wchar_t *create_wchar_path(const char *utf8)
50{
51  int
52    count;
53
54  wchar_t
55    *wideChar;
56
57  count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,NULL,0);
58  if (count > MAX_PATH)
59    {
60      char
61        buffer[MagickPathExtent];
62
63      wchar_t
64        shortPath[MAX_PATH],
65        *longPath;
66
67      (void) FormatLocaleString(buffer,MagickPathExtent,"\\\\?\\%s",utf8);
68      count+=4;
69      longPath=(wchar_t *) AcquireQuantumMemory(count,sizeof(*longPath));
70      if (longPath == (wchar_t *) NULL)
71        return((wchar_t *) NULL);
72      count=MultiByteToWideChar(CP_UTF8,0,buffer,-1,longPath,count);
73      if (count != 0)
74        count=GetShortPathNameW(longPath,shortPath,MAX_PATH);
75      longPath=(wchar_t *) RelinquishMagickMemory(longPath);
76      if (count < 5)
77        return((wchar_t *) NULL);
78      wideChar=(wchar_t *) AcquireQuantumMemory(count-3,sizeof(*wideChar));
79      wcscpy(wideChar,shortPath+4);
80      return(wideChar);
81    }
82  wideChar=(wchar_t *) AcquireQuantumMemory(count,sizeof(*wideChar));
83  if (wideChar == (wchar_t *) NULL)
84    return((wchar_t *) NULL);
85  count=MultiByteToWideChar(CP_UTF8,0,utf8,-1,wideChar,count);
86  if (count == 0)
87    {
88      wideChar=(wchar_t *) RelinquishMagickMemory(wideChar);
89      return((wchar_t *) NULL);
90    }
91  return(wideChar);
92}
93#endif
94
95static inline int access_utf8(const char *path,int mode)
96{
97#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__)
98  return(access(path,mode));
99#else
100   int
101     status;
102
103   wchar_t
104     *path_wide;
105
106   path_wide=create_wchar_path(path);
107   if (path_wide == (wchar_t *) NULL)
108     return(-1);
109   status=_waccess(path_wide,mode);
110   path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
111   return(status);
112#endif
113}
114
115static inline FILE *fopen_utf8(const char *path,const char *mode)
116{
117#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
118  return(fopen(path,mode));
119#else
120   FILE
121     *file;
122
123   wchar_t
124     *mode_wide,
125     *path_wide;
126
127   path_wide=create_wchar_path(path);
128   if (path_wide == (wchar_t *) NULL)
129     return((FILE *) NULL);
130   mode_wide=create_wchar_path(mode);
131   if (mode_wide == (wchar_t *) NULL)
132     {
133       path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
134       return((FILE *) NULL);
135     }
136   file=_wfopen(path_wide,mode_wide);
137   mode_wide=(wchar_t *) RelinquishMagickMemory(mode_wide);
138   path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
139   return(file);
140#endif
141}
142
143static inline void getcwd_utf8(char *path,size_t extent)
144{
145#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
146  char
147    *directory;
148
149   directory=getcwd(path,extent);
150   (void) directory;
151#else
152  wchar_t
153    wide_path[MagickPathExtent];
154
155  (void) _wgetcwd(wide_path,MagickPathExtent-1);
156  (void) WideCharToMultiByte(CP_UTF8,0,wide_path,-1,path,(int) extent,NULL,NULL);
157#endif
158}
159
160#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)
161typedef int
162  mode_t;
163#endif
164
165static inline int open_utf8(const char *path,int flags,mode_t mode)
166{
167#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
168  return(open(path,flags,mode));
169#else
170   int
171     status;
172
173   wchar_t
174     *path_wide;
175
176   path_wide=create_wchar_path(path);
177   if (path_wide == (wchar_t *) NULL)
178     return(-1);
179   status=_wopen(path_wide,flags,mode);
180   path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
181   return(status);
182#endif
183}
184
185static inline FILE *popen_utf8(const char *command,const char *type)
186{
187#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
188  return(popen(command,type));
189#else
190   FILE
191     *file;
192
193   wchar_t
194     *type_wide,
195     *command_wide;
196
197   command_wide=create_wchar_path(command);
198   if (command_wide == (wchar_t *) NULL)
199     return((FILE *) NULL);
200   type_wide=create_wchar_path(type);
201   if (type_wide == (wchar_t *) NULL)
202     {
203       command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
204       return((FILE *) NULL);
205     }
206   file=_wpopen(command_wide,type_wide);
207   type_wide=(wchar_t *) RelinquishMagickMemory(type_wide);
208   command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);
209   return(file);
210#endif
211}
212
213static inline int remove_utf8(const char *path)
214{
215#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
216  return(unlink(path));
217#else
218   int
219     status;
220
221   wchar_t
222     *path_wide;
223
224   path_wide=create_wchar_path(path);
225   if (path_wide == (wchar_t *) NULL)
226     return(-1);
227   status=_wremove(path_wide);
228   path_wide=(wchar_t *) RelinquishMagickMemory(path_wide);
229   return(status);
230#endif
231}
232
233static inline int rename_utf8(const char *source,const char *destination)
234{
235#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
236  return(rename(source,destination));
237#else
238   int
239     status;
240
241   wchar_t
242     *destination_wide,
243     *source_wide;
244
245   source_wide=create_wchar_path(source);
246   if (source_wide == (wchar_t *) NULL)
247     return(-1);
248   destination_wide=create_wchar_path(destination);
249   if (destination_wide == (wchar_t *) NULL)
250     {
251       source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
252       return(-1);
253     }
254   status=_wrename(source_wide,destination_wide);
255   destination_wide=(wchar_t *) RelinquishMagickMemory(destination_wide);
256   source_wide=(wchar_t *) RelinquishMagickMemory(source_wide);
257   return(status);
258#endif
259}
260
261static inline int stat_utf8(const char *path,struct stat *attributes)
262{
263#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
264  return(stat(path,attributes));
265#else
266   int
267     status;
268
269   wchar_t
270     *path_wide;
271
272   path_wide=create_wchar_path(path);
273   if (path_wide == (WCHAR *) NULL)
274     return(-1);
275   status=wstat(path_wide,attributes);
276   path_wide=(WCHAR *) RelinquishMagickMemory(path_wide);
277   return(status);
278#endif
279}
280
281#if defined(__cplusplus) || defined(c_plusplus)
282}
283#endif
284
285#endif
286