[PATCH 23/41] robocopy: add excluded file / directory parser (/XF, /XD)
Florian Eder
others.meder at gmail.com
Mon Sep 6 09:55:00 CDT 2021
Implements the /XF and /XD switches, which set file and directory names that
are excluded from any robocopy operation
Signed-off-by: Florian Eder <others.meder at gmail.com>
---
Both switches in one patch because the code is almost identical for both
---
programs/robocopy/main.c | 46 +++++++++++++++++++++++++++++++++--
programs/robocopy/robocopy.h | 4 +++
programs/robocopy/robocopy.rc | 2 ++
3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/programs/robocopy/main.c b/programs/robocopy/main.c
index 1cfbe65e94b..41ed29f1725 100644
--- a/programs/robocopy/main.c
+++ b/programs/robocopy/main.c
@@ -132,9 +132,12 @@ WCHAR *get_absolute_path_with_trailing_backslash(WCHAR *path)
static void parse_arguments(int argc, WCHAR *argv[])
{
int i;
+ BOOL is_xd = FALSE, is_xf = FALSE;
memset(&options, 0, sizeof(options));
options.files = calloc(1, offsetof(struct path_array, array) + (argc * sizeof(WCHAR*)));
+ options.excluded_filenames = calloc(1, offsetof(struct path_array, array) + (argc * sizeof(WCHAR*)));
+ options.excluded_directories = calloc(1, offsetof(struct path_array, array) + (argc * sizeof(WCHAR*)));
/* default values */
options.max_subdirectories_depth = 1;
@@ -142,6 +145,8 @@ static void parse_arguments(int argc, WCHAR *argv[])
for (i = 1; i < argc; i++)
{
if (is_valid_robocopy_flag(argv[i]))
+ {
+ is_xd = FALSE; is_xf = FALSE;
/* s - Copy Subdirectories */
if (!wcsicmp(argv[i], L"/s"))
{
@@ -183,6 +188,18 @@ static void parse_arguments(int argc, WCHAR *argv[])
options.purge_source = TRUE;
options.purge_source_files = TRUE;
}
+ /* xf - Excluded Files */
+ else if (!wcsicmp(argv[i], L"/xf"))
+ {
+ /* xf includes all following files, until the next option / flag */
+ is_xf = TRUE;
+ }
+ /* xd - Excluded Directories */
+ else if (!wcsicmp(argv[i], L"/xd"))
+ {
+ /* xd includes all following directories, until the next option / flag */
+ is_xd = TRUE;
+ }
/* lev - Limit depth of subdirectories */
else if (!wcsnicmp(argv[i], L"/lev:", 5))
{
@@ -198,13 +215,26 @@ static void parse_arguments(int argc, WCHAR *argv[])
{
WINE_FIXME("encountered an unknown robocopy flag: %S\n", argv[i]);
}
+ }
else
{
/*
*(Probably) not a flag, we can parse it as the source / the destination / a filename
- * Priority: Source > Destination > (more than one) File
+ * Priority: Excluded > Source > Destination > (more than one) File
*/
- if (!options.source)
+ if (is_xf)
+ {
+ options.excluded_filenames->array[options.excluded_filenames->size] = calloc(wcslen(argv[i]) + 1, sizeof(WCHAR));
+ wcscpy(options.excluded_filenames->array[options.excluded_filenames->size], argv[i]);
+ options.excluded_filenames->size++;
+ }
+ else if (is_xd)
+ {
+ options.excluded_directories->array[options.excluded_directories->size] = calloc(wcslen(argv[i]) + 1, sizeof(WCHAR));
+ wcscpy(options.excluded_directories->array[options.excluded_directories->size], argv[i]);
+ options.excluded_directories->size++;
+ }
+ else if (!options.source)
{
options.source = get_absolute_path_with_trailing_backslash(argv[i]);
}
@@ -327,6 +357,10 @@ static void get_file_paths_in_folder(WCHAR *directory_path, struct list *paths,
current_relative_path = get_combined_path(current_path->name, entry_data.cFileName);
current_absolute_path = get_combined_path(directory_path, current_relative_path);
+ /* Ignore if it's an excluded folder or file */
+ if (matches_array_entry(entry_data.cFileName, PathIsDirectoryW(current_absolute_path) ?
+ options.excluded_directories : options.excluded_filenames)) continue;
+
/* 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) && (!depth || depth > current_path->level)))
@@ -509,6 +543,14 @@ static void print_header(void)
for (i = 1; i < options.files->size; i++)
output_message(STRING_ADDITIONAL_INFO, options.files->array[i]);
+ if (options.excluded_filenames->size > 0) output_message(STRING_EXCLUDED_FILES, options.excluded_filenames->array[0]);
+ for (i = 1; i < options.excluded_filenames->size; i++)
+ output_message(STRING_ADDITIONAL_INFO, options.excluded_filenames->array[i]);
+
+ if (options.excluded_directories->size > 0) output_message(STRING_EXCLUDED_DIRECTORIES, options.excluded_directories->array[0]);
+ for (i = 1; i < options.excluded_directories->size; i++)
+ output_message(STRING_ADDITIONAL_INFO, options.excluded_directories->array[i]);
+
options_string = get_option_string();
if (options_string != NULL) output_message(STRING_OPTIONS, options_string);
}
diff --git a/programs/robocopy/robocopy.h b/programs/robocopy/robocopy.h
index aa58240d8cc..1818fdf90f1 100644
--- a/programs/robocopy/robocopy.h
+++ b/programs/robocopy/robocopy.h
@@ -35,6 +35,8 @@ struct robocopy_options {
WCHAR *destination;
WCHAR *source;
struct path_array* files;
+ struct path_array* excluded_filenames;
+ struct path_array* excluded_directories;
UINT max_subdirectories_depth;
BOOL user_limited_subdirectories_depth;
BOOL copy_subdirectories;
@@ -62,6 +64,8 @@ struct robocopy_statistics {
#define STRING_SOURCE 1003
#define STRING_DESTINATION 1004
#define STRING_FILES 1005
+#define STRING_EXCLUDED_FILES 1006
+#define STRING_EXCLUDED_DIRECTORIES 1007
#define STRING_ADDITIONAL_INFO 1008
#define STRING_OPTIONS 1009
#define STRING_MISSING_DESTINATION_OR_SOURCE 1010
diff --git a/programs/robocopy/robocopy.rc b/programs/robocopy/robocopy.rc
index cdb03085315..315dce5f947 100644
--- a/programs/robocopy/robocopy.rc
+++ b/programs/robocopy/robocopy.rc
@@ -29,6 +29,8 @@ STRINGTABLE
STRING_SOURCE, " Source: %1\n"
STRING_DESTINATION, " Destination: %1\n\n"
STRING_FILES, " Files: %1\n"
+ STRING_EXCLUDED_FILES, "\n Excluded Files: %1\n"
+ STRING_EXCLUDED_DIRECTORIES, "\n Excluded Dirs: %1\n"
STRING_ADDITIONAL_INFO, " %1\n"
STRING_OPTIONS, "\n Options: %1\n\n"
STRING_MISSING_DESTINATION_OR_SOURCE, "No destination or source specified, can't copy anything\n"
--
2.32.0
More information about the wine-devel
mailing list