public void ReplaceFileContentAndExtendedAttributes() { this.SkipIfExtendedAttributesAreNotAvailable(); string sourceFile = "source"; string targetFile = "target"; string backupFile = "source.bak"; IFileInfo sourceInfo = Factory.CreateFileInfo(Path.Combine(this.testFolder.FullName, sourceFile)); IFileInfo targetInfo = Factory.CreateFileInfo(Path.Combine(this.testFolder.FullName, targetFile)); IFileInfo backupInfo = Factory.CreateFileInfo(Path.Combine(this.testFolder.FullName, backupFile)); using (var stream = sourceInfo.Open(FileMode.CreateNew, FileAccess.Write)) { stream.Write(new byte[2], 0, 2); } sourceInfo.SetExtendedAttribute("test", sourceFile, false); sourceInfo.Refresh(); using (var stream = targetInfo.Open(FileMode.CreateNew, FileAccess.Write)) { stream.Write(new byte[5], 0, 5); } targetInfo.SetExtendedAttribute("test", targetFile, false); targetInfo.Refresh(); var newFileInfo = sourceInfo.Replace(targetInfo, backupInfo, true); Assert.That(newFileInfo.GetExtendedAttribute("test"), Is.EqualTo(sourceFile)); backupInfo.Refresh(); Assert.That(backupInfo.Exists, Is.True); Assert.That(backupInfo.GetExtendedAttribute("test"), Is.EqualTo(targetFile)); }
/// <summary> /// Replaces the contents of a specified destinationFile with the file described by the current IFileInfo /// object, deleting the original file, and creating a backup of the replaced file. /// Also specifies whether to ignore merge errors. /// </summary> /// <param name="destinationFile">Destination file.</param> /// <param name="destinationBackupFileName">Destination backup file name.</param> /// <param name="ignoreMetadataErrors"><c>true</c> to ignore merge errors (such as attributes and ACLs) from the replaced file to the replacement file; otherwise <c>false</c>.</param> /// <returns>A IFileInfo object that encapsulates information about the file described by the destFileName parameter.</returns> public IFileInfo Replace(IFileInfo destinationFile, IFileInfo destinationBackupFileName, bool ignoreMetadataErrors) { #if __MonoCS__ var reader = new ExtendedAttributeReaderUnix(); var oldSourceEAs = new Dictionary <string, string>(); var oldTargetEAs = new Dictionary <string, string>(); if (reader.IsFeatureAvailable(this.FullName)) { foreach (var key in reader.ListAttributeKeys(this.FullName)) { oldSourceEAs.Add(key, this.GetExtendedAttribute(key)); } foreach (var key in reader.ListAttributeKeys(destinationFile.FullName)) { oldTargetEAs.Add(key, destinationFile.GetExtendedAttribute(key)); } } #endif var result = new FileInfoWrapper(this.original.Replace(destinationFile.FullName, destinationBackupFileName.FullName, ignoreMetadataErrors)); #if __MonoCS__ foreach (var entry in oldSourceEAs) { result.SetExtendedAttribute(entry.Key, entry.Value, true); } foreach (var entry in oldTargetEAs) { destinationBackupFileName.SetExtendedAttribute(entry.Key, entry.Value, true); } #endif return(result); }
/// <summary> /// Replaces the contents of a specified destinationFile with the file described by the current IFileInfo /// object, deleting the original file, and creating a backup of the replaced file. /// Also specifies whether to ignore merge errors. /// </summary> /// <param name="destinationFile">Destination file.</param> /// <param name="destinationBackupFileName">Destination backup file name.</param> /// <param name="ignoreMetadataErrors"><c>true</c> to ignore merge errors (such as attributes and ACLs) from the replaced file to the replacement file; otherwise <c>false</c>.</param> /// <returns>A IFileInfo object that encapsulates information about the file described by the destFileName parameter.</returns> public IFileInfo Replace(IFileInfo destinationFile, IFileInfo destinationBackupFileName, bool ignoreMetadataErrors) { #if __MonoCS__ var reader = new ExtendedAttributeReaderUnix(); var oldSourceEAs = new Dictionary<string, string>(); var oldTargetEAs = new Dictionary<string, string>(); if (reader.IsFeatureAvailable(this.FullName)) { foreach (var key in reader.ListAttributeKeys(this.FullName)) { oldSourceEAs.Add(key, this.GetExtendedAttribute(key)); } foreach (var key in reader.ListAttributeKeys(destinationFile.FullName)) { oldTargetEAs.Add(key, destinationFile.GetExtendedAttribute(key)); } } #else try { #endif var result = new FileInfoWrapper(this.original.Replace(destinationFile.FullName, destinationBackupFileName.FullName, ignoreMetadataErrors)); #if __MonoCS__ foreach (var entry in oldSourceEAs) { result.SetExtendedAttribute(entry.Key, entry.Value, true); } foreach (var entry in oldTargetEAs) { destinationBackupFileName.SetExtendedAttribute(entry.Key, entry.Value, true); } return result; #else return result; } catch (IOException ex) { int error = Marshal.GetHRForException(ex) & 0xffff; if (error == 1176) { string newName = destinationFile.FullName + Guid.NewGuid().ToString() + ".sync"; IFileInfo newResult = null; try { var copy = this.original.CopyTo(newName, true); newResult = new FileInfoWrapper(copy.Replace(destinationFile.FullName, destinationBackupFileName.FullName, ignoreMetadataErrors)); this.Delete(); return newResult; } catch (Exception) { } finally { if (File.Exists(newName)) { File.Delete(newName); } } throw; } else { throw; } } #endif }
/// <summary> /// Replaces the contents of a specified destinationFile with the file described by the current IFileInfo /// object, deleting the original file, and creating a backup of the replaced file. /// Also specifies whether to ignore merge errors. /// </summary> /// <param name="destinationFile">Destination file.</param> /// <param name="destinationBackupFileName">Destination backup file name.</param> /// <param name="ignoreMetadataErrors"><c>true</c> to ignore merge errors (such as attributes and ACLs) from the replaced file to the replacement file; otherwise <c>false</c>.</param> /// <returns>A IFileInfo object that encapsulates information about the file described by the destFileName parameter.</returns> public IFileInfo Replace(IFileInfo destinationFile, IFileInfo destinationBackupFileName, bool ignoreMetadataErrors) { #if __MonoCS__ var reader = new ExtendedAttributeReaderUnix(); var oldSourceEAs = new Dictionary <string, string>(); var oldTargetEAs = new Dictionary <string, string>(); if (reader.IsFeatureAvailable(this.FullName)) { foreach (var key in reader.ListAttributeKeys(this.FullName)) { oldSourceEAs.Add(key, this.GetExtendedAttribute(key)); } foreach (var key in reader.ListAttributeKeys(destinationFile.FullName)) { oldTargetEAs.Add(key, destinationFile.GetExtendedAttribute(key)); } } #else try { #endif var result = new FileInfoWrapper(this.original.Replace(destinationFile.FullName, destinationBackupFileName.FullName, ignoreMetadataErrors)); #if __MonoCS__ foreach (var entry in oldSourceEAs) { result.SetExtendedAttribute(entry.Key, entry.Value, true); } foreach (var entry in oldTargetEAs) { destinationBackupFileName.SetExtendedAttribute(entry.Key, entry.Value, true); } return(result); #else return(result); } catch (IOException ex) { int error = Marshal.GetHRForException(ex) & 0xffff; if (error == 1176) { string newName = destinationFile.FullName + Guid.NewGuid().ToString() + ".sync"; IFileInfo newResult = null; try { var copy = this.original.CopyTo(newName, true); newResult = new FileInfoWrapper(copy.Replace(destinationFile.FullName, destinationBackupFileName.FullName, ignoreMetadataErrors)); this.Delete(); return(newResult); } catch (Exception) { } finally { if (File.Exists(newName)) { File.Delete(newName); } } throw; } else { throw; } } #endif }