Changeset 0ce9eb8 in mainline


Ignore:
Timestamp:
2026-02-10T12:52:07Z (20 hours 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
Files:
4 added
13 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
  • uspace/lib/fmgt/include/types/fmgt.h

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    9090} fmgt_error_action_t;
    9191
     92/** File management file/directory exists report */
     93typedef struct {
     94        /** File name */
     95        const char *fname;
     96} fmgt_exists_t;
     97
     98/** File management file/directory exists recovery action */
     99typedef enum {
     100        /** Overwrite */
     101        fmgt_exr_overwrite,
     102        /** Skip */
     103        fmgt_exr_skip,
     104        /** Abort */
     105        fmgt_exr_abort
     106} fmgt_exists_action_t;
     107
    92108/** File management callbacks */
    93109typedef struct {
    94110        bool (*abort_query)(void *);
    95111        fmgt_error_action_t (*io_error_query)(void *, fmgt_io_error_t *);
     112        fmgt_exists_action_t (*exists_query)(void *, fmgt_exists_t *);
    96113        void (*progress)(void *, fmgt_progress_t *);
    97114} fmgt_cb_t;
  • uspace/lib/fmgt/private/fmgt.h

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4747extern bool fmgt_abort_query(fmgt_t *);
    4848extern fmgt_error_action_t fmgt_io_error_query(fmgt_t *, fmgt_io_error_t *);
     49extern fmgt_exists_action_t fmgt_exists_query(fmgt_t *, fmgt_exists_t *);
    4950extern void fmgt_progress_init(fmgt_t *);
    5051extern void fmgt_progress_init_file(fmgt_t *, const char *);
  • uspace/lib/fmgt/src/copy.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    5050};
    5151
     52/** Open file.
     53 *
     54 * @param fmgt File management object
     55 * @param fname File name
     56 * @param rfd Place to store file descriptor
     57 * @return EOK on success or an error code
     58 */
     59static errno_t fmgt_open(fmgt_t *fmgt, const char *fname, int *rfd)
     60{
     61        fmgt_io_error_t err;
     62        fmgt_error_action_t action;
     63        errno_t rc;
     64
     65        do {
     66                rc = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ, rfd);
     67                if (rc == EOK)
     68                        break;
     69
     70                /* I/O error */
     71                err.fname = fname;
     72                err.optype = fmgt_io_open;
     73                err.rc = rc;
     74                fmgt_timer_stop(fmgt);
     75                action = fmgt_io_error_query(fmgt, &err);
     76                fmgt_timer_start(fmgt);
     77        } while (action == fmgt_er_retry);
     78
     79        return rc;
     80}
     81
     82/** Create file.
     83 *
     84 * @param fmgt File management object
     85 * @param fname Destination file name
     86 * @param rfd Place to store file descriptor
     87 * @param rskip If @c true, skip existing file and continue
     88 * @return EOK on success or an error code
     89 */
     90static errno_t fmgt_create_file(fmgt_t *fmgt, const char *fname, int *rfd,
     91    bool *rskip)
     92{
     93        fmgt_io_error_t err;
     94        fmgt_error_action_t action;
     95        fmgt_exists_t exists;
     96        fmgt_exists_action_t exaction;
     97        bool may_overwrite = false;
     98        unsigned flags;
     99        errno_t rc;
     100
     101        *rskip = false;
     102
     103        do {
     104                flags = WALK_REGULAR | (may_overwrite ? WALK_MAY_CREATE :
     105                    WALK_MUST_CREATE);
     106                rc = vfs_lookup_open(fname, flags, MODE_WRITE, rfd);
     107                if (rc == EOK)
     108                        break;
     109
     110                if (rc == EEXIST) {
     111                        /* File exists */
     112                        exists.fname = fname;
     113                        fmgt_timer_stop(fmgt);
     114                        exaction = fmgt_exists_query(fmgt, &exists);
     115                        fmgt_timer_start(fmgt);
     116
     117                        if (exaction == fmgt_exr_skip)
     118                                *rskip = true;
     119                        if (exaction != fmgt_exr_overwrite)
     120                                break;
     121
     122                        may_overwrite = true;
     123                } else {
     124                        /* I/O error */
     125                        err.fname = fname;
     126                        err.optype = fmgt_io_create;
     127                        err.rc = rc;
     128                        fmgt_timer_stop(fmgt);
     129                        action = fmgt_io_error_query(fmgt, &err);
     130                        fmgt_timer_start(fmgt);
     131
     132                        if (action != fmgt_er_retry)
     133                                break;
     134                }
     135        } while (true);
     136
     137        return rc;
     138}
     139
     140/** Create directory.
     141 *
     142 * @param fmgt File management object
     143 * @param dname Directory name
     144 * @return EOK on success or an error code
     145 */
     146static errno_t fmgt_create_dir(fmgt_t *fmgt, const char *dname)
     147{
     148        fmgt_io_error_t err;
     149        fmgt_error_action_t action;
     150        errno_t rc;
     151
     152        do {
     153                rc = vfs_link_path(dname, KIND_DIRECTORY, NULL);
     154
     155                /* It is okay if the directory exists. */
     156                if (rc == EOK || rc == EEXIST)
     157                        break;
     158
     159                /* I/O error */
     160                err.fname = dname;
     161                err.optype = fmgt_io_create;
     162                err.rc = rc;
     163
     164                fmgt_timer_stop(fmgt);
     165                action = fmgt_io_error_query(fmgt, &err);
     166                fmgt_timer_start(fmgt);
     167        } while (action == fmgt_er_retry);
     168
     169        if (rc == EEXIST)
     170                return EOK;
     171
     172        return rc;
     173}
     174
     175/** Read data from file.
     176 *
     177 * @param fmgt File management object
     178 * @param fd File descriptor
     179 * @param fname File name (for printing diagnostics)
     180 * @param pos Pointer to current position (will be updated)
     181 * @param buffer Data buffer
     182 * @param nbytes Number of bytes to read
     183 * @param nr Place to store number of bytes read
     184 * @return EOK on success or an error code
     185 */
     186static errno_t fmgt_read(fmgt_t *fmgt, int fd, const char *fname,
     187    aoff64_t *pos, void *buffer, size_t nbytes, size_t *nr)
     188{
     189        char *bp = (char *)buffer;
     190        fmgt_io_error_t err;
     191        fmgt_error_action_t action;
     192        errno_t rc;
     193
     194        do {
     195                rc = vfs_read(fd, pos, bp, nbytes, nr);
     196                if (rc == EOK)
     197                        break;
     198
     199                /* I/O error */
     200                err.fname = fname;
     201                err.optype = fmgt_io_read;
     202                err.rc = rc;
     203                fmgt_timer_stop(fmgt);
     204                action = fmgt_io_error_query(fmgt, &err);
     205                fmgt_timer_start(fmgt);
     206        } while (action == fmgt_er_retry);
     207
     208        /* Not recovered? */
     209        if (rc != EOK)
     210                return rc;
     211
     212        return EOK;
     213}
     214
     215/** Write data to file.
     216 *
     217 * @param fmgt File management object
     218 * @param fd File descriptor
     219 * @param fname File name (for printing diagnostics)
     220 * @param pos Pointer to current position (will be updated)
     221 * @param buffer Pointer to data
     222 * @param nbytes Number of bytes to write
     223 * @return EOK on success or an error code
     224 */
    52225static errno_t fmgt_write(fmgt_t *fmgt, int fd, const char *fname,
    53226    aoff64_t *pos, void *buffer, size_t nbytes)
     
    97270{
    98271        fmgt_t *fmgt = (fmgt_t *)arg;
    99         fmgt_io_error_t err;
    100         fmgt_error_action_t action;
    101         errno_t rc;
    102 
    103         do {
    104                 rc = vfs_link_path(dest, KIND_DIRECTORY, NULL);
    105 
    106                 /* It is okay if the directory exists. */
    107                 if (rc == EOK || rc == EEXIST)
    108                         break;
    109 
    110                 /* I/O error */
    111                 err.fname = dest;
    112                 err.optype = fmgt_io_create;
    113                 err.rc = rc;
    114 
    115                 fmgt_timer_stop(fmgt);
    116                 action = fmgt_io_error_query(fmgt, &err);
    117                 fmgt_timer_start(fmgt);
    118         } while (action == fmgt_er_retry);
    119 
    120         return rc;
     272
     273        (void)dest;
     274        return fmgt_create_dir(fmgt, dest);
    121275}
    122276
     
    137291        aoff64_t wpos = 0;
    138292        char *buffer;
    139         fmgt_io_error_t err;
    140         fmgt_error_action_t action;
     293        bool skip;
    141294        errno_t rc;
    142295
     
    145298                return ENOMEM;
    146299
    147         do {
    148                 rc = vfs_lookup_open(src, WALK_REGULAR, MODE_READ, &rfd);
    149                 if (rc == EOK)
    150                         break;
    151 
    152                 /* I/O error */
    153                 err.fname = src;
    154                 err.optype = fmgt_io_open;
    155                 err.rc = rc;
    156                 fmgt_timer_stop(fmgt);
    157                 action = fmgt_io_error_query(fmgt, &err);
    158                 fmgt_timer_start(fmgt);
    159         } while (action == fmgt_er_retry);
    160 
    161         /* Not recovered? */
     300        rc = fmgt_open(fmgt, src, &rfd);
    162301        if (rc != EOK) {
    163302                free(buffer);
     
    165304        }
    166305
    167         do {
    168                 rc = vfs_lookup_open(dest, WALK_REGULAR | WALK_MAY_CREATE,
    169                     MODE_WRITE, &wfd);
    170                 if (rc == EOK)
    171                         break;
    172 
    173                 /* I/O error */
    174                 err.fname = dest;
    175                 err.optype = fmgt_io_create;
    176                 err.rc = rc;
    177                 fmgt_timer_stop(fmgt);
    178                 action = fmgt_io_error_query(fmgt, &err);
    179                 fmgt_timer_start(fmgt);
    180         } while (action == fmgt_er_retry);
    181 
     306        rc = fmgt_create_file(fmgt, dest, &wfd, &skip);
    182307        if (rc != EOK) {
    183308                free(buffer);
    184309                vfs_put(rfd);
     310
     311                /* User decided to skip and continue. */
     312                if (rc == EEXIST && skip)
     313                        return EOK;
    185314                return rc;
    186315        }
     
    189318
    190319        do {
    191                 do {
    192                         rc = vfs_read(rfd, &rpos, buffer, BUFFER_SIZE, &nr);
    193                         if (rc == EOK)
    194                                 break;
    195 
    196                         /* I/O error */
    197                         err.fname = src;
    198                         err.optype = fmgt_io_read;
    199                         err.rc = rc;
    200                         fmgt_timer_stop(fmgt);
    201                         action = fmgt_io_error_query(fmgt, &err);
    202                         fmgt_timer_start(fmgt);
    203                 } while (action == fmgt_er_retry);
    204 
    205                 /* Not recovered? */
     320                rc = fmgt_read(fmgt, rfd, src, &rpos, buffer, BUFFER_SIZE,
     321                    &nr);
    206322                if (rc != EOK)
    207323                        goto error;
     
    233349}
    234350
    235 /** copy files.
     351/** Copy files.
    236352 *
    237353 * @param fmgt File management object
  • uspace/lib/fmgt/src/fmgt.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2025 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    283283}
    284284
     285/** Query caller how to recover from existing destination file/directory.
     286 *
     287 * @param fmgt File management object
     288 * @param exists File/directory exists report
     289 * @return What recovery action should be taken.
     290 */
     291fmgt_exists_action_t fmgt_exists_query(fmgt_t *fmgt, fmgt_exists_t *exists)
     292{
     293        if (fmgt->cb != NULL && fmgt->cb->exists_query != NULL)
     294                return fmgt->cb->exists_query(fmgt->cb_arg, exists);
     295        else
     296                return fmgt_exr_abort;
     297}
     298
    285299/** Return base name (without path component).
    286300 *
  • uspace/lib/ui/src/promptdialog.c

    r26a9388 r0ce9eb8  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    291291}
    292292
    293 /** Set mesage dialog callback.
     293/** Set prompt dialog callback.
    294294 *
    295295 * @param dialog Prompt dialog
Note: See TracChangeset for help on using the changeset viewer.