Changeset 0ce9eb8 in mainline for uspace/app


Ignore:
Timestamp:
2026-02-10T12:52:07Z (5 weeks ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
857fba8
Parents:
26a9388
git-author:
Jiri Svoboda <jiri@…> (2026-02-10 18:51:59)
git-committer:
Jiri Svoboda <jiri@…> (2026-02-10 12:52:07)
Message:

Ask user what to do if destination file exists while copying.

Location:
uspace/app
Files:
4 added
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/copy/copy.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4949static void copy_progress(void *, fmgt_progress_t *);
    5050static fmgt_error_action_t copy_io_error_query(void *, fmgt_io_error_t *);
     51static fmgt_exists_action_t copy_exists_query(void *, fmgt_exists_t *);
    5152
    5253static bool prog_upd = false;
     
    5960        .abort_query = copy_abort_query,
    6061        .io_error_query = copy_io_error_query,
     62        .exists_query = copy_exists_query,
    6163        .progress = copy_progress,
    6264};
     
    188190                                if (ev->key == KC_C)
    189191                                        return fmgt_er_abort;
     192                        }
     193                }
     194        }
     195}
     196
     197/** Called by fmgt to let user choose destination exists recovery action.
     198 *
     199 * @param arg Argument (not used)
     200 * @param err I/O error report
     201 * @return Error recovery action.
     202 */
     203static fmgt_exists_action_t copy_exists_query(void *arg, fmgt_exists_t *exists)
     204{
     205        cons_event_t event;
     206        kbd_event_t *ev;
     207        errno_t rc;
     208
     209        (void)arg;
     210
     211        if (nonint)
     212                return fmgt_exr_abort;
     213
     214        if (prog_upd)
     215                putchar('\n');
     216
     217        fprintf(stderr, "File %s exists.\n", exists->fname);
     218        fprintf(stderr, "[O]verwrite, [S]kip or [A]bort?\n");
     219
     220        if (con == NULL)
     221                return fmgt_exr_abort;
     222
     223        while (true) {
     224                rc = console_get_event(con, &event);
     225                if (rc != EOK)
     226                        return fmgt_exr_abort;
     227
     228                if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS) {
     229                        ev = &event.ev.key;
     230                        if ((ev->mods & KM_ALT) == 0 &&
     231                            (ev->mods & KM_CTRL) == 0) {
     232                                if (ev->c == 'o' || ev->c == 'O')
     233                                        return fmgt_exr_overwrite;
     234                                if (ev->c == 's' || ev->c == 'S')
     235                                        return fmgt_exr_skip;
     236                                if (ev->c == 'a' || ev->c == 'A')
     237                                        return fmgt_exr_abort;
     238                        }
     239                }
     240
     241                if (event.type == CEV_KEY && event.ev.key.type == KEY_PRESS) {
     242                        ev = &event.ev.key;
     243                        if ((ev->mods & KM_ALT) == 0 &&
     244                            (ev->mods & KM_SHIFT) == 0 &&
     245                            (ev->mods & KM_CTRL) != 0) {
     246                                if (ev->key == KC_C)
     247                                        return fmgt_exr_abort;
    190248                        }
    191249                }
     
    256314                putchar('\n');
    257315        if (rc != EOK) {
    258                 printf("Error creating file: %s.\n", str_error(rc));
     316                printf("Error copying file(s): %s.\n", str_error(rc));
    259317                goto error;
    260318        }
  • uspace/app/nav/copy.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    6969        .abort_query = copy_abort_query,
    7070        .io_error_query = navigator_io_error_query,
     71        .exists_query = navigator_exists_query,
    7172        .progress = copy_progress,
    7273};
  • uspace/app/nav/dlg/ioerrdlg.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    272272}
    273273
    274 /** Destroy prompt dialog.
    275  *
    276  * @param dialog Prompt dialog or @c NULL
     274/** Destroy I/O error dialog.
     275 *
     276 * @param dialog I/O error dialog or @c NULL
    277277 */
    278278void io_err_dlg_destroy(io_err_dlg_t *dialog)
     
    285285}
    286286
    287 /** Set mesage dialog callback.
    288  *
    289  * @param dialog Prompt dialog
    290  * @param cb Prompt dialog callbacks
     287/** Set I/O error dialog callback.
     288 *
     289 * @param dialog I/O error dialog
     290 * @param cb I/O error dialog callbacks
    291291 * @param arg Callback argument
    292292 */
     
    298298}
    299299
    300 /** Prompt dialog window close handler.
     300/** I/O error dialog window close handler.
    301301 *
    302302 * @param window Window
     
    313313}
    314314
    315 /** Prompt dialog window keyboard event handler.
     315/** I/O error dialog window keyboard event handler.
    316316 *
    317317 * @param window Window
     
    344344}
    345345
    346 /** Prompt dialog OK button click handler.
     346/** I/O error dialog abort button click handler.
    347347 *
    348348 * @param pbutton Push button
     
    358358}
    359359
    360 /** Prompt dialog cancel button click handler.
     360/** I/O error dialog retry button click handler.
    361361 *
    362362 * @param pbutton Push button
  • uspace/app/nav/meson.build

    r26a9388 r0ce9eb8  
    11#
    2 # Copyright (c) 2025 Jiri Svoboda
     2# Copyright (c) 2026 Jiri Svoboda
    33# All rights reserved.
    44#
     
    3030src = files(
    3131        'dlg/copydlg.c',
     32        'dlg/existsdlg.c',
    3233        'dlg/ioerrdlg.c',
    3334        'dlg/newfiledlg.c',
     
    4546test_src = files(
    4647        'dlg/copydlg.c',
     48        'dlg/existsdlg.c',
    4749        'dlg/ioerrdlg.c',
    4850        'dlg/newfiledlg.c',
     
    5658        'verify.c',
    5759        'test/dlg/copydlg.c',
     60        'test/dlg/existsdlg.c',
    5861        'test/dlg/ioerrdlg.c',
    5962        'test/dlg/newfiledlg.c',
  • uspace/app/nav/nav.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4949#include <ui/window.h>
    5050#include "copy.h"
     51#include "dlg/existsdlg.h"
    5152#include "dlg/ioerrdlg.h"
    5253#include "menu.h"
     
    106107        .bretry = navigator_io_err_retry,
    107108        .close = navigator_io_err_close
     109};
     110
     111static void navigator_exists_overwrite(exists_dlg_t *, void *);
     112static void navigator_exists_skip(exists_dlg_t *, void *);
     113static void navigator_exists_abort(exists_dlg_t *, void *);
     114static void navigator_exists_close(exists_dlg_t *, void *);
     115
     116static exists_dlg_cb_t navigator_exists_dlg_cb = {
     117        .boverwrite = navigator_exists_overwrite,
     118        .bskip = navigator_exists_skip,
     119        .babort = navigator_exists_abort,
     120        .close = navigator_exists_close
    108121};
    109122
     
    273286        navigator->io_err_act_sel = false;
    274287
     288        fibril_mutex_initialize(&navigator->exists_act_lock);
     289        fibril_condvar_initialize(&navigator->exists_act_cv);
     290        navigator->exists_act_sel = false;
     291
    275292        *rnavigator = navigator;
    276293        return EOK;
     
    857874}
    858875
     876/** Called by fmgt to query for file/directory exists recovery action.
     877 *
     878 * @param arg Argument (navigator_t *)
     879 * @param exists File/directory exists report
     880 * @return Recovery action to take.
     881 */
     882fmgt_exists_action_t navigator_exists_query(void *arg, fmgt_exists_t *exists)
     883{
     884        navigator_t *nav = (navigator_t *)arg;
     885        exists_dlg_t *dlg;
     886        exists_dlg_params_t params;
     887        fmgt_exists_action_t exists_act;
     888        char *text1;
     889        errno_t rc;
     890        int rv;
     891
     892        exists_dlg_params_init(&params);
     893        rv = asprintf(&text1, "File %s exists.", exists->fname);
     894        if (rv < 0)
     895                return fmgt_exr_abort;
     896
     897        params.text1 = text1;
     898
     899        ui_lock(nav->ui);
     900        rc = exists_dlg_create(nav->ui, &params, &dlg);
     901        if (rc != EOK) {
     902                ui_unlock(nav->ui);
     903                free(text1);
     904                return fmgt_exr_abort;
     905        }
     906
     907        exists_dlg_set_cb(dlg, &navigator_exists_dlg_cb, (void *)nav);
     908
     909        ui_unlock(nav->ui);
     910        free(text1);
     911
     912        fibril_mutex_lock(&nav->exists_act_lock);
     913
     914        while (!nav->exists_act_sel) {
     915                fibril_condvar_wait(&nav->exists_act_cv,
     916                    &nav->exists_act_lock);
     917        }
     918
     919        exists_act = nav->exists_act;
     920        nav->exists_act_sel = false;
     921        fibril_mutex_unlock(&nav->exists_act_lock);
     922
     923        return exists_act;
     924}
     925
     926/** File/directory exists dialog overwrite button was pressed.
     927 *
     928 * @param dlg File/directory exists dialog
     929 * @param arg Argument (navigator_t *)
     930 */
     931static void navigator_exists_overwrite(exists_dlg_t *dlg, void *arg)
     932{
     933        navigator_t *nav = (navigator_t *)arg;
     934
     935        exists_dlg_destroy(dlg);
     936
     937        fibril_mutex_lock(&nav->exists_act_lock);
     938        nav->exists_act = fmgt_exr_overwrite;
     939        nav->exists_act_sel = true;
     940        fibril_condvar_signal(&nav->exists_act_cv);
     941        fibril_mutex_unlock(&nav->exists_act_lock);
     942}
     943
     944/** File/directory exists dialog skip button was pressed.
     945 *
     946 * @param dlg File/directory exists dialog
     947 * @param arg Argument (navigator_t *)
     948 */
     949static void navigator_exists_skip(exists_dlg_t *dlg, void *arg)
     950{
     951        navigator_t *nav = (navigator_t *)arg;
     952
     953        exists_dlg_destroy(dlg);
     954
     955        fibril_mutex_lock(&nav->exists_act_lock);
     956        nav->exists_act = fmgt_exr_skip;
     957        nav->exists_act_sel = true;
     958        fibril_condvar_signal(&nav->exists_act_cv);
     959        fibril_mutex_unlock(&nav->exists_act_lock);
     960}
     961
     962/** File/directory exists dialog abort button was pressed.
     963 *
     964 * @param dlg File/directory exists dialog
     965 * @param arg Argument (navigator_t *)
     966 */
     967static void navigator_exists_abort(exists_dlg_t *dlg, void *arg)
     968{
     969        navigator_t *nav = (navigator_t *)arg;
     970
     971        exists_dlg_destroy(dlg);
     972
     973        fibril_mutex_lock(&nav->exists_act_lock);
     974        nav->exists_act = fmgt_exr_abort;
     975        nav->exists_act_sel = true;
     976        fibril_condvar_signal(&nav->exists_act_cv);
     977        fibril_mutex_unlock(&nav->exists_act_lock);
     978}
     979
     980/** File/directory exists dialog closure requested.
     981 *
     982 * @param dlg File/directory exists dialog
     983 * @param arg Argument (navigator_t *)
     984 */
     985static void navigator_exists_close(exists_dlg_t *dlg, void *arg)
     986{
     987        navigator_t *nav = (navigator_t *)arg;
     988
     989        exists_dlg_destroy(dlg);
     990
     991        fibril_mutex_lock(&nav->exists_act_lock);
     992        nav->exists_act = fmgt_exr_abort;
     993        nav->exists_act_sel = true;
     994        fibril_condvar_signal(&nav->exists_act_cv);
     995        fibril_mutex_unlock(&nav->exists_act_lock);
     996}
     997
    859998/** @}
    860999 */
  • uspace/app/nav/nav.h

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    5555    void *);
    5656extern fmgt_error_action_t navigator_io_error_query(void *, fmgt_io_error_t *);
     57extern fmgt_exists_action_t navigator_exists_query(void *, fmgt_exists_t *);
    5758
    5859#endif
  • uspace/app/nav/test/main.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3232
    3333PCUT_IMPORT(copydlg);
     34PCUT_IMPORT(existsdlg);
    3435PCUT_IMPORT(ioerrdlg);
    3536PCUT_IMPORT(newfiledlg);
  • uspace/app/nav/types/nav.h

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    7575        /** Synchronizes access to I/O error recovery action */
    7676        fibril_mutex_t io_err_act_lock;
     77
     78        /** @c true if user selected file/dir exists recovery action */
     79        bool exists_act_sel;
     80        /** Selected file/directory exists recovery action */
     81        fmgt_exists_action_t exists_act;
     82        /** Signalled when user selects file/directory exists recovery action */
     83        fibril_condvar_t exists_act_cv;
     84        /** Synchronizes access to file/directory exists recovery action */
     85        fibril_mutex_t exists_act_lock;
    7786} navigator_t;
    7887
Note: See TracChangeset for help on using the changeset viewer.