Changeset 2309891 in mainline


Ignore:
Timestamp:
2025-12-14T17:15:57Z (40 hours ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Parents:
144fafd
Message:

Copy files (Navigator and command line).

TODO Overwrite query, new I/O error types.

Location:
uspace
Files:
13 added
19 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/meson.build

    r144fafd r2309891  
    3535        'blkdump',
    3636        'calculator',
     37        'copy',
    3738        'corecfg',
    3839        'cpptest',
  • uspace/app/nav/menu.c

    r144fafd r2309891  
    5858        ui_menu_entry_t *medit;
    5959        ui_menu_entry_t *mverify;
     60        ui_menu_entry_t *mcopy;
    6061        ui_menu_entry_t *mfsep;
    6162        ui_menu_entry_t *mexit;
     
    104105        ui_menu_entry_set_cb(mverify, nav_menu_file_verify, (void *) menu);
    105106
     107        rc = ui_menu_entry_create(mfile, "~C~opy", "Ctrl-C", &mcopy);
     108        if (rc != EOK)
     109                goto error;
     110
     111        ui_menu_entry_set_cb(mcopy, nav_menu_file_copy, (void *) menu);
     112
    106113        rc = ui_menu_entry_sep_create(mfile, &mfsep);
    107114        if (rc != EOK)
     
    214221}
    215222
     223/** File / Copy menu entry selected.
     224 *
     225 * @param mentry Menu entry
     226 * @param arg Argument (navigator_t *)
     227 */
     228void nav_menu_file_copy(ui_menu_entry_t *mentry, void *arg)
     229{
     230        nav_menu_t *menu = (nav_menu_t *)arg;
     231
     232        if (menu->cb != NULL && menu->cb->file_copy != NULL)
     233                menu->cb->file_copy(menu->cb_arg);
     234}
     235
    216236/** File / Exit menu entry selected.
    217237 *
  • uspace/app/nav/menu.h

    r144fafd r2309891  
    5050extern void nav_menu_file_edit(ui_menu_entry_t *, void *);
    5151extern void nav_menu_file_verify(ui_menu_entry_t *, void *);
     52extern void nav_menu_file_copy(ui_menu_entry_t *, void *);
    5253extern void nav_menu_file_exit(ui_menu_entry_t *, void *);
    5354
  • uspace/app/nav/meson.build

    r144fafd r2309891  
    2929deps = [ 'fmgt', 'ui' ]
    3030src = files(
     31        'dlg/copydlg.c',
    3132        'dlg/ioerrdlg.c',
    3233        'dlg/newfiledlg.c',
    3334        'dlg/progress.c',
    3435        'dlg/verifydlg.c',
     36        'copy.c',
    3537        'main.c',
    3638        'menu.c',
     
    4244
    4345test_src = files(
     46        'dlg/copydlg.c',
    4447        'dlg/ioerrdlg.c',
    4548        'dlg/newfiledlg.c',
    4649        'dlg/progress.c',
    4750        'dlg/verifydlg.c',
     51        'copy.c',
    4852        'menu.c',
    4953        'nav.c',
     
    5155        'panel.c',
    5256        'verify.c',
     57        'test/dlg/copydlg.c',
    5358        'test/dlg/ioerrdlg.c',
    5459        'test/dlg/newfiledlg.c',
  • uspace/app/nav/nav.c

    r144fafd r2309891  
    4848#include <ui/ui.h>
    4949#include <ui/window.h>
     50#include "copy.h"
    5051#include "dlg/ioerrdlg.h"
    5152#include "menu.h"
     
    6970static void navigator_file_edit(void *);
    7071static void navigator_file_verify(void *);
     72static void navigator_file_copy(void *);
    7173static void navigator_file_exit(void *);
    7274
     
    7678        .file_edit = navigator_file_edit,
    7779        .file_verify = navigator_file_verify,
     80        .file_copy = navigator_file_copy,
    7881        .file_exit = navigator_file_exit
    7982};
     
    141144                        navigator_file_verify((void *)navigator);
    142145                        break;
     146                case KC_C:
     147                        navigator_file_copy((void *)navigator);
     148                        break;
    143149                case KC_Q:
    144150                        ui_quit(navigator->ui);
     
    325331        for (i = 0; i < navigator_panels; i++) {
    326332                if (panel_is_active(navigator->panel[i]))
     333                        return navigator->panel[i];
     334        }
     335
     336        /* This should not happen */
     337        assert(false);
     338        return NULL;
     339}
     340
     341/** Get the currently inactive navigator panel.
     342 *
     343 * @param navigator Navigator
     344 * @return Currently inactive panel
     345 */
     346panel_t *navigator_get_inactive_panel(navigator_t *navigator)
     347{
     348        int i;
     349
     350        for (i = 0; i < navigator_panels; i++) {
     351                if (!panel_is_active(navigator->panel[i]))
    327352                        return navigator->panel[i];
    328353        }
     
    561586}
    562587
     588/** File / Copy menu entry selected */
     589static void navigator_file_copy(void *arg)
     590{
     591        navigator_t *navigator = (navigator_t *)arg;
     592
     593        ui_file_list_entry_t *entry;
     594        ui_file_list_entry_attr_t attr;
     595        fmgt_flist_t *flist;
     596        panel_t *panel;
     597        errno_t rc;
     598
     599        panel = navigator_get_active_panel(navigator);
     600        entry = ui_file_list_get_cursor(panel->flist);
     601        ui_file_list_entry_get_attr(entry, &attr);
     602
     603        rc = fmgt_flist_create(&flist);
     604        if (rc != EOK)
     605                return;
     606
     607        rc = fmgt_flist_append(flist, attr.name);
     608        if (rc != EOK) {
     609                fmgt_flist_destroy(flist);
     610                return;
     611        }
     612
     613        /* flist ownership transferred */
     614        navigator_copy_dlg(navigator, flist);
     615}
     616
    563617/** File / Exit menu entry selected */
    564618static void navigator_file_exit(void *arg)
  • uspace/app/nav/nav.h

    r144fafd r2309891  
    4949extern errno_t navigator_run(const char *);
    5050extern panel_t *navigator_get_active_panel(navigator_t *);
     51extern panel_t *navigator_get_inactive_panel(navigator_t *);
    5152extern void navigator_switch_panel(navigator_t *);
    5253extern void navigator_refresh_panels(navigator_t *);
  • uspace/app/nav/panel.c

    r144fafd r2309891  
    365365}
    366366
     367/** Get current directory from panel.
     368 *
     369 * @param panel Panel
     370 * @return Path to current directory or @c NULL if out of memory
     371 */
     372char *panel_get_dir(panel_t *panel)
     373{
     374        return ui_file_list_get_dir(panel->flist);
     375}
     376
    367377/** Refresh panel contents.
    368378 *
  • uspace/app/nav/panel.h

    r144fafd r2309891  
    5858extern void panel_deactivate(panel_t *);
    5959extern errno_t panel_read_dir(panel_t *, const char *);
     60extern char *panel_get_dir(panel_t *);
    6061extern errno_t panel_refresh(panel_t *);
    6162extern void panel_activate_req(panel_t *);
  • uspace/app/nav/test/main.c

    r144fafd r2309891  
    3131PCUT_INIT;
    3232
     33PCUT_IMPORT(copydlg);
    3334PCUT_IMPORT(ioerrdlg);
    3435PCUT_IMPORT(newfiledlg);
  • uspace/app/nav/types/menu.h

    r144fafd r2309891  
    5151        /** File / Verify */
    5252        void (*file_verify)(void *);
     53        /** File / Copy */
     54        void (*file_copy)(void *);
    5355        /** File / Exit */
    5456        void (*file_exit)(void *);
  • uspace/lib/fmgt/include/fmgt.h

    r144fafd r2309891  
    4242#include <stddef.h>
    4343#include <stdint.h>
     44#include "fmgt/copy.h"
    4445#include "fmgt/flist.h"
    4546#include "fmgt/newfile.h"
     
    5253extern void fmgt_destroy(fmgt_t *);
    5354extern void fmgt_set_init_update(fmgt_t *, bool);
     55extern const char *fmgt_basename(const char *);
     56extern bool fmgt_is_dir(const char *);
    5457
    5558#endif
  • uspace/lib/fmgt/include/types/fmgt.h

    r144fafd r2309891  
    140140/** File system tree walk callbacks */
    141141typedef struct {
    142         errno_t (*dir_enter)(void *, const char *);
    143         errno_t (*dir_leave)(void *, const char *);
    144         errno_t (*file)(void *, const char *);
     142        errno_t (*dir_enter)(void *, const char *, const char *);
     143        errno_t (*dir_leave)(void *, const char *, const char *);
     144        errno_t (*file)(void *, const char *, const char *);
    145145} fmgt_walk_cb_t;
    146146
     
    149149        /** List of files or directories (walk roots) */
    150150        fmgt_flist_t *flist;
     151        /** Destination path */
     152        const char *dest;
     153        /** Copy files into destination directory. */
     154        bool into_dest;
    151155        /** Callbacks */
    152156        fmgt_walk_cb_t *cb;
  • uspace/lib/fmgt/meson.build

    r144fafd r2309891  
    2828
    2929src = files(
     30        'src/copy.c',
    3031        'src/flist.c',
    3132        'src/fmgt.c',
     
    3637
    3738test_src = files(
     39        'test/copy.c',
    3840        'test/flist.c',
    3941        'test/fmgt.c',
  • uspace/lib/fmgt/src/fmgt.c

    r144fafd r2309891  
    4040#include <stddef.h>
    4141#include <str.h>
     42#include <str.h>
    4243#include <vfs/vfs.h>
    4344#include <dirent.h>
     
    282283}
    283284
     285/** Return base name (without path component).
     286 *
     287 * @param path Pathname
     288 * @return Base name without directory components
     289 */
     290const char *fmgt_basename(const char *path)
     291{
     292        const char *p;
     293
     294        p = str_rchr(path, '/');
     295        if (p != NULL)
     296                return p + 1;
     297        else
     298                return path;
     299}
     300
     301/** Determine if pathname is an existing directory.
     302 *
     303 * @param path Pathname
     304 * @return @c true if @a path exists and is a directory
     305 */
     306bool fmgt_is_dir(const char *path)
     307{
     308        vfs_stat_t stat;
     309        errno_t rc;
     310
     311        rc = vfs_stat_path(path, &stat);
     312        if (rc != EOK)
     313                return false;
     314
     315        return stat.is_directory;
     316}
     317
    284318/** @}
    285319 */
  • uspace/lib/fmgt/src/verify.c

    r144fafd r2309891  
    3333 */
    3434
    35 //#include <dirent.h>
    3635#include <errno.h>
    3736#include <stdbool.h>
    38 //#include <stdio.h>
    3937#include <stdlib.h>
    40 //#include <stddef.h>
    41 //#include <str.h>
    4238#include <vfs/vfs.h>
    43 //#include <dirent.h>
    4439
    4540#include "fmgt.h"
     
    4742#include "../private/fmgt.h"
    4843
    49 static errno_t fmgt_verify_file(void *, const char *);
     44static errno_t fmgt_verify_file(void *, const char *, const char *);
    5045
    5146static fmgt_walk_cb_t fmgt_verify_cb = {
     
    5348};
    5449
    55 static errno_t fmgt_verify_file(void *arg, const char *fname)
     50/** Verify a single file.
     51 *
     52 * @param arg Argument (fmgt_t *)
     53 * @param fname File name
     54 * @param unused Unused
     55 * @return EOK on success or an error code
     56 */
     57static errno_t fmgt_verify_file(void *arg, const char *fname,
     58    const char *unused)
    5659{
    5760        fmgt_t *fmgt = (fmgt_t *)arg;
     
    6366        fmgt_error_action_t action;
    6467        errno_t rc;
     68
     69        (void)unused;
    6570
    6671        buffer = calloc(BUFFER_SIZE, 1);
     
    95100                        free(buffer);
    96101                        vfs_put(fd);
     102                        fmgt_final_progress_update(fmgt);
    97103                        return rc;
    98104                }
     
    104110                        free(buffer);
    105111                        vfs_put(fd);
     112                        fmgt_final_progress_update(fmgt);
    106113                        return EINTR;
    107114                }
  • uspace/lib/fmgt/src/walk.c

    r144fafd r2309891  
    4646#include "fmgt/walk.h"
    4747
    48 static errno_t fmgt_walk_subtree(fmgt_walk_params_t *, const char *);
     48static errno_t fmgt_walk_subtree(fmgt_walk_params_t *, const char *,
     49    const char *);
    4950
    5051/** Initialize walk parameters.
     
    6364 *
    6465 * @param params Walk parameters
    65  * @param fname File path
    66  *
    67  * @return EOK on success or an error code
    68  */
    69 static errno_t fmgt_walk_file(fmgt_walk_params_t *params, const char *fname)
     66 * @param fname Source path
     67 * @param dest Destination path
     68 *
     69 * @return EOK on success or an error code
     70 */
     71static errno_t fmgt_walk_file(fmgt_walk_params_t *params, const char *fname,
     72    const char *dest)
    7073{
    7174        if (params->cb->file != NULL)
    72                 return params->cb->file(params->arg, fname);
     75                return params->cb->file(params->arg, fname, dest);
    7376        else
    7477                return EOK;
     
    7881 *
    7982 * @param params Walk parameters
    80  * @param dname Directory path
     83 * @param dname Source directory
     84 * @param dest Destination path
    8185 * @return EOK on success or an error code
    8286 */
    8387static errno_t fmgt_walk_dir_enter(fmgt_walk_params_t *params,
    84     const char *dname)
     88    const char *dname, const char *dest)
    8589{
    8690        if (params->cb->dir_enter != NULL)
    87                 return params->cb->dir_enter(params->arg, dname);
     91                return params->cb->dir_enter(params->arg, dname, dest);
    8892        else
    8993                return EOK;
     
    9498 * @param params Walk parameters
    9599 * @param dname Directory path
     100 * @param dest Destination path
    96101 * @return EOK on success or an error code
    97102 */
    98103static errno_t fmgt_walk_dir_leave(fmgt_walk_params_t *params,
    99     const char *dname)
    100 {
    101         if (params->cb->dir_enter != NULL)
    102                 return params->cb->dir_leave(params->arg, dname);
     104    const char *dname, const char *dest)
     105{
     106        if (params->cb->dir_leave != NULL)
     107                return params->cb->dir_leave(params->arg, dname, dest);
    103108        else
    104109                return EOK;
     
    109114 * @param params Walk parameters
    110115 * @param dname Directory name
    111  * @return EOK on success or an error code
    112  */
    113 static errno_t fmgt_walk_dir(fmgt_walk_params_t *params, const char *dname)
     116 * @param dest Destination path or @c NULL
     117 * @return EOK on success or an error code
     118 */
     119static errno_t fmgt_walk_dir(fmgt_walk_params_t *params, const char *dname,
     120    const char *dest)
    114121{
    115122        DIR *dir = NULL;
    116123        struct dirent *de;
    117124        errno_t rc;
    118         char *pathname = NULL;
     125        char *srcpath = NULL;
     126        char *destpath = NULL;
    119127        int rv;
    120128
    121         rc = fmgt_walk_dir_enter(params, dname);
     129        rc = fmgt_walk_dir_enter(params, dname, dest);
    122130        if (rc != EOK)
    123131                goto error;
     
    131139        de = readdir(dir);
    132140        while (de != NULL) {
    133                 rv = asprintf(&pathname, "%s/%s", dname, de->d_name);
     141                rv = asprintf(&srcpath, "%s/%s", dname, de->d_name);
    134142                if (rv < 0) {
    135143                        rc = ENOMEM;
     
    137145                }
    138146
    139                 rc = fmgt_walk_subtree(params, pathname);
     147                if (dest != NULL) {
     148                        rv = asprintf(&destpath, "%s/%s", dest, de->d_name);
     149                        if (rv < 0) {
     150                                rc = ENOMEM;
     151                                free(srcpath);
     152                                goto error;
     153                        }
     154                }
     155
     156                rc = fmgt_walk_subtree(params, srcpath, destpath);
    140157                if (rc != EOK) {
    141                         free(pathname);
     158                        free(srcpath);
     159                        if (destpath != NULL)
     160                                free(destpath);
    142161                        goto error;
    143162                }
    144163
    145                 free(pathname);
     164                free(srcpath);
     165                if (destpath != NULL)
     166                        free(destpath);
    146167                de = readdir(dir);
    147168        }
    148169
    149         rc = fmgt_walk_dir_leave(params, dname);
     170        rc = fmgt_walk_dir_leave(params, dname, dest);
    150171        if (rc != EOK)
    151172                return rc;
     
    161182/** Walk subtree.
    162183 *
    163  * @params params Walk parameters.
    164  * @params fname Subtree path.
     184 * @param params Walk parameters.
     185 * @param fname Subtree path.
     186 * @param dest Destination path
    165187 *
    166188 * @return EOK on success or an error code.
    167189 */
    168 static errno_t fmgt_walk_subtree(fmgt_walk_params_t *params, const char *fname)
     190static errno_t fmgt_walk_subtree(fmgt_walk_params_t *params, const char *fname,
     191    const char *dest)
    169192{
    170193        vfs_stat_t stat;
     
    177200        if (stat.is_directory) {
    178201                /* Directory */
    179                 rc = fmgt_walk_dir(params, fname);
     202                rc = fmgt_walk_dir(params, fname, dest);
    180203                if (rc != EOK)
    181204                        return rc;
    182205        } else {
    183206                /* Not a directory */
    184                 rc = fmgt_walk_file(params, fname);
     207                rc = fmgt_walk_file(params, fname, dest);
    185208                if (rc != EOK)
    186209                        return rc;
     
    202225{
    203226        fmgt_flist_entry_t *entry;
     227        char *destname;
    204228        errno_t rc;
     229        int rv;
    205230
    206231        entry = fmgt_flist_first(params->flist);
    207232        while (entry != NULL) {
    208                 rc = fmgt_walk_subtree(params, entry->fname);
     233                if (params->into_dest) {
     234                        rv = asprintf(&destname, "%s/%s",
     235                            params->dest, fmgt_basename(entry->fname));
     236                        if (rv < 0)
     237                                return ENOMEM;
     238                } else {
     239                        destname = NULL;
     240                }
     241
     242                rc = fmgt_walk_subtree(params, entry->fname,
     243                    destname != NULL ? destname : params->dest);
    209244                if (rc != EOK)
    210245                        return rc;
  • uspace/lib/fmgt/test/walk.c

    r144fafd r2309891  
    3939PCUT_TEST_SUITE(walk);
    4040
    41 static errno_t test_walk_dir_enter(void *, const char *);
    42 static errno_t test_walk_dir_leave(void *, const char *);
    43 static errno_t test_walk_file(void *, const char *);
     41static errno_t test_walk_dir_enter(void *, const char *, const char *);
     42static errno_t test_walk_dir_leave(void *, const char *, const char *);
     43static errno_t test_walk_file(void *, const char *, const char *);
    4444
    4545static fmgt_walk_cb_t test_walk_cb = {
     
    5555        char *dirname;
    5656        char *fname;
     57        char *dest;
     58        char *de_dest;
     59        char *dl_dest;
    5760        errno_t rc;
    5861} test_resp_t;
    5962
    60 /** Walk file system tree. */
    61 PCUT_TEST(walk_success)
     63/** Walk file system tree with no destination and successful result. */
     64PCUT_TEST(walk_nodest_success)
    6265{
    6366        char buf[L_tmpnam];
     
    129132}
    130133
    131 errno_t test_walk_dir_enter(void *arg, const char *fname)
     134/** Walk file system tree with destination and successful result. */
     135PCUT_TEST(walk_dest_success)
     136{
     137        char buf[L_tmpnam];
     138        char *fname;
     139        FILE *f;
     140        char *p;
     141        int rv;
     142        fmgt_flist_t *flist;
     143        fmgt_walk_params_t params;
     144        test_resp_t resp;
     145        errno_t rc;
     146
     147        /* Create name for temporary directory */
     148        p = tmpnam(buf);
     149        PCUT_ASSERT_NOT_NULL(p);
     150
     151        /* Create temporary directory */
     152        rc = vfs_link_path(p, KIND_DIRECTORY, NULL);
     153        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     154
     155        rv = asprintf(&fname, "%s/%s", p, "a");
     156        PCUT_ASSERT_TRUE(rv >= 0);
     157
     158        f = fopen(fname, "wb");
     159        PCUT_ASSERT_NOT_NULL(f);
     160
     161        rv = fprintf(f, "X");
     162        PCUT_ASSERT_TRUE(rv >= 0);
     163
     164        rv = fclose(f);
     165        PCUT_ASSERT_INT_EQUALS(0, rv);
     166
     167        rc = fmgt_flist_create(&flist);
     168        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     169
     170        rc = fmgt_flist_append(flist, p);
     171        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     172
     173        fmgt_walk_params_init(&params);
     174        params.flist = flist;
     175        params.dest = "foo";
     176        params.cb = &test_walk_cb;
     177        params.arg = &resp;
     178
     179        resp.dir_enter = false;
     180        resp.dir_leave = false;
     181        resp.file_proc = false;
     182        resp.rc = EOK;
     183
     184        rc = fmgt_walk(&params);
     185        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     186
     187        PCUT_ASSERT_TRUE(resp.dir_enter);
     188        PCUT_ASSERT_TRUE(resp.dir_leave);
     189        PCUT_ASSERT_TRUE(resp.file_proc);
     190        PCUT_ASSERT_STR_EQUALS(p, resp.dirname);
     191        PCUT_ASSERT_STR_EQUALS(fname, resp.fname);
     192        printf("dest='%s'\n", resp.dest);
     193        printf("de_dest='%s'\n", resp.de_dest);
     194        printf("dl_dest='%s'\n", resp.dl_dest);
     195
     196        free(resp.dirname);
     197        free(resp.fname);
     198        fmgt_flist_destroy(flist);
     199
     200        rv = remove(fname);
     201        PCUT_ASSERT_INT_EQUALS(0, rv);
     202
     203        rv = remove(p);
     204        PCUT_ASSERT_INT_EQUALS(0, rv);
     205
     206        free(fname);
     207}
     208
     209errno_t test_walk_dir_enter(void *arg, const char *fname, const char *dest)
    132210{
    133211        test_resp_t *resp = (test_resp_t *)arg;
    134212        resp->dir_enter = true;
    135213        resp->dirname = str_dup(fname);
     214        resp->de_dest = str_dup(dest);
    136215        return resp->rc;
    137216}
    138217
    139 errno_t test_walk_dir_leave(void *arg, const char *fname)
     218errno_t test_walk_dir_leave(void *arg, const char *fname, const char *dest)
    140219{
    141220        test_resp_t *resp = (test_resp_t *)arg;
    142221        resp->dir_leave = true;
     222        resp->dl_dest = str_dup(dest);
    143223        return resp->rc;
    144224}
    145225
    146 errno_t test_walk_file(void *arg, const char *fname)
     226errno_t test_walk_file(void *arg, const char *fname, const char *dest)
    147227{
    148228        test_resp_t *resp = (test_resp_t *)arg;
    149229        resp->file_proc = true;
    150230        resp->fname = str_dup(fname);
     231        resp->dest = str_dup(dest);
    151232        return resp->rc;
    152233}
  • uspace/lib/ui/include/ui/filelist.h

    r144fafd r2309891  
    5050extern void ui_file_list_set_rect(ui_file_list_t *, gfx_rect_t *);
    5151extern errno_t ui_file_list_read_dir(ui_file_list_t *, const char *);
     52extern char *ui_file_list_get_dir(ui_file_list_t *);
    5253extern errno_t ui_file_list_activate(ui_file_list_t *);
    5354extern errno_t ui_file_list_refresh(ui_file_list_t *);
  • uspace/lib/ui/src/filelist.c

    r144fafd r2309891  
    424424}
    425425
     426/** Return path to the current directory.
     427 *
     428 * @return Path to current directory or @c NULL if out of memory
     429 */
     430char *ui_file_list_get_dir(ui_file_list_t *flist)
     431{
     432        return str_dup(flist->dir);
     433}
     434
    426435/** Re-read file list from directory.
    427436 *
Note: See TracChangeset for help on using the changeset viewer.