- Timestamp:
- 2025-10-09T15:44:52Z (3 months ago)
- Branches:
- master
- Children:
- cfd04c4
- Parents:
- 1a96db9
- Location:
- uspace
- Files:
-
- 9 added
- 17 edited
-
app/bdsh/cmds/modules/ls/ls.c (modified) (3 diffs)
-
app/df/df.c (modified) (8 diffs)
-
app/meson.build (modified) (2 diffs)
-
app/nav/dlg/newfiledlg.c (modified) (4 diffs)
-
app/nav/dlg/progress.c (added)
-
app/nav/dlg/progress.h (added)
-
app/nav/meson.build (modified) (2 diffs)
-
app/nav/nav.c (modified) (2 diffs)
-
app/nav/nav.h (modified) (1 diff)
-
app/nav/newfile.c (modified) (6 diffs)
-
app/nav/types/dlg/newfiledlg.h (modified) (1 diff)
-
app/nav/types/dlg/progress.h (added)
-
app/nav/types/nav.h (modified) (3 diffs)
-
app/nav/types/newfile.h (added)
-
app/newfile/doc/doxygroups.h (added)
-
app/newfile/meson.build (added)
-
app/newfile/newfile.c (added)
-
lib/c/generic/capa.c (modified) (2 diffs)
-
lib/c/include/capa.h (modified) (2 diffs)
-
lib/c/test/capa.c (modified) (2 diffs)
-
lib/fmgt/include/fmgt.h (modified) (2 diffs)
-
lib/fmgt/include/types/fmgt.h (modified) (1 diff)
-
lib/fmgt/meson.build (modified) (1 diff)
-
lib/fmgt/src/fmgt.c (modified) (5 diffs)
-
lib/fmgt/test/fmgt.c (added)
-
lib/fmgt/test/main.c (added)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/cmds/modules/ls/ls.c
r1a96db9 rc111da2 1 1 /* 2 * Copyright (c) 2025 Jiri Svoboda 2 3 * Copyright (c) 2008 Tim Post 3 4 * All rights reserved. … … 106 107 } 107 108 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, ' '); 119 113 if (sep == NULL) { 120 free(rptr);121 114 return ENOENT; 122 115 } … … 124 117 *sep = '\0'; 125 118 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); 128 120 } else if (de->s.is_directory) 129 121 printf("%-40s\t%*s\n", de->name, width, "<dir>"); -
uspace/app/df/df.c
r1a96db9 rc111da2 1 1 /* 2 * Copyright (c) 2025 Jiri Svoboda 2 3 * Copyright (c) 2013 Manuele Conti 3 4 * All rights reserved. … … 56 57 static bool display_blocks; 57 58 58 static errno_t size_to_human_readable(uint64_t, size_t, char **);59 59 static void print_header(void); 60 static errno_tprint_statfs(vfs_statfs_t *, char *, char *);60 static void print_statfs(vfs_statfs_t *, char *, char *); 61 61 static void print_usage(void); 62 62 … … 65 65 int optres, errflg = 0; 66 66 vfs_statfs_t st; 67 errno_t rc;68 67 69 68 display_blocks = false; … … 109 108 list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) { 110 109 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); 114 111 } else { 115 112 fprintf(stderr, "Cannot get information for '%s' (%s).\n", … … 120 117 putchar('\n'); 121 118 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);131 119 } 132 120 … … 141 129 } 142 130 143 static errno_tprint_statfs(vfs_statfs_t *st, char *name, char *mountpoint)131 static void print_statfs(vfs_statfs_t *st, char *name, char *mountpoint) 144 132 { 145 133 uint64_t const used_blocks = st->f_blocks - st->f_bfree; 146 134 unsigned const perc_used = PERCENTAGE(used_blocks, st->f_blocks); 147 char *str; 148 errno_t rc; 135 char str[CAPA_BLOCKS_BUFSIZE]; 149 136 150 137 printf("%10s", name); … … 152 139 if (!display_blocks) { 153 140 /* 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)); 157 143 printf(" %14s", str); 158 free(str);159 144 160 145 /* 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)); 164 148 printf(" %14s", str); 165 free(str);166 149 167 150 /* 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)); 171 153 printf(" %14s", str); 172 free(str);173 154 174 155 /* Percentage of used blocks */ … … 183 164 perc_used, mountpoint); 184 165 } 185 186 return EOK;187 error:188 printf("\nError: Out of memory.\n");189 return ENOMEM;190 166 } 191 167 -
uspace/app/meson.build
r1a96db9 rc111da2 1 1 # 2 # Copyright (c) 2025 Jiri Svoboda 2 3 # Copyright (c) 2019 Jiří Zárevúcky 3 4 # All rights reserved. … … 69 70 'nav', 70 71 'netecho', 72 'newfile', 71 73 'nic', 72 74 'nterm', -
uspace/app/nav/dlg/newfiledlg.c
r1a96db9 rc111da2 358 358 359 359 (void)window; 360 if (dialog->cb != NULL && dialog->cb-> bcancel!= NULL) {360 if (dialog->cb != NULL && dialog->cb->close != NULL) { 361 361 dialog->cb->close(dialog, dialog->arg); 362 362 } … … 373 373 { 374 374 new_file_dlg_t *dialog = (new_file_dlg_t *) arg; 375 const char *text; 375 const char *fname; 376 const char *fsize; 376 377 377 378 if (event->type == KEY_PRESS && … … 380 381 /* Confirm */ 381 382 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); 384 387 return; 385 388 } … … 404 407 { 405 408 new_file_dlg_t *dialog = (new_file_dlg_t *) arg; 406 const char *text; 409 const char *fname; 410 const char *fsize; 407 411 408 412 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); 411 416 } 412 417 } -
uspace/app/nav/meson.build
r1a96db9 rc111da2 30 30 src = files( 31 31 'dlg/newfiledlg.c', 32 'dlg/progress.c', 32 33 'main.c', 33 34 'menu.c', … … 39 40 test_src = files( 40 41 'dlg/newfiledlg.c', 42 'dlg/progress.c', 41 43 'menu.c', 42 44 'nav.c', -
uspace/app/nav/nav.c
r1a96db9 rc111da2 35 35 */ 36 36 37 #include <fibril.h> 37 38 #include <gfx/coord.h> 38 39 #include <stdio.h> … … 535 536 } 536 537 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 */ 547 static 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 */ 572 errno_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 537 598 /** @} 538 599 */ -
uspace/app/nav/nav.h
r1a96db9 rc111da2 47 47 extern void navigator_switch_panel(navigator_t *); 48 48 extern void navigator_refresh_panels(navigator_t *); 49 extern errno_t navigator_worker_start(navigator_t *, void (*)(void *), 50 void *); 49 51 50 52 #endif -
uspace/app/nav/newfile.c
r1a96db9 rc111da2 34 34 */ 35 35 36 #include <capa.h> 37 #include <fmgt.h> 36 38 #include <stdlib.h> 37 39 #include <str_error.h> … … 42 44 #include <ui/ui.h> 43 45 #include <ui/window.h> 46 #include <str.h> 44 47 #include "dlg/newfiledlg.h" 48 #include "dlg/progress.h" 45 49 #include "menu.h" 46 50 #include "newfile.h" 47 51 #include "nav.h" 48 49 static void new_file_bok(new_file_dlg_t *, void *, const char *); 52 #include "types/newfile.h" 53 54 static void new_file_bok(new_file_dlg_t *, void *, const char *, const char *); 50 55 static void new_file_bcancel(new_file_dlg_t *, void *); 51 56 static void new_file_close(new_file_dlg_t *, void *); … … 57 62 }; 58 63 64 static void new_file_progress(void *, fmgt_progress_t *); 65 66 static fmgt_cb_t new_file_fmgt_cb = { 67 .progress = new_file_progress 68 }; 69 59 70 /** Open New File dialog. 60 71 * … … 69 80 } 70 81 82 /** New file worker function. 83 * 84 * @param arg Argument (navigator_new_file_job_t) 85 */ 86 static 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; 122 error: 123 ui_lock(nav->ui); 124 progress_dlg_destroy(nav->progress_dlg); 125 ui_msg_dialog_params_init(¶ms); 126 params.caption = "Error"; 127 params.text = msg; 128 (void) ui_msg_dialog_create(nav->ui, ¶ms, &dialog); 129 ui_unlock(nav->ui); 130 free(msg); 131 } 132 71 133 /** New file dialog confirmed. 72 134 * … … 74 136 * @param arg Argument (navigator_t *) 75 137 * @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 */ 140 static void new_file_bok(new_file_dlg_t *dlg, void *arg, const char *fname, 141 const char *fsize) 78 142 { 79 143 navigator_t *nav = (navigator_t *)arg; 80 144 ui_msg_dialog_t *dialog = NULL; 145 navigator_new_file_job_t *job; 81 146 ui_msg_dialog_params_t params; 147 progress_dlg_params_t pd_params; 148 capa_spec_t fcap; 82 149 char *msg = NULL; 150 errno_t rc; 151 uint64_t nbytes; 83 152 int rv; 84 FILE *f; 153 154 rc = capa_parse(fsize, &fcap); 155 if (rc != EOK) { 156 /* invalid file size */ 157 return; 158 } 85 159 86 160 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); 91 165 if (rv < 0) 92 166 return; 93 94 ui_msg_dialog_params_init(¶ms); 95 params.caption = "Error"; 96 params.text = msg; 97 (void) ui_msg_dialog_create(nav->ui, ¶ms, &dialog); 98 free(msg); 167 goto error; 168 } 169 170 job = calloc(1, sizeof(navigator_new_file_job_t)); 171 if (job == NULL) 99 172 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; 198 error: 199 ui_msg_dialog_params_init(¶ms); 200 params.caption = "Error"; 201 params.text = msg; 202 (void) ui_msg_dialog_create(nav->ui, ¶ms, &dialog); 203 free(msg); 104 204 } 105 205 … … 126 226 } 127 227 228 /** New file progress update. 229 * 230 * @param arg Argument (navigator_t *) 231 * @param progress Progress update 232 */ 233 static 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 128 244 /** @} 129 245 */ -
uspace/app/nav/types/dlg/newfiledlg.h
r1a96db9 rc111da2 60 60 } new_file_dlg_t; 61 61 62 /** Prompt dialog callback*/62 /** New File dialog callbacks */ 63 63 typedef struct new_file_dlg_cb { 64 64 /** 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 *); 66 66 /** Cancel button was pressed */ 67 67 void (*bcancel)(new_file_dlg_t *, void *); -
uspace/app/nav/types/nav.h
r1a96db9 rc111da2 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2025 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 37 37 #define TYPES_NAV_H 38 38 39 #include <fibril.h> 39 40 #include <ui/fixed.h> 40 41 #include <ui/ui.h> … … 57 58 /** Panels */ 58 59 struct panel *panel[navigator_panels]; 60 /** Progress dialog */ 61 struct progress_dlg *progress_dlg; 62 /** Worker fibril ID */ 63 fid_t worker_fid; 59 64 } navigator_t; 65 66 /** Navigator worker job */ 67 typedef 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; 60 75 61 76 #endif -
uspace/lib/c/generic/capa.c
r1a96db9 rc111da2 1 1 /* 2 * Copyright (c) 20 15 Jiri Svoboda2 * Copyright (c) 2025 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 233 233 } 234 234 235 errno_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 265 errno_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 275 void 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 235 290 static errno_t capa_digit_val(char c, int *val) 236 291 { -
uspace/lib/c/include/capa.h
r1a96db9 rc111da2 1 1 /* 2 * Copyright (c) 20 15 Jiri Svoboda2 * Copyright (c) 2025 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 87 87 } capa_spec_t; 88 88 89 /** Size of buffer large enough for capa_blocks_format_buf */ 90 #define CAPA_BLOCKS_BUFSIZE 16 91 89 92 extern errno_t capa_format(capa_spec_t *, char **); 93 extern errno_t capa_format_buf(capa_spec_t *, char *, size_t); 94 extern errno_t capa_blocks_format(uint64_t, size_t, char **); 95 extern void capa_blocks_format_buf(uint64_t, size_t, char *, size_t); 90 96 extern errno_t capa_parse(const char *, capa_spec_t *); 91 97 extern void capa_simplify(capa_spec_t *); -
uspace/lib/c/test/capa.c
r1a96db9 rc111da2 1 1 /* 2 * Copyright (c) 2025 Jiri Svoboda 2 3 * Copyright (c) 2019 Matthieu Riolo 3 4 * All rights reserved. … … 285 286 } 286 287 288 PCUT_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 299 PCUT_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 287 307 PCUT_EXPORT(capa); -
uspace/lib/fmgt/include/fmgt.h
r1a96db9 rc111da2 39 39 40 40 #include <errno.h> 41 #include <stdbool.h> 41 42 #include <stddef.h> 43 #include <stdint.h> 42 44 #include "types/fmgt.h" 43 45 … … 45 47 extern void fmgt_set_cb(fmgt_t *, fmgt_cb_t *, void *); 46 48 extern void fmgt_destroy(fmgt_t *); 49 extern void fmgt_set_init_update(fmgt_t *, bool); 47 50 extern errno_t fmgt_new_file_suggest(char **); 51 extern errno_t fmgt_new_file(fmgt_t *, const char *, uint64_t); 48 52 49 53 #endif -
uspace/lib/fmgt/include/types/fmgt.h
r1a96db9 rc111da2 38 38 #define TYPES_FMGT_H 39 39 40 #include <capa.h> 41 #include <fibril_synch.h> 42 43 /** File management progress update */ 44 typedef 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 40 53 /** File management callbacks */ 41 54 typedef struct { 55 void (*progress)(void *, fmgt_progress_t *); 42 56 } fmgt_cb_t; 43 57 44 58 typedef struct { 59 /** Lock */ 60 fibril_mutex_t lock; 61 /** Progress update timer */ 62 fibril_timer_t *timer; 45 63 /** Callback functions */ 46 64 fmgt_cb_t *cb; 47 65 /** Argument to callback functions */ 48 66 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; 49 75 } fmgt_t; 50 76 -
uspace/lib/fmgt/meson.build
r1a96db9 rc111da2 28 28 29 29 src = files( 30 'src/fmgt.c' 30 'src/fmgt.c', 31 31 ) 32 33 test_src = files( 34 'test/fmgt.c', 35 'test/main.c', 36 ) -
uspace/lib/fmgt/src/fmgt.c
r1a96db9 rc111da2 46 46 47 47 #define NEWNAME_LEN 64 48 #define BUFFER_SIZE 16384 48 49 49 50 /** Create file management library instance. … … 59 60 if (fmgt == NULL) 60 61 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 } 61 69 62 70 *rfmgt = fmgt; … … 77 85 } 78 86 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 */ 92 void fmgt_set_init_update(fmgt_t *fmgt, bool enabled) 93 { 94 fmgt->do_init_update = enabled; 95 } 96 79 97 /** Destroy file management library instance. 80 98 * … … 83 101 void fmgt_destroy(fmgt_t *fmgt) 84 102 { 103 (void)fibril_timer_clear(fmgt->timer); 104 fibril_timer_destroy(fmgt->timer); 85 105 free(fmgt); 86 106 } … … 116 136 } 117 137 138 /** Get progress update report. 139 * 140 * @param fmgt File management object 141 * @param progress Place to store progress update 142 */ 143 static 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 */ 164 static 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 */ 182 static 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 */ 194 static 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 */ 206 static 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 */ 218 static 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 */ 230 errno_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 118 279 /** @} 119 280 */
Note:
See TracChangeset
for help on using the changeset viewer.
