Пример #1
0
    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);
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        // 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
        }
Пример #5
0
    // 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
        {
            // 属性書き込みは失敗してもよい
        }
    }
Пример #6
0
        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);
        }
Пример #7
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(">");
     }
 }
Пример #8
0
        // 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
            {
                // 属性書き込みは失敗してもよい
            }
        }