Example #1
0
        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");
            }
        }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <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);
        }
Example #6
0
        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;
        }
Example #9
0
        /// <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;
        }