From 6320b5ef45078065331cbc1e638558aa78a09880 Mon Sep 17 00:00:00 2001 From: fdsc Date: Fri, 17 Feb 2023 14:31:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BB=20=D1=86=D0=B8=D0=BA=D0=BB=20=D1=87=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B7=20=D1=80=D0=B5=D0=BA=D1=83=D1=80=D1=81=D0=B8=D1=8E?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D0=B4=D0=B8=D1=80=D0=B5=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D1=8F=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Program.cs | 230 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 170 insertions(+), 60 deletions(-) diff --git a/Program.cs b/Program.cs index 1db1561..fb63860 100644 --- a/Program.cs +++ b/Program.cs @@ -376,33 +376,6 @@ public static int Main_OneArgument(string[] args) Console.WriteLine("Prepare a list of files to data sanitization"); } - var di = new DirectoryInfo(path); - var list = di.GetFiles("*", SearchOption.AllDirectories); - - if (flags.Contains("pr")) - { - var dt = progress.creationTime; - progress = new Progress(); - progress.creationTime = dt; - - foreach (var file in list) - { - progress.cntToRewrite += 1; - progress.SizeToRewrite += file.Length; - } - - if (zFlag >= 2) - progress.SizeToRewrite *= zFlag; - if (zFlag >= 4) - throw new NotImplementedException(); - - var dirList = di.EnumerateDirectories("*", SearchOption.AllDirectories); - foreach (var file in list) - { - progress.cntToRewrite += 1; - } - } - if (flags.Contains("sl")) { progress.slowDownFlag = 1; @@ -415,17 +388,48 @@ public static int Main_OneArgument(string[] args) Console.WriteLine("ndd - do not delete directories"); } - foreach (var file in list) - { - try - { - deleteFile(file, bt, progress: progress, true, verbose: verbose); - } - catch (UnauthorizedAccessException e) - { - Console.Error.WriteLine($"Error for file '{file.FullName}'\n{e.Message}\n{e.StackTrace}"); - } - } + var di = new DirectoryInfo(path); + + try + { + if (flags.Contains("pr")) + { + // var list = di.GetFiles("*", SearchOption.AllDirectories); + var list = di.EnumerateFiles("*", SearchOption.AllDirectories); + + var dt = progress.creationTime; + progress = new Progress(); + progress.creationTime = dt; + + foreach (var file in list) + { + try + { + progress.cntToRewrite += 1; + progress.SizeToRewrite += file.Length; + } + catch + {} + } + + if (zFlag >= 2) + progress.SizeToRewrite *= zFlag; + if (zFlag >= 4) + throw new NotImplementedException(); + + var dirList = di.EnumerateDirectories("*", SearchOption.AllDirectories); + foreach (var file in list) + { + progress.cntToRewrite += 1; + } + } + } + catch (Exception e) + { + Console.Error.WriteLine($"Error for calculate progress for '{di.FullName}'\n{e.Message}\n{e.StackTrace}"); + } + + DeleteFilesFromDir(di, bt: bt, progress: progress, verbose: verbose); di.Refresh(); var checkList = di.GetFiles(); @@ -497,6 +501,70 @@ public static int Main_OneArgument(string[] args) return 0; } + // Такая рекурсия нужна, потому что часть файлов могут быть недоступны по каким-то причинам для удаления и мы должны удалить хотя бы то, что можем + static void DeleteFilesFromDir(DirectoryInfo di, List bt, Progress progress, int verbose = 0) + { + // Удаляем файлы в директории + for (int @try = 0; @try < 2; @try++) + { + try + { + var list = di.EnumerateFiles("*", SearchOption.TopDirectoryOnly); + + foreach (var file in list) + { + try + { + file.Refresh(); + + if (file.Exists) + deleteFile(file, bt, progress: progress, true, verbose: verbose); + else + if (verbose >= 2) + Console.WriteLine($"File not exists'{file.FullName}' (removed from another program?)"); + } + catch (UnauthorizedAccessException e) + { + Console.Error.WriteLine($"Error (PD) for file '{file.FullName}'\n{e.Message}\n{e.StackTrace}"); + } + catch (Exception e) + { + Console.Error.WriteLine($"Error (1) for file '{file.FullName}'\n{e.Message}\n{e.StackTrace}"); + } + } + } + catch (Exception e) + { + Console.Error.WriteLine($"Error (1) for directory '{di.FullName}'\n{e.Message}\n{e.StackTrace}"); + } + } + + // Удаляем файлы в поддиректориях + for (int @try = 0; @try < 2; @try++) + { + try + { + var list = di.EnumerateDirectories("*", SearchOption.TopDirectoryOnly); + + foreach (var dir in list) + { + try + { + DeleteFilesFromDir(dir, bt: bt, progress: progress, verbose: verbose); + } + catch (Exception e) + { + Console.Error.WriteLine($"Error (1) for subdirectory '{dir.FullName}'\n{e.Message}\n{e.StackTrace}"); + } + } + } + catch (Exception e) + { + Console.Error.WriteLine($"Error (2) for directory '{di.FullName}'\n{e.Message}\n{e.StackTrace}"); + } + } + } + private static int GetVerboseFlag(string flags) { var verbose = flags.Contains("v") ? 1 : 0; @@ -826,6 +894,19 @@ private static void deleteDir(DirectoryInfo dir, Progress progress, int verbose if (verbose > 0) Console.WriteLine($"Try to delete directory \"{dir.FullName}\""); + var dirList = dir.GetDirectories(); + foreach (var di in dirList) + { + try + { + deleteDir(di, progress: progress, verbose: verbose); + } + catch (UnauthorizedAccessException e) + { + Console.Error.WriteLine($"Error for dir {di.FullName}\n{e.Message}\n{e.StackTrace}"); + } + } + var newFileName = dir.FullName; var fn = dir.Name; @@ -857,19 +938,6 @@ private static void deleteDir(DirectoryInfo dir, Progress progress, int verbose } } - var dirList = dir.GetDirectories(); - foreach (var di in dirList) - { - try - { - deleteDir(di, progress: progress, verbose: verbose); - } - catch (UnauthorizedAccessException e) - { - Console.Error.WriteLine($"Error for dir {di.FullName}\n{e.Message}\n{e.StackTrace}"); - } - } - Directory.Delete(newFileName); if (Directory.Exists(newFileName) || Directory.Exists(oldDirName)) Console.WriteLine($"Fail to delete directory \"{oldDirName}\""); @@ -886,14 +954,48 @@ private static void deleteFile(FileInfo file, List bt, Progress progress var oldFileName = file.FullName; if (verbose > 0) - Console.WriteLine($"Try to delete file \"{oldFileName}\""); - + { + if (file.LinkTarget is null) + { + Console.WriteLine($"Try to delete file \"{oldFileName}\""); + } + else + Console.WriteLine($"The wiping has been skipped for link with name \"{oldFileName}\""); + } + + var faMode = FileAccess.Write | FileAccess.Read; + if (file.LinkTarget is null) try { DateTime now, dt = DateTime.MinValue; TimeSpan ts; - - using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Write, FileShare.None, 1, FileOptions.WriteThrough)) + + FileStream? fs = null; + try + { + fs = new FileStream(file.FullName, FileMode.Open, faMode, FileShare.None, 1, FileOptions.WriteThrough); + } + catch + { + faMode = FileAccess.Write; + if (verbose > 1) + Console.WriteLine($"Can not open file with 'rw' mode: \"{oldFileName}\"\nWill try 'w' mode"); + + fs = new FileStream(file.FullName, FileMode.Open, faMode, FileShare.None, 1, FileOptions.WriteThrough); + } + + if (!fs.CanSeek) + { + Console.WriteLine($"File not support seeking and skipped (may be pipe or another service file): \"{oldFileName}\"\nWill try 'w' mode"); + fs.Close(); + fs = null; + } + + + // Есть файлы типа pipe, они зависают при попытке открыть их только на запись, но на чтение+запись открываются нормально + // prwx------ 1 root root 0 фев 17 12:27 /tmp/clr-debug-pipe-813-1941-in| + if (fs != null) + using (fs) { if (progress.slowDownFlag > 0) dt = DateTime.Now; @@ -938,7 +1040,7 @@ private static void deleteFile(FileInfo file, List bt, Progress progress try { fs.Seek(offset, SeekOrigin.Begin); - + // Выравниваем на границу 64 кб var c = offset & 65535; if (c != 0) @@ -987,7 +1089,7 @@ private static void deleteFile(FileInfo file, List bt, Progress progress newFileName = Path.Combine(file.DirectoryName!, fn); if (newFileName == oldFileName) continue; - + if (File.Exists(newFileName) || Directory.Exists(newFileName)) { if (onlyOne) @@ -1000,7 +1102,7 @@ private static void deleteFile(FileInfo file, List bt, Progress progress deleteFile(new FileInfo(newFileName), bt, progress: progress, false); } - + file.MoveTo(newFileName); break; } @@ -1012,8 +1114,16 @@ private static void deleteFile(FileInfo file, List bt, Progress progress } } - File.Open(newFileName, FileMode.Truncate).Close(); - File.Delete(newFileName); + try + { + File.Open(newFileName, FileMode.Truncate).Close(); + File.Delete(newFileName); // Если не получилось обрезать файл, не будем и удалять его, чтобы его можно было дальше обрезать каким-то другим способом и было понятно, что удаление не закончилось успехом + } + catch (Exception e) + { + //if (verbose > 0) + Console.WriteLine($"Fail to truncate file \"{oldFileName}\" with error: '{e.Message}'"); + } progress.rewritedCnt++; progress.showMessage();