Exemple #1
0
            public async Task DoMainAsync(ProgressReporterBase r, string dirName)
            {
                await ProcessDirectoryAsync(r, dirName);

                r.ReportProgress(new ProgressData(TotalReadSize));

                Con.WriteLine($"Finished!  TotalReadSize = {TotalReadSize._ToString3()}, TotalReadNum = {TotalReadNum._ToString3()}, TotalErrorNum = {TotalErrorNum._ToString3()}");
            }
Exemple #2
0
            async Task ProcessDirectoryAsync(ProgressReporterBase r, string dirName)
            {
                var entities = await Lfs.EnumDirectoryAsync(dirName, false, EnumDirectoryFlags.None);

                foreach (var file in entities.Where(x => x.IsFile && x.IsSymbolicLink == false))
                {
                    TotalReadNum++;

                    try
                    {
                        //Con.WriteLine($"File '{file.FullPath}'");

                        using (var f = Lfs.Open(file.FullPath))
                        {
                            while (true)
                            {
                                int readSize = await f.ReadAsync(this.TmpBuffer);

                                if (readSize == 0)
                                {
                                    break;
                                }

                                TotalReadSize += readSize;

                                r.ReportProgress(new ProgressData(TotalReadSize));
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Con.WriteError($"Reading the file '{file.FullPath}' error. {ex.Message}");
                        TotalErrorNum++;
                    }
                }

                foreach (var dir in entities.Where(x => x.IsDirectory && x.Attributes.Bit(FileAttributes.ReparsePoint) == false && x.IsSymbolicLink == false))
                {
                    try
                    {
                        //Con.WriteLine($"Directory '{dir.FullPath}'");

                        await ProcessDirectoryAsync(r, dir.FullPath);
                    }
                    catch (Exception ex)
                    {
                        Con.WriteError($"Processing the directory '{dir.FullPath}' error. {ex.Message}");
                    }
                }
            }
Exemple #3
0
        public static async Task CopyFileAsync(FileSystem srcFileSystem, string srcPath, FileSystem destFileSystem, string destPath,
                                               CopyFileParams?param = null, object?state = null, CancellationToken cancel = default, RefBool?readErrorIgnored = null)
        {
            if (readErrorIgnored == null)
            {
                readErrorIgnored = new RefBool(false);
            }

            readErrorIgnored.Set(false);

            if (param == null)
            {
                param = new CopyFileParams();
            }

            srcPath = await srcFileSystem.NormalizePathAsync(srcPath, cancel : cancel);

            destPath = await destFileSystem.NormalizePathAsync(destPath, cancel : cancel);

            if (srcFileSystem == destFileSystem)
            {
                if (srcFileSystem.PathParser.PathStringComparer.Equals(srcPath, destPath))
                {
                    throw new FileException(destPath, "Both source and destination is the same file.");
                }
            }

            using (ProgressReporterBase reporter = param.ProgressReporterFactory.CreateNewReporter($"CopyFile '{srcFileSystem.PathParser.GetFileName(srcPath)}'", state))
            {
                using (var srcFile = await srcFileSystem.OpenAsync(srcPath, flags: param.Flags, cancel: cancel))
                {
                    try
                    {
                        FileMetadata srcFileMetadata = await srcFileSystem.GetFileMetadataAsync(srcPath, param.MetadataCopier.OptimizedMetadataGetFlags, cancel);

                        bool destFileExists = await destFileSystem.IsFileExistsAsync(destPath, cancel);

                        using (var destFile = await destFileSystem.CreateAsync(destPath, flags: param.Flags, doNotOverwrite: !param.Overwrite, cancel: cancel))
                        {
                            try
                            {
                                reporter.ReportProgress(new ProgressData(0, srcFileMetadata.Size));

                                Ref <uint> srcZipCrc = new Ref <uint>();

                                long copiedSize = await CopyBetweenFileBaseAsync(srcFile, destFile, param, reporter, srcFileMetadata.Size, cancel, readErrorIgnored, srcZipCrc);

                                if (param.Flags.Bit(FileFlags.CopyFile_Verify) && param.IgnoreReadError == false)
                                {
                                    // Verify を実施する
                                    // キャッシュを無効にするため、一度ファイルを閉じて再度開く

                                    await destFile.CloseAsync();

                                    using (var destFile2 = await destFileSystem.OpenAsync(destPath, flags: param.Flags, cancel: cancel))
                                    {
                                        uint destZipCrc = await CalcZipCrc32HandleAsync(destFile2, param, cancel);

                                        if (srcZipCrc.Value != destZipCrc)
                                        {
                                            // なんと Verify に失敗したぞ
                                            throw new CoresException($"CopyFile_Verify error. Src file: '{srcPath}', Dest file: '{destPath}', srcCrc: {srcZipCrc.Value}, destCrc = {destZipCrc}");
                                        }
                                    }
                                }

                                reporter.ReportProgress(new ProgressData(copiedSize, copiedSize, true));

                                await destFile.CloseAsync();

                                try
                                {
                                    await destFileSystem.SetFileMetadataAsync(destPath, param.MetadataCopier.Copy(srcFileMetadata), cancel);
                                }
                                catch (Exception ex)
                                {
                                    Con.WriteDebug($"CopyFileAsync: '{destPath}': SetFileMetadataAsync failed. Error: {ex.Message}");
                                }
                            }
                            catch
                            {
                                if (destFileExists == false)
                                {
                                    try
                                    {
                                        await destFile.CloseAsync();
                                    }
                                    catch { }

                                    try
                                    {
                                        await destFileSystem.DeleteFileAsync(destPath);
                                    }
                                    catch { }
                                }

                                throw;
                            }
                            finally
                            {
                                await destFile.CloseAsync();
                            }
                        }
                    }
                    finally
                    {
                        await srcFile.CloseAsync();
                    }
                }
            }
        }
Exemple #4
0
        public static async Task <CopyDirectoryStatus> CopyDirAsync(FileSystem srcFileSystem, string srcPath, FileSystem destFileSystem, string destPath,
                                                                    CopyDirectoryParams?param = null, object?state = null, CopyDirectoryStatus?statusObject = null, CancellationToken cancel = default)
        {
            CopyDirectoryStatus status = statusObject ?? new CopyDirectoryStatus();

            status.Clear();

            status.State     = state;
            status.StartTick = Tick64.Now;

            if (param == null)
            {
                param = new CopyDirectoryParams();
            }

            srcPath = await srcFileSystem.NormalizePathAsync(srcPath, cancel : cancel);

            destPath = await destFileSystem.NormalizePathAsync(destPath, cancel : cancel);

            if (srcFileSystem == destFileSystem)
            {
                if (srcFileSystem.PathParser.PathStringComparer.Equals(srcPath, destPath))
                {
                    throw new FileException(destPath, "Both source and destination is the same directory.");
                }
            }

            using (ProgressReporterBase dirReporter = param.EntireProgressReporterFactory.CreateNewReporter($"CopyDir '{srcFileSystem.PathParser.GetFileName(srcPath)}'", state))
            {
                DirectoryWalker walker  = new DirectoryWalker(srcFileSystem);
                bool            walkRet = await walker.WalkDirectoryAsync(srcPath,
                                                                          async (dirInfo, entries, c) =>
                {
                    c.ThrowIfCancellationRequested();

                    foreach (FileSystemEntity entity in entries)
                    {
                        c.ThrowIfCancellationRequested();

                        try
                        {
                            if (await param.ProgressCallbackProc(status, entity) == false)
                            {
                                throw new OperationCanceledException($"Copying of the file '{entity.FullPath}' is cancaled by the user.");
                            }

                            string entryName = entity.Name;
                            if (entity.IsCurrentDirectory)
                            {
                                entryName = "";
                            }

                            string srcFullPath  = srcFileSystem.PathParser.Combine(srcPath, dirInfo.RelativePath, entryName);
                            string destFullPath = destFileSystem.PathParser.Combine(destPath, srcFileSystem.PathParser.ConvertDirectorySeparatorToOtherSystem(dirInfo.RelativePath, destFileSystem.PathParser), entryName);

                            if (entity.IsDirectory == false)
                            {
                                // Copy a file
                                lock (status.LockObj)
                                    status.NumFilesTotal++;

                                FileMetadataGetFlags metadataGetFlags = FileMetadataCopier.CalcOptimizedMetadataGetFlags(param.FileMetadataCopier.Mode | FileMetadataCopyMode.Attributes);
                                FileMetadata srcFileMetadata          = await srcFileSystem.GetFileMetadataAsync(srcFullPath, metadataGetFlags, cancel);
                                FileFlags copyFileAdditionalFlags     = FileFlags.None;

                                lock (status.LockObj)
                                    status.SizeTotal += srcFileMetadata.Size;

                                if (param.CopyDirFlags.Bit(CopyDirectoryFlags.CopyFileCompressionFlag))
                                {
                                    if (srcFileMetadata.Attributes is FileAttributes attr)
                                    {
                                        if (attr.Bit(FileAttributes.Compressed))
                                        {
                                            copyFileAdditionalFlags |= FileFlags.OnCreateSetCompressionFlag;
                                        }
                                        else
                                        {
                                            copyFileAdditionalFlags |= FileFlags.OnCreateRemoveCompressionFlag;
                                        }
                                    }
                                }

                                if (param.CopyDirFlags.Bit(CopyDirectoryFlags.CopyFileSparseFlag))
                                {
                                    if (srcFileMetadata.Attributes is FileAttributes attr)
                                    {
                                        if (attr.Bit(FileAttributes.SparseFile))
                                        {
                                            copyFileAdditionalFlags |= FileFlags.SparseFile;
                                        }
                                    }
                                }

                                var copyFileParam = param.GenerateCopyFileParams(copyFileAdditionalFlags);

                                RefBool ignoredReadError = new RefBool(false);

                                await CopyFileAsync(srcFileSystem, srcFullPath, destFileSystem, destFullPath, copyFileParam, state, cancel, ignoredReadError);

                                lock (status.LockObj)
                                {
                                    status.NumFilesOk++;
                                    status.SizeOk += srcFileMetadata.Size;

                                    if (ignoredReadError)
                                    {
                                        status.IgnoreReadErrorFileNameList.Add(srcFullPath);
                                    }
                                }
                            }
                            else
                            {
                                // Make a directory
                                lock (status.LockObj)
                                {
                                    status.NumDirectoriesTotal++;
                                }

                                FileMetadataGetFlags metadataGetFlags = FileMetadataCopier.CalcOptimizedMetadataGetFlags(param.DirectoryMetadataCopier.Mode | FileMetadataCopyMode.Attributes);
                                FileMetadata srcDirMetadata           = await srcFileSystem.GetDirectoryMetadataAsync(srcFullPath, metadataGetFlags, cancel);
                                FileFlags copyDirFlags = FileFlags.None;

                                if (param.CopyDirFlags.Bit(CopyDirectoryFlags.BackupMode))
                                {
                                    copyDirFlags |= FileFlags.BackupMode;
                                }

                                if (param.CopyDirFlags.Bit(CopyDirectoryFlags.CopyDirectoryCompressionFlag))
                                {
                                    if (srcDirMetadata.Attributes is FileAttributes attr)
                                    {
                                        if (attr.Bit(FileAttributes.Compressed))
                                        {
                                            copyDirFlags |= FileFlags.OnCreateSetCompressionFlag;
                                        }
                                        else
                                        {
                                            copyDirFlags |= FileFlags.OnCreateRemoveCompressionFlag;
                                        }
                                    }
                                }

                                await destFileSystem.CreateDirectoryAsync(destFullPath, copyDirFlags, cancel);

                                FileMetadata dstDirMetadata = param.DirectoryMetadataCopier.Copy(srcDirMetadata);

                                if (param.CopyDirFlags.Bit(CopyDirectoryFlags.SetAclProtectionFlagOnRootDir))
                                {
                                    if (dirInfo.IsRoot)
                                    {
                                        if (dstDirMetadata.Security != null)
                                        {
                                            if (dstDirMetadata.Security.Acl != null)
                                            {
                                                dstDirMetadata.Security.Acl.Win32AclSddl = "!" + dstDirMetadata.Security.Acl.Win32AclSddl;
                                            }

                                            if (dstDirMetadata.Security.Audit != null)
                                            {
                                                dstDirMetadata.Security.Audit.Win32AuditSddl = "!" + dstDirMetadata.Security.Audit.Win32AuditSddl;
                                            }
                                        }
                                    }
                                }

                                await destFileSystem.SetDirectoryMetadataAsync(destFullPath, dstDirMetadata, cancel);

                                lock (status.LockObj)
                                    status.NumDirectoriesOk++;
                            }
                        }
                        catch (Exception ex)
                        {
                            if (await param.ExceptionCallbackProc(status, entity, ex) == false)
                            {
                                throw ex;
                            }
                        }
                    }

                    return(true);
                },
                                                                          async (dirInfo, entries, c) =>
                {
                    c.ThrowIfCancellationRequested();
                    foreach (FileSystemEntity entity in entries)
                    {
                        c.ThrowIfCancellationRequested();
                        string entryName = entity.Name;
                        if (entity.IsCurrentDirectory)
                        {
                            entryName = "";
                        }

                        string srcFullPath  = srcFileSystem.PathParser.Combine(srcPath, dirInfo.RelativePath, entryName);
                        string destFullPath = destFileSystem.PathParser.Combine(destPath, srcFileSystem.PathParser.ConvertDirectorySeparatorToOtherSystem(dirInfo.RelativePath, destFileSystem.PathParser), entryName);

                        if (entity.IsDirectory)
                        {
                            // Update the directory LastWriteTime metadata after placing all inside files into the directory
                            if (param.DirectoryMetadataCopier.Mode.BitAny(FileMetadataCopyMode.TimeAll))
                            {
                                FileMetadataGetFlags metadataGetFlags = FileMetadataCopier.CalcOptimizedMetadataGetFlags(param.DirectoryMetadataCopier.Mode & (FileMetadataCopyMode.TimeAll));
                                FileMetadata srcDirMetadata           = await srcFileSystem.GetDirectoryMetadataAsync(srcFullPath, metadataGetFlags, cancel);
                                FileMetadata dstDirMetadata           = param.DirectoryMetadataCopier.Copy(srcDirMetadata);
                                await destFileSystem.SetDirectoryMetadataAsync(destFullPath, dstDirMetadata, cancel);
                            }
                        }
                    }
                    return(true);
                },
                                                                          async (dirInfo, exception, c) =>
                {
                    c.ThrowIfCancellationRequested();
                    if (await param.ExceptionCallbackProc(status, dirInfo.Entity, exception) == false)
                    {
                        throw exception;
                    }
                    return(true);
                },
                                                                          param.CopyDirFlags.Bit(CopyDirectoryFlags.Recursive),
                                                                          cancel
                                                                          );
            }

            status.EndTick = Tick64.Now;

            return(status);
        }