Interruptable computing of directory size.
file.h: new type and functions for status dialog of directory computing size. Added required includes. (compute_dir_size): changed return value. Added new parameters to handle status dialig. Fixed comments. file.c: new functions for status dialog of directory computing size. (compute_dir_size): interruptable dir size computing. Changed return value. Added new parameters to handle status dialig. (panel_compute_totals): likewise. (panel_operate): likewise. cmd.c (single_dirsize_cmd): interruptable dir size computing. (dirsizes_cmd): likewise.
Этот коммит содержится в:
родитель
f021c090f9
Коммит
11bc00bea9
40
src/cmd.c
40
src/cmd.c
@ -37,7 +37,7 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "cmd.h" /* Our definitions */
|
#include "cmd.h" /* Our definitions */
|
||||||
#include "fileopctx.h" /* file_op_context_new() */
|
#include "fileopctx.h" /* file_op_context_new() */
|
||||||
#include "file.h" /* copy_file_file() */
|
#include "file.h" /* file operation routines */
|
||||||
#include "find.h" /* do_find() */
|
#include "find.h" /* do_find() */
|
||||||
#include "hotlist.h" /* hotlist_cmd() */
|
#include "hotlist.h" /* hotlist_cmd() */
|
||||||
#include "tree.h" /* tree_chdir() */
|
#include "tree.h" /* tree_chdir() */
|
||||||
@ -1197,13 +1197,21 @@ single_dirsize_cmd (void)
|
|||||||
file_entry *entry;
|
file_entry *entry;
|
||||||
off_t marked;
|
off_t marked;
|
||||||
double total;
|
double total;
|
||||||
|
ComputeDirSizeUI *ui;
|
||||||
|
|
||||||
|
ui = compute_dir_size_create_ui ();
|
||||||
|
|
||||||
entry = &(panel->dir.list[panel->selected]);
|
entry = &(panel->dir.list[panel->selected]);
|
||||||
if (S_ISDIR (entry->st.st_mode) && strcmp(entry->fname, "..") != 0) {
|
if (S_ISDIR (entry->st.st_mode) && strcmp(entry->fname, "..") != 0) {
|
||||||
total = 0.0;
|
total = 0.0;
|
||||||
compute_dir_size (entry->fname, &marked, &total);
|
|
||||||
entry->st.st_size = (off_t) total;
|
if (compute_dir_size (entry->fname, ui, compute_dir_size_update_ui,
|
||||||
entry->f.dir_size_computed = 1;
|
&marked, &total) == FILE_CONT) {
|
||||||
|
entry->st.st_size = (off_t) total;
|
||||||
|
entry->f.dir_size_computed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
compute_dir_size_destroy_ui (ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mark_moves_down)
|
if (mark_moves_down)
|
||||||
@ -1213,25 +1221,35 @@ single_dirsize_cmd (void)
|
|||||||
panel->dirty = 1;
|
panel->dirty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dirsizes_cmd (void)
|
dirsizes_cmd (void)
|
||||||
{
|
{
|
||||||
WPanel *panel = current_panel;
|
WPanel *panel = current_panel;
|
||||||
int i;
|
int i;
|
||||||
off_t marked;
|
off_t marked;
|
||||||
double total;
|
double total;
|
||||||
|
ComputeDirSizeUI *ui;
|
||||||
|
|
||||||
|
ui = compute_dir_size_create_ui ();
|
||||||
|
|
||||||
for (i = 0; i < panel->count; i++)
|
for (i = 0; i < panel->count; i++)
|
||||||
if (S_ISDIR (panel->dir.list [i].st.st_mode) &&
|
if (S_ISDIR (panel->dir.list [i].st.st_mode)
|
||||||
((panel->dirs_marked && panel->dir.list [i].f.marked) ||
|
&& ((panel->dirs_marked && panel->dir.list [i].f.marked)
|
||||||
!panel->dirs_marked) &&
|
|| !panel->dirs_marked)
|
||||||
strcmp (panel->dir.list [i].fname, "..") != 0) {
|
&& strcmp (panel->dir.list [i].fname, "..") != 0) {
|
||||||
total = 0.0l;
|
total = 0.0l;
|
||||||
compute_dir_size (panel->dir.list [i].fname, &marked, &total);
|
|
||||||
|
if (compute_dir_size (panel->dir.list [i].fname,
|
||||||
|
ui, compute_dir_size_update_ui,
|
||||||
|
&marked, &total) != FILE_CONT)
|
||||||
|
break;
|
||||||
|
|
||||||
panel->dir.list [i].st.st_size = (off_t) total;
|
panel->dir.list [i].st.st_size = (off_t) total;
|
||||||
panel->dir.list [i].f.dir_size_computed = 1;
|
panel->dir.list [i].f.dir_size_computed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compute_dir_size_destroy_ui (ui);
|
||||||
|
|
||||||
recalculate_panel_summary (panel);
|
recalculate_panel_summary (panel);
|
||||||
panel_re_sort (panel);
|
panel_re_sort (panel);
|
||||||
panel->dirty = 1;
|
panel->dirty = 1;
|
||||||
|
142
src/file.c
142
src/file.c
@ -1474,26 +1474,113 @@ panel_get_file (WPanel *panel, struct stat *stat_buf)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ComputeDirSizeUI *
|
||||||
|
compute_dir_size_create_ui (void)
|
||||||
|
{
|
||||||
|
ComputeDirSizeUI *ui;
|
||||||
|
|
||||||
|
char *b_name = N_("&Abort");
|
||||||
|
|
||||||
|
#ifdef ENABLE_NLS
|
||||||
|
b_name = _(b_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ui = g_new (ComputeDirSizeUI, 1);
|
||||||
|
|
||||||
|
ui->dlg = create_dlg (0, 0, 8, COLS/2, dialog_colors, NULL,
|
||||||
|
NULL, _("Directory size"), DLG_CENTER | DLG_TRYUP);
|
||||||
|
ui->dirname = label_new (3, 3, "");
|
||||||
|
add_widget (ui->dlg, ui->dirname);
|
||||||
|
|
||||||
|
add_widget (ui->dlg,
|
||||||
|
button_new (5, (ui->dlg->cols - strlen (b_name))/2,
|
||||||
|
FILE_ABORT, NORMAL_BUTTON, b_name, NULL));
|
||||||
|
|
||||||
|
/* We will manage the dialog without any help,
|
||||||
|
that's why we have to call init_dlg */
|
||||||
|
init_dlg (ui->dlg);
|
||||||
|
|
||||||
|
return ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compute_dir_size_destroy_ui (ComputeDirSizeUI *ui)
|
||||||
|
{
|
||||||
|
if (ui != NULL) {
|
||||||
|
/* schedule to update passive panel */
|
||||||
|
other_panel->dirty = 1;
|
||||||
|
|
||||||
|
/* close and destroy dialog */
|
||||||
|
dlg_run_done (ui->dlg);
|
||||||
|
destroy_dlg (ui->dlg);
|
||||||
|
g_free (ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileProgressStatus
|
||||||
|
compute_dir_size_update_ui (const void *ui, const char *dirname)
|
||||||
|
{
|
||||||
|
const ComputeDirSizeUI *this = (const ComputeDirSizeUI *) ui;
|
||||||
|
char *msg;
|
||||||
|
int c;
|
||||||
|
Gpm_Event event;
|
||||||
|
|
||||||
|
if (ui == NULL)
|
||||||
|
return FILE_CONT;
|
||||||
|
|
||||||
|
msg = g_strdup_printf (_("Scanning: %s"), dirname);
|
||||||
|
label_set_text (this->dirname, name_trunc (msg, this->dlg->cols - 6));
|
||||||
|
g_free (msg);
|
||||||
|
|
||||||
|
event.x = -1; /* Don't show the GPM cursor */
|
||||||
|
c = get_event (&event, 0, 0);
|
||||||
|
if (c == EV_NONE)
|
||||||
|
return FILE_CONT;
|
||||||
|
|
||||||
|
/* Reinitialize to avoid old values after events other than
|
||||||
|
selecting a button */
|
||||||
|
this->dlg->ret_value = FILE_CONT;
|
||||||
|
|
||||||
|
dlg_process_event (this->dlg, c, &event);
|
||||||
|
|
||||||
|
switch (this->dlg->ret_value) {
|
||||||
|
case B_CANCEL:
|
||||||
|
case FILE_ABORT:
|
||||||
|
return FILE_ABORT;
|
||||||
|
default:
|
||||||
|
return FILE_CONT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* compute_dir_size:
|
* compute_dir_size:
|
||||||
*
|
*
|
||||||
* Computes the number of bytes used by the files in a directory
|
* Computes the number of bytes used by the files in a directory
|
||||||
*/
|
*/
|
||||||
void
|
FileProgressStatus
|
||||||
compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
compute_dir_size (const char *dirname, const void *ui,
|
||||||
|
compute_dir_size_callback cback,
|
||||||
|
off_t *ret_marked, double *ret_total)
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *dirent;
|
struct dirent *dirent;
|
||||||
|
FileProgressStatus ret = FILE_CONT;
|
||||||
|
|
||||||
dir = mc_opendir (dirname);
|
dir = mc_opendir (dirname);
|
||||||
|
|
||||||
if (!dir)
|
if (dir == NULL)
|
||||||
return;
|
return ret;
|
||||||
|
|
||||||
while ((dirent = mc_readdir (dir)) != NULL) {
|
while ((dirent = mc_readdir (dir)) != NULL) {
|
||||||
struct stat s;
|
|
||||||
char *fullname;
|
char *fullname;
|
||||||
int res;
|
int res;
|
||||||
|
struct stat s;
|
||||||
|
|
||||||
|
ret = (cback != NULL) ? cback (ui, dirname) : FILE_CONT;
|
||||||
|
|
||||||
|
if (ret != FILE_CONT)
|
||||||
|
break;
|
||||||
|
|
||||||
if (strcmp (dirent->d_name, ".") == 0)
|
if (strcmp (dirent->d_name, ".") == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -1501,19 +1588,23 @@ compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
fullname = concat_dir_and_file (dirname, dirent->d_name);
|
fullname = concat_dir_and_file (dirname, dirent->d_name);
|
||||||
|
|
||||||
res = mc_lstat (fullname, &s);
|
res = mc_lstat (fullname, &s);
|
||||||
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
g_free (fullname);
|
g_free (fullname);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISDIR (s.st_mode)) {
|
if (S_ISDIR (s.st_mode)) {
|
||||||
off_t subdir_count = 0;
|
off_t subdir_count = 0;
|
||||||
double subdir_bytes = 0;
|
double subdir_bytes = 0;
|
||||||
|
|
||||||
compute_dir_size (fullname, &subdir_count, &subdir_bytes);
|
ret = compute_dir_size (fullname, ui, cback, &subdir_count, &subdir_bytes);
|
||||||
|
|
||||||
|
if (ret != FILE_CONT) {
|
||||||
|
g_free (fullname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
*ret_marked += subdir_count;
|
*ret_marked += subdir_count;
|
||||||
*ret_total += subdir_bytes;
|
*ret_total += subdir_bytes;
|
||||||
@ -1521,10 +1612,13 @@ compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
|||||||
(*ret_marked)++;
|
(*ret_marked)++;
|
||||||
*ret_total += s.st_size;
|
*ret_total += s.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (fullname);
|
g_free (fullname);
|
||||||
}
|
}
|
||||||
|
|
||||||
mc_closedir (dir);
|
mc_closedir (dir);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1535,8 +1629,10 @@ compute_dir_size (const char *dirname, off_t *ret_marked, double *ret_total)
|
|||||||
* as required. In addition, it checks to see if it will
|
* as required. In addition, it checks to see if it will
|
||||||
* overwrite any files by doing the copy.
|
* overwrite any files by doing the copy.
|
||||||
*/
|
*/
|
||||||
static void
|
static FileProgressStatus
|
||||||
panel_compute_totals (WPanel *panel, off_t *ret_marked, double *ret_total)
|
panel_compute_totals (WPanel *panel, const void *ui,
|
||||||
|
compute_dir_size_callback cback,
|
||||||
|
off_t *ret_marked, double *ret_total)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -1555,19 +1651,27 @@ panel_compute_totals (WPanel *panel, off_t *ret_marked, double *ret_total)
|
|||||||
char *dir_name;
|
char *dir_name;
|
||||||
off_t subdir_count = 0;
|
off_t subdir_count = 0;
|
||||||
double subdir_bytes = 0;
|
double subdir_bytes = 0;
|
||||||
|
FileProgressStatus status;
|
||||||
|
|
||||||
dir_name =
|
dir_name =
|
||||||
concat_dir_and_file (panel->cwd, panel->dir.list[i].fname);
|
concat_dir_and_file (panel->cwd, panel->dir.list[i].fname);
|
||||||
compute_dir_size (dir_name, &subdir_count, &subdir_bytes);
|
|
||||||
|
status = compute_dir_size (dir_name, ui, cback,
|
||||||
|
&subdir_count, &subdir_bytes);
|
||||||
|
g_free (dir_name);
|
||||||
|
|
||||||
|
if (status != FILE_CONT)
|
||||||
|
return FILE_ABORT;
|
||||||
|
|
||||||
*ret_marked += subdir_count;
|
*ret_marked += subdir_count;
|
||||||
*ret_total += subdir_bytes;
|
*ret_total += subdir_bytes;
|
||||||
g_free (dir_name);
|
|
||||||
} else {
|
} else {
|
||||||
(*ret_marked)++;
|
(*ret_marked)++;
|
||||||
*ret_total += s->st_size;
|
*ret_total += s->st_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FILE_CONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1940,8 +2044,18 @@ panel_operate (void *source_panel, FileOperation operation,
|
|||||||
|
|
||||||
/* Initialize variables for progress bars */
|
/* Initialize variables for progress bars */
|
||||||
if (operation != OP_MOVE && verbose && file_op_compute_totals) {
|
if (operation != OP_MOVE && verbose && file_op_compute_totals) {
|
||||||
panel_compute_totals (panel, &ctx->progress_count,
|
ComputeDirSizeUI *ui;
|
||||||
&ctx->progress_bytes);
|
FileProgressStatus status;
|
||||||
|
|
||||||
|
ui = compute_dir_size_create_ui ();
|
||||||
|
status = panel_compute_totals (panel,
|
||||||
|
ui, compute_dir_size_update_ui,
|
||||||
|
&ctx->progress_count, &ctx->progress_bytes);
|
||||||
|
compute_dir_size_destroy_ui (ui);
|
||||||
|
|
||||||
|
if (status != FILE_CONT)
|
||||||
|
goto clean_up;
|
||||||
|
|
||||||
ctx->progress_totals_computed = 1;
|
ctx->progress_totals_computed = 1;
|
||||||
} else {
|
} else {
|
||||||
ctx->progress_totals_computed = 0;
|
ctx->progress_totals_computed = 0;
|
||||||
|
28
src/file.h
28
src/file.h
@ -1,7 +1,12 @@
|
|||||||
|
/* File and directory operation routines for Midnight Commander */
|
||||||
|
|
||||||
#ifndef MC_FILE_H
|
#ifndef MC_FILE_H
|
||||||
#define MC_FILE_H
|
#define MC_FILE_H
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
#include "fileopctx.h"
|
#include "fileopctx.h"
|
||||||
|
#include "dialog.h" /* Dlg_head */
|
||||||
|
#include "widget.h" /* WLabel */
|
||||||
|
|
||||||
struct link;
|
struct link;
|
||||||
|
|
||||||
@ -25,9 +30,24 @@ extern int file_op_compute_totals;
|
|||||||
/* Report error with one file */
|
/* Report error with one file */
|
||||||
FileProgressStatus file_error (const char *format, const char *file);
|
FileProgressStatus file_error (const char *format, const char *file);
|
||||||
|
|
||||||
/* Query routines */
|
/* Compute directory size */
|
||||||
|
/* callback to update status dialog */
|
||||||
|
typedef FileProgressStatus (*compute_dir_size_callback)(const void *ui, const char *dirname);
|
||||||
|
|
||||||
void compute_dir_size (const char *dirname, off_t *ret_marked,
|
/* return value is FILE_CONT or FILE_ABORT */
|
||||||
double *ret_total);
|
FileProgressStatus compute_dir_size (const char *dirname, const void *ui,
|
||||||
|
compute_dir_size_callback cback,
|
||||||
|
off_t *ret_marked, double *ret_total);
|
||||||
|
|
||||||
#endif
|
/* status dialog of durectory size computing */
|
||||||
|
typedef struct {
|
||||||
|
Dlg_head *dlg;
|
||||||
|
WLabel *dirname;
|
||||||
|
} ComputeDirSizeUI;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MC_FILE_H */
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user