llvm.org GIT mirror llvm / 8d230cd
Misc cleanups to the FileSytem api. The main difference is the removal of std::error_code exists(const Twine &path, bool &result); It was an horribly redundant interface since a file not existing is also a valid error_code. Now we have an access function that returns just an error_code. This is the only function that has to be implemented for Unix and Windows. The functions can_write, exists and can_execute an now just wrappers. One still has to be very careful using these function to avoid introducing race conditions (Time of check to time of use). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217625 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 5 years ago
7 changed file(s) with 77 addition(s) and 97 deletion(s). Raw diff Collapse all Expand all
351351 /// not.
352352 bool exists(file_status status);
353353
354 /// @brief Can the file be accessed?
355 ///
356 /// @param path Input path.
357 /// @returns errc::success if the path can be accessed, otherwise a
358 /// platform-specific error_code.
359 enum class AccessMode { Exist, Write, Execute };
360 std::error_code access(const Twine &Path, AccessMode Mode);
361
354362 /// @brief Does file exist?
355363 ///
356 /// @param path Input path.
357 /// @param result Set to true if the file represented by status exists, false if
358 /// it does not. Undefined otherwise.
359 /// @returns errc::success if result has been successfully set, otherwise a
360 /// platform-specific error_code.
361 std::error_code exists(const Twine &path, bool &result);
362
363 /// @brief Simpler version of exists for clients that don't need to
364 /// differentiate between an error and false.
365 inline bool exists(const Twine &path) {
366 bool result;
367 return !exists(path, result) && result;
364 /// @param Path Input path.
365 /// @returns True if it exists, false otherwise.
366 inline bool exists(const Twine &Path) {
367 return !access(Path, AccessMode::Exist);
368368 }
369369
370370 /// @brief Can we execute this file?
371371 ///
372372 /// @param Path Input path.
373373 /// @returns True if we can execute it, false otherwise.
374 bool can_execute(const Twine &Path);
374 inline bool can_execute(const Twine &Path) {
375 return !access(Path, AccessMode::Execute);
376 }
375377
376378 /// @brief Can we write this file?
377379 ///
378380 /// @param Path Input path.
379381 /// @returns True if we can write to it, false otherwise.
380 bool can_write(const Twine &Path);
382 inline bool can_write(const Twine &Path) {
383 return !access(Path, AccessMode::Write);
384 }
381385
382386 /// @brief Do file_status's represent the same thing?
383387 ///
203203 // If the lock file is still expected to be there, check whether it still
204204 // is.
205205 if (!LockFileGone) {
206 bool Exists;
207 if (!sys::fs::exists(LockFileName.str(), Exists) && !Exists) {
206 if (sys::fs::access(LockFileName.c_str(), sys::fs::AccessMode::Exist) ==
207 errc::no_such_file_or_directory) {
208208 LockFileGone = true;
209209 LockFileJustDisappeared = true;
210210 }
209209 }
210210
211211 case FS_Name: {
212 bool Exists;
213 std::error_code EC = sys::fs::exists(ResultPath.begin(), Exists);
212 std::error_code EC =
213 sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
214 if (EC == errc::no_such_file_or_directory)
215 return std::error_code();
214216 if (EC)
215217 return EC;
216 if (Exists)
217 goto retry_random_path;
218 return std::error_code();
218 goto retry_random_path;
219219 }
220220
221221 case FS_Dir: {
320320 return std::error_code();
321321 }
322322
323 std::error_code exists(const Twine &path, bool &result) {
324 SmallString<128> path_storage;
325 StringRef p = path.toNullTerminatedStringRef(path_storage);
326
327 if (::access(p.begin(), F_OK) == -1) {
328 if (errno != ENOENT)
329 return std::error_code(errno, std::generic_category());
330 result = false;
331 } else
332 result = true;
333
334 return std::error_code();
335 }
336
337 bool can_write(const Twine &Path) {
323 static int convertAccessMode(AccessMode Mode) {
324 switch (Mode) {
325 case AccessMode::Exist:
326 return F_OK;
327 case AccessMode::Write:
328 return W_OK;
329 case AccessMode::Execute:
330 return R_OK | X_OK; // scripts also need R_OK.
331 }
332 llvm_unreachable("invalid enum");
333 }
334
335 std::error_code access(const Twine &Path, AccessMode Mode) {
338336 SmallString<128> PathStorage;
339337 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
340 return 0 == access(P.begin(), W_OK);
341 }
342
343 bool can_execute(const Twine &Path) {
344 SmallString<128> PathStorage;
345 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
346
347 if (0 != access(P.begin(), R_OK | X_OK))
348 return false;
349 struct stat buf;
350 if (0 != stat(P.begin(), &buf))
351 return false;
352 if (!S_ISREG(buf.st_mode))
353 return false;
354 return true;
338
339 if (::access(P.begin(), convertAccessMode(Mode)) == -1)
340 return std::error_code(errno, std::generic_category());
341
342 if (Mode == AccessMode::Execute) {
343 // Don't say that directories are executable.
344 struct stat buf;
345 if (0 != stat(P.begin(), &buf))
346 return errc::permission_denied;
347 if (!S_ISREG(buf.st_mode))
348 return errc::permission_denied;
349 }
350
351 return std::error_code();
355352 }
356353
357354 bool equivalent(file_status A, file_status B) {
250250 return std::error_code(error, std::generic_category());
251251 }
252252
253 std::error_code exists(const Twine &path, bool &result) {
254 SmallString<128> path_storage;
255 SmallVector path_utf16;
256
257 if (std::error_code ec =
258 UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))
259 return ec;
260
261 DWORD attributes = ::GetFileAttributesW(path_utf16.begin());
262
263 if (attributes == INVALID_FILE_ATTRIBUTES) {
253 std::error_code access(const Twine &Path, AccessMode Mode) {
254 SmallString<128> PathStorage;
255 SmallVector PathUtf16;
256
257 if (std::error_code EC =
258 UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16))
259 return EC;
260
261 DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin());
262
263 if (Attributes == INVALID_FILE_ATTRIBUTES) {
264264 // See if the file didn't actually exist.
265265 DWORD LastError = ::GetLastError();
266266 if (LastError != ERROR_FILE_NOT_FOUND &&
267267 LastError != ERROR_PATH_NOT_FOUND)
268268 return windows_error(LastError);
269 result = false;
270 } else
271 result = true;
272 return std::error_code();
273 }
274
275 bool can_write(const Twine &Path) {
276 // FIXME: take security attributes into account.
277 SmallString<128> PathStorage;
278 SmallVector PathUtf16;
279
280 if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16))
281 return false;
282
283 DWORD Attr = ::GetFileAttributesW(PathUtf16.begin());
284 return (Attr != INVALID_FILE_ATTRIBUTES) && !(Attr & FILE_ATTRIBUTE_READONLY);
285 }
286
287 bool can_execute(const Twine &Path) {
288 SmallString<128> PathStorage;
289 SmallVector PathUtf16;
290
291 if (UTF8ToUTF16(Path.toStringRef(PathStorage), PathUtf16))
292 return false;
293
294 DWORD Attr = ::GetFileAttributesW(PathUtf16.begin());
295 return Attr != INVALID_FILE_ATTRIBUTES;
269 return errc::no_such_file_or_directory;
270 }
271
272 if (Mode == AccessMode::Write && (Attributes & FILE_ATTRIBUTE_READONLY))
273 return errc::permission_denied;
274
275 return std::error_code();
296276 }
297277
298278 bool equivalent(file_status A, file_status B) {
66 //
77 //===----------------------------------------------------------------------===//
88
9 #include "llvm/Support/Errc.h"
910 #include "llvm/Support/FileOutputBuffer.h"
1011 #include "llvm/Support/ErrorHandling.h"
1112 #include "llvm/Support/FileSystem.h"
6465 // Do *not* commit buffer.
6566 }
6667 // Verify file does not exist (because buffer not committed).
67 bool Exists = false;
68 ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists));
69 EXPECT_FALSE(Exists);
68 ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist),
69 errc::no_such_file_or_directory);
7070 ASSERT_NO_ERROR(fs::remove(File2.str()));
7171
7272 // TEST 3: Verify sizing down case.
360360 EXPECT_EQ(B.type(), fs::file_type::file_not_found);
361361
362362 // Make sure Temp2 doesn't exist.
363 bool TempFileExists;
364 ASSERT_NO_ERROR(fs::exists(Twine(TempPath2), TempFileExists));
365 EXPECT_FALSE(TempFileExists);
363 ASSERT_EQ(fs::access(Twine(TempPath2), sys::fs::AccessMode::Exist),
364 errc::no_such_file_or_directory);
366365
367366 SmallString<64> TempPath3;
368367 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3));
385384 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));
386385
387386 // Make sure Temp1 doesn't exist.
388 ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists));
389 EXPECT_FALSE(TempFileExists);
387 ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist),
388 errc::no_such_file_or_directory);
390389
391390 #ifdef LLVM_ON_WIN32
392391 // Path name > 260 chars should get an error.