blob: 161d7e3a11275296763bbfc6eac48a39dad1bcb4 [file] [log] [blame]
Virgile Bellob2f1fb22013-08-23 12:44:05 +00001//===-- Windows.cpp ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// This file provides Windows support functions
11
12#include "lldb/Host/windows/windows.h"
13#include "lldb/Host/windows/win32.h"
14
Zachary Turner190fadc2016-03-22 17:58:09 +000015#include "llvm/Support/ConvertUTF.h"
16
Virgile Bellob2f1fb22013-08-23 12:44:05 +000017#include <stdio.h>
18#include <stdarg.h>
19#include <string.h>
20#include <stdlib.h>
21#include <io.h>
22#include <cerrno>
Hafiz Abid Qadeerbdb51592014-03-12 10:39:46 +000023#include <ctype.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000024
Ted Woodward4744ec62015-05-12 18:47:33 +000025// These prototypes are defined in <direct.h>, but it also defines chdir() and getcwd(), giving multiply defined errors
26extern "C"
27{
28 char *_getcwd(char *buffer, int maxlen);
29 int _chdir(const char *path);
30}
31
Zachary Turner190fadc2016-03-22 17:58:09 +000032namespace
33{
34bool
35utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize)
36{
37 const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8);
38 size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
39 UTF16 *target = reinterpret_cast<UTF16 *>(buf);
40 ConversionFlags flags = strictConversion;
41 return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK;
42}
43
44bool
45wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize)
46{
47 const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide);
48 size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
49 UTF8 *target = reinterpret_cast<UTF8 *>(buf);
50 ConversionFlags flags = strictConversion;
51 return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK;
52}
53}
54
Virgile Bellob2f1fb22013-08-23 12:44:05 +000055int vasprintf(char **ret, const char *fmt, va_list ap)
56{
57 char *buf;
58 int len;
59 size_t buflen;
60 va_list ap2;
61
62#if defined(_MSC_VER) || defined(__MINGW64)
63 ap2 = ap;
64 len = _vscprintf(fmt, ap2);
65#else
66 va_copy(ap2, ap);
67 len = vsnprintf(NULL, 0, fmt, ap2);
68#endif
69
70 if (len >= 0 && (buf = (char*) malloc ((buflen = (size_t) (len + 1)))) != NULL) {
71 len = vsnprintf(buf, buflen, fmt, ap);
72 *ret = buf;
73 } else {
74 *ret = NULL;
75 len = -1;
76 }
77
78 va_end(ap2);
79 return len;
80}
81
Virgile Bellod87fc152013-09-07 05:05:49 +000082char* strcasestr(const char *s, const char* find)
Virgile Bellob2f1fb22013-08-23 12:44:05 +000083{
84 char c, sc;
85 size_t len;
86
87 if ((c = *find++) != 0) {
88 c = tolower((unsigned char) c);
89 len = strlen(find);
90 do {
91 do {
92 if ((sc = *s++) == 0)
93 return 0;
94 } while ((char) tolower((unsigned char) sc) != c);
95 } while (strncasecmp(s, find, len) != 0);
96 s--;
97 }
98 return ((char *) s);
99}
100
Virgile Belloae12a362013-08-27 16:21:49 +0000101char* realpath(const char * name, char * resolved)
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000102{
Zachary Turner190fadc2016-03-22 17:58:09 +0000103 char *retname = NULL;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000104
105 /* SUSv3 says we must set `errno = EINVAL', and return NULL,
106 * if `name' is passed as a NULL pointer.
107 */
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000108 if (name == NULL)
Zachary Turner190fadc2016-03-22 17:58:09 +0000109 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000110 errno = EINVAL;
Zachary Turner190fadc2016-03-22 17:58:09 +0000111 return NULL;
112 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000113
114 /* Otherwise, `name' must refer to a readable filesystem object,
115 * if we are going to resolve its absolute path name.
116 */
Zachary Turner190fadc2016-03-22 17:58:09 +0000117 wchar_t wideNameBuffer[PATH_MAX];
118 wchar_t *wideName = wideNameBuffer;
119 if (!utf8ToWide(name, wideName, PATH_MAX))
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000120 {
Zachary Turner190fadc2016-03-22 17:58:09 +0000121 errno = EINVAL;
122 return NULL;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000123 }
124
Zachary Turner190fadc2016-03-22 17:58:09 +0000125 if (_waccess(wideName, 4) != 0)
126 return NULL;
127
128 /* If `name' didn't point to an existing entity,
129 * then we don't get to here; we simply fall past this block,
130 * returning NULL, with `errno' appropriately set by `access'.
131 *
132 * When we _do_ get to here, then we can use `_fullpath' to
133 * resolve the full path for `name' into `resolved', but first,
134 * check that we have a suitable buffer, in which to return it.
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000135 */
136
Zachary Turner190fadc2016-03-22 17:58:09 +0000137 if ((retname = resolved) == NULL)
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000138 {
Zachary Turner190fadc2016-03-22 17:58:09 +0000139 /* Caller didn't give us a buffer, so we'll exercise the
140 * option granted by SUSv3, and allocate one.
141 *
142 * `_fullpath' would do this for us, but it uses `malloc', and
143 * Microsoft's implementation doesn't set `errno' on failure.
144 * If we don't do this explicitly ourselves, then we will not
145 * know if `_fullpath' fails on `malloc' failure, or for some
146 * other reason, and we want to set `errno = ENOMEM' for the
147 * `malloc' failure case.
148 */
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000149
Zachary Turner190fadc2016-03-22 17:58:09 +0000150 retname = (char *)malloc(PATH_MAX);
151 if (retname == NULL)
152 {
153 errno = ENOMEM;
154 return NULL;
155 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000156 }
157
Zachary Turner190fadc2016-03-22 17:58:09 +0000158 /* Otherwise, when we do have a valid buffer,
159 * `_fullpath' should only fail if the path name is too long.
160 */
161
162 wchar_t wideFullPathBuffer[PATH_MAX];
163 wchar_t *wideFullPath;
164 if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL)
165 {
166 errno = ENAMETOOLONG;
167 return NULL;
168 }
169
170 // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
171 // FIXME: Check for failure
172 size_t initialLength = wcslen(wideFullPath);
173 GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
174 GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
175
176 // Convert back to UTF-8
177 if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX))
178 {
179 errno = EINVAL;
180 return NULL;
181 }
182
183 // Force drive to be upper case
184 if (retname[1] == ':')
185 retname[0] = toupper(retname[0]);
186
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000187 return retname;
188}
Virgile Bellod87fc152013-09-07 05:05:49 +0000189
190#ifdef _MSC_VER
191
192char* basename(char *path)
193{
194 char* l1 = strrchr(path, '\\');
195 char* l2 = strrchr(path, '/');
196 if (l2 > l1) l1 = l2;
197 if (!l1) return path; // no base name
198 return &l1[1];
199}
200
Ted Woodward4744ec62015-05-12 18:47:33 +0000201// use _getcwd() instead of GetCurrentDirectory() because it updates errno
Virgile Bellod87fc152013-09-07 05:05:49 +0000202char* getcwd(char* path, int max)
203{
Zachary Turner190fadc2016-03-22 17:58:09 +0000204 assert(path == NULL || max <= PATH_MAX);
205 wchar_t wpath[PATH_MAX];
206 if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX))
207 {
208 // Caller is allowed to pass in NULL for `path`.
209 // In that case, we're supposed to allocate a
210 // buffer on the caller's behalf.
211 if (path == NULL)
212 {
213 max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
214 path = (char *)malloc(max);
215 if (path == NULL)
216 {
217 errno = ENOMEM;
218 return NULL;
219 }
220 }
221 if (wideToUtf8(wresult, path, max))
222 return path;
223 }
224 return NULL;
Ted Woodward4744ec62015-05-12 18:47:33 +0000225}
226
227// use _chdir() instead of SetCurrentDirectory() because it updates errno
228int chdir(const char* path)
229{
230 return _chdir(path);
Virgile Bellod87fc152013-09-07 05:05:49 +0000231}
232
233char *dirname(char *path)
234{
235 char* l1 = strrchr(path, '\\');
236 char* l2 = strrchr(path, '/');
237 if (l2 > l1) l1 = l2;
238 if (!l1) return NULL; // no dir name
239 *l1 = 0;
240 return path;
241}
242
243int strcasecmp(const char* s1, const char* s2)
244{
Zachary Turner12f6f532014-07-29 19:08:55 +0000245 return stricmp(s1, s2);
Virgile Bellod87fc152013-09-07 05:05:49 +0000246}
247
248int strncasecmp(const char* s1, const char* s2, size_t n)
249{
Zachary Turner12f6f532014-07-29 19:08:55 +0000250 return strnicmp(s1, s2, n);
Virgile Bellod87fc152013-09-07 05:05:49 +0000251}
252
253int usleep(uint32_t useconds)
254{
Chaoren Lin0ef00272015-05-29 19:34:57 +0000255 Sleep(useconds / 1000);
256 return 0;
257}
258
Zachary Turnerfbf8dad2015-07-24 22:32:22 +0000259#if _MSC_VER < 1900
Chaoren Linee3c2062015-08-20 20:53:15 +0000260namespace lldb_private {
261int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
Chaoren Lin0ef00272015-05-29 19:34:57 +0000262{
263 int old_errno = errno;
Chaoren Linee3c2062015-08-20 20:53:15 +0000264 int r = ::vsnprintf(buffer, count, format, argptr);
Chaoren Lin0ef00272015-05-29 19:34:57 +0000265 int new_errno = errno;
266 buffer[count-1] = '\0';
267 if (r == -1 || r == count)
268 {
269 FILE *nul = fopen("nul", "w");
Chaoren Linee3c2062015-08-20 20:53:15 +0000270 int bytes_written = ::vfprintf(nul, format, argptr);
Chaoren Lin0ef00272015-05-29 19:34:57 +0000271 fclose(nul);
272 if (bytes_written < count)
273 errno = new_errno;
274 else
275 {
276 errno = old_errno;
277 r = bytes_written;
278 }
279 }
Chaoren Lin0ef00272015-05-29 19:34:57 +0000280 return r;
Virgile Bellod87fc152013-09-07 05:05:49 +0000281}
Chaoren Linee3c2062015-08-20 20:53:15 +0000282} // namespace lldb_private
Zachary Turnerfbf8dad2015-07-24 22:32:22 +0000283#endif
Virgile Bellod87fc152013-09-07 05:05:49 +0000284
285#endif // _MSC_VER