public static void DefaultSetDestinationsProc(DataVaultServerReceivedData data, DataVaultServerOptions options) { FileSystem fs = options.DestFileSystem; PathParser parser = fs.PathParser; string root = options.DestRootDirName; DataVaultData d = data.JsonData !; string timeStampStr; if (d.WithTime == false) { timeStampStr = Str.DateToStrShort(d.TimeStamp.LocalDateTime.Date); } else { timeStampStr = Str.DateTimeToStrShortWithMilliSecs(d.TimeStamp.LocalDateTime); } string relativePath = Str.CombineStringArray("/", d.SystemName, d.LogName, d.KeyType, d.KeyShortValue, d.KeyFullValue, $"{timeStampStr}-{d.SystemName}-{d.LogName}-{d.KeyType}-{d.KeyFullValue}.json"); if (d.WriteCompleteFlag ?? false) { relativePath += ".completed"; } data.AddDestinationFileName(parser.NormalizeDirectorySeparator(parser.Combine(root, relativePath))); }
public string SaveToTempFile(string ext, ReadOnlyMemory <byte> data, long lifeTimeMsecs = Consts.Timeouts.GcTempDefaultFileLifeTime, CancellationToken cancel = default) { string tmpDirPath = Env.MyGlobalTempDir._CombinePath("_tmpfiles"); DateTime now = DateTime.Now; DateTime expires; if (lifeTimeMsecs <= 0) { expires = Util.MaxDateTimeValue; } else { expires = now.AddMilliseconds(lifeTimeMsecs); } if (ext._IsEmpty()) { ext = "dat"; } if (ext.StartsWith(".") == false) { ext = "." + ext; } int seqNo = Interlocked.Increment(ref TempFileSeqNo); if ((seqNo % 100) == 0) { try { GcTempFile(); } catch { } } string fn = $"{seqNo:D8}-{Str.DateTimeToStrShortWithMilliSecs(expires)}{ext}"; string filePath = tmpDirPath._CombinePath(fn); this.WriteDataToFile(filePath, data, flags: FileFlags.AutoCreateDirectory, cancel: cancel); return(filePath); }
static void generateINFFilesForPlatform(string inf, string sys, string sys6, string dstDir, int ver, int build, DateTime date, bool selow) { string cdfFileName = Path.Combine(dstDir, "inf.cdf"); string catFileName = Path.Combine(dstDir, "inf.cat"); StringWriter sw = new StringWriter(); string txt = File.ReadAllText(inf, Str.ShiftJisEncoding); IO.DeleteFilesAndSubDirsInDir(dstDir); IO.MakeDirIfNotExists(dstDir); string dst_sys_name = Path.Combine(dstDir, Path.GetFileName(sys)); File.Copy(sys, dst_sys_name, true); string dst_sys6_name = null; if (sys6 != null) { dst_sys6_name = Path.Combine(dstDir, Path.GetFileName(sys6)); File.Copy(sys6, dst_sys6_name, true); } sw.WriteLine("[CatalogHeader]"); sw.WriteLine("name=inf.cat"); sw.WriteLine(); sw.WriteLine("[CatalogFiles]"); sw.WriteLine("<hash>{0}={0}", Path.GetFileName(dst_sys_name)); if (sys6 != null) { sw.WriteLine("<hash>{0}={0}", Path.GetFileName(dst_sys6_name)); } int i; for (i = 1; i < 128; i++) { string name = "VPN"; if (i >= 2) { name += i.ToString(); } if (selow) { name = "selow"; } //string mac = "00AC0011" + i.ToString("X2") + "01"; string mac = "000001000001"; string sys_name = "Neo_" + name + ".sys"; string body = txt; body = Str.ReplaceStr(body, "$TAG_SYS_NAME$", sys_name); body = Str.ReplaceStr(body, "$TAG_INSTANCE_NAME$", name); body = Str.ReplaceStr(body, "$TAG_MAC_ADDRESS$", mac); body = Str.ReplaceStr(body, "$YEAR$", date.Year.ToString("D4")); body = Str.ReplaceStr(body, "$MONTH$", date.Month.ToString("D2")); body = Str.ReplaceStr(body, "$DAY$", date.Day.ToString("D2")); body = Str.ReplaceStr(body, "$VER_MAJOR$", (ver / 100).ToString()); body = Str.ReplaceStr(body, "$VER_MINOR$", (ver % 100).ToString()); body = Str.ReplaceStr(body, "$VER_BUILD$", build.ToString()); body = Str.ReplaceStr(body, "[Manufacturer]", "CatalogFile.NT\t\t\t\t= inf_" + name + ".cat\r\n\r\n[Manufacturer]"); string dst_inf_name = Path.Combine(dstDir, "INF_" + name + ".inf"); if (selow) { dst_inf_name = Path.Combine(dstDir, Path.GetFileName(inf)); } if (selow) { body += "\r\n; Auto Generated " + Str.DateTimeToStrShortWithMilliSecs(DateTime.Now) + "\r\n\r\n"; } File.WriteAllText(dst_inf_name, body, Str.ShiftJisEncoding); sw.WriteLine("<hash>{0}={0}", Path.GetFileName(dst_inf_name)); if (selow) { break; } } sw.WriteLine(); File.WriteAllText(cdfFileName, sw.ToString()); // generate catalog file Directory.SetCurrentDirectory(dstDir); ExecCommand(Paths.MakeCatFilename, string.Format("\"{0}\"", cdfFileName)); // sign catalog file CodeSign.SignFile(catFileName, catFileName, "Catalog File", false); // delete cdf file File.Delete(cdfFileName); // delete sys file File.Delete(dst_sys_name); if (sys6 != null) { File.Delete(dst_sys6_name); } }
// Digital-sign the data on the memory public static byte[] SignMemory(byte[] srcData, string comment, bool kernelModeDriver, int cert_id, int sha_mode) { #if !BU_OSS int i; string out_filename = null; byte[] ret = null; string in_tmp_filename = Path.Combine(in_dir, Str.DateTimeToStrShortWithMilliSecs(DateTime.Now) + "_" + Env.MachineName + "_" + Secure.Rand63i().ToString() + ".dat"); IO.SaveFile(in_tmp_filename, srcData); for (i = 0; i < NumRetries; i++) { Sign sign = new Sign(); sign.Proxy = new WebProxy(); try { out_filename = sign.ExecSignEx(Path.GetFileName(in_tmp_filename), kernelModeDriver, comment, cert_id, sha_mode); break; } catch (Exception ex) { if (i != (NumRetries - 1)) { Kernel.SleepThread(RetryIntervals); } else { throw ex; } } } for (i = 0; i < NumRetriesForCopy; i++) { try { ret = IO.ReadFile(Path.Combine(out_dir, out_filename)); } catch (Exception ex) { if (i != (NumRetriesForCopy - 1)) { Kernel.SleepThread(RetryIntervalsForCopy); } else { throw ex; } } } string tmpFileName = IO.CreateTempFileNameByExt(".exe"); try { File.Delete(tmpFileName); } catch { } File.WriteAllBytes(tmpFileName, ret); lock (lockObj) { if (ExeSignChecker.CheckFileDigitalSignature(tmpFileName) == false) { throw new ApplicationException("CheckFileDigitalSignature failed."); } if (kernelModeDriver) { if (ExeSignChecker.IsKernelModeSignedFile(tmpFileName) == false) { throw new ApplicationException("IsKernelModeSignedFile failed."); } } } try { } catch { File.Delete(tmpFileName); } return(ret); #else // BU_OSS return(srcData); #endif // BU_OSS }
// 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 { // 属性書き込みは失敗してもよい } }
static int CopyRelease(ConsoleService c, string cmdName, string str) { ConsoleParam[] args = { }; ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args); int build, version; string name; DateTime date; Win32BuildUtil.ReadBuildInfoFromTextFile(out build, out version, out name, out date); string baseName = string.Format("v{0}-{1}-{2}-{3:D4}.{4:D2}.{5:D2}", BuildHelper.VersionIntToString(version), build, name, date.Year, date.Month, date.Day); #if !BU_OSS string destDirName = Path.Combine(Paths.ReleaseDestDir, string.Format(@"{0}-{1}-{2}-{3}", Str.DateToStrShort(BuildSoftwareList.ListCreatedDateTime), baseName, Env.MachineName, Env.UserName)); #else // !BU_OSS string destDirName = Path.Combine(Paths.ReleaseDestDir, string.Format(@"{1}", Str.DateToStrShort(BuildSoftwareList.ListCreatedDateTime), baseName, Env.MachineName, Env.UserName)); #endif #if !BU_OSS string publicDir = Path.Combine(destDirName, "Public"); #else // !BU_OSS string publicDir = destDirName; #endif #if !BU_OSS string filesReleaseDir = Path.Combine(publicDir, baseName); #else // !BU_OSS string filesReleaseDir = publicDir; #endif string autorunReleaseSrcDir = Path.Combine(publicDir, "autorun"); IO.CopyDir(Paths.ReleaseDir, filesReleaseDir, null, false, true); #if !BU_OSS IO.CopyDir(Paths.ReleaseSrckitDir, Path.Combine(destDirName, "Private"), null, false, true); IO.CopyDir(Path.Combine(Paths.BaseDirName, @"tmp\lib"), Path.Combine(destDirName, @"Private\lib"), null, false, true); #endif //IO.MakeDir(autorunReleaseSrcDir); /* * File.Copy(Path.Combine(Paths.AutorunSrcDir, "Project1.exe"), * Path.Combine(autorunReleaseSrcDir, "autorun.exe"), true); * * File.Copy(Path.Combine(Paths.AutorunSrcDir, "autorun.inf"), * Path.Combine(autorunReleaseSrcDir, "autorun.inf"), true); * * File.Copy(Path.Combine(Paths.AutorunSrcDir, "packetix.ico"), * Path.Combine(autorunReleaseSrcDir, "autorun.ico"), true);*/ // Create a batch file string batchFileName = Path.Combine(publicDir, "MakeCD.cmd"); #if !BU_OSS StreamWriter w = new StreamWriter(batchFileName); #else // !BU_OSS StringWriter w = new StringWriter(); #endif w.WriteLine(@"SETLOCAL"); w.WriteLine(@"SET BATCH_FILE_NAME=%0"); w.WriteLine(@"SET BATCH_DIR_NAME=%0\.."); w.WriteLine(@"SET NOW_TMP=%time:~0,2%"); w.WriteLine(@"SET NOW=%date:~0,4%%date:~5,2%%date:~8,2%_%NOW_TMP: =0%%time:~3,2%%time:~6,2%"); w.WriteLine(); w.WriteLine(); string[] files = Directory.GetFiles(filesReleaseDir, "*", SearchOption.AllDirectories); string cddir = "CD"; /*string.Format("CD-v{0}.{1}-{2}-{3}-{4:D4}.{5:D2}.{6:D2}", * version / 100, version % 100, build, name, * date.Year, date.Month, date.Day);*/ StringWriter txt = new StringWriter(); foreach (string filename in files) { string file = filename; BuildSoftware s = new BuildSoftware(file); // Software\Windows\PacketiX VPN Server 4.0\32bit (Intel x86)\filename.exe string cpustr = string.Format("{0} - {1}", CPUBitsUtil.CPUBitsToString(s.Cpu.Bits), s.Cpu.Title).Replace("/", "or"); string cpustr2 = cpustr; if (s.Cpu == CpuList.intel) { cpustr2 = ""; cpustr = "Intel"; } string tmp = string.Format(@"{1}\{2}\{3}\{5}{4}", 0, s.Os.Title, BuildHelper.GetSoftwareTitle(s.Software), cpustr2, Path.GetFileName(file), "" ); tmp = Str.ReplaceStr(tmp, "\\\\", "\\"); w.WriteLine("mkdir \"{1}\\{0}\"", Path.GetDirectoryName(tmp), cddir); w.WriteLine("copy /b /y \"{2}\\{0}\" \"{3}\\{1}\"", IO.GetRelativeFileName(file, filesReleaseDir), tmp, baseName, cddir); w.WriteLine(); string txt_filename = tmp; txt_filename = Str.ReplaceStr(txt_filename, "\\", "/"); string txt_description = BuildHelper.GetSoftwareTitle(s.Software); string txt_products = BuildHelper.GetSoftwareProductList(s.Software); string txt_os = s.Os.Title; string txt_cpu = s.Cpu.Title; if (s.Cpu.Bits != CPUBits.Both) { txt_cpu += " (" + CPUBitsUtil.CPUBitsToString(s.Cpu.Bits) + ")"; } else { txt_cpu += " (x86 and x64)"; } string txt_version = BuildHelper.VersionIntToString(version); string txt_build = build.ToString(); string txt_verstr = name; string txt_date = Str.DateTimeToStrShortWithMilliSecs(date); string txt_lang = "English, Japanese, Simplified Chinese"; string txt_category = "PacketiX VPN (Commercial)"; #if BU_SOFTETHER txt_category = "SoftEther VPN (Freeware)"; #endif txt.WriteLine("FILENAME\t" + txt_filename); txt.WriteLine("DESCRIPTION\t" + txt_description); txt.WriteLine("CATEGORY\t" + txt_category); txt.WriteLine("PRODUCT\t" + txt_products); txt.WriteLine("OS\t" + txt_os); txt.WriteLine("OSLIST\t" + s.Os.OSSimpleList); txt.WriteLine("CPU\t" + txt_cpu); txt.WriteLine("VERSION\t" + txt_version); txt.WriteLine("BUILD\t" + txt_build); txt.WriteLine("VERSTR\t" + txt_verstr); txt.WriteLine("DATE\t" + txt_date); txt.WriteLine("LANGUAGE\t" + txt_lang); txt.WriteLine("*"); txt.WriteLine(); } #if BU_OSS Con.WriteLine("Installer packages are built on '{0}'. Enjoy it !!", publicDir); return(0); #endif // BU_OSS /* * w.WriteLine("mkdir \"{0}\\autorun\"", cddir); * w.WriteLine("copy /b /y autorun\\autorun.ico \"{0}\\autorun\"", cddir); * w.WriteLine("copy /b /y autorun\\autorun.exe \"{0}\\autorun\"", cddir); * w.WriteLine("copy /b /y autorun\\autorun.inf \"{0}\\autorun.inf\"", cddir); * */ string zipFileName = string.Format("VPN-CD-v{0}.{1:D2}-{2}-{3}-{4:D4}.{5:D2}.{6:D2}.zip", version / 100, version % 100, build, name, date.Year, date.Month, date.Day); w.WriteLine("del {0}", zipFileName); w.WriteLine("CD {0}", cddir); w.WriteLine("zip -r -0 ../{0} *", zipFileName); w.WriteLine("cd .."); w.WriteLine("move {0} CD\\", zipFileName); w.WriteLine("rename CD {0}-tree", baseName); w.WriteLine(); w.Close(); // Copy of fastcopy string fastcopy_dest = Path.Combine(destDirName, @"Private\fastcopy_bin"); IO.MakeDirIfNotExists(fastcopy_dest); File.Copy(Path.Combine(Paths.UtilityDirName, "FastCopy.exe"), Path.Combine(fastcopy_dest, "FastCopy.exe"), true); File.Copy(Path.Combine(Paths.UtilityDirName, "FastEx64.dll"), Path.Combine(fastcopy_dest, "FastEx64.dll"), true); File.Copy(Path.Combine(Paths.UtilityDirName, "FastExt1.dll"), Path.Combine(fastcopy_dest, "FastExt1.dll"), true); string fastcopy_exe = @"..\Private\fastcopy_bin\FastCopy.exe"; // Create a upload batch string uploadBatchFileName = Path.Combine(publicDir, "UploadNow.cmd"); #if !BU_OSS w = new StreamWriter(uploadBatchFileName); #endif // !BU_OSS string folder_name = "packetix"; #if BU_SOFTETHER folder_name = "softether"; #endif w.WriteLine(@"mkdir \\download\FILES\{1}\{0}-tree", baseName, folder_name); w.WriteLine(@"{0} /cmd=force_copy /exclude={3} /auto_close /force_start /estimate /open_window /error_stop=TRUE /bufsize=128 /disk_mode=diff /speed=full /verify {1}-tree /to=\\download\FILES\{2}\{1}-tree", fastcopy_exe, baseName, folder_name, "\"*files.txt*\""); w.WriteLine(); /* * w.WriteLine(@"mkdir \\downloadjp\FILES\{1}\{0}-tree", baseName, folder_name); * w.WriteLine(@"{0} /cmd=force_copy /exclude={3} /auto_close /force_start /estimate /open_window /error_stop=TRUE /bufsize=128 /disk_mode=diff /speed=full /verify {1}-tree /to=\\downloadjp\FILES\{2}\{1}-tree", fastcopy_exe, baseName, folder_name, * "\"*files.txt*\""); * * w.WriteLine();*/ w.WriteLine(@"copy /y /b {0}-tree\files.txt \\download\FILES\{1}\{0}-tree\files.txt", baseName, folder_name); //w.WriteLine(@"copy /y /b {0}-tree\files.txt \\downloadjp\FILES\{1}\{0}-tree\files.txt", baseName, folder_name); w.WriteLine(); w.WriteLine(@"pause"); w.WriteLine(); w.Close(); txt.WriteLine("FILENAME\t" + zipFileName); #if BU_SOFTETHER txt.WriteLine("DESCRIPTION\t" + "ZIP CD-ROM Image Package of SoftEther VPN (for Admins)"); txt.WriteLine("CATEGORY\t" + "SoftEther VPN (Freeware)"); txt.WriteLine("PRODUCT\t" + "ZIP CD-ROM Image Package of SoftEther VPN"); #else // BU_SOFTETHER txt.WriteLine("DESCRIPTION\t" + "ZIP CD-ROM Image Package of PacketiX VPN (for Admins)"); txt.WriteLine("CATEGORY\t" + "PacketiX VPN (Commercial)"); txt.WriteLine("PRODUCT\t" + "ZIP CD-ROM Image Package of PacketiX VPN"); #endif // BU_SOFTETHER txt.WriteLine("OS\t" + "Any"); txt.WriteLine("OSLIST\t" + "Any"); txt.WriteLine("CPU\t" + "CD-ROM"); txt.WriteLine("VERSION\t" + BuildHelper.VersionIntToString(version)); txt.WriteLine("BUILD\t" + build.ToString()); txt.WriteLine("VERSTR\t" + name); txt.WriteLine("DATE\t" + Str.DateTimeToStrShortWithMilliSecs(date)); txt.WriteLine("LANGUAGE\t" + "English, Japanese, Simplified Chinese"); txt.WriteLine("*"); txt.WriteLine(); IO.MakeDirIfNotExists(Path.Combine(publicDir, cddir)); File.WriteAllText(Path.Combine(Path.Combine(publicDir, cddir), "files.txt"), txt.ToString(), Str.Utf8Encoding); // Execution of batch file string old_cd = Environment.CurrentDirectory; try { Environment.CurrentDirectory = Path.GetDirectoryName(batchFileName); } catch { } Win32BuildUtil.ExecCommand(Paths.CmdFileName, string.Format("/C \"{0}\"", batchFileName)); try { Environment.CurrentDirectory = old_cd; } catch { } Con.WriteLine(); Con.WriteLine("'{0}' に出力されました。", destDirName); return(0); }
static void Net_Test3_PlainTcp_Server() { using (var listener = LocalNet.CreateListener(new TcpListenParam( async(listener2, sock) => { sock.StartPCapRecorder(new PCapFileEmitter(new PCapFileEmitterOptions(new FilePath(@"c:\tmp\190611\" + Str.DateTimeToStrShortWithMilliSecs(DateTime.Now) + ".pcapng", flags: FileFlags.AutoCreateDirectory)))); var stream = sock.GetStream(); StreamWriter w = new StreamWriter(stream); while (true) { w.WriteLine(DateTimeOffset.Now._ToDtStr(true)); await w.FlushAsync(); await Task.Delay(100); } }, null, 9821))) { Con.ReadLine(">"); } }
// 1 つのディレクトリをバックアップする public async Task DoSingleDirBackupAsync(string srcDir, string destDir, CancellationToken cancel, string?ignoreDirNames = null) { DateTimeOffset now = DateTimeOffset.Now; FileSystemEntity[]? srcDirEnum = null; string[] ignoreDirNamesList = ignoreDirNames._NonNull()._Split(StringSplitOptions.RemoveEmptyEntries, ",", ";"); FileMetadata?srcDirMetadata = null; try { 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 つずつバックアップする foreach (FileSystemEntity srcFile in srcDirEnum.Where(x => x.IsFile)) { string destFilePath = Fs.PathParser.Combine(destDir, srcFile.Name); FileMetadata?srcFileMetadata = null; 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 (destExistsMetadata.Size != srcFile.Size) { // ファイルサイズが異なる 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; } if (fileChangedOrNew) { // ファイルが新しいか、または更新された場合は、そのファイルをバックアップする // ただし、バックアップ先に同名のファイルがすでに存在する場合は、 // xxxx.0123.old のような形式でまだ存在しない連番に古いファイル名をリネームする if (exists) { string newOldFileName; // 連番でかつ存在していないファイル名を決定する for (int i = 0; ; i++) { string newOldFileNameCandidate = $"{srcFile.Name}.{i:D4}.old"; if (srcDirEnum.Where(x => x.Name._IsSamei(newOldFileNameCandidate)).Any() == false) { if (await Fs.IsFileExistsAsync(Fs.PathParser.Combine(destDir, newOldFileNameCandidate), cancel) == false) { newOldFileName = newOldFileNameCandidate; break; } } } // 変更されたファイル名を .old ファイルにリネーム実行する await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileRename", destFilePath, Fs.PathParser.Combine(destDir, newOldFileName))); await Fs.MoveFileAsync(destFilePath, Fs.PathParser.Combine(destDir, newOldFileName), cancel); } // ファイルをコピーする // 属性は、ファイルの日付情報のみコピーする await WriteLogAsync(DirSuperBackupLogType.Info, Str.CombineStringArrayForCsv("FileCopy", srcFile.FullPath, destFilePath)); await Fs.CopyFileAsync(srcFile.FullPath, destFilePath, new CopyFileParams(flags : FileFlags.BackupMode | FileFlags.CopyFile_Verify, metadataCopier : new FileMetadataCopier(FileMetadataCopyMode.TimeAll)), cancel : cancel); Stat.Copy_NumFiles++; Stat.Copy_TotalSize += srcFile.Size; } else { 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)); } // このファイルに関するメタデータを追加する if (srcFileMetadata != null) { destDirNewMetaData.FileList.Add(new DirSuperBackupMetadataFile() { FileName = srcFile.Name, MetaData = srcFileMetadata }); } } // 新しいメタデータをファイル名でソートする 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, cancel : cancel); } catch (Exception ex) { Stat.Error_Dir++; // ディレクトリ単位のエラー発生 await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError", srcDir, destDir, ex.Message)); } // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため) try { if (srcDirMetadata != null) { await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel); } } catch { // 属性書き込みは失敗してもよい } if (srcDirEnum != null) { 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); } } } } catch (Exception ex) { // 何らかのディレクトリ単位のエラーで catch されていないものが発生 Stat.Error_Dir++; // ディレクトリ単位のエラー発生 await WriteLogAsync(DirSuperBackupLogType.Error, Str.CombineStringArrayForCsv("DirError", srcDir, destDir, ex.Message)); } } // 再度 宛先ディレクトリの日付情報のみ属性書き込みする (Linux の場合、中のファイルを更新するとディレクトリの日時が変ってしまうため) try { if (srcDirMetadata != null) { await Fs.SetFileMetadataAsync(destDir, srcDirMetadata.Clone(FileMetadataCopyMode.TimeAll), cancel); } } catch { // 属性書き込みは失敗してもよい } }