blob: 9d0e70e6d1261bf418f3e0b0d0ca60f92b55830c [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
Zachary Turnerf343968f2016-08-09 23:06:08 +000012#include "lldb/Host/PosixApi.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000013#include "lldb/Host/windows/windows.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 <cerrno>
Hafiz Abid Qadeerbdb51592014-03-12 10:39:46 +000019#include <ctype.h>
Kate Stoneb9c1b512016-09-06 20:57:50 +000020#include <io.h>
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
Virgile Bellob2f1fb22013-08-23 12:44:05 +000025
Kate Stoneb9c1b512016-09-06 20:57:50 +000026namespace {
27bool utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) {
Dimitar Vlahovski7ca05302016-09-30 14:36:17 +000028 const llvm::UTF8 *sourceStart = reinterpret_cast<const llvm::UTF8 *>(utf8);
Kate Stoneb9c1b512016-09-06 20:57:50 +000029 size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
Dimitar Vlahovski7ca05302016-09-30 14:36:17 +000030 llvm::UTF16 *target = reinterpret_cast<llvm::UTF16 *>(buf);
Dimitar Vlahovski17d9caf2016-09-30 15:41:33 +000031 llvm::ConversionFlags flags = llvm::strictConversion;
Dimitar Vlahovski7ca05302016-09-30 14:36:17 +000032 return llvm::ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target,
33 target + bufSize, flags) == llvm::conversionOK;
Zachary Turner190fadc2016-03-22 17:58:09 +000034}
35
Kate Stoneb9c1b512016-09-06 20:57:50 +000036bool wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) {
Dimitar Vlahovski7ca05302016-09-30 14:36:17 +000037 const llvm::UTF16 *sourceStart = reinterpret_cast<const llvm::UTF16 *>(wide);
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
Dimitar Vlahovski7ca05302016-09-30 14:36:17 +000039 llvm::UTF8 *target = reinterpret_cast<llvm::UTF8 *>(buf);
Dimitar Vlahovski17d9caf2016-09-30 15:41:33 +000040 llvm::ConversionFlags flags = llvm::strictConversion;
Dimitar Vlahovski7ca05302016-09-30 14:36:17 +000041 return llvm::ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target,
42 target + bufSize, flags) == llvm::conversionOK;
Zachary Turner190fadc2016-03-22 17:58:09 +000043}
44}
45
Kate Stoneb9c1b512016-09-06 20:57:50 +000046int vasprintf(char **ret, const char *fmt, va_list ap) {
47 char *buf;
48 int len;
49 size_t buflen;
50 va_list ap2;
Virgile Bellob2f1fb22013-08-23 12:44:05 +000051
52#if defined(_MSC_VER) || defined(__MINGW64)
Kate Stoneb9c1b512016-09-06 20:57:50 +000053 ap2 = ap;
54 len = _vscprintf(fmt, ap2);
Virgile Bellob2f1fb22013-08-23 12:44:05 +000055#else
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 va_copy(ap2, ap);
57 len = vsnprintf(NULL, 0, fmt, ap2);
Virgile Bellob2f1fb22013-08-23 12:44:05 +000058#endif
59
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 if (len >= 0 &&
61 (buf = (char *)malloc((buflen = (size_t)(len + 1)))) != NULL) {
62 len = vsnprintf(buf, buflen, fmt, ap);
63 *ret = buf;
64 } else {
65 *ret = NULL;
66 len = -1;
67 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +000068
Kate Stoneb9c1b512016-09-06 20:57:50 +000069 va_end(ap2);
70 return len;
Virgile Bellob2f1fb22013-08-23 12:44:05 +000071}
72
Kate Stoneb9c1b512016-09-06 20:57:50 +000073char *strcasestr(const char *s, const char *find) {
74 char c, sc;
75 size_t len;
Virgile Bellob2f1fb22013-08-23 12:44:05 +000076
Kate Stoneb9c1b512016-09-06 20:57:50 +000077 if ((c = *find++) != 0) {
78 c = tolower((unsigned char)c);
79 len = strlen(find);
80 do {
81 do {
82 if ((sc = *s++) == 0)
83 return 0;
84 } while ((char)tolower((unsigned char)sc) != c);
85 } while (strncasecmp(s, find, len) != 0);
86 s--;
87 }
88 return ((char *)s);
Virgile Bellob2f1fb22013-08-23 12:44:05 +000089}
90
Kate Stoneb9c1b512016-09-06 20:57:50 +000091char *realpath(const char *name, char *resolved) {
92 char *retname = NULL;
Virgile Bellob2f1fb22013-08-23 12:44:05 +000093
Kate Stoneb9c1b512016-09-06 20:57:50 +000094 /* SUSv3 says we must set `errno = EINVAL', and return NULL,
95 * if `name' is passed as a NULL pointer.
96 */
97 if (name == NULL) {
98 errno = EINVAL;
99 return NULL;
100 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 /* Otherwise, `name' must refer to a readable filesystem object,
103 * if we are going to resolve its absolute path name.
104 */
105 wchar_t wideNameBuffer[PATH_MAX];
106 wchar_t *wideName = wideNameBuffer;
107 if (!utf8ToWide(name, wideName, PATH_MAX)) {
108 errno = EINVAL;
109 return NULL;
110 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112 if (_waccess(wideName, 4) != 0)
113 return NULL;
Zachary Turner190fadc2016-03-22 17:58:09 +0000114
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115 /* If `name' didn't point to an existing entity,
116 * then we don't get to here; we simply fall past this block,
117 * returning NULL, with `errno' appropriately set by `access'.
118 *
119 * When we _do_ get to here, then we can use `_fullpath' to
120 * resolve the full path for `name' into `resolved', but first,
121 * check that we have a suitable buffer, in which to return it.
122 */
123
124 if ((retname = resolved) == NULL) {
125 /* Caller didn't give us a buffer, so we'll exercise the
126 * option granted by SUSv3, and allocate one.
Zachary Turner190fadc2016-03-22 17:58:09 +0000127 *
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 * `_fullpath' would do this for us, but it uses `malloc', and
129 * Microsoft's implementation doesn't set `errno' on failure.
130 * If we don't do this explicitly ourselves, then we will not
131 * know if `_fullpath' fails on `malloc' failure, or for some
132 * other reason, and we want to set `errno = ENOMEM' for the
133 * `malloc' failure case.
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000134 */
135
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136 retname = (char *)malloc(PATH_MAX);
137 if (retname == NULL) {
138 errno = ENOMEM;
139 return NULL;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000140 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 }
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000142
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 /* Otherwise, when we do have a valid buffer,
144 * `_fullpath' should only fail if the path name is too long.
145 */
Zachary Turner190fadc2016-03-22 17:58:09 +0000146
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 wchar_t wideFullPathBuffer[PATH_MAX];
148 wchar_t *wideFullPath;
149 if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) ==
150 NULL) {
151 errno = ENAMETOOLONG;
152 return NULL;
153 }
Zachary Turner190fadc2016-03-22 17:58:09 +0000154
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
156 // FIXME: Check for failure
157 size_t initialLength = wcslen(wideFullPath);
158 GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
159 GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
Zachary Turner190fadc2016-03-22 17:58:09 +0000160
Kate Stoneb9c1b512016-09-06 20:57:50 +0000161 // Convert back to UTF-8
162 if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) {
163 errno = EINVAL;
164 return NULL;
165 }
Zachary Turner190fadc2016-03-22 17:58:09 +0000166
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167 // Force drive to be upper case
168 if (retname[1] == ':')
169 retname[0] = toupper(retname[0]);
Zachary Turner190fadc2016-03-22 17:58:09 +0000170
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171 return retname;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000172}
Virgile Bellod87fc152013-09-07 05:05:49 +0000173
174#ifdef _MSC_VER
175
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176char *basename(char *path) {
177 char *l1 = strrchr(path, '\\');
178 char *l2 = strrchr(path, '/');
179 if (l2 > l1)
180 l1 = l2;
181 if (!l1)
182 return path; // no base name
183 return &l1[1];
Virgile Bellod87fc152013-09-07 05:05:49 +0000184}
185
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186char *dirname(char *path) {
187 char *l1 = strrchr(path, '\\');
188 char *l2 = strrchr(path, '/');
189 if (l2 > l1)
190 l1 = l2;
191 if (!l1)
192 return NULL; // no dir name
193 *l1 = 0;
194 return path;
Virgile Bellod87fc152013-09-07 05:05:49 +0000195}
196
Kate Stoneb9c1b512016-09-06 20:57:50 +0000197int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); }
198
199int strncasecmp(const char *s1, const char *s2, size_t n) {
200 return strnicmp(s1, s2, n);
Virgile Bellod87fc152013-09-07 05:05:49 +0000201}
202
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203int usleep(uint32_t useconds) {
204 Sleep(useconds / 1000);
205 return 0;
Chaoren Lin0ef00272015-05-29 19:34:57 +0000206}
207
Zachary Turnerfbf8dad2015-07-24 22:32:22 +0000208#if _MSC_VER < 1900
Chaoren Linee3c2062015-08-20 20:53:15 +0000209namespace lldb_private {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) {
211 int old_errno = errno;
212 int r = ::vsnprintf(buffer, count, format, argptr);
213 int new_errno = errno;
214 buffer[count - 1] = '\0';
215 if (r == -1 || r == count) {
216 FILE *nul = fopen("nul", "w");
217 int bytes_written = ::vfprintf(nul, format, argptr);
218 fclose(nul);
219 if (bytes_written < count)
220 errno = new_errno;
221 else {
222 errno = old_errno;
223 r = bytes_written;
Chaoren Lin0ef00272015-05-29 19:34:57 +0000224 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000225 }
226 return r;
Virgile Bellod87fc152013-09-07 05:05:49 +0000227}
Chaoren Linee3c2062015-08-20 20:53:15 +0000228} // namespace lldb_private
Zachary Turnerfbf8dad2015-07-24 22:32:22 +0000229#endif
Virgile Bellod87fc152013-09-07 05:05:49 +0000230
231#endif // _MSC_VER