From fe34628a814a22ff1c07e64a21028d8cb5240771 Mon Sep 17 00:00:00 2001 From: Corey Berla Date: Mon, 23 Jan 2023 14:26:52 -0800 Subject: file-operations: Warn before copying/moving >4GiB file to FAT Nautilus attempts to copy/move >4GiB files to a FAT volume and fail once it reaches the 4GiB threshold. The verify_destination() function already scans all of the source files before a copy / move, so we can add a 4GiB check with almost no overhead. Add attributes to the SourceInfo to track the largest file. If that file exceeds 4GiB, warn before initiating the operation. Similar to the existing before of copying to a volume with insufficient space, allow forcing the copy. Fixes: https://gitlab.gnome.org/GNOME/nautilus/-/issues/1899 --- src/nautilus-file-operations.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c index 09780b35b..78a72a210 100644 --- a/src/nautilus-file-operations.c +++ b/src/nautilus-file-operations.c @@ -269,6 +269,7 @@ G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (SourceInfo, source_info_clear) #define LONG_JOB_THRESHOLD_IN_SECONDS 2 #define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH 50 +#define MAXIMUM_FAT_FILE_SIZE G_MAXUINT32 #define IS_IO_ERROR(__error, KIND) (((__error)->domain == G_IO_ERROR && (__error)->code == G_IO_ERROR_ ## KIND)) @@ -3728,8 +3729,8 @@ scan_sources (GList *files, static void verify_destination (CommonJob *job, GFile *dest, - char **dest_fs_id, - goffset required_size) + GStrv dest_fs_id, + SourceInfo *source_info) { GFileInfo *info, *fsinfo; GError *error; @@ -3740,6 +3741,7 @@ verify_destination (CommonJob *job, int response; GFileType file_type; gboolean dest_is_symlink = FALSE; + goffset required_size = (source_info != NULL) ? source_info->num_bytes : -1; if (dest_fs_id) { @@ -3921,6 +3923,29 @@ retry: } } + if (!job_aborted (job) && + source_info != NULL && source_info->largest_file_bytes >= G_MAXUINT32 && + (g_strcmp0 (fs_type, "exfat") == 0 || g_strcmp0 (fs_type, "msdos") == 0)) + { + g_autofree gchar *formatted_size = g_format_size (source_info->largest_file_bytes); + + primary = g_strdup (_("File too Large for Destination")); + secondary = g_strdup (_("The FAT filesystem does not allow files over 4GiB.")); + /* Translators: Example string is "file.txt has a size of 5GiB" */ + details = g_strdup_printf (_("%s has a size of %s"), + source_info->largest_file_name, + formatted_size); + response = run_warning (job, + primary, secondary, details, + FALSE, + CANCEL, FORCE_OPERATION, NULL); + + if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) + { + abort_job (job); + } + } + if (!job_aborted (job) && g_file_info_get_attribute_boolean (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)) @@ -6101,7 +6126,7 @@ nautilus_file_operations_copy (GTask *task, verify_destination (&job->common, dest, &dest_fs_id, - source_info.num_bytes); + &source_info); g_object_unref (dest); if (job_aborted (common)) { @@ -6799,7 +6824,7 @@ nautilus_file_operations_move (GTask *task, verify_destination (&job->common, job->destination, &dest_fs_id, - -1); + NULL); if (job_aborted (common)) { goto aborted; @@ -6846,7 +6871,7 @@ nautilus_file_operations_move (GTask *task, verify_destination (&job->common, job->destination, NULL, - source_info.num_bytes); + &source_info); if (job_aborted (common)) { goto aborted; @@ -7126,7 +7151,7 @@ link_task_thread_func (GTask *task, verify_destination (&job->common, job->destination, NULL, - -1); + NULL); if (job_aborted (common)) { return; @@ -7650,7 +7675,7 @@ create_task_thread_func (GTask *task, verify_destination (common, job->dest_dir, - NULL, -1); + NULL, NULL); if (job_aborted (common)) { return; -- cgit v1.2.1