LLDB  mainline
Windows.cpp
Go to the documentation of this file.
1 //===-- Windows.cpp ---------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // This file provides Windows support functions
10 
11 #include "lldb/Host/PosixApi.h"
13 
14 #include "llvm/Support/ConvertUTF.h"
15 
16 #include <assert.h>
17 #include <cerrno>
18 #include <ctype.h>
19 #include <io.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 namespace {
26 bool utf8ToWide(const char *utf8, wchar_t *buf, size_t bufSize) {
27  const llvm::UTF8 *sourceStart = reinterpret_cast<const llvm::UTF8 *>(utf8);
28  size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
29  llvm::UTF16 *target = reinterpret_cast<llvm::UTF16 *>(buf);
30  llvm::ConversionFlags flags = llvm::strictConversion;
31  return llvm::ConvertUTF8toUTF16(&sourceStart, sourceStart + sourceLen, &target,
32  target + bufSize, flags) == llvm::conversionOK;
33 }
34 
35 bool wideToUtf8(const wchar_t *wide, char *buf, size_t bufSize) {
36  const llvm::UTF16 *sourceStart = reinterpret_cast<const llvm::UTF16 *>(wide);
37  size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
38  llvm::UTF8 *target = reinterpret_cast<llvm::UTF8 *>(buf);
39  llvm::ConversionFlags flags = llvm::strictConversion;
40  return llvm::ConvertUTF16toUTF8(&sourceStart, sourceStart + sourceLen, &target,
41  target + bufSize, flags) == llvm::conversionOK;
42 }
43 }
44 
45 int vasprintf(char **ret, const char *fmt, va_list ap) {
46  char *buf;
47  int len;
48  size_t buflen;
49  va_list ap2;
50 
51 #if defined(_MSC_VER) || defined(__MINGW64)
52  ap2 = ap;
53  len = _vscprintf(fmt, ap2);
54 #else
55  va_copy(ap2, ap);
56  len = vsnprintf(NULL, 0, fmt, ap2);
57 #endif
58 
59  if (len >= 0 &&
60  (buf = (char *)malloc((buflen = (size_t)(len + 1)))) != NULL) {
61  len = vsnprintf(buf, buflen, fmt, ap);
62  *ret = buf;
63  } else {
64  *ret = NULL;
65  len = -1;
66  }
67 
68  va_end(ap2);
69  return len;
70 }
71 
72 char *strcasestr(const char *s, const char *find) {
73  char c, sc;
74  size_t len;
75 
76  if ((c = *find++) != 0) {
77  c = tolower((unsigned char)c);
78  len = strlen(find);
79  do {
80  do {
81  if ((sc = *s++) == 0)
82  return 0;
83  } while ((char)tolower((unsigned char)sc) != c);
84  } while (strncasecmp(s, find, len) != 0);
85  s--;
86  }
87  return ((char *)s);
88 }
89 
90 char *realpath(const char *name, char *resolved) {
91  char *retname = NULL;
92 
93  /* SUSv3 says we must set `errno = EINVAL', and return NULL,
94  * if `name' is passed as a NULL pointer.
95  */
96  if (name == NULL) {
97  errno = EINVAL;
98  return NULL;
99  }
100 
101  /* Otherwise, `name' must refer to a readable filesystem object,
102  * if we are going to resolve its absolute path name.
103  */
104  wchar_t wideNameBuffer[PATH_MAX];
105  wchar_t *wideName = wideNameBuffer;
106  if (!utf8ToWide(name, wideName, PATH_MAX)) {
107  errno = EINVAL;
108  return NULL;
109  }
110 
111  if (_waccess(wideName, 4) != 0)
112  return NULL;
113 
114  /* If `name' didn't point to an existing entity,
115  * then we don't get to here; we simply fall past this block,
116  * returning NULL, with `errno' appropriately set by `access'.
117  *
118  * When we _do_ get to here, then we can use `_fullpath' to
119  * resolve the full path for `name' into `resolved', but first,
120  * check that we have a suitable buffer, in which to return it.
121  */
122 
123  if ((retname = resolved) == NULL) {
124  /* Caller didn't give us a buffer, so we'll exercise the
125  * option granted by SUSv3, and allocate one.
126  *
127  * `_fullpath' would do this for us, but it uses `malloc', and
128  * Microsoft's implementation doesn't set `errno' on failure.
129  * If we don't do this explicitly ourselves, then we will not
130  * know if `_fullpath' fails on `malloc' failure, or for some
131  * other reason, and we want to set `errno = ENOMEM' for the
132  * `malloc' failure case.
133  */
134 
135  retname = (char *)malloc(PATH_MAX);
136  if (retname == NULL) {
137  errno = ENOMEM;
138  return NULL;
139  }
140  }
141 
142  /* Otherwise, when we do have a valid buffer,
143  * `_fullpath' should only fail if the path name is too long.
144  */
145 
146  wchar_t wideFullPathBuffer[PATH_MAX];
147  wchar_t *wideFullPath;
148  if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) ==
149  NULL) {
150  errno = ENAMETOOLONG;
151  return NULL;
152  }
153 
154  // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
155  // FIXME: Check for failure
156  size_t initialLength = wcslen(wideFullPath);
157  GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
158  GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
159 
160  // Convert back to UTF-8
161  if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) {
162  errno = EINVAL;
163  return NULL;
164  }
165 
166  // Force drive to be upper case
167  if (retname[1] == ':')
168  retname[0] = toupper(retname[0]);
169 
170  return retname;
171 }
172 
173 #ifdef _MSC_VER
174 
175 char *basename(char *path) {
176  char *l1 = strrchr(path, '\\');
177  char *l2 = strrchr(path, '/');
178  if (l2 > l1)
179  l1 = l2;
180  if (!l1)
181  return path; // no base name
182  return &l1[1];
183 }
184 
185 char *dirname(char *path) {
186  char *l1 = strrchr(path, '\\');
187  char *l2 = strrchr(path, '/');
188  if (l2 > l1)
189  l1 = l2;
190  if (!l1)
191  return NULL; // no dir name
192  *l1 = 0;
193  return path;
194 }
195 
196 int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); }
197 
198 int strncasecmp(const char *s1, const char *s2, size_t n) {
199  return strnicmp(s1, s2, n);
200 }
201 
202 int usleep(uint32_t useconds) {
203  Sleep(useconds / 1000);
204  return 0;
205 }
206 
207 #if _MSC_VER < 1900
208 namespace lldb_private {
209 int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) {
210  int old_errno = errno;
211  int r = ::vsnprintf(buffer, count, format, argptr);
212  int new_errno = errno;
213  buffer[count - 1] = '\0';
214  if (r == -1 || r == count) {
215  FILE *nul = fopen("nul", "w");
216  int bytes_written = ::vfprintf(nul, format, argptr);
217  fclose(nul);
218  if (bytes_written < count)
219  errno = new_errno;
220  else {
221  errno = old_errno;
222  r = bytes_written;
223  }
224  }
225  return r;
226 }
227 } // namespace lldb_private
228 #endif
229 
230 #endif // _MSC_VER
int vasprintf(char **ret, const char *fmt, va_list ap)
Definition: Windows.cpp:45
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
char * realpath(const char *name, char *resolved)
Definition: Windows.cpp:90
int usleep(uint32_t useconds)
char * dirname(char *path)
int strncasecmp(const char *s1, const char *s2, size_t n)
char * basename(char *path)
char * strcasestr(const char *s, const char *find)
Definition: Windows.cpp:72
int strcasecmp(const char *s1, const char *s2)
#define PATH_MAX