From ba8099fe575846ee08a4501e900c71bef53caafb Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sun, 13 Oct 2024 17:44:09 +0300 Subject: [PATCH] Calculate pauses in file operations. * (file_op_context_t): new 'pauses' member. * (file_error): pass file operation context to calculate pause. * (real_warn_same_file): likewise. * (real_do_file_error): likewise. * (real_query_recursive): calculate pause. * (overwrite_query_dialog): likewise. * (calc_copy_file_progress): calculate use ctx->pauses to calculate ETA. * (warn_same_file): * (check_same_file): * (check_hardlinks): * (make_symlink): * (do_file_error): * (files_error): * (try_remove_file): * (move_file_file): * (try_erase_dir): * (do_move_dir_dir): * (copy_file_file): * (copy_dir_dir): * (panel_operate): * (tree_move): related changes. Signed-off-by: Andrew Borodin --- src/filemanager/file.c | 169 +++++++++++++++++++++++--------------- src/filemanager/file.h | 3 +- src/filemanager/filegui.c | 5 ++ src/filemanager/filegui.h | 3 + src/filemanager/tree.c | 2 +- 5 files changed, 114 insertions(+), 68 deletions(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index ccf92a8cad..38f80ec3db 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -361,7 +361,7 @@ is_in_linklist (const GSList *lp, const vfs_path_t *vpath, const struct stat *sb */ static hardlink_status_t -check_hardlinks (const vfs_path_t *src_vpath, const struct stat *src_stat, +check_hardlinks (file_op_context_t *ctx, const vfs_path_t *src_vpath, const struct stat *src_stat, const vfs_path_t *dst_vpath, gboolean *ignore_all) { link_t *lnk; @@ -405,7 +405,7 @@ check_hardlinks (const vfs_path_t *src_vpath, const struct stat *src_stat, FileProgressStatus status; status = - file_error (TRUE, _("Cannot stat hardlink source file \"%s\"\n%s"), + file_error (ctx, TRUE, _("Cannot stat hardlink source file \"%s\"\n%s"), vfs_path_as_str (lnk->dst_vpath)); if (status == FILE_ABORT) return HARDLINK_ABORT; @@ -425,7 +425,7 @@ check_hardlinks (const vfs_path_t *src_vpath, const struct stat *src_stat, FileProgressStatus status; status = - file_error (TRUE, _("Cannot create target hardlink \"%s\"\n%s"), + file_error (ctx, TRUE, _("Cannot create target hardlink \"%s\"\n%s"), vfs_path_as_str (dst_vpath)); if (status == FILE_ABORT) return HARDLINK_ABORT; @@ -461,7 +461,7 @@ check_hardlinks (const vfs_path_t *src_vpath, const struct stat *src_stat, */ errno = 0; status = - file_error (FALSE, _("Cannot create target hardlink \"%s\""), + file_error (ctx, FALSE, _("Cannot create target hardlink \"%s\""), vfs_path_as_str (dst_vpath)); if (status == FILE_ABORT) @@ -524,7 +524,8 @@ make_symlink (file_op_context_t *ctx, const vfs_path_t *src_vpath, const vfs_pat return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot read source link \"%s\"\n%s"), src_path); + return_status = + file_error (ctx, TRUE, _("Cannot read source link \"%s\"\n%s"), src_path); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_RETRY) @@ -608,7 +609,8 @@ make_symlink (file_op_context_t *ctx, const vfs_path_t *src_vpath, const vfs_pat return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot create target symlink \"%s\"\n%s"), dst_path); + return_status = + file_error (ctx, TRUE, _("Cannot create target symlink \"%s\"\n%s"), dst_path); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_RETRY) @@ -843,13 +845,17 @@ progress_update_one (gboolean success, file_op_context_t *ctx, off_t add) /* --------------------------------------------------------------------------------------------- */ static FileProgressStatus -real_warn_same_file (enum OperationMode mode, const char *fmt, const char *a, const char *b) +real_warn_same_file (file_op_context_t *ctx, enum OperationMode mode, const char *fmt, + const char *a, const char *b) { + gint64 t; char *msg; int result = 0; const char *head_msg; int width_a, width_b, width; + t = g_get_monotonic_time (); + head_msg = mode == Foreground ? MSG_ERROR : _("Background process error"); width_a = str_term_width1 (a); @@ -885,44 +891,46 @@ real_warn_same_file (enum OperationMode mode, const char *fmt, const char *a, co g_free (msg); do_refresh (); + ctx->pauses += g_get_monotonic_time () - t; + return (result == 1) ? FILE_ABORT : FILE_SKIP; } /* --------------------------------------------------------------------------------------------- */ static FileProgressStatus -warn_same_file (const char *fmt, const char *a, const char *b) +warn_same_file (file_op_context_t *ctx, const char *fmt, const char *a, const char *b) { #ifdef ENABLE_BACKGROUND /* *INDENT-OFF* */ union { void *p; - FileProgressStatus (*f) (enum OperationMode, const char *fmt, const char *a, const char *b); + FileProgressStatus (*f) (file_op_context_t *ctx, enum OperationMode, const char *fmt, const char *a, const char *b); } pntr; /* *INDENT-ON* */ pntr.f = real_warn_same_file; if (mc_global.we_are_background) - return parent_call (pntr.p, NULL, 3, strlen (fmt), fmt, strlen (a), a, strlen (b), b); + return parent_call (pntr.p, ctx, 3, strlen (fmt), fmt, strlen (a), a, strlen (b), b); #endif - return real_warn_same_file (Foreground, fmt, a, b); + return real_warn_same_file (ctx, Foreground, fmt, a, b); } /* --------------------------------------------------------------------------------------------- */ static gboolean -check_same_file (const char *a, const struct stat *ast, const char *b, const struct stat *bst, - FileProgressStatus *status) +check_same_file (file_op_context_t *ctx, const char *a, const struct stat *ast, const char *b, + const struct stat *bst, FileProgressStatus *status) { if (ast->st_dev != bst->st_dev || ast->st_ino != bst->st_ino) return FALSE; if (S_ISDIR (ast->st_mode)) - *status = warn_same_file (_("\"%s\"\nand\n\"%s\"\nare the same directory"), a, b); + *status = warn_same_file (ctx, _("\"%s\"\nand\n\"%s\"\nare the same directory"), a, b); else - *status = warn_same_file (_("\"%s\"\nand\n\"%s\"\nare the same file"), a, b); + *status = warn_same_file (ctx, _("\"%s\"\nand\n\"%s\"\nare the same file"), a, b); return TRUE; } @@ -931,11 +939,16 @@ check_same_file (const char *a, const struct stat *ast, const char *b, const str /* {{{ Query/status report routines */ static FileProgressStatus -real_do_file_error (enum OperationMode mode, gboolean allow_retry, const char *error) +real_do_file_error (file_op_context_t *ctx, enum OperationMode mode, gboolean allow_retry, + const char *error) { + gint64 t; int result; const char *msg; + if (ctx != NULL) + t = g_get_monotonic_time (); + msg = mode == Foreground ? MSG_ERROR : _("Background process error"); if (allow_retry) @@ -945,6 +958,9 @@ real_do_file_error (enum OperationMode mode, gboolean allow_retry, const char *e else result = query_dialog (msg, error, D_ERROR, 3, _("&Ignore"), _("Ignore a&ll"), _("&Abort")); + if (ctx != NULL) + ctx->pauses += g_get_monotonic_time () - t; + switch (result) { case 0: @@ -976,9 +992,12 @@ real_query_recursive (file_op_context_t *ctx, enum OperationMode mode, const cha { if (ctx->recursive_result < RECURSIVE_ALWAYS) { + gint64 t; const char *msg; char *text; + t = g_get_monotonic_time (); + msg = mode == Foreground ? _("Directory \"%s\" not empty.\nDelete it recursively?") : _("Background process:\nDirectory \"%s\" not empty.\nDelete it recursively?"); @@ -994,6 +1013,8 @@ real_query_recursive (file_op_context_t *ctx, enum OperationMode mode, const cha if (ctx->recursive_result != RECURSIVE_ABORT) do_refresh (); + + ctx->pauses += g_get_monotonic_time () - t; } switch (ctx->recursive_result) @@ -1016,22 +1037,22 @@ real_query_recursive (file_op_context_t *ctx, enum OperationMode mode, const cha #ifdef ENABLE_BACKGROUND static FileProgressStatus -do_file_error (gboolean allow_retry, const char *str) +do_file_error (file_op_context_t *ctx, gboolean allow_retry, const char *str) { /* *INDENT-OFF* */ union { void *p; - FileProgressStatus (*f) (enum OperationMode, gboolean, const char *); + FileProgressStatus (*f) (file_op_context_t *ctx, enum OperationMode, gboolean, const char *); } pntr; /* *INDENT-ON* */ pntr.f = real_do_file_error; if (mc_global.we_are_background) - return parent_call (pntr.p, NULL, 2, sizeof (allow_retry), allow_retry, strlen (str), str); + return parent_call (pntr.p, ctx, 2, sizeof (allow_retry), allow_retry, strlen (str), str); else - return real_do_file_error (Foreground, allow_retry, str); + return real_do_file_error (ctx, Foreground, allow_retry, str); } /* --------------------------------------------------------------------------------------------- */ @@ -1111,7 +1132,7 @@ query_replace (file_op_context_t *ctx, const char *src, struct stat *src_stat, c /** Report error with two files */ static FileProgressStatus -files_error (const char *format, const char *file1, const char *file2) +files_error (file_op_context_t *ctx, const char *format, const char *file1, const char *file2) { char buf[BUF_MEDIUM]; char *nfile1, *nfile2; @@ -1122,7 +1143,7 @@ files_error (const char *format, const char *file1, const char *file2) g_free (nfile1); g_free (nfile2); - return do_file_error (TRUE, buf); + return do_file_error (ctx, TRUE, buf); } /* }}} */ @@ -1139,7 +1160,7 @@ calc_copy_file_progress (file_op_context_t *ctx, gint64 tv_current, off_t file_p rotate_dash (TRUE); /* Compute ETA */ - dt = (tv_current - ctx->transfer_start) / (double) G_USEC_PER_SEC; + dt = (tv_current - ctx->pauses - ctx->transfer_start) / (double) G_USEC_PER_SEC; if (file_part == 0) ctx->eta_secs = 0.0; @@ -1157,7 +1178,7 @@ calc_copy_file_progress (file_op_context_t *ctx, gint64 tv_current, off_t file_p copied_bytes = ctx->total_progress_bytes + file_part; - dt = (tv_current - ctx->total_transfer_start) / (double) G_USEC_PER_SEC; + dt = (tv_current - ctx->pauses - ctx->total_transfer_start) / (double) G_USEC_PER_SEC; if (copied_bytes == 0) ctx->total_eta_secs = 0; @@ -1176,7 +1197,8 @@ try_remove_file (file_op_context_t *ctx, const vfs_path_t *vpath, FileProgressSt { while (mc_unlink (vpath) != 0 && !ctx->ignore_all) { - *status = file_error (TRUE, _("Cannot remove file \"%s\"\n%s"), vfs_path_as_str (vpath)); + *status = + file_error (ctx, TRUE, _("Cannot remove file \"%s\"\n%s"), vfs_path_as_str (vpath)); if (*status == FILE_RETRY) continue; if (*status == FILE_IGNORE_ALL) @@ -1232,7 +1254,7 @@ move_file_file (const WPanel *panel, file_op_context_t *ctx, const char *s, cons return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot stat file \"%s\"\n%s"), s); + return_status = file_error (ctx, TRUE, _("Cannot stat file \"%s\"\n%s"), s); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; } @@ -1243,7 +1265,7 @@ move_file_file (const WPanel *panel, file_op_context_t *ctx, const char *s, cons if (mc_lstat (dst_vpath, &dst_stat) == 0) { - if (check_same_file (s, &src_stat, d, &dst_stat, &return_status)) + if (check_same_file (ctx, s, &src_stat, d, &dst_stat, &return_status)) goto ret; if (S_ISDIR (dst_stat.st_mode)) @@ -1299,7 +1321,7 @@ move_file_file (const WPanel *panel, file_op_context_t *ctx, const char *s, cons return_status = FILE_IGNORE_ALL; else { - return_status = files_error (_("Cannot move file \"%s\" to \"%s\"\n%s"), s, d); + return_status = files_error (ctx, _("Cannot move file \"%s\" to \"%s\"\n%s"), s, d); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_RETRY) @@ -1414,7 +1436,7 @@ try_erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath) while (my_rmdir (dir) != 0 && !ctx->ignore_all) { - return_status = file_error (TRUE, _("Cannot remove directory \"%s\"\n%s"), dir); + return_status = file_error (ctx, TRUE, _("Cannot remove directory \"%s\"\n%s"), dir); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status != FILE_RETRY) @@ -1607,7 +1629,7 @@ do_move_dir_dir (const WPanel *panel, file_op_context_t *ctx, const char *s, con dstat_ok = (mc_stat (dst_vpath, &dst_stat) == 0); - if (dstat_ok && check_same_file (s, &src_stat, d, &dst_stat, &return_status)) + if (dstat_ok && check_same_file (ctx, s, &src_stat, d, &dst_stat, &return_status)) goto ret_fast; if (!dstat_ok) @@ -1653,9 +1675,10 @@ do_move_dir_dir (const WPanel *panel, file_op_context_t *ctx, const char *s, con else { if (S_ISDIR (dst_stat.st_mode)) - return_status = file_error (TRUE, _("Cannot overwrite directory \"%s\"\n%s"), d); + return_status = + file_error (ctx, TRUE, _("Cannot overwrite directory \"%s\"\n%s"), d); else - return_status = file_error (TRUE, _("Cannot overwrite file \"%s\"\n%s"), d); + return_status = file_error (ctx, TRUE, _("Cannot overwrite file \"%s\"\n%s"), d); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_RETRY) @@ -1676,7 +1699,8 @@ do_move_dir_dir (const WPanel *panel, file_op_context_t *ctx, const char *s, con { if (!ctx->ignore_all) { - return_status = files_error (_("Cannot move directory \"%s\" to \"%s\"\n%s"), s, d); + return_status = + files_error (ctx, _("Cannot move directory \"%s\" to \"%s\"\n%s"), s, d); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_RETRY) @@ -2299,7 +2323,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa else { return_status = - file_error (TRUE, _("Cannot overwrite directory \"%s\"\n%s"), dst_path); + file_error (ctx, TRUE, _("Cannot overwrite directory \"%s\"\n%s"), dst_path); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_RETRY) @@ -2318,7 +2342,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot stat source file \"%s\"\n%s"), src_path); + return_status = + file_error (ctx, TRUE, _("Cannot stat source file \"%s\"\n%s"), src_path); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; } @@ -2349,7 +2374,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa else { return_status = - file_error (TRUE, _("Cannot get ext2 attributes of source file \"%s\"\n%s"), + file_error (ctx, TRUE, _("Cannot get ext2 attributes of source file \"%s\"\n%s"), src_path); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; @@ -2367,7 +2392,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa if (dst_exists) { /* Destination already exists */ - if (check_same_file (src_path, &src_stat, dst_path, &dst_stat, &return_status)) + if (check_same_file (ctx, src_path, &src_stat, dst_path, &dst_stat, &return_status)) goto ret_fast; /* Should we replace destination? */ @@ -2387,7 +2412,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa /* Check the hardlinks */ if (!ctx->follow_links) { - switch (check_hardlinks (src_vpath, &src_stat, dst_vpath, &ctx->ignore_all)) + switch (check_hardlinks (ctx, src_vpath, &src_stat, dst_vpath, &ctx->ignore_all)) { case HARDLINK_OK: /* We have made a hardlink - no more processing is necessary */ @@ -2421,7 +2446,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa ctx->ignore_all = TRUE; else return_status = - file_error (TRUE, + file_error (ctx, TRUE, _("Cannot set ext2 attributes of target file \"%s\"\n%s"), dst_path); @@ -2448,7 +2473,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa && !ctx->ignore_all) { return_status = - file_error (TRUE, _("Cannot create special file \"%s\"\n%s"), dst_path); + file_error (ctx, TRUE, _("Cannot create special file \"%s\"\n%s"), dst_path); if (return_status == FILE_RETRY) continue; if (return_status == FILE_IGNORE_ALL) @@ -2461,7 +2486,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa && mc_chown (dst_vpath, src_stat.st_uid, src_stat.st_gid) != 0 && !ctx->ignore_all) { - temp_status = file_error (TRUE, _("Cannot chown target file \"%s\"\n%s"), dst_path); + temp_status = + file_error (ctx, TRUE, _("Cannot chown target file \"%s\"\n%s"), dst_path); if (temp_status == FILE_IGNORE) break; if (temp_status == FILE_IGNORE_ALL) @@ -2476,7 +2502,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa while (ctx->preserve && mc_chmod (dst_vpath, src_stat.st_mode & ctx->umask_kill) != 0 && !ctx->ignore_all) { - temp_status = file_error (TRUE, _("Cannot chmod target file \"%s\"\n%s"), dst_path); + temp_status = + file_error (ctx, TRUE, _("Cannot chmod target file \"%s\"\n%s"), dst_path); if (temp_status == FILE_IGNORE) break; if (temp_status == FILE_IGNORE_ALL) @@ -2497,7 +2524,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa break; temp_status = - file_error (TRUE, _("Cannot set ext2 attributes of target file \"%s\"\n%s"), + file_error (ctx, TRUE, _("Cannot set ext2 attributes of target file \"%s\"\n%s"), dst_path); if (temp_status == FILE_IGNORE) break; @@ -2527,7 +2554,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot open source file \"%s\"\n%s"), src_path); + return_status = + file_error (ctx, TRUE, _("Cannot open source file \"%s\"\n%s"), src_path); if (return_status == FILE_RETRY) continue; if (return_status == FILE_IGNORE_ALL) @@ -2550,7 +2578,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot fstat source file \"%s\"\n%s"), src_path); + return_status = + file_error (ctx, TRUE, _("Cannot fstat source file \"%s\"\n%s"), src_path); if (return_status == FILE_RETRY) continue; if (return_status == FILE_IGNORE_ALL) @@ -2583,7 +2612,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa else { return_status = - file_error (TRUE, _("Cannot create target file \"%s\"\n%s"), dst_path); + file_error (ctx, TRUE, _("Cannot create target file \"%s\"\n%s"), dst_path); if (return_status == FILE_RETRY) continue; if (return_status == FILE_IGNORE_ALL) @@ -2615,7 +2644,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot fstat target file \"%s\"\n%s"), dst_path); + return_status = + file_error (ctx, TRUE, _("Cannot fstat target file \"%s\"\n%s"), dst_path); if (return_status == FILE_RETRY) continue; if (return_status == FILE_IGNORE_ALL) @@ -2636,7 +2666,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa } return_status = - file_error (TRUE, _("Cannot preallocate space for target file \"%s\"\n%s"), dst_path); + file_error (ctx, TRUE, _("Cannot preallocate space for target file \"%s\"\n%s"), + dst_path); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; @@ -2698,7 +2729,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa while ((n_read = mc_read (src_desc, buf, bufsize)) < 0 && !ctx->ignore_all) { return_status = - file_error (TRUE, _("Cannot read source file \"%s\"\n%s"), src_path); + file_error (ctx, TRUE, _("Cannot read source file \"%s\"\n%s"), src_path); if (return_status == FILE_RETRY) continue; if (return_status == FILE_IGNORE_ALL) @@ -2738,7 +2769,8 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa return_status = FILE_IGNORE_ALL; else return_status = - file_error (TRUE, _("Cannot write target file \"%s\"\n%s"), dst_path); + file_error (ctx, TRUE, _("Cannot write target file \"%s\"\n%s"), + dst_path); if (return_status == FILE_IGNORE) { @@ -2801,6 +2833,10 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa query_dialog (Q_ ("DialogTitle|Copy"), _("Incomplete file was retrieved"), D_ERROR, 3, _("&Delete"), _("&Keep"), _("&Continue copy")); + ctx->pauses += g_get_monotonic_time () - tv_current; + + /* update info forced */ + calc_copy_file_progress (ctx, tv_current, file_part, file_size - ctx->do_reget); switch (query_res) { @@ -2831,7 +2867,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa rotate_dash (FALSE); while (src_desc != -1 && mc_close (src_desc) < 0 && !ctx->ignore_all) { - temp_status = file_error (TRUE, _("Cannot close source file \"%s\"\n%s"), src_path); + temp_status = file_error (ctx, TRUE, _("Cannot close source file \"%s\"\n%s"), src_path); if (temp_status == FILE_RETRY) continue; if (temp_status == FILE_ABORT) @@ -2843,7 +2879,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa while (dest_desc != -1 && mc_close (dest_desc) < 0 && !ctx->ignore_all) { - temp_status = file_error (TRUE, _("Cannot close target file \"%s\"\n%s"), dst_path); + temp_status = file_error (ctx, TRUE, _("Cannot close target file \"%s\"\n%s"), dst_path); if (temp_status == FILE_RETRY) continue; if (temp_status == FILE_IGNORE_ALL) @@ -2871,7 +2907,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa while (ctx->preserve_uidgid && mc_chown (dst_vpath, src_uid, src_gid) != 0 && !ctx->ignore_all) { - temp_status = file_error (TRUE, _("Cannot chown target file \"%s\"\n%s"), dst_path); + temp_status = file_error (ctx, TRUE, _("Cannot chown target file \"%s\"\n%s"), dst_path); if (temp_status == FILE_ABORT) { return_status = FILE_ABORT; @@ -2892,7 +2928,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa while (ctx->preserve && mc_chmod (dst_vpath, (src_mode & ctx->umask_kill)) != 0 && !ctx->ignore_all) { - temp_status = file_error (TRUE, _("Cannot chmod target file \"%s\"\n%s"), dst_path); + temp_status = file_error (ctx, TRUE, _("Cannot chmod target file \"%s\"\n%s"), dst_path); if (temp_status == FILE_ABORT) { return_status = FILE_ABORT; @@ -2936,7 +2972,7 @@ copy_file_file (file_op_context_t *ctx, const char *src_path, const char *dst_pa } temp_status = - file_error (TRUE, _("Cannot set ext2 attributes for target file \"%s\"\n%s"), + file_error (ctx, TRUE, _("Cannot set ext2 attributes for target file \"%s\"\n%s"), dst_path); if (temp_status == FILE_ABORT) return_status = FILE_ABORT; @@ -3000,7 +3036,7 @@ copy_dir_dir (file_op_context_t *ctx, const char *s, const char *d, gboolean top return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot stat source directory \"%s\"\n%s"), s); + return_status = file_error (ctx, TRUE, _("Cannot stat source directory \"%s\"\n%s"), s); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; } @@ -3021,8 +3057,8 @@ copy_dir_dir (file_op_context_t *ctx, const char *s, const char *d, gboolean top else { return_status = - file_error (TRUE, _("Cannot get ext2 attributes of source directory \"%s\"\n%s"), - s); + file_error (ctx, TRUE, + _("Cannot get ext2 attributes of source directory \"%s\"\n%s"), s); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_ABORT) @@ -3050,7 +3086,7 @@ copy_dir_dir (file_op_context_t *ctx, const char *s, const char *d, gboolean top /* Check the hardlinks */ if (ctx->preserve) { - switch (check_hardlinks (src_vpath, &src_stat, dst_vpath, &ctx->ignore_all)) + switch (check_hardlinks (ctx, src_vpath, &src_stat, dst_vpath, &ctx->ignore_all)) { case HARDLINK_OK: /* We have made a hardlink - no more processing is necessary */ @@ -3071,7 +3107,7 @@ copy_dir_dir (file_op_context_t *ctx, const char *s, const char *d, gboolean top return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Source \"%s\" is not a directory\n%s"), s); + return_status = file_error (ctx, TRUE, _("Source \"%s\" is not a directory\n%s"), s); if (return_status == FILE_RETRY) goto retry_src_stat; if (return_status == FILE_IGNORE_ALL) @@ -3122,7 +3158,7 @@ copy_dir_dir (file_op_context_t *ctx, const char *s, const char *d, gboolean top else { return_status = - file_error (TRUE, _("Destination \"%s\" must be a directory\n%s"), d); + file_error (ctx, TRUE, _("Destination \"%s\" must be a directory\n%s"), d); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; if (return_status == FILE_RETRY) @@ -3155,7 +3191,7 @@ copy_dir_dir (file_op_context_t *ctx, const char *s, const char *d, gboolean top else { return_status = - file_error (TRUE, _("Cannot create target directory \"%s\"\n%s"), d); + file_error (ctx, TRUE, _("Cannot create target directory \"%s\"\n%s"), d); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; } @@ -3179,7 +3215,8 @@ copy_dir_dir (file_op_context_t *ctx, const char *s, const char *d, gboolean top return_status = FILE_IGNORE_ALL; else { - return_status = file_error (TRUE, _("Cannot chown target directory \"%s\"\n%s"), d); + return_status = + file_error (ctx, TRUE, _("Cannot chown target directory \"%s\"\n%s"), d); if (return_status == FILE_IGNORE_ALL) ctx->ignore_all = TRUE; } @@ -3618,7 +3655,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl break; if (ctx->ignore_all - || file_error (TRUE, _("Destination \"%s\" must be a directory\n%s"), + || file_error (ctx, TRUE, _("Destination \"%s\" must be a directory\n%s"), dest) != FILE_RETRY) goto clean_up; } @@ -3702,13 +3739,13 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl /* {{{ Query/status report routines */ /** Report error with one file */ FileProgressStatus -file_error (gboolean allow_retry, const char *format, const char *file) +file_error (file_op_context_t *ctx, gboolean allow_retry, const char *format, const char *file) { char buf[BUF_MEDIUM]; g_snprintf (buf, sizeof (buf), format, path_trunc (file, 30), unix_error_string (errno)); - return do_file_error (allow_retry, buf); + return do_file_error (ctx, allow_retry, buf); } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/filemanager/file.h b/src/filemanager/file.h index 26d4814a0f..dc84f76f44 100644 --- a/src/filemanager/file.h +++ b/src/filemanager/file.h @@ -54,7 +54,8 @@ gboolean panel_operate (void *source_panel, FileOperation op, gboolean force_sin /* Error reporting routines */ /* Report error with one file */ -FileProgressStatus file_error (gboolean allow_retry, const char *format, const char *file); +FileProgressStatus file_error (file_op_context_t *ctx, gboolean allow_retry, const char *format, + const char *file); /* return value is FILE_CONT or FILE_ABORT */ FileProgressStatus compute_dir_size (const vfs_path_t * dirname_vpath, dirsize_status_msg_t * sm, diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index 93702d1ad4..c8ddba9c25 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -505,6 +505,7 @@ overwrite_query_dialog (file_op_context_t *ctx, enum OperationMode mode) const int gap = 1; + gint64 t; file_progress_ui_t *ui = ctx->ui; Widget *wd; WGroup *g; @@ -521,6 +522,8 @@ overwrite_query_dialog (file_op_context_t *ctx, enum OperationMode mode) unsigned long yes_id, no_id; int result; + t = g_get_monotonic_time (); + if (mode == Foreground) title = _("File exists"); else @@ -693,6 +696,8 @@ overwrite_query_dialog (file_op_context_t *ctx, enum OperationMode mode) widget_destroy (wd); + ctx->pauses += t - g_get_monotonic_time (); + return (result == B_CANCEL) ? REPLACE_ABORT : (replace_action_t) result; #undef ADD_BUTTON diff --git a/src/filemanager/filegui.h b/src/filemanager/filegui.h index 211d896b0c..954df96289 100644 --- a/src/filemanager/filegui.h +++ b/src/filemanager/filegui.h @@ -147,6 +147,9 @@ typedef struct /* Used in OP_MOVE between copy and remove directories */ size_t prev_total_progress_count; + /* Time of pauses in query dialogs */ + gint64 pauses; + /* User interface data goes here */ void *ui; } file_op_context_t; diff --git a/src/filemanager/tree.c b/src/filemanager/tree.c index 228fb4dec7..16aa9719ff 100644 --- a/src/filemanager/tree.c +++ b/src/filemanager/tree.c @@ -763,7 +763,7 @@ tree_move (WTree *tree, const char *default_dest) message (D_ERROR, MSG_ERROR, _("Cannot stat the destination\n%s"), unix_error_string (errno)); else if (!S_ISDIR (buf.st_mode)) - file_error (TRUE, _("Destination \"%s\" must be a directory\n%s"), dest); + file_error (NULL, TRUE, _("Destination \"%s\" must be a directory\n%s"), dest); else { file_op_context_t *ctx;