diff --git a/gio/gfile.c b/gio/gfile.c index c7658caa2..8c3fc48de 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -2743,10 +2743,12 @@ open_source_for_copy (GFile *source, static gboolean should_copy (GFileAttributeInfo *info, gboolean copy_all_attributes, - gboolean skip_perms) + gboolean skip_perms, + gboolean skip_modified_time) { - if (skip_perms && strcmp(info->name, "unix::mode") == 0) - return FALSE; + if ((skip_perms && strcmp(info->name, "unix::mode") == 0) || + (skip_modified_time && strncmp(info->name, "time::modified", 14) == 0)) + return FALSE; if (copy_all_attributes) return info->flags & G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED; @@ -2789,6 +2791,7 @@ g_file_build_attribute_list_for_copy (GFile *file, int i; gboolean copy_all_attributes; gboolean skip_perms; + gboolean skip_modified_time; g_return_val_if_fail (G_IS_FILE (file), NULL); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); @@ -2796,6 +2799,7 @@ g_file_build_attribute_list_for_copy (GFile *file, copy_all_attributes = flags & G_FILE_COPY_ALL_METADATA; skip_perms = (flags & G_FILE_COPY_TARGET_DEFAULT_PERMS) != 0; + skip_modified_time = (flags & G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME) != 0; /* Ignore errors here, if the target supports no attributes there is * nothing to copy. We still honor the cancellable though. @@ -2823,7 +2827,7 @@ g_file_build_attribute_list_for_copy (GFile *file, { for (i = 0; i < attributes->n_infos; i++) { - if (should_copy (&attributes->infos[i], copy_all_attributes, skip_perms)) + if (should_copy (&attributes->infos[i], copy_all_attributes, skip_perms, skip_modified_time)) { if (first) first = FALSE; @@ -2839,7 +2843,7 @@ g_file_build_attribute_list_for_copy (GFile *file, { for (i = 0; i < namespaces->n_infos; i++) { - if (should_copy (&namespaces->infos[i], copy_all_attributes, FALSE)) + if (should_copy (&namespaces->infos[i], copy_all_attributes, FALSE, FALSE)) { if (first) first = FALSE; diff --git a/gio/gio-tool-copy.c b/gio/gio-tool-copy.c index 4a1dc4368..1b7ab48dc 100644 --- a/gio/gio-tool-copy.c +++ b/gio/gio-tool-copy.c @@ -40,6 +40,7 @@ static gboolean preserve = FALSE; static gboolean backup = FALSE; static gboolean no_dereference = FALSE; static gboolean default_permissions = FALSE; +static gboolean default_modified_time = FALSE; static const GOptionEntry entries[] = { { "no-target-directory", 'T', 0, G_OPTION_ARG_NONE, &no_target_directory, N_("No target directory"), NULL }, @@ -49,6 +50,7 @@ static const GOptionEntry entries[] = { { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, N_("Backup existing destination files"), NULL }, { "no-dereference", 'P', 0, G_OPTION_ARG_NONE, &no_dereference, N_("Never follow symbolic links"), NULL }, { "default-permissions", 0, 0, G_OPTION_ARG_NONE, &default_permissions, N_("Use default permissions for the destination"), NULL }, + { "default-modified-time", 0, 0, G_OPTION_ARG_NONE, &default_modified_time, N_("Use default file modification timestamps for the destination"), NULL }, G_OPTION_ENTRY_NULL }; @@ -181,6 +183,8 @@ handle_copy (int argc, char *argv[], gboolean do_help) flags |= G_FILE_COPY_ALL_METADATA; if (default_permissions) flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS; + if (default_modified_time) + flags |= G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME; error = NULL; start_time = g_get_monotonic_time (); diff --git a/gio/gioenums.h b/gio/gioenums.h index c820cd36d..a524acca8 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -314,6 +314,8 @@ typedef enum { * @G_FILE_COPY_ALL_METADATA: Copy all file metadata instead of just default set used for copy (see #GFileInfo). * @G_FILE_COPY_NO_FALLBACK_FOR_MOVE: Don't use copy and delete fallback if native move not supported. * @G_FILE_COPY_TARGET_DEFAULT_PERMS: Leaves target file with default perms, instead of setting the source file perms. + * @G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME: Use default modification + * timestamps instead of copying them from the source file. Since 2.80 * * Flags used when copying or moving files. */ @@ -324,7 +326,8 @@ typedef enum { G_FILE_COPY_NOFOLLOW_SYMLINKS = (1 << 2), G_FILE_COPY_ALL_METADATA = (1 << 3), G_FILE_COPY_NO_FALLBACK_FOR_MOVE = (1 << 4), - G_FILE_COPY_TARGET_DEFAULT_PERMS = (1 << 5) + G_FILE_COPY_TARGET_DEFAULT_PERMS = (1 << 5), + G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME GIO_AVAILABLE_ENUMERATOR_IN_2_80 = (1 << 6), } GFileCopyFlags; diff --git a/gio/tests/file.c b/gio/tests/file.c index 310981b5d..3ece6d4fa 100644 --- a/gio/tests/file.c +++ b/gio/tests/file.c @@ -2451,12 +2451,15 @@ test_copy_preserve_mode (void) { 0600, 0600, TRUE, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS }, /* The same behaviour should hold if the destination file is not being * overwritten because it doesn’t already exist: */ + { 0600, 0600, FALSE, G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME | G_FILE_COPY_ALL_METADATA }, { 0600, 0600, FALSE, G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA }, { 0600, 0600, FALSE, G_FILE_COPY_NOFOLLOW_SYMLINKS }, /* Anything with %G_FILE_COPY_TARGET_DEFAULT_PERMS should use the current * umask for the destination file: */ { 0600, 0666 & ~current_umask, TRUE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA }, { 0600, 0666 & ~current_umask, TRUE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS }, + { 0600, 0666 & ~current_umask, FALSE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME | G_FILE_COPY_ALL_METADATA }, + { 0600, 0666 & ~current_umask, FALSE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME }, { 0600, 0666 & ~current_umask, FALSE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA }, { 0600, 0666 & ~current_umask, FALSE, G_FILE_COPY_TARGET_DEFAULT_PERMS | G_FILE_COPY_NOFOLLOW_SYMLINKS }, }; @@ -3375,6 +3378,9 @@ test_build_attribute_list_for_copy (void) G_FILE_COPY_TARGET_DEFAULT_PERMS, G_FILE_COPY_ALL_METADATA, G_FILE_COPY_ALL_METADATA | G_FILE_COPY_TARGET_DEFAULT_PERMS, + G_FILE_COPY_ALL_METADATA | G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME, + G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME | G_FILE_COPY_TARGET_DEFAULT_PERMS, + G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME, }; gsize i; char *attrs; @@ -3416,8 +3422,16 @@ test_build_attribute_list_for_copy (void) } #endif #ifdef HAVE_UTIMES - g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",")); - g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ",")); + if (flags & G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME) + { + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",")); + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ",")); + } + else + { + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",")); + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ",")); + } if (flags & G_FILE_COPY_ALL_METADATA) { g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ",")); @@ -3430,8 +3444,16 @@ test_build_attribute_list_for_copy (void) } #endif #ifdef HAVE_UTIMENSAT - g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",")); - g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC ",")); + if (flags & G_FILE_COPY_TARGET_DEFAULT_MODIFIED_TIME) + { + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",")); + g_assert_null (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC ",")); + } + else + { + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED ",")); + g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC ",")); + } if (flags & G_FILE_COPY_ALL_METADATA) { g_assert_nonnull (g_strstr_len (attrs_with_commas, -1, "," G_FILE_ATTRIBUTE_TIME_ACCESS ","));