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