Status: Fixed The implementation is a mix of the the three mentioned methods (issue #247). There is a commandline option called --open-file-policy, which can be set to "ignore", "snapshot" or "copy". The "ignore" setting does the same as previous version, simply exclude the file from the backup set. If the setting is either "snapshot" or "copy", and the file it locked, it is opened in non-excusive read mode. Once open, a in-memory signature file is generated. This is compared to the previous signature to detect changes, just as the normal operation. If the file has not changed, the file is skipped as it would normally be. If the file has changed and the policy is "snapshot", the file will be processed as normal, but during the file read, a new signature is generated. This new signature is stored in the signature archives. When writing the new signature, it is compared to the original signature. If the file has changed during the backup operation, a warning is written to the output log. If the policy was set to "copy", the modified file is copied to a temporary location, while a new signature is generated. If the copy fails due to a file change, the file is omitted from the backup set. If the copy succeeds, the file is known to not have changed during the first access and the copy, which gives some assurance that the file is not actively being written, at the expense of a copy operation. The default setting is "snapshot", because this is likely to work in most scenarios, and potentially produces a broken file rather than guarantee a missing file (by "ignore"). Note that when reading an open file, there is always a chance that the file is being written, so you may end up with a broken file in the backup. This is also true for the VSS and LVM snapshots, except for VSS-aware applications. The "copy" method is meant to minimize this risk, but there is no guarantee that the file is in an acceptable state, just because it has not been written for any period. git-svn-id: https://duplicati.googlecode.com/svn/trunk@588 59da171f-624f-0410-aa54-27559c288bec
105 lines
4.4 KiB
C#
105 lines
4.4 KiB
C#
#region Disclaimer / License
|
|
// Copyright (C) 2010, Kenneth Skovhede
|
|
// http://www.hexad.dk, opensource@hexad.dk
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
//
|
|
#endregion
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Duplicati.Library.SharpRSync
|
|
{
|
|
public static class Utility
|
|
{
|
|
/// <summary>
|
|
/// Some streams can return a number that is less than the requested number of bytes.
|
|
/// This is usually due to fragmentation, and is solved by issuing a new read.
|
|
/// This function wraps that functionality.
|
|
/// </summary>
|
|
/// <param name="stream">The stream to read</param>
|
|
/// <param name="buf">The buffer to read into</param>
|
|
/// <returns>The actual number of bytes read</returns>
|
|
public static int ForceStreamRead(System.IO.Stream stream, byte[] buf)
|
|
{
|
|
return ForceStreamRead(stream, buf, 0, buf.Length);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Some streams can return a number that is less than the requested number of bytes.
|
|
/// This is usually due to fragmentation, and is solved by issuing a new read.
|
|
/// This function wraps that functionality.
|
|
/// </summary>
|
|
/// <param name="stream">The stream to read</param>
|
|
/// <param name="buf">The buffer to read into</param>
|
|
/// <param name="count">The amout of bytes to read</param>
|
|
/// <returns>The actual number of bytes read</returns>
|
|
public static int ForceStreamRead(System.IO.Stream stream, byte[] buf, int count)
|
|
{
|
|
return ForceStreamRead(stream, buf, 0, count);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Some streams can return a number that is less than the requested number of bytes.
|
|
/// This is usually due to fragmentation, and is solved by issuing a new read.
|
|
/// This function wraps that functionality.
|
|
/// </summary>
|
|
/// <param name="stream">The stream to read</param>
|
|
/// <param name="buf">The buffer to read into</param>
|
|
/// <param name="index">The index into which the writing starts</param>
|
|
/// <param name="count">The amout of bytes to read</param>
|
|
/// <returns>The actual number of bytes read</returns>
|
|
public static int ForceStreamRead(System.IO.Stream stream, byte[] buf, int index, int count)
|
|
{
|
|
//Non fragmenting streams skip here
|
|
if (stream is System.IO.FileStream || stream is System.IO.MemoryStream)
|
|
return stream.Read(buf, index, count);
|
|
|
|
int a;
|
|
int read = 0;
|
|
do
|
|
{
|
|
a = stream.Read(buf, index, count);
|
|
index += a;
|
|
read += a;
|
|
count -= a;
|
|
}
|
|
while (a != 0 && count > 0);
|
|
|
|
return read;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies a number of bytes from one stream into another.
|
|
/// </summary>
|
|
/// <param name="input">The stream to read from</param>
|
|
/// <param name="output">The stream to write to</param>
|
|
/// <param name="count">The number of bytes to copy</param>
|
|
public static void StreamCopy(System.IO.Stream input, System.IO.Stream output, long count)
|
|
{
|
|
byte[] buf = new byte[4096];
|
|
while (count > 0)
|
|
{
|
|
int a = input.Read(buf, 0, (int)Math.Min(count, buf.Length));
|
|
if (a <= 0)
|
|
throw new Exception(Strings.Utility.UnexpectedEndOfStreamError);
|
|
output.Write(buf, 0, a);
|
|
count -= a;
|
|
}
|
|
}
|
|
}
|
|
}
|