@@ -38,9 +38,10 @@ using namespace llbuild::basic;
3838
3939bool sys::chdir (const char *fileName) {
4040#if defined(_WIN32)
41- llvm::SmallVector<llvm::UTF16, 20 > wFileName;
42- llvm::convertUTF8ToUTF16String (fileName, wFileName);
43- return SetCurrentDirectoryW ((LPCWSTR)wFileName.data ());
41+ llvm::SmallVector<wchar_t , MAX_PATH> wFileName;
42+ if (llvm::sys::path::widenPath (fileName, wFileName))
43+ return false ;
44+ return ::_wchdir (wFileName.data ()) == 0 ;
4445#else
4546 return ::chdir (fileName) == 0 ;
4647#endif
@@ -63,10 +64,13 @@ time_t filetimeToTime_t(FILETIME ft) {
6364
6465int sys::lstat (const char *fileName, sys::StatStruct *buf) {
6566#if defined(_WIN32)
66- llvm::SmallVector<llvm::UTF16, 20 > wfilename;
67- llvm::convertUTF8ToUTF16String (fileName, wfilename);
67+ llvm::SmallVector<wchar_t , MAX_PATH> wfilename;
68+ if (llvm::sys::path::widenPath (fileName, wfilename)) {
69+ errno = EINVAL;
70+ return -1 ;
71+ }
6872 HANDLE h = CreateFileW (
69- /* lpFileName=*/ (LPCWSTR) wfilename.data (),
73+ /* lpFileName=*/ wfilename.data (),
7074 /* dwDesiredAccess=*/ 0 ,
7175 /* dwShareMode=*/ FILE_SHARE_READ,
7276 /* lpSecurityAttributes=*/ NULL ,
@@ -123,7 +127,10 @@ int sys::lstat(const char *fileName, sys::StatStruct *buf) {
123127
124128bool sys::mkdir (const char * fileName) {
125129#if defined(_WIN32)
126- return _mkdir (fileName) == 0 ;
130+ llvm::SmallVector<wchar_t , MAX_PATH> wfilename;
131+ if (llvm::sys::path::widenPath (fileName, wfilename))
132+ return false ;
133+ return ::_wmkdir (wfilename.data ()) == 0 ;
127134#else
128135 return ::mkdir (fileName, S_IRWXU | S_IRWXG | S_IRWXO) == 0 ;
129136#endif
@@ -164,15 +171,25 @@ int sys::read(int fileHandle, void *destinationBuffer,
164171
165172int sys::rmdir (const char *path) {
166173#if defined(_WIN32)
167- return ::_rmdir (path);
174+ llvm::SmallVector<wchar_t , MAX_PATH> wpath;
175+ if (llvm::sys::path::widenPath (path, wpath)) {
176+ errno = EINVAL;
177+ return -1 ;
178+ }
179+ return ::_wrmdir (wpath.data ());
168180#else
169181 return ::rmdir (path);
170182#endif
171183}
172184
173185int sys::stat (const char *fileName, StatStruct *buf) {
174186#if defined(_WIN32)
175- return ::_stat (fileName, buf);
187+ llvm::SmallVector<wchar_t , MAX_PATH> wfilename;
188+ if (llvm::sys::path::widenPath (fileName, wfilename)) {
189+ errno = EINVAL;
190+ return -1 ;
191+ }
192+ return ::_wstat (wfilename.data (), buf);
176193#else
177194 return ::stat (fileName, buf);
178195#endif
@@ -181,19 +198,21 @@ int sys::stat(const char *fileName, StatStruct *buf) {
181198// Create a symlink named linkPath which contains the string pointsTo
182199int sys::symlink (const char *pointsTo, const char *linkPath) {
183200#if defined(_WIN32)
184- llvm::SmallVector<llvm::UTF16, 20 > wPointsTo;
185- llvm::convertUTF8ToUTF16String (pointsTo, wPointsTo);
186- llvm::SmallVector<llvm::UTF16, 20 > wLinkPath;
187- llvm::convertUTF8ToUTF16String (linkPath, wLinkPath);
188- DWORD attributes = GetFileAttributesW ((LPCWSTR)wPointsTo.data ());
201+ llvm::SmallVector<wchar_t , MAX_PATH> wPointsTo;
202+ if (llvm::sys::path::widenPath (pointsTo, wPointsTo))
203+ return -1 ;
204+ llvm::SmallVector<wchar_t , MAX_PATH> wLinkPath;
205+ if (llvm::sys::path::widenPath (linkPath, wLinkPath))
206+ return -1 ;
207+ DWORD attributes = GetFileAttributesW (wPointsTo.data ());
189208 DWORD directoryFlag = (attributes != INVALID_FILE_ATTRIBUTES &&
190209 attributes & FILE_ATTRIBUTE_DIRECTORY)
191210 ? SYMBOLIC_LINK_FLAG_DIRECTORY
192211 : 0 ;
193212 // Note that CreateSymbolicLinkW takes its arguments in reverse order
194213 // compared to symlink/_symlink
195214 return !::CreateSymbolicLinkW (
196- (LPCWSTR) wLinkPath.data (), (LPCWSTR) wPointsTo.data (),
215+ wLinkPath.data (), wPointsTo.data (),
197216 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | directoryFlag);
198217#else
199218 return ::symlink (pointsTo, linkPath);
@@ -202,7 +221,12 @@ int sys::symlink(const char *pointsTo, const char *linkPath) {
202221
203222int sys::unlink (const char *fileName) {
204223#if defined(_WIN32)
205- return ::_unlink (fileName);
224+ llvm::SmallVector<wchar_t , MAX_PATH> wfilename;
225+ if (llvm::sys::path::widenPath (fileName, wfilename)) {
226+ errno = EINVAL;
227+ return -1 ;
228+ }
229+ return ::_wunlink (wfilename.data ());
206230#else
207231 return ::unlink (fileName);
208232#endif
@@ -263,14 +287,15 @@ int sys::raiseOpenFileLimit(llbuild_rlim_t limit) {
263287sys::MATCH_RESULT sys::filenameMatch (const std::string& pattern,
264288 const std::string& filename) {
265289#if defined(_WIN32)
266- llvm::SmallVector<llvm::UTF16, 20 > wpattern;
267- llvm::SmallVector<llvm::UTF16, 20 > wfilename;
290+ llvm::SmallVector<wchar_t , MAX_PATH > wpattern;
291+ llvm::SmallVector<wchar_t , MAX_PATH > wfilename;
268292
269- llvm::convertUTF8ToUTF16String (pattern, wpattern);
270- llvm::convertUTF8ToUTF16String (filename, wfilename);
293+ if (llvm::sys::path::widenPath (pattern, wpattern) ||
294+ llvm::sys::path::widenPath (filename, wfilename))
295+ return sys::MATCH_ERROR;
271296
272297 bool result =
273- PathMatchSpecW ((LPCWSTR) wfilename.data (), (LPCWSTR) wpattern.data ());
298+ PathMatchSpecW (wfilename.data (), wpattern.data ());
274299 return result ? sys::MATCH : sys::NO_MATCH;
275300#else
276301 int result = fnmatch (pattern.c_str (), filename.c_str (), 0 );
@@ -342,9 +367,17 @@ std::string sys::makeTmpDir() {
342367#if defined(_WIN32)
343368 char path[MAX_PATH];
344369 tmpnam_s (path, MAX_PATH);
345- llvm::SmallVector<llvm::UTF16, 20 > wPath;
346- llvm::convertUTF8ToUTF16String (path, wPath);
347- CreateDirectoryW ((LPCWSTR)wPath.data (), NULL );
370+ llvm::SmallVector<wchar_t , MAX_PATH> wPath;
371+ if (llvm::sys::path::widenPath (path, wPath))
372+ return std::string ();
373+ if (!CreateDirectoryW (wPath.data (), NULL )) {
374+ DWORD error = GetLastError ();
375+ if (error != ERROR_ALREADY_EXISTS) {
376+ fprintf (stderr, " Failed to create temporary directory '%s': error code %lu\n " ,
377+ path, (unsigned long )error);
378+ return std::string ();
379+ }
380+ }
348381 return std::string (path);
349382#else
350383 if (const char *tmpDir = std::getenv (" TMPDIR" )) {
@@ -371,15 +404,10 @@ std::string sys::getPathSeparators() {
371404
372405sys::ModuleTraits<>::Handle sys::OpenLibrary (const char *path) {
373406#if defined(_WIN32)
374- int cchLength =
375- MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, path, strlen (path),
376- nullptr , 0 );
377- std::u16string buffer (cchLength + 1 , 0 );
378- MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, path, strlen (path),
379- const_cast <LPWSTR>(reinterpret_cast <LPCWSTR>(buffer.data ())),
380- buffer.size ());
381-
382- return LoadLibraryW (reinterpret_cast <LPCWSTR>(buffer.data ()));
407+ llvm::SmallVector<wchar_t , MAX_PATH> wPath;
408+ if (llvm::sys::path::widenPath (path, wPath))
409+ return nullptr ;
410+ return LoadLibraryW (wPath.data ());
383411#else
384412 return dlopen (path, RTLD_LAZY);
385413#endif
0 commit comments