# HG changeset patch # User nadvornik # Date 1216763168 0 # Node ID 9427c91951e87caa53ecfaef950d0dc6e6213a9c # Parent 2f9edd196dcadf2d1c5413ebff29c4fe8f77c72b basic infrastructure for early error and dangerous operations checking it needs more work diff -r 2f9edd196dca -r 9427c91951e8 src/filedata.c --- a/src/filedata.c Tue Jul 22 18:27:12 2008 +0000 +++ b/src/filedata.c Tue Jul 22 21:46:08 2008 +0000 @@ -1621,12 +1621,54 @@ /* * check dest paths - dest image exists, etc. - * returns FIXME * it should detect all possible problems with the planned operation + * FIXME: add more tests */ + +gint file_data_check_ci_dest(FileData *fd) +{ + gint ret = CHANGE_OK; + + g_assert(fd->change); + + if (fd->change->dest && + strcmp(fd->change->dest, fd->path) != 0 && + isname(fd->change->dest)) + { + ret |= CHANGE_DEST_EXISTS; + DEBUG_1("Change checked: destination exists: %s -> %s", fd->path, fd->change->dest); + } + + if (!access_file(fd->path, R_OK)) + { + ret |= CHANGE_NO_PERM; + DEBUG_1("Change checked: no read permission: %s", fd->path); + } + + fd->change->error = ret; + if (ret == 0) DEBUG_1("Change checked: OK: %s", fd->path); + + return ret; +} + gint file_data_sc_check_ci_dest(FileData *fd) { + GList *work; + int ret; + + ret = file_data_check_ci_dest(fd); + + work = fd->sidecar_files; + while (work) + { + FileData *sfd = work->data; + + ret |= file_data_check_ci_dest(sfd); + work = work->next; + } + + return ret; } diff -r 2f9edd196dca -r 9427c91951e8 src/typedefs.h --- a/src/typedefs.h Tue Jul 22 18:27:12 2008 +0000 +++ b/src/typedefs.h Tue Jul 22 21:46:08 2008 +0000 @@ -149,6 +149,13 @@ NOTIFY_TYPE_CHANGE /* generic change described by fd->change */ } NotifyType; +typedef enum { + CHANGE_OK = 0, + CHANGE_DEST_EXISTS = 1 << 0, + CHANGE_ERROR_MASK = (~0) << 1, /* the values below are fatal errors */ + CHANGE_NO_PERM = 1 << 1 +} ChangeError; + #define MAX_SPLIT_IMAGES 4 @@ -427,6 +434,7 @@ FileDataChangeType type; gchar *source; gchar *dest; + gint error; }; struct _FileData { diff -r 2f9edd196dca -r 9427c91951e8 src/utilops.c --- a/src/utilops.c Tue Jul 22 18:27:12 2008 +0000 +++ b/src/utilops.c Tue Jul 22 21:46:08 2008 +0000 @@ -800,6 +800,87 @@ } } + +static void file_util_check_resume_cb(GenericDialog *gd, gpointer data) +{ + UtilityData *ud = data; + ud->phase = UTILITY_PHASE_CHECKED; + file_util_dialog_run(ud); +} + +static void file_util_check_abort_cb(GenericDialog *gd, gpointer data) +{ + UtilityData *ud = data; + ud->phase = UTILITY_PHASE_START; + file_util_dialog_run(ud); +} + +void file_util_check_ci(UtilityData *ud) +{ + gint error = CHANGE_OK; + + if (ud->dir_fd) + { + error = file_data_sc_check_ci_dest(ud->dir_fd); + } + else + { + GList *work = ud->flist; + while (work) + { + FileData *fd; + + fd = work->data; + work = work->next; + + error |= file_data_sc_check_ci_dest(fd); + } + } + + if (!error) + { + ud->phase = UTILITY_PHASE_CHECKED; + file_util_dialog_run(ud); + return; + } + + // FIXME: the dialogs needs better error messages with a list of files and error descriptions + if (!(error & CHANGE_ERROR_MASK)) + { + /* just a warning */ + GenericDialog *d; + + d = file_util_gen_dlg("This operation can be dangerous", GQ_WMCLASS, "dlg_confirm", + ud->parent, TRUE, + file_util_check_abort_cb, ud); + + generic_dialog_add_message(d, GTK_STOCK_DIALOG_WARNING, NULL, "Really continue?"); + + generic_dialog_add_button(d, GTK_STOCK_GO_FORWARD, _("Co_ntinue"), + file_util_check_resume_cb, TRUE); + gtk_widget_show(d->dialog); + return; + } + else + { + /* fatal error */ + GenericDialog *d; + + d = file_util_gen_dlg("This operation can't continue", GQ_WMCLASS, "dlg_confirm", + ud->parent, TRUE, + file_util_check_abort_cb, ud); + generic_dialog_add_message(d, GTK_STOCK_DIALOG_WARNING, NULL, "This operation can't continue"); + + gtk_widget_show(d->dialog); + return; + } + +} + + + + + static void file_util_cancel_cb(GenericDialog *gd, gpointer data) { UtilityData *ud = data; @@ -1360,8 +1441,8 @@ ud->phase = UTILITY_PHASE_ENTERING; break; case UTILITY_PHASE_ENTERING: - /* FIXME use file_data_sc_check_ci_dest to detect problems and eventually go back to PHASE_START - or to PHASE_CANCEL */ + file_util_check_ci(ud); + break; ud->phase = UTILITY_PHASE_CHECKED; case UTILITY_PHASE_CHECKED: