Implements the /XX and /XL flags, which prevent the overwriting / deletion of files that only exist in the source, but not the destination, or only the destination, but not the source, by flags like /PURGE or /MOVE
Signed-off-by: Florian Eder others.meder@gmail.com --- programs/robocopy/main.c | 26 ++++++++++++++++++++++++-- programs/robocopy/robocopy.h | 2 ++ 2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/programs/robocopy/main.c b/programs/robocopy/main.c index 2fc0c39503d..620154b58c8 100644 --- a/programs/robocopy/main.c +++ b/programs/robocopy/main.c @@ -254,6 +254,16 @@ static void parse_arguments(int argc, WCHAR *argv[]) /* xd includes all following directories, until the next option / flag */ is_xd = TRUE; } + /* xx - Ignore files in destination that are not also in source */ + else if (!wcsicmp(argv[i], L"/xx")) + { + options.exclude_files_not_in_source = TRUE; + } + /* xl - Create no new files in destination folder */ + else if (!wcsicmp(argv[i], L"/xl")) + { + options.create_no_new_files = TRUE; + } /* lev - Limit depth of subdirectories */ else if (!wcsnicmp(argv[i], L"/lev:", 5)) { @@ -483,6 +493,8 @@ static BOOL is_valid_file(WCHAR *source, WCHAR *destination) if (destination_handle == INVALID_HANDLE_VALUE) { CloseHandle(source_handle); + /* ignore file if no file at the destination path exist and no no files should be created */ + if (options.create_no_new_files) return FALSE; return TRUE; } GetFileTime(destination_handle, &destination_creation_time, &destination_access_time, &destination_modified_time); @@ -533,7 +545,9 @@ static BOOL perform_copy(struct robocopy_statistics *statistics) if (PathIsDirectoryW(current_absolute_path)) { /* ignore empty directories if empty subdirectories are not copied */ - if ((PathIsDirectoryEmptyW(current_absolute_path) && !options.copy_empty_subdirectories)) continue; + if ((PathIsDirectoryEmptyW(current_absolute_path) && !options.copy_empty_subdirectories) || + options.create_no_new_files) + continue;
/* Create the directory path and then create the directory itself */ if (!options.dry_run && (!create_directory_path(target_path) || @@ -586,7 +600,7 @@ static BOOL perform_copy(struct robocopy_statistics *statistics) else statistics->extra_files = TRUE;
/* if purge is specified (and xx is not set), we delete the (non-excluded) extra files and folders from the destination */ - if (options.purge_destination) + if (options.purge_destination && !options.exclude_files_not_in_source) { current_absolute_path = get_combined_path(options.destination, current_path->name); /* only files or empty folders */ @@ -662,6 +676,14 @@ static WCHAR *get_option_string(void) if (options.dont_overwrite_older_files) wcscat(temp_string, L"/XO ");
+ /* Ignore files in destination only */ + if (options.exclude_files_not_in_source) + wcscat(temp_string, L"/XX "); + + /* No new files */ + if (options.create_no_new_files) + wcscat(temp_string, L"/XL "); + /* Max File Size */ if (options.max_size != MAXLONGLONG) swprintf(temp_string + wcslen(temp_string), ARRAY_SIZE(temp_string) - wcslen(temp_string), diff --git a/programs/robocopy/robocopy.h b/programs/robocopy/robocopy.h index cf396f88dfc..376c466d907 100644 --- a/programs/robocopy/robocopy.h +++ b/programs/robocopy/robocopy.h @@ -52,6 +52,8 @@ struct robocopy_options { FILETIME max_time; BOOL dont_overwrite_newer_files; BOOL dont_overwrite_older_files; + BOOL exclude_files_not_in_source; + BOOL create_no_new_files; };
struct robocopy_statistics {