source: mainline/uspace/app/nav/newfile.c@ bb4d0b5

Last change on this file since bb4d0b5 was bb4d0b5, checked in by Jiri Svoboda <jiri@…>, 3 weeks ago

Allow user to decide whether to retry or abort when I/O error occurs.

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup nav
30 * @{
31 */
32/**
33 * @file Navigator New File.
34 */
35
36#include <capa.h>
37#include <fmgt.h>
38#include <stdlib.h>
39#include <str_error.h>
40#include <ui/fixed.h>
41#include <ui/filelist.h>
42#include <ui/msgdialog.h>
43#include <ui/resource.h>
44#include <ui/ui.h>
45#include <ui/window.h>
46#include <stdbool.h>
47#include <str.h>
48#include "dlg/newfiledlg.h"
49#include "dlg/progress.h"
50#include "menu.h"
51#include "newfile.h"
52#include "nav.h"
53#include "types/newfile.h"
54
55static void new_file_bok(new_file_dlg_t *, void *, const char *, const char *,
56 bool);
57static void new_file_bcancel(new_file_dlg_t *, void *);
58static void new_file_close(new_file_dlg_t *, void *);
59
60static new_file_dlg_cb_t new_file_cb = {
61 .bok = new_file_bok,
62 .bcancel = new_file_bcancel,
63 .close = new_file_close
64};
65
66static bool new_file_abort_query(void *);
67static void new_file_progress(void *, fmgt_progress_t *);
68
69static fmgt_cb_t new_file_fmgt_cb = {
70 .abort_query = new_file_abort_query,
71 .io_error_query = navigator_io_error_query,
72 .progress = new_file_progress,
73};
74
75/** Open New File dialog.
76 *
77 * @param navigator Navigator
78 */
79void navigator_new_file_dlg(navigator_t *navigator)
80{
81 new_file_dlg_t *dlg;
82
83 new_file_dlg_create(navigator->ui, &dlg);
84 new_file_dlg_set_cb(dlg, &new_file_cb, (void *)navigator);
85}
86
87/** New file worker function.
88 *
89 * @param arg Argument (navigator_new_file_job_t)
90 */
91static void new_file_wfunc(void *arg)
92{
93 fmgt_t *fmgt = NULL;
94 navigator_new_file_job_t *job = (navigator_new_file_job_t *)arg;
95 char *msg = NULL;
96 navigator_t *nav = job->navigator;
97 ui_msg_dialog_t *dialog = NULL;
98 ui_msg_dialog_params_t params;
99 errno_t rc;
100 int rv;
101
102 rc = fmgt_create(&fmgt);
103 if (rc != EOK) {
104 /* out of memory */
105 return;
106 }
107
108 fmgt_set_cb(fmgt, &new_file_fmgt_cb, (void *)nav);
109 fmgt_set_init_update(fmgt, true);
110
111 rc = fmgt_new_file(fmgt, job->fname, job->nbytes,
112 job->sparse ? nf_sparse : nf_none);
113 if (rc != EOK) {
114 rv = asprintf(&msg, "Error creating file (%s).",
115 str_error(rc));
116 if (rv < 0)
117 return;
118 goto error;
119 }
120
121 fmgt_destroy(fmgt);
122 ui_lock(nav->ui);
123 progress_dlg_destroy(nav->progress_dlg);
124 navigator_refresh_panels(nav);
125 ui_unlock(nav->ui);
126 free(job);
127 return;
128error:
129 fmgt_destroy(fmgt);
130 ui_lock(nav->ui);
131 progress_dlg_destroy(nav->progress_dlg);
132 navigator_refresh_panels(nav);
133 ui_msg_dialog_params_init(&params);
134 params.caption = "Error";
135 params.text = msg;
136 (void) ui_msg_dialog_create(nav->ui, &params, &dialog);
137 ui_unlock(nav->ui);
138 free(msg);
139}
140
141/** New file dialog confirmed.
142 *
143 * @param dlg New file dialog
144 * @param arg Argument (navigator_t *)
145 * @param fname New file name
146 * @param fsize New file size
147 * @param sparse @c true to create a sparse file
148 */
149static void new_file_bok(new_file_dlg_t *dlg, void *arg, const char *fname,
150 const char *fsize, bool sparse)
151{
152 navigator_t *nav = (navigator_t *)arg;
153 ui_msg_dialog_t *dialog = NULL;
154 navigator_new_file_job_t *job;
155 ui_msg_dialog_params_t params;
156 progress_dlg_params_t pd_params;
157 capa_spec_t fcap;
158 char *msg = NULL;
159 errno_t rc;
160 uint64_t nbytes;
161 int rv;
162
163 rc = capa_parse(fsize, &fcap);
164 if (rc != EOK) {
165 /* invalid file size */
166 return;
167 }
168
169 new_file_dlg_destroy(dlg);
170
171 rc = capa_to_blocks(&fcap, cv_nom, 1, &nbytes);
172 if (rc != EOK) {
173 rv = asprintf(&msg, "File size too large (%s).", fsize);
174 if (rv < 0)
175 return;
176 goto error;
177 }
178
179 job = calloc(1, sizeof(navigator_new_file_job_t));
180 if (job == NULL)
181 return;
182
183 job->navigator = nav;
184 job->fname = fname;
185 job->nbytes = nbytes;
186 job->sparse = sparse;
187
188 progress_dlg_params_init(&pd_params);
189 pd_params.caption = "Creating new file";
190
191 rc = progress_dlg_create(nav->ui, &pd_params, &nav->progress_dlg);
192 if (rc != EOK) {
193 msg = str_dup("Out of memory.");
194 if (msg == NULL)
195 return;
196 goto error;
197 }
198
199 progress_dlg_set_cb(nav->progress_dlg, &navigator_progress_cb,
200 (void *)nav);
201
202 rc = navigator_worker_start(nav, new_file_wfunc, (void *)job);
203 if (rc != EOK) {
204 msg = str_dup("Out of memory.");
205 if (msg == NULL)
206 return;
207 goto error;
208 }
209
210 return;
211error:
212 ui_msg_dialog_params_init(&params);
213 params.caption = "Error";
214 params.text = msg;
215 (void) ui_msg_dialog_create(nav->ui, &params, &dialog);
216 free(msg);
217}
218
219/** New file dialog cancelled.
220 *
221 * @param dlg New file dialog
222 * @param arg Argument (navigator_t *)
223 */
224static void new_file_bcancel(new_file_dlg_t *dlg, void *arg)
225{
226 (void)arg;
227 new_file_dlg_destroy(dlg);
228}
229
230/** New file dialog closed.
231 *
232 * @param dlg New file dialog
233 * @param arg Argument (navigator_t *)
234 */
235static void new_file_close(new_file_dlg_t *dlg, void *arg)
236{
237 (void)arg;
238 new_file_dlg_destroy(dlg);
239}
240
241/** New file abort query.
242 *
243 * @param arg Argument (navigator_t *)
244 * @return @c true iff abort is requested
245 */
246static bool new_file_abort_query(void *arg)
247{
248 navigator_t *nav = (navigator_t *)arg;
249
250 return nav->abort_op;
251}
252
253/** New file progress update.
254 *
255 * @param arg Argument (navigator_t *)
256 * @param progress Progress update
257 */
258static void new_file_progress(void *arg, fmgt_progress_t *progress)
259{
260 navigator_t *nav = (navigator_t *)arg;
261 char buf[128];
262
263 snprintf(buf, sizeof(buf), "Written %s of %s (%s done).",
264 progress->curf_procb, progress->curf_totalb,
265 progress->curf_percent);
266 progress_dlg_set_curf_prog(nav->progress_dlg, buf);
267}
268
269/** @}
270 */
Note: See TracBrowser for help on using the repository browser.