Reparse point data that is used by the LazyCopy driver.
Exemple #1
0
        /// <summary>
        /// Creates a new <c>LazyCopy</c> file.
        /// </summary>
        /// <param name="path">Path to the reparse point to get data from.</param>
        /// <param name="fileData">Reparse file data to be set for the <paramref name="path"/>.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="path"/> is <see langword="null"/> or empty.
        ///     <para>-or-</para>
        /// <paramref name="fileData"/> is <see langword="null"/>.
        ///     <para>-or-</para>
        /// <paramref name="fileData"/> contains <see langword="null"/> or empty file path.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="fileData"/> contains negative file size.</exception>
        /// <exception cref="IOException">File cannot be created.</exception>
        /// <exception cref="InvalidOperationException">Reparse point data cannot be set.</exception>
        public static void CreateLazyCopyFile(string path, LazyCopyFileData fileData)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (fileData == null)
            {
                throw new ArgumentNullException(nameof(fileData));
            }

            if (string.IsNullOrEmpty(fileData.RemotePath))
            {
                throw new ArgumentNullException(nameof(fileData));
            }

            if (fileData.FileSize < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(fileData), fileData.FileSize, "File size is negative.");
            }

            string           normalizedPath = LongPathCommon.NormalizePath(path);
            LongPathFileInfo fileInfo       = new LongPathFileInfo(normalizedPath);

            bool shouldCreateFile = false;

            if (!fileInfo.Exists || fileInfo.Length > 0)
            {
                LongPathDirectory.CreateDirectory(fileInfo.DirectoryName);
                shouldCreateFile = true;
            }
            else if (!fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
            {
                shouldCreateFile = true;
            }
            else if (fileInfo.Attributes.HasFlag(FileAttributes.ReadOnly))
            {
                fileInfo.Attributes &= ~FileAttributes.ReadOnly;
            }

            if (shouldCreateFile)
            {
                using (fileInfo.Create())
                {
                    // Do nothing.
                }
            }

            // If the original file is empty, we don't need to set a reparse point for it.
            if (fileData.FileSize == 0)
            {
                return;
            }

            ReparsePointHelper.SetReparsePointData(
                path,
                new object[] // Custom serialization layout for the LazyCopyFileData object.
            {
                (long)(fileData.UseCustomHandler ? 1L : 0L),
                (long)fileData.FileSize,
                // Add the prefix, if the custom handling is needed for the file.
                Encoding.Unicode.GetBytes(
                    (fileData.UseCustomHandler ? fileData.RemotePath : PathHelper.ChangeDriveLetterToDeviceName(fileData.RemotePath))
                    + '\0')
            },
                LazyCopyFileHelper.LazyCopyReparseTag,
                LazyCopyFileHelper.LazyCopyReparseGuid);

            // Set the proper file attributes.
            LongPathCommon.SetAttributes(path, FileAttributes.ReparsePoint | FileAttributes.NotContentIndexed | FileAttributes.Offline);
        }
        /// <summary>
        /// Creates a new <c>LazyCopy</c> file.
        /// </summary>
        /// <param name="path">Path to the reparse point to get data from.</param>
        /// <param name="fileData">Reparse file data to be set for the <paramref name="path"/>.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="path"/> is <see langword="null"/> or empty.
        ///     <para>-or-</para>
        /// <paramref name="fileData"/> is <see langword="null"/>.
        ///     <para>-or-</para>
        /// <paramref name="fileData"/> contains <see langword="null"/> or empty file path.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="fileData"/> contains negative file size.</exception>
        /// <exception cref="IOException">File cannot be created.</exception>
        /// <exception cref="InvalidOperationException">Reparse point data cannot be set.</exception>
        public static void CreateLazyCopyFile(string path, LazyCopyFileData fileData)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (fileData == null)
            {
                throw new ArgumentNullException(nameof(fileData));
            }

            if (string.IsNullOrEmpty(fileData.RemotePath))
            {
                throw new ArgumentNullException(nameof(fileData));
            }

            if (fileData.FileSize < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(fileData), fileData.FileSize, "File size is negative.");
            }

            string normalizedPath     = LongPathCommon.NormalizePath(path);
            LongPathFileInfo fileInfo = new LongPathFileInfo(normalizedPath);

            bool shouldCreateFile = false;
            if (!fileInfo.Exists || fileInfo.Length > 0)
            {
                LongPathDirectory.CreateDirectory(fileInfo.DirectoryName);
                shouldCreateFile = true;
            }
            else if (!fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
            {
                shouldCreateFile = true;
            }
            else if (fileInfo.Attributes.HasFlag(FileAttributes.ReadOnly))
            {
                fileInfo.Attributes &= ~FileAttributes.ReadOnly;
            }

            if (shouldCreateFile)
            {
                using (fileInfo.Create())
                {
                    // Do nothing.
                }
            }

            // If the original file is empty, we don't need to set a reparse point for it.
            if (fileData.FileSize == 0)
            {
                return;
            }

            ReparsePointHelper.SetReparsePointData(
                path,
                new object[] // Custom serialization layout for the LazyCopyFileData object.
                {
                    (long)(fileData.UseCustomHandler ? 1L : 0L),
                    (long)fileData.FileSize,
                    // Add the prefix, if the custom handling is needed for the file.
                    Encoding.Unicode.GetBytes(
                        (fileData.UseCustomHandler ? fileData.RemotePath : PathHelper.ChangeDriveLetterToDeviceName(fileData.RemotePath))
                        + '\0')
                },
                LazyCopyFileHelper.LazyCopyReparseTag,
                LazyCopyFileHelper.LazyCopyReparseGuid);

            // Set the proper file attributes.
            LongPathCommon.SetAttributes(path, FileAttributes.ReparsePoint | FileAttributes.NotContentIndexed | FileAttributes.Offline);
        }