/// The file should be opened in append mode.
OF_Append = 4,
- /// Delete the file on close. Only makes a difference on windows.
+ /// The returned handle can be used for deleting the file. Only makes a
+ /// difference on windows.
OF_Delete = 8,
/// When a child process is launched, this file should remain open in the
// The open file descriptor.
int FD = -1;
+#ifdef _WIN32
+ // Whether we need to manually remove the file on close.
+ bool RemoveOnClose = false;
+#endif
+
// Keep this with the given name.
Error keep(const Twine &Name);
FD = Other.FD;
Other.Done = true;
Other.FD = -1;
+#ifdef _WIN32
+ RemoveOnClose = Other.RemoveOnClose;
+ Other.RemoveOnClose = false;
+#endif
return *this;
}
FD = -1;
#ifdef _WIN32
- // On windows closing will remove the file.
- TmpName = "";
- return Error::success();
+ // On Windows, closing will remove the file, if we set the delete
+ // disposition. If not, remove it manually.
+ bool Remove = RemoveOnClose;
#else
- // Always try to close and remove.
+ // Always try to remove the file.
+ bool Remove = true;
+#endif
std::error_code RemoveEC;
- if (!TmpName.empty()) {
+ if (Remove && !TmpName.empty()) {
RemoveEC = fs::remove(TmpName);
+#ifndef _WIN32
sys::DontRemoveFileOnSignal(TmpName);
+#endif
if (!RemoveEC)
TmpName = "";
+ } else {
+ TmpName = "";
}
return errorCodeToError(RemoveEC);
-#endif
}
Error TempFile::keep(const Twine &Name) {
// If we can't cancel the delete don't rename.
auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
std::error_code RenameEC = setDeleteDisposition(H, false);
+ bool ShouldDelete = false;
if (!RenameEC) {
RenameEC = rename_handle(H, Name);
// If rename failed because it's cross-device, copy instead
if (RenameEC ==
std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) {
RenameEC = copy_file(TmpName, Name);
- setDeleteDisposition(H, true);
+ ShouldDelete = true;
}
}
- // If we can't rename, discard the temporary file.
+ // If we can't rename or copy, discard the temporary file.
if (RenameEC)
- setDeleteDisposition(H, true);
+ ShouldDelete = true;
+ if (ShouldDelete) {
+ if (!RemoveOnClose)
+ setDeleteDisposition(H, true);
+ else
+ remove(TmpName);
+ }
#else
std::error_code RenameEC = fs::rename(TmpName, Name);
if (RenameEC) {
return errorCodeToError(EC);
TempFile Ret(ResultPath, FD);
-#ifndef _WIN32
+#ifdef _WIN32
+ auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
+ if (std::error_code EC = setDeleteDisposition(H, true)) {
+ Ret.RemoveOnClose = true;
+ }
+#else
if (sys::RemoveFileOnSignal(ResultPath)) {
// Make sure we delete the file when RemoveFileOnSignal fails.
consumeError(Ret.discard());
// Check if the file is on a network (non-local) drive. If so, don't
// continue when DeleteFile is true, since it prevents opening the file for
- // writes. Note -- this will leak temporary files on disk, but only when the
- // target file is on a network drive.
+ // writes.
SmallVector<wchar_t, 128> FinalPath;
if (std::error_code EC = realPathFromHandle(Handle, FinalPath))
return EC;
return EC;
if (!IsLocal)
- return std::error_code();
+ return errc::not_supported;
// The file is on a local drive, we can safely set FILE_DISPOSITION_INFO's
// flag.
}
}
- if (Flags & OF_Delete) {
- if ((EC = setDeleteDisposition(Result, true))) {
- ::CloseHandle(Result);
- return errorCodeToError(EC);
- }
- }
return Result;
}