protected override async Task <FileMetadata> GetFileMetadataImplAsync(string path, FileMetadataGetFlags flags = FileMetadataGetFlags.DefaultAll, CancellationToken cancel = default) { using (VfsPathParserContext ctx = await ParsePathInternalAsync(path, cancel)) { if (ctx.Exception != null) { throw ctx.Exception; } if (ctx.LastEntity is VfsFile file) { return(await file.GetMetadataAsync(cancel)); } else { throw new VfsNotFoundException(path, "File not found."); } } }
protected override Task <FileMetadata> GetDirectoryMetadataImplAsync(string path, FileMetadataGetFlags flags = FileMetadataGetFlags.DefaultAll, CancellationToken cancel = default) => UnderlayFileSystem.GetDirectoryMetadataAsync(path, flags | FileMetadataGetFlags.NoAlternateStream | FileMetadataGetFlags.NoSecurity, cancel);
protected override Task <FileMetadata> GetFileMetadataImplAsync(string path, FileMetadataGetFlags flags = FileMetadataGetFlags.DefaultAll, CancellationToken cancel = default) { return(Task.FromResult(this.Commit.GetFileMetadata(path))); }
protected override async Task <FileMetadata> GetFileMetadataImplAsync(string path, FileMetadataGetFlags flags = FileMetadataGetFlags.DefaultAll, CancellationToken cancel = default) { // Try physical file first try { return(await UnderlayFileSystem.GetFileMetadataAsync(path, flags, cancel)); } catch { } LargeFileSystem.ParsedPath[] physicalFiles = await GetPhysicalFileStateInternal(path, cancel); var lastFileParsed = physicalFiles.OrderBy(x => x.FileNumber).LastOrDefault(); if (lastFileParsed == null) { // File not found throw new IOException($"The file '{path}' not found."); } else { // Large file exists checked { FileMetadata ret = await UnderlayFileSystem.GetFileMetadataAsync(lastFileParsed.PhysicalFilePath, flags | FileMetadataGetFlags.NoSecurity | FileMetadataGetFlags.NoAlternateStream, cancel); long sizeOfLastFile = ret.Size; sizeOfLastFile = Math.Min(sizeOfLastFile, Params.MaxSinglePhysicalFileSize); long currentFileSize = lastFileParsed.FileNumber * Params.MaxSinglePhysicalFileSize + sizeOfLastFile; ret.Size = currentFileSize; ret.PhysicalSize = physicalFiles.Sum(x => x.PhysicalEntity !.PhysicalSize); ret.CreationTime = physicalFiles.Min(x => x.PhysicalEntity !.CreationTime); ret.LastWriteTime = physicalFiles.Max(x => x.PhysicalEntity !.LastWriteTime); ret.LastAccessTime = physicalFiles.Max(x => x.PhysicalEntity !.LastAccessTime); return(ret); } } }
protected override async Task <FileMetadata> GetFileMetadataImplAsync(string path, FileMetadataGetFlags flags = FileMetadataGetFlags.DefaultAll, CancellationToken cancel = default) { FileMetadata physicalMetadata = await UnderlayFileSystem.GetFileMetadataAsync(path, flags, cancel); try { long headerOffset = 0; long physicalSize = physicalMetadata.Size; using (FileObject physicalFile = await UnderlayFileSystem.OpenAsync(path)) { byte[] bomRead = new byte[3]; Memory <byte> tmp = new byte[3]; if (await physicalFile.ReadRandomAsync(0, tmp, cancel) == tmp.Length) { if (tmp.Span.SequenceEqual(Str.BOM_UTF_8.Span)) { headerOffset = 3; } } physicalSize = await physicalFile.GetFileSizeAsync(true, cancel) - headerOffset; if (physicalSize >= 0) { physicalMetadata.Size = physicalSize; } } } catch { } return(physicalMetadata); }
protected override Task <FileMetadata> GetFileMetadataImplAsync(string path, FileMetadataGetFlags flags = FileMetadataGetFlags.DefaultAll, CancellationToken cancel = default) => UnderlayFileSystem.GetFileMetadataAsync(path, flags, cancel);
protected override Task <FileMetadata> GetFileMetadataImplAsync(string path, FileMetadataGetFlags flags = FileMetadataGetFlags.DefaultAll, CancellationToken cancel = default) { path = MapPathVirtualToPhysical(path); return(base.GetFileMetadataImplAsync(path, flags, cancel)); }
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); }