public void CanGetVolumePath() { VolumeMap map = CreateMapOfAllLocalVolumes(); ulong thisVolumeSerial; SafeFileHandle directoryHandle; FileUtilities.TryOpenDirectory(TemporaryDirectory, FileShare.ReadWrite | FileShare.Delete, out directoryHandle); using (directoryHandle) { XAssert.IsNotNull(directoryHandle, "Failed to open the TemporaryDirectory, which we just created"); thisVolumeSerial = FileUtilities.GetVolumeSerialNumberByHandle(directoryHandle); } VolumeGuidPath volumePath = map.TryGetVolumePathBySerial(thisVolumeSerial); XAssert.IsTrue(volumePath.IsValid); var openResult = FileUtilities.TryOpenDirectory(volumePath.Path, FileShare.ReadWrite | FileShare.Delete, out directoryHandle); using (directoryHandle) { XAssert.IsTrue(openResult.Succeeded, "Failed to open the volume root (but we didn't ask for any access)"); XAssert.IsTrue(openResult.OpenedOrTruncatedExistingFile); XAssert.IsNotNull(directoryHandle); XAssert.AreEqual(thisVolumeSerial, FileUtilities.GetVolumeSerialNumberByHandle(directoryHandle), "The volume root path has the wrong volume serial"); } }
/// <summary> /// Creates a volume root handle or retrieves an existing one. /// </summary> /// <remarks> /// This is the un-synchronized get-or-add operation resulting in <see cref="VolumeAccessor"/> /// not being thread-safe. /// The returned handle should not be disposed. /// </remarks> private SafeFileHandle TryGetVolumeHandle(ulong volumeSerial) { SafeFileHandle volumeHandle; if (!m_volumeHandles.TryGetValue(volumeSerial, out volumeHandle)) { VolumeGuidPath volumeRootPath = m_map.TryGetVolumePathBySerial(volumeSerial); if (!volumeRootPath.IsValid) { return(null); } OpenFileResult openResult = FileUtilities.TryCreateOrOpenFile( volumeRootPath.GetDevicePath(), FileDesiredAccess.GenericRead, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.None, out volumeHandle); if (!openResult.Succeeded) { Contract.Assert(volumeHandle == null); return(null); } m_volumeHandles.Add(volumeSerial, volumeHandle); } return(volumeHandle); }
/// <summary> /// Creates a volume root handle or retrieves an existing one. /// </summary> /// <remarks> /// This is the un-synchronized get-or-add operation resulting in <see cref="FileAccessor"/> /// not being thread-safe. /// </remarks> private SafeFileHandle TryGetVolumeRoot(ulong volumeSerial) { SafeFileHandle volumeRootHandle; if (!m_volumeRootHandles.TryGetValue(volumeSerial, out volumeRootHandle)) { VolumeGuidPath volumeRootPath = m_map.TryGetVolumePathBySerial(volumeSerial); if (!volumeRootPath.IsValid) { return(null); } if ( !FileUtilities.TryOpenDirectory( volumeRootPath.Path, FileShare.ReadWrite | FileShare.Delete, out volumeRootHandle).Succeeded) { Contract.Assert(volumeRootHandle == null); return(null); } m_volumeRootHandles.Add(volumeSerial, volumeRootHandle); } return(volumeRootHandle); }
/// <summary> /// Deserializes into an instance of <see cref="VolumeMap"/>. /// </summary> public static VolumeMap Deserialize(BuildXLReader reader) { Contract.Requires(reader != null); var volumeMap = new VolumeMap(); int count = reader.ReadInt32Compact(); for (int i = 0; i < count; ++i) { ulong serialNumber = reader.ReadUInt64(); bool isValid = reader.ReadBoolean(); VolumeGuidPath path = isValid ? VolumeGuidPath.Create(reader.ReadString()) : VolumeGuidPath.Invalid; volumeMap.m_volumePathsBySerial.Add(serialNumber, path); } int numJunctionRoots = reader.ReadInt32Compact(); for (int i = 0; i < numJunctionRoots; ++i) { string path = reader.ReadString(); var id = FileIdAndVolumeId.Deserialize(reader); volumeMap.m_junctionRootFileIds.Add(path, id); } return(volumeMap); }
public static VolumeGuidPath ReadVolumeGuidPath(this ChangeJournalServiceProtocolReader reader) { Contract.Requires(reader != null); string maybePath = reader.ReadString(); VolumeGuidPath path; if (!VolumeGuidPath.TryCreate(maybePath, out path)) { throw new BuildXLException("Expected a volume GUID path"); } return(path); }
private OpenFileResult OpenVolumeHandle(VolumeGuidPath path, out SafeFileHandle volumeHandle) { Contract.Requires(path.IsValid); #pragma warning disable SA1114 // Parameter list must follow declaration return(FileUtilities.TryOpenDirectory( // Unprivileged and privileged read journal operations require different types of handles. // Do not ask why, this is learned after some painful experience :( IsJournalUnprivileged ? path.Path : path.GetDevicePath(), FileDesiredAccess.GenericRead, FileShare.ReadWrite | FileShare.Delete, FileFlagsAndAttributes.None, out volumeHandle)); }
public void CanGetFullGuidPathFromHandle() { List <Tuple <VolumeGuidPath, ulong> > volumePathsAndSerials = FileUtilities.ListVolumeGuidPathsAndSerials(); using (SafeFileHandle directoryHandle = OpenTemporaryDirectory()) { string directoryHandlePath = FileUtilities.GetFinalPathNameByHandle(directoryHandle, volumeGuidPath: true); XAssert.IsFalse(string.IsNullOrEmpty(directoryHandlePath)); XAssert.IsTrue(directoryHandlePath.StartsWith(@"\\?\"), "GUID paths must start with a long-path prefix"); XAssert.IsTrue(directoryHandlePath.EndsWith(Path.GetFileName(TemporaryDirectory)), "GUID path must end in the directory name (even if there are symlinks, mounted volumes, etc.)"); ulong serial = FileUtilities.GetVolumeSerialNumberByHandle(directoryHandle); VolumeGuidPath volumeGuidPath = volumePathsAndSerials.Single(t => t.Item2 == serial).Item1; XAssert.IsTrue(directoryHandlePath.ToCanonicalizedPath().StartsWith(volumeGuidPath.Path.ToCanonicalizedPath()), "GUID path fo the volume should be a prefix of the path to the directory"); } }
/// <nodoc /> public ReadJournalRequest( VolumeGuidPath volumeGuidPath, ulong journalId, Usn startUsn, Usn?endUsn = default(Usn?), int?extraReadCount = default(int?), TimeSpan?timeLimit = default(TimeSpan?)) { Contract.Requires(volumeGuidPath.IsValid); Contract.Requires(!extraReadCount.HasValue || extraReadCount >= 0); m_volumeGuidPath = volumeGuidPath; JournalId = journalId; StartUsn = startUsn; EndUsn = endUsn; ExtraReadCount = extraReadCount; TimeLimit = timeLimit; }
/// <summary> /// Deserializes into an instance of <see cref="VolumeMap"/>. /// </summary> public static VolumeMap Deserialize(BuildXLReader reader) { Contract.Requires(reader != null); var volumeMap = new VolumeMap(); int count = reader.ReadInt32Compact(); for (int i = 0; i < count; ++i) { ulong serialNumber = reader.ReadUInt64(); bool isValid = reader.ReadBoolean(); VolumeGuidPath path = isValid ? VolumeGuidPath.Create(reader.ReadString()) : VolumeGuidPath.Invalid; volumeMap.m_volumePathsBySerial.Add(serialNumber, path); } ReadDictionary(reader, volumeMap.m_junctionRootFileIds); ReadDictionary(reader, volumeMap.m_gvfsProjections); return(volumeMap); }
public static void WriteVolumeGuidPath(this ChangeJournalServiceProtocolWriter writer, VolumeGuidPath volumeGuidPath) { Contract.Requires(writer != null); Contract.Requires(volumeGuidPath.IsValid); writer.Write(volumeGuidPath.Path); }
/// <nodoc /> public QueryJournalRequest(VolumeGuidPath volumeGuidPath) { Contract.Requires(volumeGuidPath.IsValid); m_volumeGuidPath = volumeGuidPath; }