Beispiel #1
0
 protected LargeFileObject(FileSystem fileSystem, FileParameters fileParams, LargeFileSystem.ParsedPath[] relatedFiles) : base(fileSystem, fileParams)
 {
     this.LargeFileSystem     = (LargeFileSystem)fileSystem;
     this.UnderlayFileSystem  = this.LargeFileSystem.UnderlayFileSystem;
     this.InitialRelatedFiles = relatedFiles;
 }
Beispiel #2
0
            public FileImpl(VfsRandomAccessFile file, IRandomAccess <byte> randomAccessBase, string fullPath, FileSystem fileSystem, FileParameters fileParams)
                : base(new ConcurrentRandomAccess <byte>(randomAccessBase), fileSystem, fileParams)
            {
                this.File = file;
                this.File.AddHandleRef();

                try
                {
                    this.FullPath = fullPath;
                }
                catch
                {
                    this.File.ReleaseHandleRef();
                    throw;
                }
            }
Beispiel #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();
                    }
                }
            }
        }
Beispiel #4
0
 public static void CopyFile(FileSystem srcFileSystem, string srcPath, FileSystem destFileSystem, string destPath,
                             CopyFileParams?param = null, object?state = null, CancellationToken cancel = default, RefBool?readErrorIgnored = null)
 => CopyFileAsync(srcFileSystem, srcPath, destFileSystem, destPath, param, state, cancel, readErrorIgnored)._GetResult();
Beispiel #5
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);
        }