Esempio n. 1
0
        /// <summary>
        /// This sample application accepts two input parameters:
        /// * source file - file with actual data which content should be copied to the target file, when it's opened.
        /// * target file - empty file to be created. When this file is opened, its contents are downloaded from the source file.
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            if (args.Length != 2 || string.IsNullOrEmpty(args[0]) || string.IsNullOrEmpty(args[1]))
            {
                Console.Out.WriteLine("sampleclient.exe \"<source_file_with_data>\" \"<local_file>\"");
                return;
            }

            string sourceFileName = args[0].Trim();
            string targetFileName = args[1].Trim();
            var targetFile        = new LongPathFileInfo(targetFileName);

            if (sourceFileName.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || sourceFileName.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
            {
                LazyCopyFileHelper.CreateLazyCopyFile(targetFile.FullName, new LazyCopyFileData { RemotePath = sourceFileName, FileSize = 404, UseCustomHandler = true });
            }
            else
            {
                var sourceFile = new LongPathFileInfo(sourceFileName);
                if (!sourceFile.Exists)
                {
                    Console.Out.WriteLine("Source file doesn't exist: " + sourceFile);
                    return;
                }

                LazyCopyFileHelper.CreateLazyCopyFile(targetFile.FullName, new LazyCopyFileData { RemotePath = sourceFile.FullName, FileSize = sourceFile.Length });
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Copies the <paramref name="sourceFileInfo"/> to the <paramref name="targetFileInfo"/>.
        /// </summary>
        /// <param name="sourceFileInfo">Source file to be copied.</param>
        /// <param name="targetFileInfo">Target file.</param>
        /// <returns><see langword="true"/>, if the file was created or overwritten; <see langword="false"/>, if the file was skipped.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="sourceFileInfo"/> or <paramref name="targetFileInfo"/> is <see langword="null"/>.</exception>
        /// <exception cref="FileNotFoundException"><paramref name="sourceFileInfo"/> does not exist.</exception>
        public static bool CopyFile(LongPathFileInfo sourceFileInfo, LongPathFileInfo targetFileInfo)
        {
            if (sourceFileInfo == null)
            {
                throw new ArgumentNullException(nameof(sourceFileInfo));
            }

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

            // Will throw an exception, if the source file does not exist.
            if (sourceFileInfo.Match(targetFileInfo))
            {
                return false;
            }

            LongPathDirectory.CreateDirectory(targetFileInfo.DirectoryName);
            sourceFileInfo.CopyTo(targetFileInfo.FullName, true);

            LongPathCommon.SetAttributes(targetFileInfo.FullName, FileAttributes.Normal);
            LongPathCommon.SetTimestamps(targetFileInfo.FullName, sourceFileInfo.CreationTime, sourceFileInfo.LastAccessTime, sourceFileInfo.LastWriteTime);

            return true;
        }
Esempio n. 3
0
        /// <summary>
        /// Checks whether two files have the same size and timestamps.
        /// </summary>
        /// <param name="file1">First file info.</param>
        /// <param name="file2">Second file info.</param>
        /// <returns>Whether or not the files are likely the same.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="file1"/> or <paramref name="file2"/> is <see langword="null"/>.</exception>
        /// <exception cref="FileNotFoundException"><paramref name="file1"/> file does not exist.</exception>
        public static bool Match(this LongPathFileInfo file1, LongPathFileInfo file2)
        {
            if (file1 == null)
            {
                throw new ArgumentNullException(nameof(file1));
            }

            if (!file1.Exists)
            {
                throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, "File file does not exist: {0}", file1.FullName));
            }

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

            return file2.Exists
                && file1.Length           == file2.Length
                && file1.CreationTimeUtc  == file2.CreationTimeUtc
                && file1.LastWriteTimeUtc == file2.LastWriteTimeUtc;
        }
Esempio n. 4
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);
        }
Esempio n. 5
0
        /// <summary>
        /// Gets the LazyCopy reparse data from the <paramref name="path"/> given.
        /// </summary>
        /// <param name="path">Path to the file to get the reparse data from.</param>
        /// <returns>
        /// Reparse data found or <see langword="null"/>, if it's not set.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="path"/> is <see langword="null"/> or empty.</exception>
        /// <exception cref="IOException">File cannot be opened.</exception>
        /// <exception cref="InvalidOperationException">Reparse point data cannot be retrieved.</exception>
        public static LazyCopyFileData GetReparseData(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            string normalizedPath     = LongPathCommon.NormalizePath(path);
            LongPathFileInfo fileInfo = new LongPathFileInfo(normalizedPath);
            if (!fileInfo.Exists || !fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint))
            {
                return null;
            }

            try
            {
                LazyCopyReparseData data = ReparsePointHelper.GetReparsePointData<LazyCopyReparseData>(path, LazyCopyFileHelper.LazyCopyReparseTag, LazyCopyFileHelper.LazyCopyReparseGuid);
                bool useCustomHandler    = data.UseCustomHandler > 0;

                return new LazyCopyFileData
                {
                    UseCustomHandler = useCustomHandler,
                    FileSize         = data.FileSize,
                    RemotePath       = useCustomHandler ? data.RemotePath : PathHelper.ChangeDeviceNameToDriveLetter(data.RemotePath)
                };
            }
            catch (InvalidOperationException)
            {
                return null;
            }
        }