Changeset c111da2 in mainline for uspace


Ignore:
Timestamp:
2025-10-09T15:44:52Z (3 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
cfd04c4
Parents:
1a96db9
Message:

Create non-zero size file in Navigator, new newfile utility.

Location:
uspace
Files:
9 added
17 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/cmds/modules/ls/ls.c

    r1a96db9 rc111da2  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2008 Tim Post
    34 * All rights reserved.
     
    106107                }
    107108
    108                 capa_spec_t capa;
    109                 capa_from_blocks(de->s.size, 1, &capa);
    110                 capa_simplify(&capa);
    111 
    112                 char *rptr;
    113                 errno_t rc = capa_format(&capa, &rptr);
    114                 if (rc != EOK) {
    115                         return rc;
    116                 }
    117 
    118                 char *sep = str_rchr(rptr, ' ');
     109                char fsize[CAPA_BLOCKS_BUFSIZE];
     110                capa_blocks_format_buf(de->s.size, 1, fsize, sizeof(fsize));
     111
     112                char *sep = str_rchr(fsize, ' ');
    119113                if (sep == NULL) {
    120                         free(rptr);
    121114                        return ENOENT;
    122115                }
     
    124117                *sep = '\0';
    125118
    126                 printf("%-40s\t%*s %2s\n", de->name, width - 3, rptr, sep + 1);
    127                 free(rptr);
     119                printf("%-40s\t%*s %2s\n", de->name, width - 3, fsize, sep + 1);
    128120        } else if (de->s.is_directory)
    129121                printf("%-40s\t%*s\n", de->name, width, "<dir>");
  • uspace/app/df/df.c

    r1a96db9 rc111da2  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2013 Manuele Conti
    34 * All rights reserved.
     
    5657static bool display_blocks;
    5758
    58 static errno_t size_to_human_readable(uint64_t, size_t, char **);
    5959static void print_header(void);
    60 static errno_t print_statfs(vfs_statfs_t *, char *, char *);
     60static void print_statfs(vfs_statfs_t *, char *, char *);
    6161static void print_usage(void);
    6262
     
    6565        int optres, errflg = 0;
    6666        vfs_statfs_t st;
    67         errno_t rc;
    6867
    6968        display_blocks = false;
     
    109108        list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) {
    110109                if (vfs_statfs_path(mtab_ent->mp, &st) == 0) {
    111                         rc = print_statfs(&st, mtab_ent->fs_name, mtab_ent->mp);
    112                         if (rc != EOK)
    113                                 return 1;
     110                        print_statfs(&st, mtab_ent->fs_name, mtab_ent->mp);
    114111                } else {
    115112                        fprintf(stderr, "Cannot get information for '%s' (%s).\n",
     
    120117        putchar('\n');
    121118        return 0;
    122 }
    123 
    124 static errno_t size_to_human_readable(uint64_t nblocks, size_t block_size, char **rptr)
    125 {
    126         capa_spec_t capa;
    127 
    128         capa_from_blocks(nblocks, block_size, &capa);
    129         capa_simplify(&capa);
    130         return capa_format(&capa, rptr);
    131119}
    132120
     
    141129}
    142130
    143 static errno_t print_statfs(vfs_statfs_t *st, char *name, char *mountpoint)
     131static void print_statfs(vfs_statfs_t *st, char *name, char *mountpoint)
    144132{
    145133        uint64_t const used_blocks = st->f_blocks - st->f_bfree;
    146134        unsigned const perc_used = PERCENTAGE(used_blocks, st->f_blocks);
    147         char *str;
    148         errno_t rc;
     135        char str[CAPA_BLOCKS_BUFSIZE];
    149136
    150137        printf("%10s", name);
     
    152139        if (!display_blocks) {
    153140                /* Print size */
    154                 rc = size_to_human_readable(st->f_blocks, st->f_bsize, &str);
    155                 if (rc != EOK)
    156                         goto error;
     141                capa_blocks_format_buf(st->f_blocks, st->f_bsize, str,
     142                    sizeof(str));
    157143                printf(" %14s", str);
    158                 free(str);
    159144
    160145                /* Number of used blocks */
    161                 rc = size_to_human_readable(used_blocks, st->f_bsize, &str);
    162                 if (rc != EOK)
    163                         goto error;
     146                capa_blocks_format_buf(used_blocks, st->f_bsize, str,
     147                    sizeof(str));
    164148                printf(" %14s", str);
    165                 free(str);
    166149
    167150                /* Number of available blocks */
    168                 rc = size_to_human_readable(st->f_bfree, st->f_bsize, &str);
    169                 if (rc != EOK)
    170                         goto error;
     151                capa_blocks_format_buf(st->f_bfree, st->f_bsize, str,
     152                    sizeof(str));
    171153                printf(" %14s", str);
    172                 free(str);
    173154
    174155                /* Percentage of used blocks */
     
    183164                    perc_used, mountpoint);
    184165        }
    185 
    186         return EOK;
    187 error:
    188         printf("\nError: Out of memory.\n");
    189         return ENOMEM;
    190166}
    191167
  • uspace/app/meson.build

    r1a96db9 rc111da2  
    11#
     2# Copyright (c) 2025 Jiri Svoboda
    23# Copyright (c) 2019 Jiří Zárevúcky
    34# All rights reserved.
     
    6970        'nav',
    7071        'netecho',
     72        'newfile',
    7173        'nic',
    7274        'nterm',
  • uspace/app/nav/dlg/newfiledlg.c

    r1a96db9 rc111da2  
    358358
    359359        (void)window;
    360         if (dialog->cb != NULL && dialog->cb->bcancel != NULL) {
     360        if (dialog->cb != NULL && dialog->cb->close != NULL) {
    361361                dialog->cb->close(dialog, dialog->arg);
    362362        }
     
    373373{
    374374        new_file_dlg_t *dialog = (new_file_dlg_t *) arg;
    375         const char *text;
     375        const char *fname;
     376        const char *fsize;
    376377
    377378        if (event->type == KEY_PRESS &&
     
    380381                        /* Confirm */
    381382                        if (dialog->cb != NULL && dialog->cb->bok != NULL) {
    382                                 text = ui_entry_get_text(dialog->ename);
    383                                 dialog->cb->bok(dialog, dialog->arg, text);
     383                                fname = ui_entry_get_text(dialog->ename);
     384                                fsize = ui_entry_get_text(dialog->esize);
     385                                dialog->cb->bok(dialog, dialog->arg, fname,
     386                                    fsize);
    384387                                return;
    385388                        }
     
    404407{
    405408        new_file_dlg_t *dialog = (new_file_dlg_t *) arg;
    406         const char *text;
     409        const char *fname;
     410        const char *fsize;
    407411
    408412        if (dialog->cb != NULL && dialog->cb->bok != NULL) {
    409                 text = ui_entry_get_text(dialog->ename);
    410                 dialog->cb->bok(dialog, dialog->arg, text);
     413                fname = ui_entry_get_text(dialog->ename);
     414                fsize = ui_entry_get_text(dialog->esize);
     415                dialog->cb->bok(dialog, dialog->arg, fname, fsize);
    411416        }
    412417}
  • uspace/app/nav/meson.build

    r1a96db9 rc111da2  
    3030src = files(
    3131        'dlg/newfiledlg.c',
     32        'dlg/progress.c',
    3233        'main.c',
    3334        'menu.c',
     
    3940test_src = files(
    4041        'dlg/newfiledlg.c',
     42        'dlg/progress.c',
    4143        'menu.c',
    4244        'nav.c',
  • uspace/app/nav/nav.c

    r1a96db9 rc111da2  
    3535 */
    3636
     37#include <fibril.h>
    3738#include <gfx/coord.h>
    3839#include <stdio.h>
     
    535536}
    536537
     538/** Wrapper fibril function for worker function.
     539 *
     540 * This is the main fibril function for the worker fibril. It executes
     541 * the worker function, then clears worker FID to indicate the worker
     542 * is finished.
     543 *
     544 * @param arg Argument (navigator_worker_job_t *)
     545 * @return EOK
     546 */
     547static errno_t navigator_worker_func(void *arg)
     548{
     549        navigator_worker_job_t *job = (navigator_worker_job_t *)arg;
     550
     551        job->wfunc(job->arg);
     552        job->navigator->worker_fid = 0;
     553        free(job);
     554        return EOK;
     555}
     556
     557/** Start long-time work in a worker fibril.
     558 *
     559 * Actions which can take time (file operations) cannot block the main UI
     560 * fibril. This function will start an action in the worker fibril, i.e.,
     561 * in the background. At the same time the caller should create a modal
     562 * progress dialog that will be shown until the work is completed.
     563 *
     564 * (Only a single worker can execute at any given time).
     565 *
     566 * @param nav Navigator
     567 * @param wfunc Worker main function
     568 * @param arg Argument to worker function
     569 *
     570 * @return EOK on success or an error code
     571 */
     572errno_t navigator_worker_start(navigator_t *nav, void (*wfunc)(void *),
     573    void *arg)
     574{
     575        navigator_worker_job_t *job;
     576
     577        if (nav->worker_fid != 0)
     578                return EBUSY;
     579
     580        job = calloc(1, sizeof(navigator_worker_job_t));
     581        if (job == NULL)
     582                return ENOMEM;
     583
     584        job->navigator = nav;
     585        job->wfunc = wfunc;
     586        job->arg = arg;
     587
     588        nav->worker_fid = fibril_create(navigator_worker_func, (void *)job);
     589        if (nav->worker_fid == 0) {
     590                free(job);
     591                return ENOMEM;
     592        }
     593
     594        fibril_add_ready(nav->worker_fid);
     595        return EOK;
     596}
     597
    537598/** @}
    538599 */
  • uspace/app/nav/nav.h

    r1a96db9 rc111da2  
    4747extern void navigator_switch_panel(navigator_t *);
    4848extern void navigator_refresh_panels(navigator_t *);
     49extern errno_t navigator_worker_start(navigator_t *, void (*)(void *),
     50    void *);
    4951
    5052#endif
  • uspace/app/nav/newfile.c

    r1a96db9 rc111da2  
    3434 */
    3535
     36#include <capa.h>
     37#include <fmgt.h>
    3638#include <stdlib.h>
    3739#include <str_error.h>
     
    4244#include <ui/ui.h>
    4345#include <ui/window.h>
     46#include <str.h>
    4447#include "dlg/newfiledlg.h"
     48#include "dlg/progress.h"
    4549#include "menu.h"
    4650#include "newfile.h"
    4751#include "nav.h"
    48 
    49 static void new_file_bok(new_file_dlg_t *, void *, const char *);
     52#include "types/newfile.h"
     53
     54static void new_file_bok(new_file_dlg_t *, void *, const char *, const char *);
    5055static void new_file_bcancel(new_file_dlg_t *, void *);
    5156static void new_file_close(new_file_dlg_t *, void *);
     
    5762};
    5863
     64static void new_file_progress(void *, fmgt_progress_t *);
     65
     66static fmgt_cb_t new_file_fmgt_cb = {
     67        .progress = new_file_progress
     68};
     69
    5970/** Open New File dialog.
    6071 *
     
    6980}
    7081
     82/** New file worker function.
     83 *
     84 * @param arg Argument (navigator_new_file_job_t)
     85 */
     86static void new_file_wfunc(void *arg)
     87{
     88        fmgt_t *fmgt = NULL;
     89        navigator_new_file_job_t *job = (navigator_new_file_job_t *)arg;
     90        char *msg = NULL;
     91        navigator_t *nav = job->navigator;
     92        ui_msg_dialog_t *dialog = NULL;
     93        ui_msg_dialog_params_t params;
     94        errno_t rc;
     95        int rv;
     96
     97        rc = fmgt_create(&fmgt);
     98        if (rc != EOK) {
     99                /* out of memory */
     100                return;
     101        }
     102
     103        fmgt_set_cb(fmgt, &new_file_fmgt_cb, (void *)nav);
     104        fmgt_set_init_update(fmgt, true);
     105
     106        rc = fmgt_new_file(fmgt, job->fname, job->nbytes);
     107        if (rc != EOK) {
     108                rv = asprintf(&msg, "Error creating file (%s).",
     109                    str_error(rc));
     110                if (rv < 0)
     111                        return;
     112                goto error;
     113        }
     114
     115        fmgt_destroy(fmgt);
     116        ui_lock(nav->ui);
     117        progress_dlg_destroy(nav->progress_dlg);
     118        navigator_refresh_panels(nav);
     119        ui_unlock(nav->ui);
     120        free(job);
     121        return;
     122error:
     123        ui_lock(nav->ui);
     124        progress_dlg_destroy(nav->progress_dlg);
     125        ui_msg_dialog_params_init(&params);
     126        params.caption = "Error";
     127        params.text = msg;
     128        (void) ui_msg_dialog_create(nav->ui, &params, &dialog);
     129        ui_unlock(nav->ui);
     130        free(msg);
     131}
     132
    71133/** New file dialog confirmed.
    72134 *
     
    74136 * @param arg Argument (navigator_t *)
    75137 * @param fname New file name
    76  */
    77 static void new_file_bok(new_file_dlg_t *dlg, void *arg, const char *fname)
     138 * @param fsize New file size
     139 */
     140static void new_file_bok(new_file_dlg_t *dlg, void *arg, const char *fname,
     141    const char *fsize)
    78142{
    79143        navigator_t *nav = (navigator_t *)arg;
    80144        ui_msg_dialog_t *dialog = NULL;
     145        navigator_new_file_job_t *job;
    81146        ui_msg_dialog_params_t params;
     147        progress_dlg_params_t pd_params;
     148        capa_spec_t fcap;
    82149        char *msg = NULL;
     150        errno_t rc;
     151        uint64_t nbytes;
    83152        int rv;
    84         FILE *f;
     153
     154        rc = capa_parse(fsize, &fcap);
     155        if (rc != EOK) {
     156                /* invalid file size */
     157                return;
     158        }
    85159
    86160        new_file_dlg_destroy(dlg);
    87         f = fopen(fname, "wx");
    88         if (f == NULL) {
    89                 rv = asprintf(&msg, "Error creating file (%s).",
    90                     str_error(errno));
     161
     162        rc = capa_to_blocks(&fcap, cv_nom, 1, &nbytes);
     163        if (rc != EOK) {
     164                rv = asprintf(&msg, "File size too large (%s).", fsize);
    91165                if (rv < 0)
    92166                        return;
    93 
    94                 ui_msg_dialog_params_init(&params);
    95                 params.caption = "Error";
    96                 params.text = msg;
    97                 (void) ui_msg_dialog_create(nav->ui, &params, &dialog);
    98                 free(msg);
     167                goto error;
     168        }
     169
     170        job = calloc(1, sizeof(navigator_new_file_job_t));
     171        if (job == NULL)
    99172                return;
    100         }
    101 
    102         fclose(f);
    103         navigator_refresh_panels(nav);
     173
     174        job->navigator = nav;
     175        job->fname = fname;
     176        job->nbytes = nbytes;
     177
     178        progress_dlg_params_init(&pd_params);
     179        pd_params.caption = "Creating new file";
     180
     181        rc = progress_dlg_create(nav->ui, &pd_params, &nav->progress_dlg);
     182        if (rc != EOK) {
     183                msg = str_dup("Out of memory.");
     184                if (msg == NULL)
     185                        return;
     186                goto error;
     187        }
     188
     189        rc = navigator_worker_start(nav, new_file_wfunc, (void *)job);
     190        if (rc != EOK) {
     191                msg = str_dup("Out of memory.");
     192                if (msg == NULL)
     193                        return;
     194                goto error;
     195        }
     196
     197        return;
     198error:
     199        ui_msg_dialog_params_init(&params);
     200        params.caption = "Error";
     201        params.text = msg;
     202        (void) ui_msg_dialog_create(nav->ui, &params, &dialog);
     203        free(msg);
    104204}
    105205
     
    126226}
    127227
     228/** New file progress update.
     229 *
     230 * @param arg Argument (navigator_t *)
     231 * @param progress Progress update
     232 */
     233static void new_file_progress(void *arg, fmgt_progress_t *progress)
     234{
     235        navigator_t *nav = (navigator_t *)arg;
     236        char buf[128];
     237
     238        snprintf(buf, sizeof(buf), "Written %s of %s (%s done).",
     239            progress->curf_procb, progress->curf_totalb,
     240            progress->curf_percent);
     241        progress_dlg_set_curf_prog(nav->progress_dlg, buf);
     242}
     243
    128244/** @}
    129245 */
  • uspace/app/nav/types/dlg/newfiledlg.h

    r1a96db9 rc111da2  
    6060} new_file_dlg_t;
    6161
    62 /** Prompt dialog callback */
     62/** New File dialog callbacks */
    6363typedef struct new_file_dlg_cb {
    6464        /** OK button was pressed */
    65         void (*bok)(new_file_dlg_t *, void *, const char *);
     65        void (*bok)(new_file_dlg_t *, void *, const char *, const char *);
    6666        /** Cancel button was pressed */
    6767        void (*bcancel)(new_file_dlg_t *, void *);
  • uspace/app/nav/types/nav.h

    r1a96db9 rc111da2  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3737#define TYPES_NAV_H
    3838
     39#include <fibril.h>
    3940#include <ui/fixed.h>
    4041#include <ui/ui.h>
     
    5758        /** Panels */
    5859        struct panel *panel[navigator_panels];
     60        /** Progress dialog */
     61        struct progress_dlg *progress_dlg;
     62        /** Worker fibril ID */
     63        fid_t worker_fid;
    5964} navigator_t;
     65
     66/** Navigator worker job */
     67typedef struct {
     68        /** Navigator */
     69        navigator_t *navigator;
     70        /** Worker function */
     71        void (*wfunc)(void *);
     72        /** Worker argument */
     73        void *arg;
     74} navigator_worker_job_t;
    6075
    6176#endif
  • uspace/lib/c/generic/capa.c

    r1a96db9 rc111da2  
    11/*
    2  * Copyright (c) 2015 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    233233}
    234234
     235errno_t capa_format_buf(capa_spec_t *capa, char *buf, size_t bufsize)
     236{
     237        errno_t rc;
     238        const char *sunit;
     239        uint64_t ipart;
     240        uint64_t fpart;
     241        uint64_t div;
     242
     243        sunit = NULL;
     244
     245        assert(capa->cunit < CU_LIMIT);
     246
     247        rc = ipow10_u64(capa->dp, &div);
     248        if (rc != EOK)
     249                return rc;
     250
     251        ipart = capa->m / div;
     252        fpart = capa->m % div;
     253
     254        sunit = cu_str[capa->cunit];
     255        if (capa->dp > 0) {
     256                snprintf(buf, bufsize, "%" PRIu64 ".%0*" PRIu64 " %s", ipart,
     257                    (int)capa->dp, fpart, sunit);
     258        } else {
     259                snprintf(buf, bufsize, "%" PRIu64 " %s", ipart, sunit);
     260        }
     261
     262        return EOK;
     263}
     264
     265errno_t capa_blocks_format(uint64_t nblocks, size_t block_size,
     266    char **rptr)
     267{
     268        capa_spec_t capa;
     269
     270        capa_from_blocks(nblocks, block_size, &capa);
     271        capa_simplify(&capa);
     272        return capa_format(&capa, rptr);
     273}
     274
     275void capa_blocks_format_buf(uint64_t nblocks, size_t block_size,
     276    char *buf, size_t bsize)
     277{
     278        capa_spec_t capa;
     279        errno_t rc;
     280
     281        capa_from_blocks(nblocks, block_size, &capa);
     282        capa_simplify(&capa);
     283
     284        /* Should not get range error because of nblocks * block_size limits */
     285        rc = capa_format_buf(&capa, buf, bsize);
     286        assert(rc == EOK);
     287        (void)rc;
     288}
     289
    235290static errno_t capa_digit_val(char c, int *val)
    236291{
  • uspace/lib/c/include/capa.h

    r1a96db9 rc111da2  
    11/*
    2  * Copyright (c) 2015 Jiri Svoboda
     2 * Copyright (c) 2025 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    8787} capa_spec_t;
    8888
     89/** Size of buffer large enough for capa_blocks_format_buf */
     90#define CAPA_BLOCKS_BUFSIZE 16
     91
    8992extern errno_t capa_format(capa_spec_t *, char **);
     93extern errno_t capa_format_buf(capa_spec_t *, char *, size_t);
     94extern errno_t capa_blocks_format(uint64_t, size_t, char **);
     95extern void capa_blocks_format_buf(uint64_t, size_t, char *, size_t);
    9096extern errno_t capa_parse(const char *, capa_spec_t *);
    9197extern void capa_simplify(capa_spec_t *);
  • uspace/lib/c/test/capa.c

    r1a96db9 rc111da2  
    11/*
     2 * Copyright (c) 2025 Jiri Svoboda
    23 * Copyright (c) 2019 Matthieu Riolo
    34 * All rights reserved.
     
    285286}
    286287
     288PCUT_TEST(capa_blocks_format)
     289{
     290        errno_t rc;
     291        char *str;
     292
     293        rc = capa_blocks_format(42, 1, &str);
     294        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     295        PCUT_ASSERT_STR_EQUALS("42 B", str);
     296        free(str);
     297}
     298
     299PCUT_TEST(capa_blocks_format_buf)
     300{
     301        char str[CAPA_BLOCKS_BUFSIZE];
     302
     303        capa_blocks_format_buf(42, 1, str, sizeof(str));
     304        PCUT_ASSERT_STR_EQUALS("42 B", str);
     305}
     306
    287307PCUT_EXPORT(capa);
  • uspace/lib/fmgt/include/fmgt.h

    r1a96db9 rc111da2  
    3939
    4040#include <errno.h>
     41#include <stdbool.h>
    4142#include <stddef.h>
     43#include <stdint.h>
    4244#include "types/fmgt.h"
    4345
     
    4547extern void fmgt_set_cb(fmgt_t *, fmgt_cb_t *, void *);
    4648extern void fmgt_destroy(fmgt_t *);
     49extern void fmgt_set_init_update(fmgt_t *, bool);
    4750extern errno_t fmgt_new_file_suggest(char **);
     51extern errno_t fmgt_new_file(fmgt_t *, const char *, uint64_t);
    4852
    4953#endif
  • uspace/lib/fmgt/include/types/fmgt.h

    r1a96db9 rc111da2  
    3838#define TYPES_FMGT_H
    3939
     40#include <capa.h>
     41#include <fibril_synch.h>
     42
     43/** File management progress update */
     44typedef struct {
     45        /** Current file processed bytes */
     46        char curf_procb[CAPA_BLOCKS_BUFSIZE];
     47        /** Total bytes to process for current file */
     48        char curf_totalb[CAPA_BLOCKS_BUFSIZE];
     49        /** Percent of current file processed */
     50        char curf_percent[5];
     51} fmgt_progress_t;
     52
    4053/** File management callbacks */
    4154typedef struct {
     55        void (*progress)(void *, fmgt_progress_t *);
    4256} fmgt_cb_t;
    4357
    4458typedef struct {
     59        /** Lock */
     60        fibril_mutex_t lock;
     61        /** Progress update timer */
     62        fibril_timer_t *timer;
    4563        /** Callback functions */
    4664        fmgt_cb_t *cb;
    4765        /** Argument to callback functions */
    4866        void *cb_arg;
     67        /** Bytes processed from current file */
     68        uint64_t curf_procb;
     69        /** Total size of current file */
     70        uint64_t curf_totalb;
     71        /** Progress was displayed for current file */
     72        bool curf_progr;
     73        /** Post an immediate initial progress update */
     74        bool do_init_update;
    4975} fmgt_t;
    5076
  • uspace/lib/fmgt/meson.build

    r1a96db9 rc111da2  
    2828
    2929src = files(
    30         'src/fmgt.c'
     30        'src/fmgt.c',
    3131)
     32
     33test_src = files(
     34        'test/fmgt.c',
     35        'test/main.c',
     36)
  • uspace/lib/fmgt/src/fmgt.c

    r1a96db9 rc111da2  
    4646
    4747#define NEWNAME_LEN 64
     48#define BUFFER_SIZE 16384
    4849
    4950/** Create file management library instance.
     
    5960        if (fmgt == NULL)
    6061                return ENOMEM;
     62
     63        fibril_mutex_initialize(&fmgt->lock);
     64        fmgt->timer = fibril_timer_create(&fmgt->lock);
     65        if (fmgt->timer == NULL) {
     66                free(fmgt);
     67                return ENOMEM;
     68        }
    6169
    6270        *rfmgt = fmgt;
     
    7785}
    7886
     87/** Configure whether to give immediate initial progress update.
     88 *
     89 * @param fmgt File management object
     90 * @param enabled @c true to post and immediate initial progress update
     91 */
     92void fmgt_set_init_update(fmgt_t *fmgt, bool enabled)
     93{
     94        fmgt->do_init_update = enabled;
     95}
     96
    7997/** Destroy file management library instance.
    8098 *
     
    83101void fmgt_destroy(fmgt_t *fmgt)
    84102{
     103        (void)fibril_timer_clear(fmgt->timer);
     104        fibril_timer_destroy(fmgt->timer);
    85105        free(fmgt);
    86106}
     
    116136}
    117137
     138/** Get progress update report.
     139 *
     140 * @param fmgt File management object
     141 * @param progress Place to store progress update
     142 */
     143static void fmgt_get_progress(fmgt_t *fmgt, fmgt_progress_t *progress)
     144{
     145        unsigned percent;
     146
     147        if (fmgt->curf_totalb > 0)
     148                percent = fmgt->curf_procb * 100 / fmgt->curf_totalb;
     149        else
     150                percent = 100;
     151
     152        capa_blocks_format_buf(fmgt->curf_procb, 1, progress->curf_procb,
     153            sizeof(progress->curf_procb));
     154        capa_blocks_format_buf(fmgt->curf_totalb, 1, progress->curf_totalb,
     155            sizeof(progress->curf_totalb));
     156        snprintf(progress->curf_percent, sizeof(progress->curf_percent), "%u%%",
     157            percent);
     158}
     159
     160/** Give the caller progress update.
     161 *
     162 * @param fmgt File management object
     163 */
     164static void fmgt_progress_update(fmgt_t *fmgt)
     165{
     166        fmgt_progress_t progress;
     167
     168        if (fmgt->cb != NULL && fmgt->cb->progress != NULL) {
     169                fmgt_get_progress(fmgt, &progress);
     170                fmgt->curf_progr = true;
     171                fmgt->cb->progress(fmgt->cb_arg, &progress);
     172        }
     173}
     174
     175/** Provide initial progress update (if required).
     176 *
     177 * The caller configures the file management object regarding whether
     178 * initial updates are required.
     179 *
     180 * @param fmgt File management object
     181 */
     182static void fmgt_initial_progress_update(fmgt_t *fmgt)
     183{
     184        if (fmgt->do_init_update)
     185                fmgt_progress_update(fmgt);
     186}
     187
     188/** Provide final progress update (if required).
     189 *
     190 * Final update is provided only if a previous progress update was given.
     191 *
     192 * @param fmgt File management object
     193 */
     194static void fmgt_final_progress_update(fmgt_t *fmgt)
     195{
     196        if (fmgt->curf_progr)
     197                fmgt_progress_update(fmgt);
     198}
     199
     200/** Progress timer function.
     201 *
     202 * Periodically called to provide progress updates.
     203 *
     204 * @param arg Argument (fmgt_t *)
     205 */
     206static void fmgt_timer_fun(void *arg)
     207{
     208        fmgt_t *fmgt = (fmgt_t *)arg;
     209
     210        fmgt_progress_update(fmgt);
     211        fibril_timer_set(fmgt->timer, 500000, fmgt_timer_fun, (void *)fmgt);
     212}
     213
     214/** Start progress update timer.
     215 *
     216 * @param fmgt File management object
     217 */
     218static void fmgt_timer_start(fmgt_t *fmgt)
     219{
     220        fibril_timer_set(fmgt->timer, 500000, fmgt_timer_fun, (void *)fmgt);
     221}
     222
     223/** Create new file.
     224 *
     225 * @param fmgt File management object
     226 * @param fname File name
     227 * @param fsize Size of new file (number of zero bytes to fill in)
     228 * @return EOK on success or an error code
     229 */
     230errno_t fmgt_new_file(fmgt_t *fmgt, const char *fname, uint64_t fsize)
     231{
     232        int fd;
     233        size_t nw;
     234        aoff64_t pos = 0;
     235        uint64_t now;
     236        char *buffer;
     237        errno_t rc;
     238
     239        buffer = calloc(BUFFER_SIZE, 1);
     240        if (buffer == NULL)
     241                return ENOMEM;
     242
     243        rc = vfs_lookup_open(fname, WALK_REGULAR | WALK_MUST_CREATE,
     244            MODE_WRITE, &fd);
     245        if (rc != EOK) {
     246                free(buffer);
     247                return rc;
     248        }
     249
     250        fmgt->curf_procb = 0;
     251        fmgt->curf_totalb = fsize;
     252        fmgt->curf_progr = false;
     253        fmgt_timer_start(fmgt);
     254
     255        fmgt_initial_progress_update(fmgt);
     256
     257        while (fmgt->curf_procb < fsize) {
     258                now = fsize - fmgt->curf_procb;
     259                if (now > BUFFER_SIZE)
     260                        now = BUFFER_SIZE;
     261
     262                rc = vfs_write(fd, &pos, buffer, now, &nw);
     263                if (rc != EOK) {
     264                        free(buffer);
     265                        vfs_put(fd);
     266                        fmgt_final_progress_update(fmgt);
     267                        return rc;
     268                }
     269
     270                fmgt->curf_procb += nw;
     271        }
     272
     273        free(buffer);
     274        vfs_put(fd);
     275        fmgt_final_progress_update(fmgt);
     276        return EOK;
     277}
     278
    118279/** @}
    119280 */
Note: See TracChangeset for help on using the changeset viewer.