blob: a1ee5d6e31324bf0260f2ae43413ca2e2b7391ce [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"
Zachary Turnerf343968f2016-08-09 23:06:08 +000013#include "lldb/Host/PosixApi.h"
Virgile Bellob2f1fb22013-08-23 12:44:05 +000014
Zachary Turner190fadc2016-03-22 17:58:09 +000015#include "llvm/Support/ConvertUTF.h"
16
Chaoren Lin167c7962016-04-19 01:09:37 +000017#include <assert.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000018#include <stdio.h>
19#include <stdarg.h>
20#include <string.h>
21#include <stdlib.h>
22#include <io.h>
23#include <cerrno>
Hafiz Abid Qadeerbdb51592014-03-12 10:39:46 +000024#include <ctype.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000025
Ted Woodward4744ec62015-05-12 18:47:33 +000026// These prototypes are defined in <direct.h>, but it also defines chdir() and getcwd(), giving multiply defined errors
27extern "C"
28{
29 char *_getcwd(char *buffer, int maxlen);
30 int _chdir(const char *path);
31}
32
Zachary Turner190fadc2016-03-22 17:58:09 +000033namespace
34{
35bool
36utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize)
37{
38 const UTF8 *sourceStart = reinterpret_cast<const UTF8 *>(utf8);
39 size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
40 UTF16 *target = reinterpret_cast<UTF16 *>(buf);
41 ConversionFlags flags = strictConversion;
42 return ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK;
43}
44
45bool
46wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize)
47{
48 const UTF16 *sourceStart = reinterpret_cast<const UTF16 *>(wide);
49 size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
50 UTF8 *target = reinterpret_cast<UTF8 *>(buf);
51 ConversionFlags flags = strictConversion;
52 return ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target, target + bufSize, flags) == conversionOK;
53}
54}
55
Virgile Bellob2f1fb22013-08-23 12:44:05 +000056int vasprintf(char **ret, const char *fmt, va_list ap)
57{
58 char *buf;
59 int len;
60 size_t buflen;
61 va_list ap2;
62
63#if defined(_MSC_VER) || defined(__MINGW64)
64 ap2 = ap;
65 len = _vscprintf(fmt, ap2);
66#else
67 va_copy(ap2, ap);
68 len = vsnprintf(NULL, 0, fmt, ap2);
69#endif
70
71 if (len >= 0 && (buf = (char*) malloc ((buflen = (size_t) (len + 1)))) != NULL) {
72 len = vsnprintf(buf, buflen, fmt, ap);
73 *ret = buf;
74 } else {
75 *ret = NULL;
76 len = -1;
77 }
78
79 va_end(ap2);
80 return len;
81}
82
Virgile Bellod87fc152013-09-07 05:05:49 +000083char* strcasestr(const char *s, const char* find)
Virgile Bellob2f1fb22013-08-23 12:44:05 +000084{
85 char c, sc;
86 size_t len;
87
88 if ((c = *find++) != 0) {
89 c = tolower((unsigned char) c);
90 len = strlen(find);
91 do {
92 do {
93 if ((sc = *s++) == 0)
94 return 0;
95 } while ((char) tolower((unsigned char) sc) != c);
96 } while (strncasecmp(s, find, len) != 0);
97 s--;
98 }
99 return ((char *) s);
100}
101
Virgile Belloae12a362013-08-27 16:21:49 +0000102char* realpath(const char * name, char * resolved)
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000103{
Zachary Turner190fadc2016-03-22 17:58:09 +0000104 char *retname = NULL;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000105
106 /* SUSv3 says we must set `errno = EINVAL', and return NULL,
107 * if `name' is passed as a NULL pointer.
108 */
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000109 if (name == NULL)
Zachary Turner190fadc2016-03-22 17:58:09 +0000110 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000111 errno = EINVAL;
Zachary Turner190fadc2016-03-22 17:58:09 +0000112 return NULL;
113 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000114
115 /* Otherwise, `name' must refer to a readable filesystem object,
116 * if we are going to resolve its absolute path name.
117 */
Zachary Turner190fadc2016-03-22 17:58:09 +0000118 wchar_t wideNameBuffer[PATH_MAX];
119 wchar_t *wideName = wideNameBuffer;
120 if (!utf8ToWide(name, wideName, PATH_MAX))
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000121 {
Zachary Turner190fadc2016-03-22 17:58:09 +0000122 errno = EINVAL;
123 return NULL;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000124 }
125
Zachary Turner190fadc2016-03-22 17:58:09 +0000126 if (_waccess(wideName, 4) != 0)
127 return NULL;
128
129 /* If `name' didn't point to an existing entity,
130 * then we don't get to here; we simply fall past this block,
131 * returning NULL, with `errno' appropriately set by `access'.
132 *
133 * When we _do_ get to here, then we can use `_fullpath' to
134 * resolve the full path for `name' into `resolved', but first,
135 * check that we have a suitable buffer, in which to return it.
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000136 */
137
Zachary Turner190fadc2016-03-22 17:58:09 +0000138 if ((retname = resolved) == NULL)
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000139 {
Zachary Turner190fadc2016-03-22 17:58:09 +0000140 /* Caller didn't give us a buffer, so we'll exercise the
141 * option granted by SUSv3, and allocate one.
142 *
143 * `_fullpath' would do this for us, but it uses `malloc', and
144 * Microsoft's implementation doesn't set `errno' on failure.
145 * If we don't do this explicitly ourselves, then we will not
146 * know if `_fullpath' fails on `malloc' failure, or for some
147 * other reason, and we want to set `errno = ENOMEM' for the
148 * `malloc' failure case.
149 */
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000150
Zachary Turner190fadc2016-03-22 17:58:09 +0000151 retname = (char *)malloc(PATH_MAX);
152 if (retname == NULL)
153 {
154 errno = ENOMEM;
155 return NULL;
156 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000157 }
158
Zachary Turner190fadc2016-03-22 17:58:09 +0000159 /* Otherwise, when we do have a valid buffer,
160 * `_fullpath' should only fail if the path name is too long.
161 */
162
163 wchar_t wideFullPathBuffer[PATH_MAX];
164 wchar_t *wideFullPath;
165 if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL)
166 {
167 errno = ENAMETOOLONG;
168 return NULL;
169 }
170
171 // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
172 // FIXME: Check for failure
173 size_t initialLength = wcslen(wideFullPath);
174 GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
175 GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
176
177 // Convert back to UTF-8
178 if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX))
179 {
180 errno = EINVAL;
181 return NULL;
182 }
183
184 // Force drive to be upper case
185 if (retname[1] == ':')
186 retname[0] = toupper(retname[0]);
187
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000188 return retname;
189}
Virgile Bellod87fc152013-09-07 05:05:49 +0000190
191#ifdef _MSC_VER
192
193char* basename(char *path)
194{
195 char* l1 = strrchr(path, '\\');
196 char* l2 = strrchr(path, '/');
197 if (l2 > l1) l1 = l2;
198 if (!l1) return path; // no base name
199 return &l1[1];
200}
201
Ted Woodward4744ec62015-05-12 18:47:33 +0000202// use _getcwd() instead of GetCurrentDirectory() because it updates errno
Virgile Bellod87fc152013-09-07 05:05:49 +0000203char* getcwd(char* path, int max)
204{
Zachary Turner190fadc2016-03-22 17:58:09 +0000205 assert(path == NULL || max <= PATH_MAX);
206 wchar_t wpath[PATH_MAX];
207 if (wchar_t *wresult = _wgetcwd(wpath, PATH_MAX))
208 {
209 // Caller is allowed to pass in NULL for `path`.
210 // In that case, we're supposed to allocate a
211 // buffer on the caller's behalf.
212 if (path == NULL)
213 {
214 max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
215 path = (char *)malloc(max);
216 if (path == NULL)
217 {
218 errno = ENOMEM;
219 return NULL;
220 }
221 }
222 if (wideToUtf8(wresult, path, max))
223 return path;
224 }
225 return NULL;
Ted Woodward4744ec62015-05-12 18:47:33 +0000226}
227
228// use _chdir() instead of SetCurrentDirectory() because it updates errno
229int chdir(const char* path)
230{
231 return _chdir(path);
Virgile Bellod87fc152013-09-07 05:05:49 +0000232}
233
234char *dirname(char *path)
235{
236 char* l1 = strrchr(path, '\\');
237 char* l2 = strrchr(path, '/');
238 if (l2 > l1) l1 = l2;
239 if (!l1) return NULL; // no dir name
240 *l1 = 0;
241 return path;
242}
243
244int strcasecmp(const char* s1, const char* s2)
245{
Zachary Turner12f6f532014-07-29 19:08:55 +0000246 return stricmp(s1, s2);
Virgile Bellod87fc152013-09-07 05:05:49 +0000247}
248
249int strncasecmp(const char* s1, const char* s2, size_t n)
250{
Zachary Turner12f6f532014-07-29 19:08:55 +0000251 return strnicmp(s1, s2, n);
Virgile Bellod87fc152013-09-07 05:05:49 +0000252}
253
254int usleep(uint32_t useconds)
255{
Chaoren Lin0ef00272015-05-29 19:34:57 +0000256 Sleep(useconds / 1000);
257 return 0;
258}
259
Zachary Turnerfbf8dad2015-07-24 22:32:22 +0000260#if _MSC_VER < 1900
Chaoren Linee3c2062015-08-20 20:53:15 +0000261namespace lldb_private {
262int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
Chaoren Lin0ef00272015-05-29 19:34:57 +0000263{
264 int old_errno = errno;
Chaoren Linee3c2062015-08-20 20:53:15 +0000265 int r = ::vsnprintf(buffer, count, format, argptr);
Chaoren Lin0ef00272015-05-29 19:34:57 +0000266 int new_errno = errno;
267 buffer[count-1] = '\0';
268 if (r == -1 || r == count)
269 {
270 FILE *nul = fopen("nul", "w");
Chaoren Linee3c2062015-08-20 20:53:15 +0000271 int bytes_written = ::vfprintf(nul, format, argptr);
Chaoren Lin0ef00272015-05-29 19:34:57 +0000272 fclose(nul);
273 if (bytes_written < count)
274 errno = new_errno;
275 else
276 {
277 errno = old_errno;
278 r = bytes_written;
279 }
280 }
Chaoren Lin0ef00272015-05-29 19:34:57 +0000281 return r;
Virgile Bellod87fc152013-09-07 05:05:49 +0000282}
Chaoren Linee3c2062015-08-20 20:53:15 +0000283} // namespace lldb_private
Zachary Turnerfbf8dad2015-07-24 22:32:22 +0000284#endif
Virgile Bellod87fc152013-09-07 05:05:49 +0000285
286#endif // _MSC_VER