MCPcopy Create free account
hub / github.com/ddnet/ddnet / fs_remove

Function fs_remove

src/base/fs.cpp:526–584  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

524}
525
526int fs_remove(const char *filename)
527{
528#if defined(CONF_FAMILY_WINDOWS)
529 if(fs_is_dir(filename))
530 {
531 // Not great, but otherwise using this function on a folder would only rename the folder but fail to delete it.
532 return 1;
533 }
534 const std::wstring wide_filename = windows_utf8_to_wide(filename);
535
536 unsigned random_num;
537 secure_random_fill(&random_num, sizeof(random_num));
538 std::wstring wide_filename_temp;
539 do
540 {
541 char suffix[64];
542 str_format(suffix, sizeof(suffix), ".%08X.toberemoved", random_num);
543 wide_filename_temp = wide_filename + windows_utf8_to_wide(suffix);
544 ++random_num;
545 } while(GetFileAttributesW(wide_filename_temp.c_str()) != INVALID_FILE_ATTRIBUTES);
546
547 // The DeleteFileW function only marks the file for deletion but the deletion may not take effect immediately, which can
548 // cause subsequent operations using this filename to fail until all handles are closed. The MoveFileExW function with the
549 // MOVEFILE_WRITE_THROUGH flag is guaranteed to wait for the file to be moved on disk, so we first rename the file to be
550 // deleted to a random temporary name and then mark that for deletion, to ensure that the filename is usable immediately.
551 if(MoveFileExW(wide_filename.c_str(), wide_filename_temp.c_str(), MOVEFILE_WRITE_THROUGH) == 0)
552 {
553 const DWORD error = GetLastError();
554 if(error == ERROR_FILE_NOT_FOUND)
555 {
556 return 0; // Success: Renaming failed because the original file did not exist.
557 }
558 const std::string filename_temp = windows_wide_to_utf8(wide_filename_temp.c_str()).value_or("(invalid filename)");
559 log_error("filesystem", "Failed to rename file '%s' to '%s' for removal (%ld '%s')", filename, filename_temp.c_str(), error, windows_format_system_message(error).c_str());
560 return 1;
561 }
562 if(DeleteFileW(wide_filename_temp.c_str()) != 0)
563 {
564 return 0; // Success: Marked the renamed file for deletion successfully.
565 }
566 const DWORD error = GetLastError();
567 if(error == ERROR_FILE_NOT_FOUND)
568 {
569 return 0; // Success: Another process deleted the renamed file we were about to delete?!
570 }
571 const std::string filename_temp = windows_wide_to_utf8(wide_filename_temp.c_str()).value_or("(invalid filename)");
572 log_error("filesystem", "Failed to remove file '%s' (%ld '%s')", filename_temp.c_str(), error, windows_format_system_message(error).c_str());
573 // Success: While the temporary could not be deleted, this is also considered success because the original file does not exist anymore.
574 // Callers of this function expect that the original file does not exist anymore if and only if the function succeeded.
575 return 0;
576#else
577 if(unlink(filename) == 0 || errno == ENOENT)
578 {
579 return 0;
580 }
581 log_error("filesystem", "Failed to remove file '%s' (%d '%s')", filename, errno, strerror(errno));
582 return 1;
583#endif

Callers 15

ProcessFunction · 0.85
RemoveFileMethod · 0.85
RemoveBinaryFileMethod · 0.85
InitMethod · 0.85
ShutdownMethod · 0.85
OnCompletionInternalMethod · 0.85
OnValidationMethod · 0.85
InitAndroidFunction · 0.85
ExpectMethod · 0.85
TestFileReadFunction · 0.85
TestFileLengthFunction · 0.85
TESTFunction · 0.85

Calls 6

fs_is_dirFunction · 0.85
windows_utf8_to_wideFunction · 0.85
secure_random_fillFunction · 0.85
str_formatFunction · 0.85
windows_wide_to_utf8Function · 0.85

Tested by 9

ExpectMethod · 0.68
TestFileReadFunction · 0.68
TestFileLengthFunction · 0.68
TESTFunction · 0.68
~AsyncMethod · 0.68
ExpectFunction · 0.68
TestFileLineReaderRawFunction · 0.68
TESTFunction · 0.68