@@ -38,9 +38,10 @@ using namespace llbuild::basic;
38
38
39
39
bool sys::chdir (const char *fileName) {
40
40
#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 , 128 > wFileName;
42
+ if (llvm::sys::path::widenPath (fileName, wFileName))
43
+ return false ;
44
+ return SetCurrentDirectoryW (wFileName.data ());
44
45
#else
45
46
return ::chdir (fileName) == 0 ;
46
47
#endif
@@ -63,10 +64,13 @@ time_t filetimeToTime_t(FILETIME ft) {
63
64
64
65
int sys::lstat (const char *fileName, sys::StatStruct *buf) {
65
66
#if defined(_WIN32)
66
- llvm::SmallVector<llvm::UTF16, 20 > wfilename;
67
- llvm::convertUTF8ToUTF16String (fileName, wfilename);
67
+ llvm::SmallVector<wchar_t , 128 > wfilename;
68
+ if (llvm::sys::path::widenPath (fileName, wfilename)) {
69
+ errno = EINVAL;
70
+ return -1 ;
71
+ }
68
72
HANDLE h = CreateFileW (
69
- /* lpFileName=*/ (LPCWSTR) wfilename.data (),
73
+ /* lpFileName=*/ wfilename.data (),
70
74
/* dwDesiredAccess=*/ 0 ,
71
75
/* dwShareMode=*/ FILE_SHARE_READ,
72
76
/* lpSecurityAttributes=*/ NULL ,
@@ -123,7 +127,10 @@ int sys::lstat(const char *fileName, sys::StatStruct *buf) {
123
127
124
128
bool sys::mkdir (const char * fileName) {
125
129
#if defined(_WIN32)
126
- return _mkdir (fileName) == 0 ;
130
+ llvm::SmallVector<wchar_t , 128 > wfilename;
131
+ if (llvm::sys::path::widenPath (fileName, wfilename))
132
+ return false ;
133
+ return CreateDirectoryW (wfilename.data (), NULL ) != 0 ;
127
134
#else
128
135
return ::mkdir (fileName, S_IRWXU | S_IRWXG | S_IRWXO) == 0 ;
129
136
#endif
@@ -164,15 +171,73 @@ int sys::read(int fileHandle, void *destinationBuffer,
164
171
165
172
int sys::rmdir (const char *path) {
166
173
#if defined(_WIN32)
167
- return ::_rmdir (path);
174
+ llvm::SmallVector<wchar_t , 128 > wpath;
175
+ if (llvm::sys::path::widenPath (path, wpath)) {
176
+ errno = EINVAL;
177
+ return -1 ;
178
+ }
179
+ if (RemoveDirectoryW (wpath.data ())) {
180
+ return 0 ;
181
+ } else {
182
+ int err = GetLastError ();
183
+ if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
184
+ errno = ENOENT;
185
+ } else if (err == ERROR_ACCESS_DENIED) {
186
+ errno = EACCES;
187
+ } else if (err == ERROR_DIR_NOT_EMPTY) {
188
+ errno = ENOTEMPTY;
189
+ } else {
190
+ errno = EINVAL;
191
+ }
192
+ return -1 ;
193
+ }
168
194
#else
169
195
return ::rmdir (path);
170
196
#endif
171
197
}
172
198
173
199
int sys::stat (const char *fileName, StatStruct *buf) {
174
200
#if defined(_WIN32)
175
- return ::_stat (fileName, buf);
201
+ llvm::SmallVector<wchar_t , 128 > wfilename;
202
+ if (llvm::sys::path::widenPath (fileName, wfilename)) {
203
+ errno = EINVAL;
204
+ return -1 ;
205
+ }
206
+
207
+ WIN32_FILE_ATTRIBUTE_DATA fileData;
208
+ if (!GetFileAttributesExW (wfilename.data (), GetFileExInfoStandard, &fileData)) {
209
+ int err = GetLastError ();
210
+ if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
211
+ errno = ENOENT;
212
+ } else if (err == ERROR_ACCESS_DENIED) {
213
+ errno = EACCES;
214
+ } else {
215
+ errno = EINVAL;
216
+ }
217
+ return -1 ;
218
+ }
219
+
220
+ // Fill the stat structure
221
+ buf->st_gid = 0 ;
222
+ buf->st_atime = filetimeToTime_t (fileData.ftLastAccessTime );
223
+ buf->st_ctime = filetimeToTime_t (fileData.ftCreationTime );
224
+ buf->st_dev = 0 ;
225
+ buf->st_ino = 0 ;
226
+ buf->st_rdev = 0 ;
227
+ buf->st_mode = (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR : _S_IFREG;
228
+ buf->st_mode |= (fileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _S_IREAD : _S_IREAD | _S_IWRITE;
229
+
230
+ llvm::StringRef extension = llvm::sys::path::extension (llvm::StringRef (fileName));
231
+ if (extension == " .exe" || extension == " .cmd" || extension == " .bat" || extension == " .com" ) {
232
+ buf->st_mode |= _S_IEXEC;
233
+ }
234
+
235
+ buf->st_mtime = filetimeToTime_t (fileData.ftLastWriteTime );
236
+ buf->st_nlink = 1 ;
237
+ buf->st_size = ((long long )fileData.nFileSizeHigh << 32 ) | fileData.nFileSizeLow ;
238
+ buf->st_uid = 0 ;
239
+
240
+ return 0 ;
176
241
#else
177
242
return ::stat (fileName, buf);
178
243
#endif
@@ -181,19 +246,21 @@ int sys::stat(const char *fileName, StatStruct *buf) {
181
246
// Create a symlink named linkPath which contains the string pointsTo
182
247
int sys::symlink (const char *pointsTo, const char *linkPath) {
183
248
#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 ());
249
+ llvm::SmallVector<wchar_t , 128 > wPointsTo;
250
+ if (llvm::sys::path::widenPath (pointsTo, wPointsTo))
251
+ return -1 ;
252
+ llvm::SmallVector<wchar_t , 128 > wLinkPath;
253
+ if (llvm::sys::path::widenPath (linkPath, wLinkPath))
254
+ return -1 ;
255
+ DWORD attributes = GetFileAttributesW (wPointsTo.data ());
189
256
DWORD directoryFlag = (attributes != INVALID_FILE_ATTRIBUTES &&
190
257
attributes & FILE_ATTRIBUTE_DIRECTORY)
191
258
? SYMBOLIC_LINK_FLAG_DIRECTORY
192
259
: 0 ;
193
260
// Note that CreateSymbolicLinkW takes its arguments in reverse order
194
261
// compared to symlink/_symlink
195
262
return !::CreateSymbolicLinkW (
196
- (LPCWSTR) wLinkPath.data (), (LPCWSTR) wPointsTo.data (),
263
+ wLinkPath.data (), wPointsTo.data (),
197
264
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | directoryFlag);
198
265
#else
199
266
return ::symlink (pointsTo, linkPath);
@@ -202,7 +269,24 @@ int sys::symlink(const char *pointsTo, const char *linkPath) {
202
269
203
270
int sys::unlink (const char *fileName) {
204
271
#if defined(_WIN32)
205
- return ::_unlink (fileName);
272
+ llvm::SmallVector<wchar_t , 128 > wfilename;
273
+ if (llvm::sys::path::widenPath (fileName, wfilename)) {
274
+ errno = EINVAL;
275
+ return -1 ;
276
+ }
277
+ if (DeleteFileW (wfilename.data ())) {
278
+ return 0 ;
279
+ } else {
280
+ int err = GetLastError ();
281
+ if (err == ERROR_FILE_NOT_FOUND) {
282
+ errno = ENOENT;
283
+ } else if (err == ERROR_ACCESS_DENIED) {
284
+ errno = EACCES;
285
+ } else {
286
+ errno = EINVAL;
287
+ }
288
+ return -1 ;
289
+ }
206
290
#else
207
291
return ::unlink (fileName);
208
292
#endif
@@ -263,14 +347,15 @@ int sys::raiseOpenFileLimit(llbuild_rlim_t limit) {
263
347
sys::MATCH_RESULT sys::filenameMatch (const std::string& pattern,
264
348
const std::string& filename) {
265
349
#if defined(_WIN32)
266
- llvm::SmallVector<llvm::UTF16, 20 > wpattern;
267
- llvm::SmallVector<llvm::UTF16, 20 > wfilename;
350
+ llvm::SmallVector<wchar_t , 128 > wpattern;
351
+ llvm::SmallVector<wchar_t , 128 > wfilename;
268
352
269
- llvm::convertUTF8ToUTF16String (pattern, wpattern);
270
- llvm::convertUTF8ToUTF16String (filename, wfilename);
353
+ if (llvm::sys::path::widenPath (pattern, wpattern) ||
354
+ llvm::sys::path::widenPath (filename, wfilename))
355
+ return sys::MATCH_ERROR;
271
356
272
357
bool result =
273
- PathMatchSpecW ((LPCWSTR) wfilename.data (), (LPCWSTR) wpattern.data ());
358
+ PathMatchSpecW (wfilename.data (), wpattern.data ());
274
359
return result ? sys::MATCH : sys::NO_MATCH;
275
360
#else
276
361
int result = fnmatch (pattern.c_str (), filename.c_str (), 0 );
@@ -342,9 +427,10 @@ std::string sys::makeTmpDir() {
342
427
#if defined(_WIN32)
343
428
char path[MAX_PATH];
344
429
tmpnam_s (path, MAX_PATH);
345
- llvm::SmallVector<llvm::UTF16, 20 > wPath;
346
- llvm::convertUTF8ToUTF16String (path, wPath);
347
- CreateDirectoryW ((LPCWSTR)wPath.data (), NULL );
430
+ llvm::SmallVector<wchar_t , 128 > wPath;
431
+ if (llvm::sys::path::widenPath (path, wPath))
432
+ return std::string ();
433
+ CreateDirectoryW (wPath.data (), NULL );
348
434
return std::string (path);
349
435
#else
350
436
if (const char *tmpDir = std::getenv (" TMPDIR" )) {
@@ -371,15 +457,10 @@ std::string sys::getPathSeparators() {
371
457
372
458
sys::ModuleTraits<>::Handle sys::OpenLibrary (const char *path) {
373
459
#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 ()));
460
+ llvm::SmallVector<wchar_t , 128 > wPath;
461
+ if (llvm::sys::path::widenPath (path, wPath))
462
+ return nullptr ;
463
+ return LoadLibraryW (wPath.data ());
383
464
#else
384
465
return dlopen (path, RTLD_LAZY);
385
466
#endif
0 commit comments