From: Florian Eder Subject: [PATCH 07/41] robocopy: add max subdirectory depth (/LEV) Message-Id: <20210906145518.346132-7-others.meder@gmail.com> Date: Mon, 6 Sep 2021 14:54:44 +0000 In-Reply-To: <20210906145518.346132-1-others.meder@gmail.com> References: <20210906145518.346132-1-others.meder@gmail.com> Implements the /LEV:n switch, which sets the max subdirectory depth and sets default depth to 1 Signed-off-by: Florian Eder --- programs/robocopy/main.c | 27 +++++++++++++++++++++++---- programs/robocopy/robocopy.h | 2 ++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/programs/robocopy/main.c b/programs/robocopy/main.c index 050258ddab2..747c242e7de 100644 --- a/programs/robocopy/main.c +++ b/programs/robocopy/main.c @@ -136,10 +136,26 @@ static void parse_arguments(int argc, WCHAR *argv[]) memset(&options, 0, sizeof(options)); options.files = calloc(1, offsetof(struct path_array, array) + (argc * sizeof(WCHAR*))); + /* default values */ + options.max_subdirectories_depth = 1; + for (i = 1; i < argc; i++) { if (is_valid_robocopy_flag(argv[i])) - WINE_FIXME("encountered an unknown robocopy flag: %S\n", argv[i]); + /* lev - Limit depth of subdirectories */ + if (!wcsnicmp(argv[i], L"/lev:", 5)) + { + long value = 0; + value = wcstol(&(argv[i][5]), NULL, 10); + if (value >= 0) + { + options.max_subdirectories_depth = (UINT)value; + } + } + else + { + WINE_FIXME("encountered an unknown robocopy flag: %S\n", argv[i]); + } else { /* @@ -220,7 +236,7 @@ static BOOL create_directory_path(WCHAR *path) return TRUE; } -static void get_file_paths_in_folder(WCHAR *directory_path, struct list *paths) +static void get_file_paths_in_folder(WCHAR *directory_path, struct list *paths, UINT depth) { HANDLE temp_handle; struct path *new_path, *current_path; @@ -232,6 +248,7 @@ static void get_file_paths_in_folder(WCHAR *directory_path, struct list *paths) /* initialize list with a empty relative path */ new_path = calloc(1, sizeof(struct path)); new_path->name = calloc(2, sizeof(WCHAR)); + new_path->level = 1; list_add_tail(paths, &new_path->entry); LIST_FOR_EACH_ENTRY(current_path, paths, struct path, entry) @@ -258,10 +275,11 @@ static void get_file_paths_in_folder(WCHAR *directory_path, struct list *paths) /* If this entry is a matching file or empty directory, add it to the list of results */ if ((!PathIsDirectoryW(current_absolute_path) && matches_array_entry(entry_data.cFileName, options.files)) || - (PathIsDirectoryW(current_absolute_path))) + (PathIsDirectoryW(current_absolute_path) && (!depth || depth > current_path->level))) { new_path = calloc(1, sizeof(struct path)); new_path->name = wcsdup(current_relative_path); + new_path->level = current_path->level + 1; list_add_tail(paths, &new_path->entry); } } @@ -288,7 +306,7 @@ static BOOL perform_copy(void) create_directory_path(options.destination); /* get files in the destination folder and source folder */ - get_file_paths_in_folder(options.source, &paths_source); + get_file_paths_in_folder(options.source, &paths_source, options.max_subdirectories_depth); /* get files in the source folder */ LIST_FOR_EACH_ENTRY(current_path, &paths_source, struct path, entry) @@ -307,6 +325,7 @@ static BOOL perform_copy(void) } else { + create_directory_path(target_path); if (!CopyFileW(current_absolute_path, target_path, FALSE)) output_error(STRING_ERROR_WRITE_FILE, GetLastError(), strip_path_prefix(target_path)); else diff --git a/programs/robocopy/robocopy.h b/programs/robocopy/robocopy.h index 1cd0a427c03..0e33effe331 100644 --- a/programs/robocopy/robocopy.h +++ b/programs/robocopy/robocopy.h @@ -23,6 +23,7 @@ struct path { struct list entry; WCHAR *name; + UINT level; }; struct path_array { @@ -34,6 +35,7 @@ struct robocopy_options { WCHAR *destination; WCHAR *source; struct path_array* files; + UINT max_subdirectories_depth; }; /* Resource strings */ -- 2.32.0