public void MTime_IsModifiedTime() { var info = FS.FileInfo.FromFileName(@"c:\home\file.txt"); var entity = new FileSystemEntity(info); Assert.That(entity.MTime, Is.EqualTo(info.LastWriteTimeUtc)); }
public void MimeType_IsContentTypeForFile(string filename, string expectedType) { var info = FS.FileInfo.FromFileName(@"c:\home\" + filename); var entity = new FileSystemEntity(info); Assert.That(entity.MimeType, Is.EqualTo(expectedType)); }
public void Size_IsZeroForDirectory() { var info = FS.DirectoryInfo.FromDirectoryName(@"c:\home"); var entity = new FileSystemEntity(info); Assert.That(entity.Size, Is.Zero); }
public void CTime_IsCreationTime() { var info = FS.FileInfo.FromFileName(@"c:\home\file.txt"); var entity = new FileSystemEntity(info); Assert.That(entity.CTime, Is.EqualTo(info.CreationTimeUtc)); }
public void Size_MeasuresContentForFile() { var info = FS.FileInfo.FromFileName(@"c:\home\file.txt"); var entity = new FileSystemEntity(info); Assert.That(entity.Size, Is.EqualTo("content".Length)); }
public void Path_IsFullPath() { var info = FS.FileInfo.FromFileName(@"c:\home\file.txt"); var entity = new FileSystemEntity(info); Assert.That(entity.Path, Is.EqualTo(info.FullName)); }
public void Name_IsFilename() { var info = FS.FileInfo.FromFileName(@"c:\home\file.txt"); var entity = new FileSystemEntity(info); Assert.That(entity.Name, Is.EqualTo(info.Name)); }
private List <FileSystemEntity> GetFileSystemTree(string rootPath) { if (string.IsNullOrEmpty(rootPath)) { return(new List <FileSystemEntity>()); } var fileInfos = new List <FileSystemEntity>(); var filesAndDirectories = Directory.GetFileSystemEntries(rootPath); foreach (var fileName in filesAndDirectories) { if (File.Exists(fileName)) { fileInfos.Add(new FileSystemEntity(fileName)); } else if (Directory.Exists(fileName)) { var directoryInfo = new FileSystemEntity(fileName); directoryInfo.Children.AddRange(this.GetFileSystemTree(fileName)); fileInfos.Add(directoryInfo); } } return(fileInfos); }
public void MimeType_IsInodeTypeForDirectory() { var info = FS.DirectoryInfo.FromDirectoryName(@"c:\home"); var entity = new FileSystemEntity(info); Assert.That(entity.MimeType, Does.Contain("directory")); }
async Task <bool> DefaultExceptionCallback(CopyDirectoryStatus status, FileSystemEntity entity, Exception exception) { Con.WriteError($"Error: '{entity.FullPath}': {exception.Message}"); await Task.CompletedTask; return(true); }
public static void BrowseFileInfo(FileSystemEntity fse, BusyIndicator busyIndicator) { if (fse.Type == FileSystemEntityType.Folder) { return; } BrowseFileInfo(fse.DocumentInfo, busyIndicator); }
FileSystemEntity[] GetDirectoryItemsInternal(string dirPath, Tree tree) { dirPath = GitRepository.NormalizePath(dirPath); List <FileSystemEntity> ret = new List <FileSystemEntity>(); var curLastCommit = GetLastCommitForObject(dirPath); FileSystemEntity cur = new FileSystemEntity( fullPath: dirPath, name: ".", attributes: FileAttributes.Directory, creationTime: curLastCommit.Author.When, lastWriteTime: curLastCommit.Author.When, lastAccessTime: curLastCommit.Author.When ); ret.Add(cur); foreach (var item in tree) { string fullPath = GitRepository.PathParser.Combine(dirPath, item.Name); var lastCommit = GetLastCommitForObject(fullPath); if (item.TargetType == TreeEntryTargetType.Tree) { Tree subTree = (Tree)item.Target; FileSystemEntity e = new FileSystemEntity( fullPath : fullPath, name: item.Name, attributes: FileAttributes.Directory, creationTime: lastCommit.Author.When, lastWriteTime: lastCommit.Author.When, lastAccessTime: lastCommit.Author.When ); ret.Add(e); } else if (item.TargetType == TreeEntryTargetType.Blob) { Blob blob = (Blob)item.Target; FileSystemEntity e = new FileSystemEntity( fullPath: fullPath, name: item.Name, attributes: FileAttributes.Normal, size: blob.Size, physicalSize: blob.Size, creationTime: lastCommit.Author.When, lastWriteTime: lastCommit.Author.When, lastAccessTime: lastCommit.Author.When ); ret.Add(e); } } return(ret.ToArray()); }
public void ReadOnly_FileWhenFileIsNormal() { var info = FS.FileInfo.FromFileName(@"c:\home\file.txt"); info.Attributes = FileAttributes.Normal; var entity = new FileSystemEntity(info); Assert.That(entity.ReadOnly, Is.False); }
private void BrowseFileInfo(FileSystemEntity fse) { if (fse.Type == FileSystemEntityType.Folder && fse.FolderId > 0) { OpenFolder(fse.FolderId); } else { Utility.Utility.BrowseFileInfo(fse, BusyIndicator1); } }
private void CreatePresenter(FileSystemEntity initialFile) { new DecipherFormPresenter(decipherForm.Object, rsaFactory.Object, keySerializer, commandsContainer.Object, initialFile, environmentHelper.Object, messageHelper.Object, fileUnifier.Object); }
async Task <bool> DefaultProgressCallback(CopyDirectoryStatus status, FileSystemEntity entity) { if (this.CopyDirFlags.Bit(CopyDirectoryFlags.SilenceSuccessfulReport) == false) { Con.WriteInfo($"Copying: '{entity.FullPath}'"); } await Task.CompletedTask; return(true); }
FileSystemEntity GetActualLocation(FileSystemPath path) { if (!TryGetArchivePath(path, out var archivePath)) { return(FileSystemEntity.Create(FileSystem, path)); } var archiveFile = (File)GetActualLocation(archivePath); var usage = GetArchiveFs(archiveFile); return(FileSystemEntity.Create(usage.FileSystem, GetRelativePath(path))); }
public static FileSystemItem FromEntity(FileSystemEntity entity) { return(new FileSystemItem { Name = entity.Name, CreationDate = entity.CreationDate, ModificationTime = entity.CreationDate, LastAccessTime = entity.LastAccessTime, Attributes = entity.Attributes, Owner = entity.Owner, Permissions = entity.Permissions, }); }
/// <summary> /// Get the files and\or folders specified by the given path and pattern. /// </summary> /// <param name="entityType">Whether Files, Directories or both.</param> /// <param name="path">The path to search.</param> /// <param name="pattern">The pattern to search.</param> /// <param name="projectDirectory">The directory for the project within which the call is made</param> /// <param name="stripProjectDirectory">If true the project directory should be stripped</param> /// <returns></returns> private static string[] GetAccessibleFileSystemEntries(FileSystemEntity entityType, string path, string pattern, string projectDirectory, bool stripProjectDirectory) { string[] files = null; switch (entityType) { case FileSystemEntity.Files: files = GetAccessibleFiles(path, pattern, projectDirectory, stripProjectDirectory); break; case FileSystemEntity.Directories: files = GetAccessibleDirectories(path, pattern); break; case FileSystemEntity.FilesAndDirectories: files = GetAccessibleFilesAndDirectories(path, pattern); break; default: ErrorUtilities.VerifyThrow(false, "Unexpected filesystem entity type."); break; } return files; }
private static string[] GetAccessibleFileSystemEntries(FileSystemEntity entityType, string path, string pattern, string projectDirectory, bool stripProjectDirectory) { switch (entityType) { case FileSystemEntity.Files: return(GetAccessibleFiles(path, pattern, projectDirectory, stripProjectDirectory)); case FileSystemEntity.Directories: return(GetAccessibleDirectories(path, pattern)); case FileSystemEntity.FilesAndDirectories: return(GetAccessibleFilesAndDirectories(path, pattern)); } Microsoft.Build.Shared.ErrorUtilities.VerifyThrow(false, "Unexpected filesystem entity type."); return(null); }
private void AddItem(FileSystemEntity entity) { listView.SmallImageList.Images.Add(entity.Icon); var item = new ListViewItem(entity.Name); if (entity.IsCryptoFile) { item.BackColor = RsaFileColor; } item.ImageIndex = listView.SmallImageList.Images.Count - 1; item.Tag = entity; item.SubItems.Add(entity.IsFile ? entity.Length.ToString() : string.Empty); item.SubItems.Add(entity.Type); item.SubItems.Add(entity.ModifiedDate.ToString()); listView.Items.Add(item); }
public async Task <IActionResult> DownloadAsync(string directory, string filename) { FileSystemEntity entity = null; switch (directory) { case "AuditLogs": entity = Repository.AuditLogs.GetFileByFilename(filename); break; } if (entity == null) { return(NotFound()); } var contentType = ContentTypeProvider.TryGetContentType(entity.Filename, out string type) ? type : "application/octet-stream"; return(File(entity.Content, contentType)); }
private void SelectUserFolderTreeItem(FileSystemEntity fse) { if (fse == null) { return; } var sItem = UserFoldersTree.SelectedItem as TreeViewItem; if (sItem != null && sItem.Items != null && sItem.Items.Count > 0) { foreach (TreeViewItem item in sItem.Items) { var tmp = item.DataContext as FileSystemEntity; if (tmp != null && (ReferenceEquals(tmp, fse) || tmp.FolderId == fse.FolderId)) { item.IsSelected = true; break; } } } }
//获取文件描述历史 public List <DocumentRelease> GetReleaseHistory(FileSystemEntity fse) { var filters = new EntityFilters { And = true }; filters.Add(fse.Type == FileSystemEntityType.File ? new EntityFilter { Operator = FilterOperator.Equal, PropertyName = "DocumentId", Value = fse.FileId } : new EntityFilter { Operator = FilterOperator.Equal, PropertyName = "FolderId", Value = fse.FolderId }); return(SqlHelper.Filter <DocumentRelease>(filters, true, false)); }
/// <exception cref="ArgumentNullException">any argument is null</exception> public DecipherFormPresenter(IDecipherForm form, IRsaFactory rsaFactory, KeySerializer keySerializer, ICommandsContainer commandsContainer, FileSystemEntity initialFile, IEnvironmentHelper environmentHelper, IMessageHelper messageHelper, IFileUnifier fileUnifier) { Checker.CheckNull(form, rsaFactory, keySerializer, commandsContainer, initialFile); this.form = form; this.rsaFactory = rsaFactory; this.keySerializer = keySerializer; this.commandsContainer = commandsContainer; this.environmentHelper = environmentHelper; this.messageHelper = messageHelper; this.fileUnifier = fileUnifier; form.OutputDirectoryPath = GetOutputDirectoryPath(initialFile); form.Decipher += form_Decipher; form.CancelDecipher += form_CancelDecipher; form.OutputFileNameChanged += form_OutputFileNameChanged; form.PrivateKeyChanged += form_PrivateKeyChanged; }
internal static IEnumerable<string> FilterDirectories(Glob glob, IEnumerable<string> directories, FileSystemEntity resultType, FileSystemEnumerator enumerator) { IEnumerable<Item> items = Enumerable.Empty<Item>(); IEnumerable<Item> subItemsStart = directories.Select( t => new Item(ExpandEnvironmentVariables(t), FileSystemEntity.Directory)).ToArray(); foreach (SegmentSequence sub in glob.segments) { IEnumerable<Item> subItems = subItemsStart; subItems = sub.Enumerate(subItems, enumerator); items = items.Concat(subItems); } // TODO Should inform the last segment of the result type rather than filter here return items .Where(t => t.Item2 == resultType) .Select(t => t.Item1) .Distinct(); }
protected override async Task <FileSystemEntity[]> EnumDirectoryImplAsync(string directoryPath, EnumDirectoryFlags flags, CancellationToken cancel = default) { checked { FileSystemEntity[] dirEntities = await UnderlayFileSystem.EnumDirectoryAsync(directoryPath, false, flags, cancel); var relatedFiles = dirEntities.Where(x => x.IsDirectory == false).Where(x => x.Name.IndexOf(Params.SplitStr) != -1); var sortedRelatedFiles = relatedFiles.ToList(); sortedRelatedFiles.Sort((x, y) => x.Name._Cmp(y.Name, PathParser.PathStringComparison)); sortedRelatedFiles.Reverse(); Dictionary <string, FileSystemEntity> parsedFileDictionaly = new Dictionary <string, FileSystemEntity>(PathParser.PathStringComparer); var normalFiles = dirEntities.Where(x => x.IsDirectory == false).Where(x => x.Name.IndexOf(Params.SplitStr) == -1); var normalFileHashSet = new HashSet <string>(normalFiles.Select(x => x.Name), PathParser.PathStringComparer); foreach (FileSystemEntity f in sortedRelatedFiles) { try { // Split files ParsedPath parsed = new ParsedPath(this, f.FullPath, f); if (parsedFileDictionaly.ContainsKey(parsed.LogicalFileName) == false) { FileSystemEntity newFileEntity = new FileSystemEntity( fullPath: parsed.LogicalFilePath, name: PathParser.GetFileName(parsed.LogicalFileName), size: f.Size + parsed.FileNumber * Params.MaxSinglePhysicalFileSize, physicalSize: f.PhysicalSize, attributes: f.Attributes, creationTime: f.CreationTime, lastWriteTime: f.LastWriteTime, lastAccessTime: f.LastAccessTime ); parsedFileDictionaly.Add(parsed.LogicalFileName, newFileEntity); } else { var fileEntity = parsedFileDictionaly[parsed.LogicalFileName]; fileEntity.PhysicalSize += f.PhysicalSize; if (fileEntity.CreationTime > f.CreationTime) { fileEntity.CreationTime = f.CreationTime; } if (fileEntity.LastWriteTime < f.LastWriteTime) { fileEntity.LastWriteTime = f.LastWriteTime; } if (fileEntity.LastAccessTime < f.LastAccessTime) { fileEntity.LastAccessTime = f.LastAccessTime; } } } catch { } } var logicalFiles = parsedFileDictionaly.Values.Where(x => normalFileHashSet.Contains(x.Name) == false); var retList = dirEntities.Where(x => x.IsDirectory) .Concat(logicalFiles) .Concat(normalFiles) .OrderByDescending(x => x.IsDirectory) .ThenBy(x => x.Name); return(retList._ToArrayList()); } }
protected override int DoCompare(FileSystemEntity first, FileSystemEntity second) { return(!first.IsFile ? 0 : first.Length.CompareTo(second.Length)); }
// 1 つのディレクトリをバックアップする public async Task DoSingleDirBackupAsync(string srcDir, string destDir, CancellationToken cancel = default, string?ignoreDirNames = null) { DateTimeOffset now = DateTimeOffset.Now; FileSystemEntity[]? srcDirEnum = null; string[] ignoreDirNamesList = ignoreDirNames._NonNull()._Split(StringSplitOptions.RemoveEmptyEntries, ",", ";"); FileMetadata?srcDirMetadata = null; bool noError = true; try { if (srcDir._IsSamei(destDir)) { throw new CoresException($"srcDir == destDir. Directory path: '{srcDir}'"); } srcDirMetadata = await Fs.GetDirectoryMetadataAsync(srcDir, cancel : cancel); srcDirEnum = (await Fs.EnumDirectoryAsync(srcDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray(); FileSystemEntity[] destDirEnum = new FileSystemEntity[0]; DirSuperBackupMetadata?destDirOldMetaData = null; DirSuperBackupMetadata destDirNewMetaData; // 宛先ディレクトリがすでに存在しているかどうか検査する if (await Fs.IsDirectoryExistsAsync(destDir, cancel)) { destDirEnum = await Fs.EnumDirectoryAsync(destDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel); // 宛先ディレクトリに存在するメタデータファイルのうち最新のファイルを取得する destDirOldMetaData = await GetLatestMetaDataFileNameAsync(destDir, destDirEnum, cancel); } else { // 宛先ディレクトリがまだ存在していない場合は作成する await Fs.CreateDirectoryAsync(destDir, FileFlags.BackupMode | FileFlags.AutoCreateDirectory, cancel); } // 宛先ディレクトリの日付情報のみ属性書き込みする try { await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel); } catch { // 属性書き込みは失敗してもよい } // 新しいメタデータを作成する destDirNewMetaData = new DirSuperBackupMetadata(); destDirNewMetaData.FileList = new List <DirSuperBackupMetadataFile>(); destDirNewMetaData.TimeStamp = now; destDirNewMetaData.DirMetadata = srcDirMetadata; destDirNewMetaData.DirList = new List <string>(); // 元ディレクトリに存在するサブディレクトリ名一覧をメタデータに追記する foreach (var subDir in srcDirEnum.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false)) { // シンボリックリンクは無視する if (subDir.IsSymbolicLink == false) { // 無視リストのいずれにも合致しない場合のみ if (ignoreDirNamesList.Where(x => x._IsSamei(subDir.Name)).Any() == false) { destDirNewMetaData.DirList.Add(subDir.Name); } } } // 元ディレクトリに存在するファイルを 1 つずつバックアップする var fileEntries = srcDirEnum.Where(x => x.IsFile); RefInt concurrentNum = new RefInt(); AsyncLock SafeLock = new AsyncLock(); await TaskUtil.ForEachAsync(Options.NumThreads, fileEntries, async (srcFile, taskIndex, cancel) => { long?encryptedPhysicalSize = null; await Task.Yield(); string destFilePath = Fs.PathParser.Combine(destDir, srcFile.Name); if (Options.EncryptPassword._IsNullOrZeroLen() == false) { destFilePath += Consts.Extensions.CompressedXtsAes256; } FileMetadata?srcFileMetadata = null; concurrentNum.Increment(); try { srcFileMetadata = await Fs.GetFileMetadataAsync(srcFile.FullPath, cancel: cancel); // このファイルと同一のファイル名がすでに宛先ディレクトリに物理的に存在するかどうか確認する bool exists = await Fs.IsFileExistsAsync(destFilePath, cancel); bool fileChangedOrNew = false; if (exists) { // すでに宛先ディレクトリに存在する物理的なファイルのメタデータを取得する FileMetadata destExistsMetadata = await Fs.GetFileMetadataAsync(destFilePath, cancel: cancel); if (Options.EncryptPassword._IsNullOrZeroLen()) { // 暗号化なし // ファイルサイズを比較する if (destExistsMetadata.Size != srcFile.Size) { // ファイルサイズが異なる fileChangedOrNew = true; } } else { // 暗号化あり // 宛先ディレクトリのメタデータにファイル情報が存在し、そのメタデータ情報におけるファイルサイズが元ファイルと同じであり、 // かつそのメタデータ情報に記載されている EncryptedPhysicalSize が宛先ディレクトリにある物理ファイルと全く同一である // 場合は、宛先ファイルが正しく存在すると仮定する string tmp1 = Fs.PathParser.GetFileName(destFilePath); if ((destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSamei(tmp1) && x.EncryptedPhysicalSize == destExistsMetadata.Size && x.MetaData.Size == srcFile.Size).Any() ?? false) == false) { // ファイルサイズが異なるとみなす fileChangedOrNew = true; } } // 日付を比較する。ただし宛先ディレクトリの物理的なファイルの日付は信用できないので、メタデータ上のファイルサイズと比較する if (destDirOldMetaData != null) { DirSuperBackupMetadataFile?existsFileMetadataFromDirMetadata = destDirOldMetaData.FileList.Where(x => x.FileName._IsSamei(srcFile.Name)).SingleOrDefault(); if (existsFileMetadataFromDirMetadata == null) { // メタデータ上に存在しない fileChangedOrNew = true; } else { if (existsFileMetadataFromDirMetadata.MetaData !.LastWriteTime !.Value.Ticks != srcFileMetadata.LastWriteTime !.Value.Ticks) { // 最終更新日時が異なる fileChangedOrNew = true; } } } else { // 宛先ディレクトリ上にメタデータがない fileChangedOrNew = true; } } else { // 新しいファイルである fileChangedOrNew = true; } string?oldFilePathToDelete = null; if (fileChangedOrNew) { // ファイルが新しいか、または更新された場合は、そのファイルをバックアップする // ただし、バックアップ先に同名のファイルがすでに存在する場合は、 // .old.xxxx.YYYYMMDD_HHMMSS.0123._backup_history のような形式でまだ存在しない連番に古いファイル名をリネームする if (exists) { using (await SafeLock.LockWithAwait(cancel)) { string yymmdd = Str.DateTimeToStrShort(DateTime.UtcNow); string newOldFileName; // 連番でかつ存在していないファイル名を決定する for (int i = 0; ; i++) { string newOldFileNameCandidate = $".old.{Fs.PathParser.GetFileName(destFilePath)}.{yymmdd}.{i:D4}{Consts.Extensions.DirSuperBackupHistory}"; if (srcDirEnum.Where(x => x.Name._IsSamei(newOldFileNameCandidate)).Any() == false) { if (await Fs.IsFileExistsAsync(Fs.PathParser.Combine(destDir, newOldFileNameCandidate), cancel) == false) { newOldFileName = newOldFileNameCandidate; break; } } } // 変更されたファイル名を ._backup_history ファイルにリネーム実行する string newOldFilePath = Fs.PathParser.Combine(destDir, newOldFileName); await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileRename", destFilePath, newOldFilePath)); await Fs.MoveFileAsync(destFilePath, newOldFilePath, cancel); oldFilePathToDelete = newOldFilePath; // 隠しファイルにする try { var meta = await Fs.GetFileMetadataAsync(newOldFilePath, cancel: cancel); if (meta.Attributes != null && meta.Attributes.Bit(FileAttributes.Hidden) == false) { FileMetadata meta2 = new FileMetadata(attributes: meta.Attributes.BitAdd(FileAttributes.Hidden)); await Fs.SetFileMetadataAsync(newOldFilePath, meta2, cancel); } } catch { } } } // ファイルをコピーする // 属性は、ファイルの日付情報のみコピーする await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileCopy", srcFile.FullPath, destFilePath)); FileFlags flags = FileFlags.BackupMode | FileFlags.Async; if (this.Options.Flags.Bit(DirSuperBackupFlags.BackupNoVerify) == false) { flags |= FileFlags.CopyFile_Verify; } await Fs.CopyFileAsync(srcFile.FullPath, destFilePath, new CopyFileParams(flags: flags, metadataCopier: new FileMetadataCopier(FileMetadataCopyMode.TimeAll), encryptOption: Options.EncryptPassword._IsNullOrZeroLen() ? EncryptOption.None : EncryptOption.Encrypt | EncryptOption.Compress, encryptPassword: Options.EncryptPassword, deleteFileIfVerifyFailed: true), cancel: cancel); try { if (Options.EncryptPassword._IsNullOrZeroLen() == false) { var newFileMetadata = await Fs.GetFileMetadataAsync(destFilePath, FileMetadataGetFlags.NoPhysicalFileSize, cancel); encryptedPhysicalSize = newFileMetadata.Size; } } catch { } if (Options.Flags.Bit(DirSuperBackupFlags.BackupMakeHistory) == false) { // History を残さない場合 // コピーに成功したので ._backup_history ファイルは削除する if (oldFilePathToDelete._IsNotZeroLen()) { try { await Fs.DeleteFileAsync(oldFilePathToDelete, flags: FileFlags.BackupMode | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel); } catch { } } } Stat.Copy_NumFiles++; Stat.Copy_TotalSize += srcFile.Size; } else { if (Options.EncryptPassword._IsNullOrZeroLen() == false) { string tmp1 = Fs.PathParser.GetFileName(destFilePath); encryptedPhysicalSize = destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSame(tmp1) && x.MetaData.Size == srcFile.Size).FirstOrDefault()?.EncryptedPhysicalSize; if (encryptedPhysicalSize.HasValue == false) { encryptedPhysicalSize = destDirOldMetaData?.FileList.Where(x => x.EncrypedFileName._IsSamei(tmp1) && x.MetaData.Size == srcFile.Size).FirstOrDefault()?.EncryptedPhysicalSize; } } Stat.Skip_NumFiles++; Stat.Skip_TotalSize += srcFile.Size; // ファイルの日付情報のみ更新する try { await Fs.SetFileMetadataAsync(destFilePath, srcFileMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel); } catch { // ファイルの日付情報の更新は失敗してもよい } } } catch (Exception ex) { Stat.Error_NumFiles++; Stat.Error_TotalSize += srcFile.Size; // ファイル単位のエラー発生 await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("FileError", srcFile.FullPath, destFilePath, ex.Message)); noError = false; } finally { concurrentNum.Decrement(); } // このファイルに関するメタデータを追加する if (srcFileMetadata != null) { lock (destDirNewMetaData.FileList) { destDirNewMetaData.FileList.Add(new DirSuperBackupMetadataFile() { FileName = srcFile.Name, EncrypedFileName = Options.EncryptPassword._IsNullOrZeroLen() ? null : srcFile.Name + Consts.Extensions.CompressedXtsAes256, MetaData = srcFileMetadata, EncryptedPhysicalSize = encryptedPhysicalSize, }); } } }, cancel : cancel); // 新しいメタデータをファイル名でソートする destDirNewMetaData.FileList = destDirNewMetaData.FileList.OrderBy(x => x.FileName, StrComparer.IgnoreCaseComparer).ToList(); destDirNewMetaData.DirList = destDirNewMetaData.DirList.OrderBy(x => x, StrComparer.IgnoreCaseComparer).ToList(); // 新しいメタデータを書き込む string newMetadataFilePath = Fs.PathParser.Combine(destDir, $"{PrefixMetadata}{Str.DateTimeToStrShortWithMilliSecs(now.UtcDateTime)}{SuffixMetadata}"); await Fs.WriteJsonToFileAsync(newMetadataFilePath, destDirNewMetaData, FileFlags.BackupMode | FileFlags.OnCreateSetCompressionFlag, cancel : cancel); } catch (Exception ex) { Stat.Error_Dir++; noError = false; // ディレクトリ単位のエラー発生 await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError1", srcDir, destDir, ex.Message)); } // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため) try { if (srcDirMetadata != null) { await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel); } } catch { // 属性書き込みは失敗してもよい } if (srcDirEnum != null) { bool ok = false; try { // ソースディレクトリの列挙に成功した場合は、サブディレクトリに対して再帰的に実行する foreach (var subDir in srcDirEnum.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false)) { // シンボリックリンクは無視する if (subDir.IsSymbolicLink == false) { // 無視リストのいずれにも合致しない場合のみ if (ignoreDirNamesList.Where(x => x._IsSamei(subDir.Name)).Any() == false) { await DoSingleDirBackupAsync(Fs.PathParser.Combine(srcDir, subDir.Name), Fs.PathParser.Combine(destDir, subDir.Name), cancel, ignoreDirNames); } } } ok = true; } catch (Exception ex) { // 何らかのディレクトリ単位のエラーで catch されていないものが発生 Stat.Error_Dir++; // ディレクトリ単位のエラー発生 await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError2", srcDir, destDir, ex.Message)); } if (ok) { if (noError) { // ここまでの処理で何も問題がなければ (このディレクトリ内のすべてのファイルのコピーやメタデータの更新に成功しているなであれば) // Sync オプションが付与されている場合、不要なサブディレクトリとファイルを削除する if (this.Options.Flags.Bit(DirSuperBackupFlags.BackupSync)) { try { // 両方のディレクトリを再列挙いたします var srcDirEnum2 = (await Fs.EnumDirectoryAsync(srcDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray(); var destDirEnum2 = (await Fs.EnumDirectoryAsync(destDir, false, EnumDirectoryFlags.NoGetPhysicalSize, cancel)).OrderBy(x => x.Name, StrComparer.IgnoreCaseComparer).ToArray(); // 余分なファイルを削除いたします var extraFiles = destDirEnum2.Where(x => x.IsFile && x.IsSymbolicLink == false) .Where(x => x.Name._StartWithi(DirSuperBackup.PrefixMetadata) == false && x.Name._EndsWithi(DirSuperBackup.SuffixMetadata) == false) .Where(x => srcDirEnum2.Where(y => y.IsFile && y.Name._IsSameiTrim(x.Name)).Any() == false) .Where(x => srcDirEnum2.Where(y => y.IsFile && (y.Name + Consts.Extensions.CompressedXtsAes256)._IsSameiTrim(x.Name)).Any() == false); foreach (var extraFile in extraFiles) { string fullPath = Fs.PathParser.Combine(destDir, extraFile.Name); await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("DirSyncDeleteFile", fullPath)); try { await Fs.DeleteFileAsync(fullPath, FileFlags.BackupMode | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel); Stat.SyncDelete_NumFiles++; } catch (Exception ex) { Stat.Error_NumDeleteFiles++; await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncDeleteFileError", fullPath, ex.Message)); } } // 余分なサブディレクトリを削除いたします var extraSubDirs = destDirEnum2.Where(x => x.IsDirectory && x.IsCurrentOrParentDirectory == false && x.IsSymbolicLink == false) .Where(x => srcDirEnum2.Where(y => y.IsDirectory && y.IsCurrentOrParentDirectory == false && y.Name._IsSameiTrim(x.Name)).Any() == false); foreach (var extraSubDir in extraSubDirs) { string fullPath = Fs.PathParser.Combine(destDir, extraSubDir.Name); await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("DirSyncDeleteSubDir", fullPath)); try { await Fs.DeleteDirectoryAsync(fullPath, true, cancel); Stat.SyncDelete_NumDirs++; } catch (Exception ex) { Stat.Error_NumDeleteDirs++; await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncDeleteSubDirError", fullPath, ex.Message)); } } } catch (Exception ex) { // 何らかのディレクトリ単位のエラーで catch されていないものが発生 Stat.Error_Dir++; // ディレクトリ単位のエラー発生 await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirSyncEnumError", srcDir, destDir, ex.Message)); } } } } } // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため) try { if (srcDirMetadata != null) { await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel); } } catch { // 属性書き込みは失敗してもよい } }
protected override async Task <FileSystemEntity[]> EnumDirectoryImplAsync(string directoryPath, EnumDirectoryFlags flags, CancellationToken cancel = default) { using (VfsPathParserContext ctx = await ParsePathInternalAsync(directoryPath, cancel)) { if (ctx.Exception != null) { throw ctx.Exception; } if (ctx.LastEntity is VfsDirectory thisDirObject) { var entities = await thisDirObject.EnumEntitiesAsync(flags, cancel); List <FileSystemEntity> ret = new List <FileSystemEntity>(); FileSystemEntity thisDir = new FileSystemEntity( fullPath: ctx.NormalizedPath, name: ".", attributes: thisDirObject.Attributes, creationTime: thisDirObject.CreationTime, lastWriteTime: thisDirObject.LastWriteTime, lastAccessTime: thisDirObject.LastAccessTime ); ret.Add(thisDir); foreach (var entity in entities) { if (entity is VfsDirectory dirObject) { FileMetadata meta = await dirObject.GetMetadataAsync(cancel); FileSystemEntity dir = new FileSystemEntity( fullPath: PathParser.Combine(ctx.NormalizedPath, entity.Name), name: entity.Name, attributes: meta.Attributes ?? FileAttributes.Directory, creationTime: meta.CreationTime ?? Util.ZeroDateTimeOffsetValue, lastWriteTime: meta.LastWriteTime ?? Util.ZeroDateTimeOffsetValue, lastAccessTime: meta.LastAccessTime ?? Util.ZeroDateTimeOffsetValue ); ret.Add(dir); } else if (entity is VfsFile fileObject) { FileMetadata meta = await fileObject.GetMetadataAsync(cancel); FileSystemEntity file = new FileSystemEntity( fullPath: PathParser.Combine(ctx.NormalizedPath, entity.Name), name: entity.Name, size: meta.Size, physicalSize: meta.PhysicalSize, attributes: meta.Attributes ?? FileAttributes.Directory, creationTime: meta.CreationTime ?? Util.ZeroDateTimeOffsetValue, lastWriteTime: meta.LastWriteTime ?? Util.ZeroDateTimeOffsetValue, lastAccessTime: meta.LastAccessTime ?? Util.ZeroDateTimeOffsetValue ); ret.Add(file); } } return(ret.ToArray()); } else { throw new VfsNotFoundException(directoryPath, "Directory not found."); } } }
private static string[] GetAccessibleFileSystemEntries(FileSystemEntity entityType, string path, string pattern, string projectDirectory, bool stripProjectDirectory) { switch (entityType) { case FileSystemEntity.Files: return GetAccessibleFiles(path, pattern, projectDirectory, stripProjectDirectory); case FileSystemEntity.Directories: return GetAccessibleDirectories(path, pattern); case FileSystemEntity.FilesAndDirectories: return GetAccessibleFilesAndDirectories(path, pattern); } Microsoft.Build.Shared.ErrorUtilities.VerifyThrow(false, "Unexpected filesystem entity type."); return null; }
private static bool CheckFile(FileSystemEntity file) { return(file != null && file.IsCryptoFile); }
protected override int DoCompare(FileSystemEntity first, FileSystemEntity second) { return(first.ModifiedDate.CompareTo(second.ModifiedDate)); }