Merge pull request #395 from NextTurn/move

Implement atomic file movement
pull/385/head
Oleg Nenashev 2020-02-10 05:40:36 -05:00 committed by GitHub
commit ad329b60ca
4 changed files with 50 additions and 19 deletions

View File

@ -106,7 +106,7 @@ namespace winsw
continue; continue;
} }
CopyFile(tokens[0], tokens[1]); MoveFile(tokens[0], tokens[1]);
} }
} }
finally finally
@ -118,16 +118,15 @@ namespace winsw
/// <summary> /// <summary>
/// File replacement. /// File replacement.
/// </summary> /// </summary>
private void CopyFile(string sourceFileName, string destFileName) private void MoveFile(string sourceFileName, string destFileName)
{ {
try try
{ {
File.Delete(destFileName); FileHelper.MoveOrReplaceFile(sourceFileName, destFileName);
File.Move(sourceFileName, destFileName);
} }
catch (IOException e) catch (IOException e)
{ {
LogEvent("Failed to copy :" + sourceFileName + " to " + destFileName + " because " + e.Message); LogEvent("Failed to move :" + sourceFileName + " to " + destFileName + " because " + e.Message);
} }
} }

View File

@ -181,14 +181,7 @@ namespace winsw
#endif #endif
} }
#if NETCOREAPP FileHelper.MoveOrReplaceFile(To + ".tmp", To);
File.Move(tmpFilePath, To, true);
#else
if (File.Exists(To))
File.Delete(To);
File.Move(tmpFilePath, To);
#endif
} }
#if NET20 #if NET20

View File

@ -8,6 +8,7 @@ using System.Threading;
#if !VNEXT #if !VNEXT
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
#endif #endif
using winsw.Util;
namespace winsw namespace winsw
{ {
@ -52,16 +53,15 @@ namespace winsw
/// <summary> /// <summary>
/// File replacement. /// File replacement.
/// </summary> /// </summary>
protected void CopyFile(string sourceFileName, string destFileName) protected void MoveFile(string sourceFileName, string destFileName)
{ {
try try
{ {
File.Delete(destFileName); FileHelper.MoveOrReplaceFile(sourceFileName, destFileName);
File.Move(sourceFileName, destFileName);
} }
catch (IOException e) catch (IOException e)
{ {
EventLogger.LogEvent("Failed to copy :" + sourceFileName + " to " + destFileName + " because " + e.Message); EventLogger.LogEvent("Failed to move :" + sourceFileName + " to " + destFileName + " because " + e.Message);
} }
} }
} }
@ -286,10 +286,10 @@ namespace winsw
public override void log(StreamReader outputReader, StreamReader errorReader) public override void log(StreamReader outputReader, StreamReader errorReader)
{ {
if (!OutFileDisabled) if (!OutFileDisabled)
CopyFile(OutputLogFileName, OutputLogFileName + ".old"); MoveFile(OutputLogFileName, OutputLogFileName + ".old");
if (!ErrFileDisabled) if (!ErrFileDisabled)
CopyFile(ErrorLogFileName, ErrorLogFileName + ".old"); MoveFile(ErrorLogFileName, ErrorLogFileName + ".old");
base.log(outputReader, errorReader); base.log(outputReader, errorReader);
} }

View File

@ -0,0 +1,39 @@
#if !NETCOREAPP
using System.ComponentModel;
#endif
using System.IO;
#if !NETCOREAPP
using System.Runtime.InteropServices;
#endif
namespace winsw.Util
{
public static class FileHelper
{
public static void MoveOrReplaceFile(string sourceFileName, string destFileName)
{
#if NETCOREAPP
File.Move(sourceFileName, destFileName, true);
#else
string sourceFilePath = Path.GetFullPath(sourceFileName);
string destFilePath = Path.GetFullPath(destFileName);
if (!NativeMethods.MoveFileEx(sourceFilePath, destFilePath, NativeMethods.MOVEFILE_REPLACE_EXISTING | NativeMethods.MOVEFILE_COPY_ALLOWED))
{
throw new Win32Exception();
}
#endif
}
#if !NETCOREAPP
private static class NativeMethods
{
internal const uint MOVEFILE_REPLACE_EXISTING = 0x01;
internal const uint MOVEFILE_COPY_ALLOWED = 0x02;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "MoveFileExW")]
internal static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, uint dwFlags);
}
#endif
}
}