LLDB  mainline
Windows.cpp
Go to the documentation of this file.
1 //===-- Windows.cpp -------------------------------------------------------===//
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  va_copy(ap2, ap);
52  len = vsnprintf(NULL, 0, fmt, ap2);
53 
54  if (len >= 0 &&
55  (buf = (char *)malloc((buflen = (size_t)(len + 1)))) != NULL) {
56  len = vsnprintf(buf, buflen, fmt, ap);
57  *ret = buf;
58  } else {
59  *ret = NULL;
60  len = -1;
61  }
62 
63  va_end(ap2);
64  return len;
65 }
66 
67 char *strcasestr(const char *s, const char *find) {
68  char c, sc;
69  size_t len;
70 
71  if ((c = *find++) != 0) {
72  c = tolower((unsigned char)c);
73  len = strlen(find);
74  do {
75  do {
76  if ((sc = *s++) == 0)
77  return 0;
78  } while ((char)tolower((unsigned char)sc) != c);
79  } while (strncasecmp(s, find, len) != 0);
80  s--;
81  }
82  return const_cast<char *>(s);
83 }
84 
85 char *realpath(const char *name, char *resolved) {
86  char *retname = NULL;
87 
88  /* SUSv3 says we must set `errno = EINVAL', and return NULL,
89  * if `name' is passed as a NULL pointer.
90  */
91  if (name == NULL) {
92  errno = EINVAL;
93  return NULL;
94  }
95 
96  /* Otherwise, `name' must refer to a readable filesystem object,
97  * if we are going to resolve its absolute path name.
98  */
99  wchar_t wideNameBuffer[PATH_MAX];
100  wchar_t *wideName = wideNameBuffer;
101  if (!utf8ToWide(name, wideName, PATH_MAX)) {
102  errno = EINVAL;
103  return NULL;
104  }
105 
106  if (_waccess(wideName, 4) != 0)
107  return NULL;
108 
109  /* If `name' didn't point to an existing entity,
110  * then we don't get to here; we simply fall past this block,
111  * returning NULL, with `errno' appropriately set by `access'.
112  *
113  * When we _do_ get to here, then we can use `_fullpath' to
114  * resolve the full path for `name' into `resolved', but first,
115  * check that we have a suitable buffer, in which to return it.
116  */
117 
118  if ((retname = resolved) == NULL) {
119  /* Caller didn't give us a buffer, so we'll exercise the
120  * option granted by SUSv3, and allocate one.
121  *
122  * `_fullpath' would do this for us, but it uses `malloc', and
123  * Microsoft's implementation doesn't set `errno' on failure.
124  * If we don't do this explicitly ourselves, then we will not
125  * know if `_fullpath' fails on `malloc' failure, or for some
126  * other reason, and we want to set `errno = ENOMEM' for the
127  * `malloc' failure case.
128  */
129 
130  retname = (char *)malloc(PATH_MAX);
131  if (retname == NULL) {
132  errno = ENOMEM;
133  return NULL;
134  }
135  }
136 
137  /* Otherwise, when we do have a valid buffer,
138  * `_fullpath' should only fail if the path name is too long.
139  */
140 
141  wchar_t wideFullPathBuffer[PATH_MAX];
142  wchar_t *wideFullPath;
143  if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) ==
144  NULL) {
145  errno = ENAMETOOLONG;
146  return NULL;
147  }
148 
149  // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
150  // FIXME: Check for failure
151  size_t initialLength = wcslen(wideFullPath);
152  GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
153  GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
154 
155  // Convert back to UTF-8
156  if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX)) {
157  errno = EINVAL;
158  return NULL;
159  }
160 
161  // Force drive to be upper case
162  if (retname[1] == ':')
163  retname[0] = toupper(retname[0]);
164 
165  return retname;
166 }
167 
168 #ifdef _MSC_VER
169 
170 char *basename(char *path) {
171  char *l1 = strrchr(path, '\\');
172  char *l2 = strrchr(path, '/');
173  if (l2 > l1)
174  l1 = l2;
175  if (!l1)
176  return path; // no base name
177  return &l1[1];
178 }
179 
180 char *dirname(char *path) {
181  char *l1 = strrchr(path, '\\');
182  char *l2 = strrchr(path, '/');
183  if (l2 > l1)
184  l1 = l2;
185  if (!l1)
186  return NULL; // no dir name
187  *l1 = 0;
188  return path;
189 }
190 
191 int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); }
192 
193 int strncasecmp(const char *s1, const char *s2, size_t n) {
194  return strnicmp(s1, s2, n);
195 }
196 
197 #if _MSC_VER < 1900
198 namespace lldb_private {
199 int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) {
200  int old_errno = errno;
201  int r = ::vsnprintf(buffer, count, format, argptr);
202  int new_errno = errno;
203  buffer[count - 1] = '\0';
204  if (r == -1 || r == count) {
205  FILE *nul = fopen("nul", "w");
206  int bytes_written = ::vfprintf(nul, format, argptr);
207  fclose(nul);
208  if (bytes_written < count)
209  errno = new_errno;
210  else {
211  errno = old_errno;
212  r = bytes_written;
213  }
214  }
215  return r;
216 }
217 } // namespace lldb_private
218 #endif
219 
220 #endif // _MSC_VER
int vasprintf(char **ret, const char *fmt, va_list ap)
Definition: Windows.cpp:45
A class that represents a running process on the host machine.
char * realpath(const char *name, char *resolved)
Definition: Windows.cpp:85
char * strcasestr(const char *s, const char *find)
Definition: Windows.cpp:67
#define PATH_MAX
#define NULL