From 12ccfdff6c869566d58b9ee037101e07dc1a5e1e Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sat, 27 Nov 2010 16:35:59 +0300 Subject: [PATCH 1/6] Ticket #2429: overflow of file operation counters. Use uintmax_t type instead of double for summary size of several files. Signed-off-by: Andrew Borodin --- lib/util.c | 28 +++++++++++++--------------- lib/util.h | 7 ++++--- src/filemanager/cmd.c | 14 ++++++-------- src/filemanager/file.c | 20 ++++++++++---------- src/filemanager/file.h | 6 ++---- src/filemanager/filegui.c | 5 ++--- src/filemanager/filegui.h | 3 +-- src/filemanager/fileopctx.c | 2 +- src/filemanager/fileopctx.h | 8 ++++---- src/filemanager/panel.c | 12 ++++++------ src/filemanager/panel.h | 4 +++- 11 files changed, 52 insertions(+), 57 deletions(-) diff --git a/lib/util.c b/lib/util.c index 76f9e8fff..0195ea152 100644 --- a/lib/util.c +++ b/lib/util.c @@ -326,30 +326,30 @@ path_trunc (const char *path, size_t trunc_len) /* --------------------------------------------------------------------------------------------- */ const char * -size_trunc (double size, gboolean use_si) +size_trunc (uintmax_t size, gboolean use_si) { static char x[BUF_TINY]; - long int divisor = 1; + uintmax_t divisor = 1; const char *xtra = ""; - if (size > 999999999L) + if (size > 999999999UL) { divisor = use_si ? 1000 : 1024; xtra = use_si ? "k" : "K"; - if (size / divisor > 999999999L) + if (size / divisor > 999999999UL) { divisor = use_si ? (1000 * 1000) : (1024 * 1024); xtra = use_si ? "m" : "M"; } } - g_snprintf (x, sizeof (x), "%.0f%s", (size / divisor), xtra); + g_snprintf (x, sizeof (x), "%.0f%s", 1.0 * size / divisor, xtra); return x; } /* --------------------------------------------------------------------------------------------- */ const char * -size_trunc_sep (double size, gboolean use_si) +size_trunc_sep (uintmax_t size, gboolean use_si) { static char x[60]; int count; @@ -359,7 +359,7 @@ size_trunc_sep (double size, gboolean use_si) p = y = size_trunc (size, use_si); p += strlen (p) - 1; d = x + sizeof (x) - 1; - *d-- = 0; + *d-- = '\0'; while (p >= y && isalpha ((unsigned char) *p)) *d-- = *p--; for (count = 0; p >= y; count++) @@ -389,11 +389,12 @@ size_trunc_sep (double size, gboolean use_si) */ void -size_trunc_len (char *buffer, unsigned int len, off_t size, int units, gboolean use_si) +size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si) { /* Avoid taking power for every file. */ - static const off_t power10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, - 1000000000 + static const uintmax_t power10[] = + { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static const char *const suffix[] = { "", "K", "M", "G", "T", "P", "E", "Z", "Y", NULL }; static const char *const suffix_lc[] = { "", "k", "m", "g", "t", "p", "e", "z", "y", NULL }; @@ -408,8 +409,7 @@ size_trunc_len (char *buffer, unsigned int len, off_t size, int units, gboolean * We can't just multiply by 1024 - that might cause overflow * if off_t type is too small */ - if (units && use_si) - { + if (use_si) for (j = 0; j < units; j++) { size_remain = ((size % 125) * 1024) / 1000; /* size mod 125, recalculated */ @@ -417,7 +417,6 @@ size_trunc_len (char *buffer, unsigned int len, off_t size, int units, gboolean size = size * 128; /* This will convert size from multiple of 1024 to multiple of 1000 */ size += size_remain; /* Re-add remainder lost by division/multiplication */ } - } for (j = units; suffix[j] != NULL; j++) { @@ -438,8 +437,7 @@ size_trunc_len (char *buffer, unsigned int len, off_t size, int units, gboolean if (size < power10[len - (j > 0)]) { - g_snprintf (buffer, len + 1, "%lu%s", (unsigned long) size, - use_si ? suffix_lc[j] : suffix[j]); + g_snprintf (buffer, len + 1, "%ju%s", size, use_si ? suffix_lc[j] : suffix[j]); break; } diff --git a/lib/util.h b/lib/util.h index d77d13a5f..a6aa3a444 100644 --- a/lib/util.h +++ b/lib/util.h @@ -9,6 +9,7 @@ #include #include +#include /* uintmax_t */ #include /*** typedefs(not structures) and defined constants **********************************************/ @@ -70,18 +71,18 @@ const char *path_trunc (const char *path, size_t trunc_len); /* return a static string representing size, appending "K" or "M" for * big sizes. * NOTE: uses the same static buffer as size_trunc_sep. */ -const char *size_trunc (double size, gboolean use_si); +const char *size_trunc (uintmax_t size, gboolean use_si); /* return a static string representing size, appending "K" or "M" for * big sizes. Separates every three digits by ",". * NOTE: uses the same static buffer as size_trunc. */ -const char *size_trunc_sep (double size, gboolean use_si); +const char *size_trunc_sep (uintmax_t size, gboolean use_si); /* Print file SIZE to BUFFER, but don't exceed LEN characters, * not including trailing 0. BUFFER should be at least LEN+1 long. * * Units: size units (0=bytes, 1=Kbytes, 2=Mbytes, etc.) */ -void size_trunc_len (char *buffer, unsigned int len, off_t size, int units, gboolean use_si); +void size_trunc_len (char *buffer, unsigned int len, uintmax_t size, int units, gboolean use_si); const char *string_perm (mode_t mode_bits); /* @modifies path. @returns pointer into path. */ diff --git a/src/filemanager/cmd.c b/src/filemanager/cmd.c index f1b51f598..426e550c2 100644 --- a/src/filemanager/cmd.c +++ b/src/filemanager/cmd.c @@ -1492,16 +1492,15 @@ single_dirsize_cmd (void) { WPanel *panel = current_panel; file_entry *entry; - off_t marked; - double total; - ComputeDirSizeUI *ui; entry = &(panel->dir.list[panel->selected]); if (S_ISDIR (entry->st.st_mode) && strcmp (entry->fname, "..") != 0) { - ui = compute_dir_size_create_ui (); + off_t marked; + uintmax_t total = 0; + ComputeDirSizeUI *ui; - total = 0.0; + ui = compute_dir_size_create_ui (); if (compute_dir_size (entry->fname, ui, compute_dir_size_update_ui, &marked, &total, TRUE) == FILE_CONT) @@ -1531,8 +1530,6 @@ dirsizes_cmd (void) { WPanel *panel = current_panel; int i; - off_t marked; - double total; ComputeDirSizeUI *ui; ui = compute_dir_size_create_ui (); @@ -1542,7 +1539,8 @@ dirsizes_cmd (void) && ((panel->dirs_marked && panel->dir.list[i].f.marked) || !panel->dirs_marked) && strcmp (panel->dir.list[i].fname, "..") != 0) { - total = 0.0l; + off_t marked; + uintmax_t total = 0; if (compute_dir_size (panel->dir.list[i].fname, ui, compute_dir_size_update_ui, &marked, &total, diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 84ea2aad9..fd57b85f6 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -421,7 +421,7 @@ progress_update_one (FileOpTotalContext * tctx, FileOpContext * ctx, off_t add, if (is_toplevel_file || ctx->progress_totals_computed) { tctx->progress_count++; - tctx->progress_bytes += add; + tctx->progress_bytes += (uintmax_t) add; } if (tv_start.tv_sec == 0) { @@ -516,7 +516,7 @@ copy_file_file_display_progress (FileOpTotalContext * tctx, FileOpContext * ctx, /* 5. Compute total ETA and BPS */ if (ctx->progress_bytes != 0) { - double remain_bytes; + uintmax_t remain_bytes; tctx->copyed_bytes = tctx->progress_bytes + n_read_total + ctx->do_reget; remain_bytes = ctx->progress_bytes - tctx->copyed_bytes; #if 1 @@ -858,12 +858,12 @@ panel_get_file (WPanel * panel, struct stat *stat_buf) static FileProgressStatus panel_compute_totals (const WPanel * panel, const void *ui, compute_dir_size_callback cback, - off_t * ret_marked, double *ret_total, gboolean compute_symlinks) + off_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks) { int i; *ret_marked = 0; - *ret_total = 0.0; + *ret_total = 0; for (i = 0; i < panel->count; i++) { @@ -878,7 +878,7 @@ panel_compute_totals (const WPanel * panel, const void *ui, { char *dir_name; off_t subdir_count = 0; - double subdir_bytes = 0; + uintmax_t subdir_bytes = 0; FileProgressStatus status; dir_name = concat_dir_and_file (panel->cwd, panel->dir.list[i].fname); @@ -896,7 +896,7 @@ panel_compute_totals (const WPanel * panel, const void *ui, else { (*ret_marked)++; - *ret_total += s->st_size; + *ret_total += (uintmax_t) s->st_size; } } @@ -2116,7 +2116,7 @@ compute_dir_size_update_ui (const void *ui, const char *dirname) FileProgressStatus compute_dir_size (const char *dirname, const void *ui, compute_dir_size_callback cback, - off_t * ret_marked, double *ret_total, gboolean compute_symlinks) + off_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks) { int res; struct stat s; @@ -2134,7 +2134,7 @@ compute_dir_size (const char *dirname, const void *ui, if (S_ISLNK (s.st_mode)) { (*ret_marked)++; - *ret_total += s.st_size; + *ret_total += (uintmax_t) s.st_size; return ret; } } @@ -2170,7 +2170,7 @@ compute_dir_size (const char *dirname, const void *ui, if (S_ISDIR (s.st_mode)) { off_t subdir_count = 0; - double subdir_bytes = 0; + uintmax_t subdir_bytes = 0; ret = compute_dir_size (fullname, ui, cback, &subdir_count, &subdir_bytes, @@ -2188,7 +2188,7 @@ compute_dir_size (const char *dirname, const void *ui, else { (*ret_marked)++; - *ret_total += s.st_size; + *ret_total += (uintmax_t) s.st_size; } g_free (fullname); diff --git a/src/filemanager/file.h b/src/filemanager/file.h index 4b08f7d92..d5b4382f0 100644 --- a/src/filemanager/file.h +++ b/src/filemanager/file.h @@ -5,8 +5,7 @@ #ifndef MC__FILE_H #define MC__FILE_H -#include /* off_t */ -#include +#include /* off_t, uintmax_t */ #include "lib/global.h" #include "lib/widget.h" @@ -56,10 +55,9 @@ FileProgressStatus file_error (const char *format, const char *file); /* return value is FILE_CONT or FILE_ABORT */ FileProgressStatus compute_dir_size (const char *dirname, const void *ui, compute_dir_size_callback cback, - off_t * ret_marked, double *ret_total, + off_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks); - ComputeDirSizeUI *compute_dir_size_create_ui (void); void compute_dir_size_destroy_ui (ComputeDirSizeUI * ui); FileProgressStatus compute_dir_size_update_ui (const void *ui, const char *dirname); diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index d9dcc160d..1054e87ff 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -750,7 +750,7 @@ file_progress_show_count (FileOpContext * ctx, off_t done, off_t total) /* --------------------------------------------------------------------------------------------- */ void -file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, double copyed_bytes, +file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, uintmax_t copyed_bytes, gboolean need_show_total_summary) { char buffer[BUF_TINY]; @@ -768,7 +768,7 @@ file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, double ui = ctx->ui; - if (ctx->progress_bytes > 0) + if (ctx->progress_bytes != 0) { gauge_set_value (ui->progress_total_gauge, 1024, (int) (1024 * copyed_bytes / ctx->progress_bytes)); @@ -795,7 +795,6 @@ file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, double g_snprintf (buffer, BUF_TINY, _("Total: %s of %s"), buffer2, buffer3); label_set_text (ui->total_bytes_label, buffer); - } /* }}} */ diff --git a/src/filemanager/filegui.h b/src/filemanager/filegui.h index 29cb12fa9..2910198ec 100644 --- a/src/filemanager/filegui.h +++ b/src/filemanager/filegui.h @@ -31,7 +31,6 @@ void file_op_context_create_ui_without_init (FileOpContext * ctx, gboolean with_ filegui_dialog_type_t dialog_type); void file_op_context_destroy_ui (FileOpContext * ctx); - char *file_mask_dialog (FileOpContext * ctx, FileOperation operation, gboolean only_one, const char *format, const void *text, @@ -43,7 +42,7 @@ void file_progress_show (FileOpContext * ctx, off_t done, off_t total, const char *stalled_msg, gboolean force_update); void file_progress_show_count (FileOpContext * ctx, off_t done, off_t total); void file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, - double copyed_bytes, gboolean need_show_total_summary); + uintmax_t copyed_bytes, gboolean need_show_total_summary); void file_progress_show_source (FileOpContext * ctx, const char *path); void file_progress_show_target (FileOpContext * ctx, const char *path); void file_progress_show_deleting (FileOpContext * ctx, const char *path); diff --git a/src/filemanager/fileopctx.c b/src/filemanager/fileopctx.c index 87a2d2f11..8cce80997 100644 --- a/src/filemanager/fileopctx.c +++ b/src/filemanager/fileopctx.c @@ -70,7 +70,7 @@ file_op_context_new (FileOperation op) ctx = g_new0 (FileOpContext, 1); ctx->operation = op; ctx->eta_secs = 0.0; - ctx->progress_bytes = 0.0; + ctx->progress_bytes = 0; ctx->op_preserve = TRUE; ctx->do_reget = 1; ctx->stat_func = mc_lstat; diff --git a/src/filemanager/fileopctx.h b/src/filemanager/fileopctx.h index a2b7b24f1..9bb991869 100644 --- a/src/filemanager/fileopctx.h +++ b/src/filemanager/fileopctx.h @@ -17,6 +17,7 @@ #include #include #include +#include /* uintmax_t */ #include "lib/global.h" @@ -85,7 +86,7 @@ typedef struct FileOpContext /* Counters for progress indicators */ off_t progress_count; - double progress_bytes; + uintmax_t progress_bytes; /* The value of the "preserve Attributes" checkbox in the copy file dialog. * We can't use the value of "ctx->preserve" because it can change in order @@ -154,8 +155,8 @@ typedef struct FileOpContext typedef struct { off_t progress_count; - double progress_bytes; - double copyed_bytes; + uintmax_t progress_bytes; + uintmax_t copyed_bytes; size_t bps; size_t bps_count; struct timeval transfer_start; @@ -163,7 +164,6 @@ typedef struct gboolean ask_overwrite; gboolean is_toplevel_file; - } FileOpTotalContext; /*** global variables defined in .c file *********************************************************/ diff --git a/src/filemanager/panel.c b/src/filemanager/panel.c index 9692a471f..5bdf376ec 100644 --- a/src/filemanager/panel.c +++ b/src/filemanager/panel.c @@ -975,7 +975,7 @@ display_total_marked_size (WPanel * panel, int y, int x, gboolean size_only) * First make "N bytes", then insert it into "X in M files". */ g_snprintf (b_bytes, sizeof (b_bytes), - ngettext ("%s byte", "%s bytes", (unsigned long) panel->total), + ngettext ("%s byte", "%s bytes", panel->total), size_trunc_sep (panel->total, panels_options.kilobyte_si)); if (!size_only) g_snprintf (buffer, sizeof (buffer), @@ -3791,7 +3791,7 @@ do_file_mark (WPanel * panel, int idx, int mark) return; /* Only '..' can't be marked, '.' isn't visible */ - if (!strcmp (panel->dir.list[idx].fname, "..")) + if (strcmp (panel->dir.list[idx].fname, "..") == 0) return; file_mark (panel, idx, mark); @@ -3801,11 +3801,11 @@ do_file_mark (WPanel * panel, int idx, int mark) if (S_ISDIR (panel->dir.list[idx].st.st_mode)) { if (panel->dir.list[idx].f.dir_size_computed) - panel->total += panel->dir.list[idx].st.st_size; + panel->total += (uintmax_t) panel->dir.list[idx].st.st_size; panel->dirs_marked++; } else - panel->total += panel->dir.list[idx].st.st_size; + panel->total += (uintmax_t) panel->dir.list[idx].st.st_size; set_colors (panel); } else @@ -3813,11 +3813,11 @@ do_file_mark (WPanel * panel, int idx, int mark) if (S_ISDIR (panel->dir.list[idx].st.st_mode)) { if (panel->dir.list[idx].f.dir_size_computed) - panel->total -= panel->dir.list[idx].st.st_size; + panel->total -= (uintmax_t) panel->dir.list[idx].st.st_size; panel->dirs_marked--; } else - panel->total -= panel->dir.list[idx].st.st_size; + panel->total -= (uintmax_t) panel->dir.list[idx].st.st_size; panel->marked--; } } diff --git a/src/filemanager/panel.h b/src/filemanager/panel.h index d95130b9b..bf136c53e 100644 --- a/src/filemanager/panel.h +++ b/src/filemanager/panel.h @@ -5,6 +5,8 @@ #ifndef MC__PANEL_H #define MC__PANEL_H +#include /* uintmax_t */ + #include "lib/global.h" /* gboolean */ #include "lib/fs.h" /* MC_MAXPATHLEN */ #include "lib/strutil.h" @@ -84,7 +86,7 @@ typedef struct WPanel int count; /* Number of files in dir structure */ int marked; /* Count of marked files */ int dirs_marked; /* Count of marked directories */ - double total; /* Bytes in marked files */ + uintmax_t total; /* Bytes in marked files */ int top_file; /* The file showed on the top of the panel */ int selected; /* Index to the selected file */ int reverse; /* Show listing in reverse? */ From 3e7b58d5afe3693246b16602e93f2a5c52cae6c1 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sat, 27 Nov 2010 17:59:53 +0300 Subject: [PATCH 2/6] Use size_t instead of off_t for file counters during file operations. Signed-off-by: Andrew Borodin --- src/filemanager/cmd.c | 4 ++-- src/filemanager/file.c | 17 ++++++++--------- src/filemanager/file.h | 2 +- src/filemanager/filegui.c | 6 ++---- src/filemanager/filegui.h | 2 +- src/filemanager/fileopctx.h | 4 ++-- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/filemanager/cmd.c b/src/filemanager/cmd.c index 426e550c2..b20937ce8 100644 --- a/src/filemanager/cmd.c +++ b/src/filemanager/cmd.c @@ -1496,7 +1496,7 @@ single_dirsize_cmd (void) entry = &(panel->dir.list[panel->selected]); if (S_ISDIR (entry->st.st_mode) && strcmp (entry->fname, "..") != 0) { - off_t marked; + size_t marked = 0; uintmax_t total = 0; ComputeDirSizeUI *ui; @@ -1539,7 +1539,7 @@ dirsizes_cmd (void) && ((panel->dirs_marked && panel->dir.list[i].f.marked) || !panel->dirs_marked) && strcmp (panel->dir.list[i].fname, "..") != 0) { - off_t marked; + size_t marked = 0; uintmax_t total = 0; if (compute_dir_size (panel->dir.list[i].fname, diff --git a/src/filemanager/file.c b/src/filemanager/file.c index fd57b85f6..eac0edde4 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -668,23 +668,22 @@ erase_file (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, return FILE_ABORT; mc_refresh (); - if (tctx->progress_count && mc_lstat (s, &buf)) + if (tctx->progress_count != 0 && mc_lstat (s, &buf) != 0) { /* ignore, most likely the mc_unlink fails, too */ buf.st_size = 0; } - while (mc_unlink (s)) + while (mc_unlink (s) != 0) { return_status = file_error (_("Cannot delete file \"%s\"\n%s"), s); if (return_status != FILE_RETRY) return return_status; } - if (tctx->progress_count) - return progress_update_one (tctx, ctx, buf.st_size, is_toplevel_file); - else + if (tctx->progress_count == 0) return FILE_CONT; + return progress_update_one (tctx, ctx, buf.st_size, is_toplevel_file); } /* --------------------------------------------------------------------------------------------- */ @@ -858,7 +857,7 @@ panel_get_file (WPanel * panel, struct stat *stat_buf) static FileProgressStatus panel_compute_totals (const WPanel * panel, const void *ui, compute_dir_size_callback cback, - off_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks) + size_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks) { int i; @@ -877,7 +876,7 @@ panel_compute_totals (const WPanel * panel, const void *ui, if (S_ISDIR (s->st_mode)) { char *dir_name; - off_t subdir_count = 0; + size_t subdir_count = 0; uintmax_t subdir_bytes = 0; FileProgressStatus status; @@ -2116,7 +2115,7 @@ compute_dir_size_update_ui (const void *ui, const char *dirname) FileProgressStatus compute_dir_size (const char *dirname, const void *ui, compute_dir_size_callback cback, - off_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks) + size_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks) { int res; struct stat s; @@ -2169,7 +2168,7 @@ compute_dir_size (const char *dirname, const void *ui, if (S_ISDIR (s.st_mode)) { - off_t subdir_count = 0; + size_t subdir_count = 0; uintmax_t subdir_bytes = 0; ret = diff --git a/src/filemanager/file.h b/src/filemanager/file.h index d5b4382f0..a6cc6567b 100644 --- a/src/filemanager/file.h +++ b/src/filemanager/file.h @@ -55,7 +55,7 @@ FileProgressStatus file_error (const char *format, const char *file); /* return value is FILE_CONT or FILE_ABORT */ FileProgressStatus compute_dir_size (const char *dirname, const void *ui, compute_dir_size_callback cback, - off_t * ret_marked, uintmax_t *ret_total, + size_t * ret_marked, uintmax_t *ret_total, gboolean compute_symlinks); ComputeDirSizeUI *compute_dir_size_create_ui (void); diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index 1054e87ff..e19f49cc0 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -726,7 +726,7 @@ file_progress_show (FileOpContext * ctx, off_t done, off_t total, /* --------------------------------------------------------------------------------------------- */ void -file_progress_show_count (FileOpContext * ctx, off_t done, off_t total) +file_progress_show_count (FileOpContext * ctx, size_t done, size_t total) { char buffer[BUF_TINY]; FileOpContextUI *ui; @@ -741,9 +741,7 @@ file_progress_show_count (FileOpContext * ctx, off_t done, off_t total) if (!verbose) return; - g_snprintf (buffer, BUF_TINY, _("Files processed: %llu of %llu"), - (unsigned long long) done, (unsigned long long) total); - + g_snprintf (buffer, BUF_TINY, _("Files processed: %zu of %zu"), done, total); label_set_text (ui->total_files_processed_label, buffer); } diff --git a/src/filemanager/filegui.h b/src/filemanager/filegui.h index 2910198ec..207784293 100644 --- a/src/filemanager/filegui.h +++ b/src/filemanager/filegui.h @@ -40,7 +40,7 @@ FileProgressStatus check_progress_buttons (FileOpContext * ctx); void file_progress_show (FileOpContext * ctx, off_t done, off_t total, const char *stalled_msg, gboolean force_update); -void file_progress_show_count (FileOpContext * ctx, off_t done, off_t total); +void file_progress_show_count (FileOpContext * ctx, size_t done, size_t total); void file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, uintmax_t copyed_bytes, gboolean need_show_total_summary); void file_progress_show_source (FileOpContext * ctx, const char *path); diff --git a/src/filemanager/fileopctx.h b/src/filemanager/fileopctx.h index 9bb991869..aaf542016 100644 --- a/src/filemanager/fileopctx.h +++ b/src/filemanager/fileopctx.h @@ -85,7 +85,7 @@ typedef struct FileOpContext int dialog_type; /* Counters for progress indicators */ - off_t progress_count; + size_t progress_count; uintmax_t progress_bytes; /* The value of the "preserve Attributes" checkbox in the copy file dialog. @@ -154,7 +154,7 @@ typedef struct FileOpContext typedef struct { - off_t progress_count; + size_t progress_count; uintmax_t progress_bytes; uintmax_t copyed_bytes; size_t bps; From a95d786742e4e6da887ab84a6750c74d1dcb7b47 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sat, 27 Nov 2010 18:24:33 +0300 Subject: [PATCH 3/6] Optimization of verbose operations with several files. Check values of verbose and dialog type outside of file_progress_show_count() and file_progress_show_total() to avoid double checks of those options and extra function calls. Signed-off-by: Andrew Borodin --- src/filemanager/file.c | 35 +++++++++++++++++++++-------------- src/filemanager/filegui.c | 21 +++++++-------------- src/filemanager/filegui.h | 9 +-------- src/filemanager/fileopctx.h | 9 ++++++++- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index eac0edde4..e8e7e1414 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -430,8 +430,11 @@ progress_update_one (FileOpTotalContext * tctx, FileOpContext * ctx, off_t add, gettimeofday (&tv_current, (struct timezone *) NULL); if ((tv_current.tv_sec - tv_start.tv_sec) > FILEOP_UPDATE_INTERVAL) { - file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); - file_progress_show_total (tctx, ctx, tctx->progress_bytes, TRUE); + if (verbose && ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM) + { + file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); + file_progress_show_total (tctx, ctx, tctx->progress_bytes, TRUE); + } tv_start.tv_sec = tv_current.tv_sec; } @@ -1507,13 +1510,18 @@ copy_file_file (FileOpTotalContext * tctx, FileOpContext * ctx, } { - gboolean force_update = - (tv_current.tv_sec - tctx->transfer_start.tv_sec) > FILEOP_UPDATE_INTERVAL; - file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); - file_progress_show_total (tctx, ctx, - tctx->progress_bytes + n_read_total + ctx->do_reget, - force_update); + gboolean force_update; + force_update = + (tv_current.tv_sec - tctx->transfer_start.tv_sec) > FILEOP_UPDATE_INTERVAL; + + if (verbose && ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM) + { + file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); + file_progress_show_total (tctx, ctx, + tctx->progress_bytes + n_read_total + ctx->do_reget, + force_update); + } file_progress_show (ctx, n_read_total + ctx->do_reget, file_size, stalled_msg, force_update); @@ -2588,16 +2596,15 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl if (value == FILE_CONT) do_file_mark (panel, i, 0); - file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); - - if (verbose) + if (verbose && ctx->dialog_type == FILEGUI_DIALOG_MULTI_ITEM) { + file_progress_show_count (ctx, tctx->progress_count, ctx->progress_count); file_progress_show_total (tctx, ctx, tctx->progress_bytes, FALSE); - - if (operation != OP_DELETE) - file_progress_show (ctx, 0, 0, "", FALSE); } + if (operation != OP_DELETE) + file_progress_show (ctx, 0, 0, "", FALSE); + if (check_progress_buttons (ctx) == FILE_ABORT) break; diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index e19f49cc0..0dca1a8e2 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -687,6 +687,9 @@ file_progress_show (FileOpContext * ctx, off_t done, off_t total, char buffer2[BUF_TINY]; char buffer3[BUF_TINY]; + if (!verbose) + return; + g_return_if_fail (ctx != NULL); if (ctx->ui == NULL) @@ -694,9 +697,6 @@ file_progress_show (FileOpContext * ctx, off_t done, off_t total, ui = ctx->ui; - if (!verbose) - return; - if (total == 0) { gauge_show (ui->progress_file_gauge, 0); @@ -733,14 +733,11 @@ file_progress_show_count (FileOpContext * ctx, size_t done, size_t total) g_return_if_fail (ctx != NULL); - if (ctx->dialog_type != FILEGUI_DIALOG_MULTI_ITEM || ctx->ui == NULL) + if (ctx->ui == NULL) return; ui = ctx->ui; - if (!verbose) - return; - g_snprintf (buffer, BUF_TINY, _("Files processed: %zu of %zu"), done, total); label_set_text (ui->total_files_processed_label, buffer); } @@ -749,7 +746,7 @@ file_progress_show_count (FileOpContext * ctx, size_t done, size_t total) void file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, uintmax_t copyed_bytes, - gboolean need_show_total_summary) + gboolean show_summary) { char buffer[BUF_TINY]; char buffer2[BUF_TINY]; @@ -758,10 +755,7 @@ file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, uintma struct timeval tv_current; FileOpContextUI *ui; - if (!verbose) - return; - - if (ctx->dialog_type != FILEGUI_DIALOG_MULTI_ITEM || ctx->ui == NULL) + if (ctx->ui == NULL) return; ui = ctx->ui; @@ -775,8 +769,7 @@ file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, uintma else gauge_show (ui->progress_total_gauge, 0); - - if (!need_show_total_summary && tctx->bps == 0) + if (!show_summary && tctx->bps == 0) return; gettimeofday (&tv_current, NULL); diff --git a/src/filemanager/filegui.h b/src/filemanager/filegui.h index 207784293..17350362a 100644 --- a/src/filemanager/filegui.h +++ b/src/filemanager/filegui.h @@ -10,13 +10,6 @@ /*** typedefs(not structures) and defined constants **********************************************/ -typedef enum -{ - FILEGUI_DIALOG_ONE_ITEM, - FILEGUI_DIALOG_MULTI_ITEM, - FILEGUI_DIALOG_DELETE_ITEM -} filegui_dialog_type_t; - /*** enums ***************************************************************************************/ /*** structures declarations (and typedefs of structures)*****************************************/ @@ -42,7 +35,7 @@ void file_progress_show (FileOpContext * ctx, off_t done, off_t total, const char *stalled_msg, gboolean force_update); void file_progress_show_count (FileOpContext * ctx, size_t done, size_t total); void file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, - uintmax_t copyed_bytes, gboolean need_show_total_summary); + uintmax_t copyed_bytes, gboolean show_summary); void file_progress_show_source (FileOpContext * ctx, const char *path); void file_progress_show_target (FileOpContext * ctx, const char *path); void file_progress_show_deleting (FileOpContext * ctx, const char *path); diff --git a/src/filemanager/fileopctx.h b/src/filemanager/fileopctx.h index aaf542016..251758e60 100644 --- a/src/filemanager/fileopctx.h +++ b/src/filemanager/fileopctx.h @@ -28,6 +28,13 @@ typedef int (*mc_stat_fn) (const char *filename, struct stat * buf); /*** enums ***************************************************************************************/ +typedef enum +{ + FILEGUI_DIALOG_ONE_ITEM, + FILEGUI_DIALOG_MULTI_ITEM, + FILEGUI_DIALOG_DELETE_ITEM +} filegui_dialog_type_t; + typedef enum { OP_COPY = 0, @@ -82,7 +89,7 @@ typedef struct FileOpContext /* Whether the panel total has been computed */ gboolean progress_totals_computed; - int dialog_type; + filegui_dialog_type_t dialog_type; /* Counters for progress indicators */ size_t progress_count; From d14f0485753847af0a9e7fa7dedabc4565a4e4e4 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sat, 27 Nov 2010 18:50:19 +0300 Subject: [PATCH 4/6] Removed unneeded checks. Signed-off-by: Andrew Borodin --- src/filemanager/filegui.c | 9 +++------ src/filemanager/fileopctx.c | 7 +------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index 0dca1a8e2..5efbd8571 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -655,22 +655,19 @@ file_op_context_create_ui (FileOpContext * ctx, gboolean with_eta, void file_op_context_destroy_ui (FileOpContext * ctx) { - FileOpContextUI *ui; - g_return_if_fail (ctx != NULL); - if (ctx->ui) + if (ctx->ui != NULL) { - ui = ctx->ui; + FileOpContextUI *ui = (FileOpContextUI *) ctx->ui; dlg_run_done (ui->op_dlg); destroy_dlg (ui->op_dlg); g_free (ui); + ctx->ui = NULL; } the_hint->widget.y = last_hint_line; - - ctx->ui = NULL; } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/filemanager/fileopctx.c b/src/filemanager/fileopctx.c index 8cce80997..d12e18f00 100644 --- a/src/filemanager/fileopctx.c +++ b/src/filemanager/fileopctx.c @@ -96,13 +96,9 @@ file_op_context_destroy (FileOpContext * ctx) { g_return_if_fail (ctx != NULL); - if (ctx->ui) - file_op_context_destroy_ui (ctx); - + file_op_context_destroy_ui (ctx); mc_search_free (ctx->search_handle); - /** \todo FIXME: do we need to free ctx->dest_mask? */ - g_free (ctx); } @@ -123,7 +119,6 @@ file_op_total_context_new (void) void file_op_total_context_destroy (FileOpTotalContext * tctx) { - g_return_if_fail (tctx != NULL); g_free (tctx); } From bd4dd44ac84098d8f7f34099d66b34e9566b2e18 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sat, 27 Nov 2010 19:03:15 +0300 Subject: [PATCH 5/6] Unification of ctx and ctx->ui checks. ... and type accuracy. Signed-off-by: Andrew Borodin --- src/filemanager/filegui.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index 5efbd8571..e81ea6b88 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -497,8 +497,7 @@ check_progress_buttons (FileOpContext * ctx) Gpm_Event event; FileOpContextUI *ui; - if (ctx->ui == NULL) - return FILE_CONT; + g_return_val_if_fail (ctx->ui != NULL, FILE_CONT); ui = ctx->ui; @@ -688,9 +687,7 @@ file_progress_show (FileOpContext * ctx, off_t done, off_t total, return; g_return_if_fail (ctx != NULL); - - if (ctx->ui == NULL) - return; + g_return_if_fail (ctx->ui != NULL); ui = ctx->ui; @@ -729,12 +726,9 @@ file_progress_show_count (FileOpContext * ctx, size_t done, size_t total) FileOpContextUI *ui; g_return_if_fail (ctx != NULL); - - if (ctx->ui == NULL) - return; + g_return_if_fail (ctx->ui != NULL); ui = ctx->ui; - g_snprintf (buffer, BUF_TINY, _("Files processed: %zu of %zu"), done, total); label_set_text (ui->total_files_processed_label, buffer); } @@ -752,8 +746,8 @@ file_progress_show_total (FileOpTotalContext * tctx, FileOpContext * ctx, uintma struct timeval tv_current; FileOpContextUI *ui; - if (ctx->ui == NULL) - return; + g_return_if_fail (ctx != NULL); + g_return_if_fail (ctx->ui != NULL); ui = ctx->ui; @@ -795,23 +789,21 @@ file_progress_show_source (FileOpContext * ctx, const char *s) FileOpContextUI *ui; g_return_if_fail (ctx != NULL); - - if (ctx->ui == NULL) - return; + g_return_if_fail (ctx->ui != NULL); ui = ctx->ui; if (s != NULL) { #ifdef WITH_FULL_PATHS - int i = strlen (current_panel->cwd); + size_t i; + + i = strlen (current_panel->cwd); /* We remove the full path we have added before */ - if (!strncmp (s, current_panel->cwd, i)) - { + if (strncmp (s, current_panel->cwd, i) == 0) if (s[i] == PATH_SEP) s += i + 1; - } #endif /* WITH_FULL_PATHS */ label_set_text (ui->file_label[0], _("Source")); @@ -832,9 +824,7 @@ file_progress_show_target (FileOpContext * ctx, const char *s) FileOpContextUI *ui; g_return_if_fail (ctx != NULL); - - if (ctx->ui == NULL) - return; + g_return_if_fail (ctx->ui != NULL); ui = ctx->ui; @@ -858,9 +848,7 @@ file_progress_show_deleting (FileOpContext * ctx, const char *s) FileOpContextUI *ui; g_return_if_fail (ctx != NULL); - - if (ctx->ui == NULL) - return; + g_return_if_fail (ctx->ui != NULL); ui = ctx->ui; label_set_text (ui->file_label[0], _("Deleting")); From 17783a240c2e4317a00f8ecd427d7a61630ae273 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sat, 27 Nov 2010 19:08:37 +0300 Subject: [PATCH 6/6] Adjust formatting output of source and destination file sizes ... and replaced tabs by spaces in defines. Signed-off-by: Andrew Borodin --- src/filemanager/filegui.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/filemanager/filegui.c b/src/filemanager/filegui.c index e81ea6b88..e111e2723 100644 --- a/src/filemanager/filegui.c +++ b/src/filemanager/filegui.c @@ -283,15 +283,14 @@ file_bps_prepare_for_show (char *buffer, long bps) static replace_action_t overwrite_query_dialog (FileOpContext * ctx, enum OperationMode mode) { -#define ADD_RD_BUTTON(i)\ - add_widget (ui->replace_dlg,\ - button_new (rd_widgets [i].ypos, rd_widgets [i].xpos, rd_widgets [i].value,\ - NORMAL_BUTTON, rd_widgets [i].text, 0)) +#define ADD_RD_BUTTON(i) \ + add_widget (ui->replace_dlg, \ + button_new (rd_widgets [i].ypos, rd_widgets [i].xpos, rd_widgets [i].value, \ + NORMAL_BUTTON, rd_widgets [i].text, 0)) -#define ADD_RD_LABEL(i, p1, p2)\ - g_snprintf (buffer, sizeof (buffer), rd_widgets [i].text, p1, p2);\ - add_widget (ui->replace_dlg,\ - label_new (rd_widgets [i].ypos, rd_widgets [i].xpos, buffer)) +#define ADD_RD_LABEL(i, p1, p2) \ + g_snprintf (buffer, sizeof (buffer), rd_widgets [i].text, p1, p2); \ + add_widget (ui->replace_dlg, label_new (rd_widgets [i].ypos, rd_widgets [i].xpos, buffer)) /* dialog sizes */ const int rd_ylen = 17; @@ -309,17 +308,10 @@ overwrite_query_dialog (FileOpContext * ctx, enum OperationMode mode) { N_("Target file already exists!"), 3, 4, 0 }, /* 1 */ { "%s", 4, 4, 0 }, -#if (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64) || (defined _LARGE_FILES && _LARGE_FILES) /* 2 */ - { N_("Source date: %s, size %llu"), 6, 4, 0 }, + { N_("Source date: %s, size %ju"), 6, 4, 0 }, /* 3 */ - { N_("Target date: %s, size %llu"), 7, 4, 0 }, -#else - /* 2 */ - { N_("Source date: %s, size %u"), 6, 4, 0 }, - /* 3 */ - { N_("Target date: %s, size %u"), 7, 4, 0 }, -#endif + { N_("Target date: %s, size %ju"), 7, 4, 0 }, /* 4 */ { N_("&Abort"), 14, 25, REPLACE_ABORT }, /* 5 */ @@ -436,10 +428,10 @@ overwrite_query_dialog (FileOpContext * ctx, enum OperationMode mode) add_widget (ui->replace_dlg, label_new (rd_widgets[1].ypos, (rd_xlen - stripped_name_len) / 2, stripped_name)); - /* source date */ - ADD_RD_LABEL (2, file_date (ui->s_stat->st_mtime), (off_t) ui->s_stat->st_size); - /* destination date */ - ADD_RD_LABEL (3, file_date (ui->d_stat->st_mtime), (off_t) ui->d_stat->st_size); + /* source date and size */ + ADD_RD_LABEL (2, file_date (ui->s_stat->st_mtime), (uintmax_t) ui->s_stat->st_size); + /* destination date and size */ + ADD_RD_LABEL (3, file_date (ui->d_stat->st_mtime), (uintmax_t) ui->d_stat->st_size); ADD_RD_BUTTON (4); /* Abort */ ADD_RD_BUTTON (5); /* If size differs */