[PATCH 28/41] robocopy: add min / max file size flag (/MIN, /MAX)

Florian Eder others.meder at gmail.com
Mon Sep 6 09:55:05 CDT 2021


Implements the /MIN:n and /MAX:n switches, which causes only files
smaller or bigger than the set values to be included in any copy operation

Signed-off-by: Florian Eder <others.meder at gmail.com>
---
Both switches in one patch, as both are very closely connected and share
some code
---
 programs/robocopy/main.c     | 46 ++++++++++++++++++++++++++++++++++++
 programs/robocopy/robocopy.h |  2 ++
 2 files changed, 48 insertions(+)

diff --git a/programs/robocopy/main.c b/programs/robocopy/main.c
index 4f1b07e8954..47ed5a12371 100644
--- a/programs/robocopy/main.c
+++ b/programs/robocopy/main.c
@@ -141,6 +141,7 @@ static void parse_arguments(int argc, WCHAR *argv[])
 
     /* default values */
     options.max_subdirectories_depth = 1;
+    options.max_size = MAXLONGLONG;
 
     for (i = 1; i < argc; i++)
     {
@@ -216,6 +217,20 @@ static void parse_arguments(int argc, WCHAR *argv[])
                     options.user_limited_subdirectories_depth = TRUE;
                 }
             }
+            /* max - Include only smaller files */
+            else if (!wcsnicmp(argv[i], L"/max:", 5))
+            {
+                LONGLONG value = 0;
+                if (swscanf(&(argv[i][5]), L"%lld", &value) == 1 && value >= 0)
+                    options.max_size = value;
+            }
+            /* min - Include only bigger files */
+            else if (!wcsnicmp(argv[i], L"/min:", 5))
+            {
+                LONGLONG value = 0;
+                if (swscanf(&(argv[i][5]), L"%lld", &value) == 1 && value >= 0)
+                    options.min_size = value;
+            }
             else
             {
                 WINE_FIXME("encountered an unknown robocopy flag: %S\n", argv[i]);
@@ -381,6 +396,24 @@ static void get_file_paths_in_folder(WCHAR *directory_path, struct list *paths,
     }
 }
 
+static BOOL is_valid_file(WCHAR *source)
+{
+    HANDLE source_handle;
+    LARGE_INTEGER source_size;
+    source_handle = CreateFileW(source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+    if (source_handle == INVALID_HANDLE_VALUE) return FALSE;
+    GetFileSizeEx(source_handle, &source_size);
+    /* ignore file if source is not within max / min size */
+    if (source_size.QuadPart < options.min_size ||
+        source_size.QuadPart > options.max_size)
+    {
+        CloseHandle(source_handle);
+        return FALSE;
+    }
+    CloseHandle(source_handle);
+    return TRUE;
+}
+
 static BOOL perform_copy(struct robocopy_statistics *statistics)
 {
     struct list paths_source, paths_destination;
@@ -425,6 +458,9 @@ static BOOL perform_copy(struct robocopy_statistics *statistics)
         }
         else
         {
+            /* ignore file if the file size is not within the allowed limits */
+            if (!is_valid_file(current_absolute_path)) continue;
+
             if (options.dry_run || copy_or_move_file(current_absolute_path, target_path, options.purge_source_files))
             {
                 output_message(options.purge_source_files ? STRING_MOVE_FILE : STRING_CREATE_FILE, strip_path_prefix(target_path));
@@ -532,6 +568,16 @@ static WCHAR *get_option_string(void)
             wcscat(temp_string, L"/MOV ");
     }
 
+    /* Max File Size */
+    if (options.max_size != MAXLONGLONG)
+        swprintf(temp_string + wcslen(temp_string), ARRAY_SIZE(temp_string) - wcslen(temp_string),
+                 L"/MAX:%lld ", options.max_size);
+
+    /* Min File Size */
+    if (options.min_size != 0)
+        swprintf(temp_string + wcslen(temp_string), ARRAY_SIZE(temp_string) - wcslen(temp_string),
+                 L"/MIN:%lld ", options.min_size);
+
     string = wcsdup(temp_string);
     return string;
 }
diff --git a/programs/robocopy/robocopy.h b/programs/robocopy/robocopy.h
index 9e3137109b8..0d498a9649c 100644
--- a/programs/robocopy/robocopy.h
+++ b/programs/robocopy/robocopy.h
@@ -46,6 +46,8 @@ struct robocopy_options {
     BOOL purge_destination;
     BOOL mirror;
     BOOL dry_run;
+    LONGLONG min_size;
+    LONGLONG max_size;
 };
 
 struct robocopy_statistics {
-- 
2.32.0




More information about the wine-devel mailing list