/// <summary> /// Constructs a new USN helper instance /// </summary> /// <param name="volumeRoot">The root volume where the USN lookup is performed</param> internal USNJournal(string volumeRoot) { if (Utility.Utility.IsClientLinux) { throw new Interface.UserInformationException(Strings.USNHelper.LinuxNotSupportedError, "UsnOnLinuxNotSupported"); } m_volume = Utility.Utility.AppendDirSeparator(volumeRoot); try { var device = GetDeviceNameFromPath(m_volume); m_volumeHandle = Win32USN.CreateFile(device, Win32USN.FileAccess.GenericRead, Win32USN.FileShare.ReadWrite, IntPtr.Zero, Win32USN.CreationDisposition.OpenExisting, Win32USN.FileAttributes.BackupSemantics, IntPtr.Zero); if (m_volumeHandle == null || m_volumeHandle.IsInvalid) { throw new Win32Exception(Marshal.GetLastWin32Error()); } Win32USN.ControlWithOutput(m_volumeHandle, Win32USN.FsCtl.QueryUSNJournal, ref m_journal); m_volumeRootRefNumber = GetFileRefNumber(volumeRoot); } catch { Dispose(); throw; } }
/// <summary> /// Constructs a new USN helper instance /// </summary> /// <param name="path">The path to the folder to perform USN services</param> /// <param name="volumeRoot">The root volume where the USN lookup is performed</param> internal USNHelper(string path, string volumeRoot) { if (Utility.Utility.IsClientLinux) { throw new Duplicati.Library.Interface.UserInformationException(Strings.USNHelper.LinuxNotSupportedError, "UsnOnLinuxNotSupported"); } if (!System.IO.Path.IsPathRooted(path)) { throw new Exception(string.Format("Path {0} is not rooted", path)); } m_path = Utility.Utility.AppendDirSeparator(path); try { string devicename = @"\\.\" + System.IO.Path.GetPathRoot(path).TrimEnd('\\'); if (volumeRoot != null) { volumeRoot = volumeRoot.TrimEnd('\\'); } m_volumeHandle = Win32USN.CreateFile(volumeRoot == null ? devicename : volumeRoot, Win32USN.EFileAccess.GenericRead, Win32USN.EFileShare.ReadWrite, IntPtr.Zero, Win32USN.ECreationDisposition.OpenExisting, Win32USN.EFileAttributes.BackupSemantics, IntPtr.Zero); if (m_volumeHandle == null || m_volumeHandle.IsInvalid) { throw new Win32Exception(Marshal.GetLastWin32Error()); } uint bytesReturned = 0; if (!Win32USN.DeviceIoControl(m_volumeHandle, Win32USN.EIOControlCode.FsctlQueryUsnJournal, null, 0, out m_journal, (uint)Marshal.SizeOf(typeof(Win32USN.USN_JOURNAL_DATA)), ref bytesReturned, IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } Win32USN.BY_HANDLE_FILE_INFORMATION fileInfo; using (SafeFileHandle driveHandle = Win32USN.CreateFile(System.IO.Path.GetPathRoot(path), Win32USN.EFileAccess.GenericRead, Win32USN.EFileShare.ReadWrite, IntPtr.Zero, Win32USN.ECreationDisposition.OpenExisting, Win32USN.EFileAttributes.BackupSemantics, IntPtr.Zero)) if (!Win32USN.GetFileInformationByHandle(driveHandle, out fileInfo)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } m_volumeRootFileNameReferenceNumber = ((ulong)fileInfo.FileIndexHigh << 32) | ((ulong)fileInfo.FileIndexLow); } catch { if (m_volumeHandle != null) { m_volumeHandle.Dispose(); m_volumeHandle = null; } throw; } if (this.FileSystemEntries.Count == 0) { throw new Exception(Strings.USNHelper.SafeGuardError); } }
/// <summary> /// Get NTFS file reference number (FRN) from path /// </summary> /// <param name="filePath">Input path</param> /// <returns>NTFS file reference number</returns> private static ulong GetFileRefNumber(string filePath) { Win32USN.BY_HANDLE_FILE_INFORMATION fileInfo; using (var driveHandle = Win32USN.CreateFile(filePath, Win32USN.FileAccess.GenericRead, Win32USN.FileShare.ReadWrite, IntPtr.Zero, Win32USN.CreationDisposition.OpenExisting, Win32USN.FileAttributes.BackupSemantics, IntPtr.Zero)) { if (!Win32USN.GetFileInformationByHandle(driveHandle, out fileInfo)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } return(((ulong)fileInfo.FileIndexHigh << 32) | fileInfo.FileIndexLow); }