source: mainline/uspace/lib/c/generic/vol.c@ 64ffd83

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 64ffd83 was 64ffd83, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Configuring mount point for (newly created) paritions.

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/*
2 * Copyright (c) 2015 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 libc
30 * @{
31 */
32/** @file Volume service API
33 */
34
35#include <abi/ipc/interfaces.h>
36#include <errno.h>
37#include <ipc/services.h>
38#include <ipc/vol.h>
39#include <loc.h>
40#include <stdlib.h>
41#include <str.h>
42#include <vfs/vfs.h>
43#include <vol.h>
44
45/** Create Volume service session.
46 *
47 * @param rvol Place to store pointer to volume service session.
48 * @return EOK on success, ENOMEM if out of memory, EIO if service
49 * cannot be contacted.
50 */
51errno_t vol_create(vol_t **rvol)
52{
53 vol_t *vol;
54 service_id_t vol_svcid;
55 errno_t rc;
56
57 vol = calloc(1, sizeof(vol_t));
58 if (vol == NULL) {
59 rc = ENOMEM;
60 goto error;
61 }
62
63 rc = loc_service_get_id(SERVICE_NAME_VOLSRV, &vol_svcid, 0);
64 if (rc != EOK) {
65 rc = ENOENT;
66 goto error;
67 }
68
69 vol->sess = loc_service_connect(vol_svcid, INTERFACE_VOL, 0);
70 if (vol->sess == NULL) {
71 rc = EIO;
72 goto error;
73 }
74
75 *rvol = vol;
76 return EOK;
77error:
78 free(vol);
79 return rc;
80}
81
82/** Destroy volume service session.
83 *
84 * @param vol Volume service session
85 */
86void vol_destroy(vol_t *vol)
87{
88 if (vol == NULL)
89 return;
90
91 async_hangup(vol->sess);
92 free(vol);
93}
94
95/** Get list of IDs into a buffer of fixed size.
96 *
97 * @param vol Volume service
98 * @param method IPC method
99 * @param arg1 First argument
100 * @param id_buf Buffer to store IDs
101 * @param buf_size Buffer size
102 * @param act_size Place to store actual size of complete data.
103 *
104 * @return EOK on success or an error code.
105 */
106static errno_t vol_get_ids_once(vol_t *vol, sysarg_t method, sysarg_t arg1,
107 sysarg_t *id_buf, size_t buf_size, size_t *act_size)
108{
109 async_exch_t *exch = async_exchange_begin(vol->sess);
110
111 ipc_call_t answer;
112 aid_t req = async_send_1(exch, method, arg1, &answer);
113 errno_t rc = async_data_read_start(exch, id_buf, buf_size);
114
115 async_exchange_end(exch);
116
117 if (rc != EOK) {
118 async_forget(req);
119 return rc;
120 }
121
122 errno_t retval;
123 async_wait_for(req, &retval);
124
125 if (retval != EOK) {
126 return retval;
127 }
128
129 *act_size = IPC_GET_ARG1(answer);
130 return EOK;
131}
132
133/** Get list of IDs.
134 *
135 * Returns an allocated array of service IDs.
136 *
137 * @param vol Volume service
138 * @param method IPC method
139 * @param arg1 IPC argument 1
140 * @param data Place to store pointer to array of IDs
141 * @param count Place to store number of IDs
142 * @return EOK on success or an error code
143 */
144static errno_t vol_get_ids_internal(vol_t *vol, sysarg_t method, sysarg_t arg1,
145 sysarg_t **data, size_t *count)
146{
147 *data = NULL;
148 *count = 0;
149
150 size_t act_size = 0;
151 errno_t rc = vol_get_ids_once(vol, method, arg1, NULL, 0, &act_size);
152 if (rc != EOK)
153 return rc;
154
155 size_t alloc_size = act_size;
156 service_id_t *ids = malloc(alloc_size);
157 if (ids == NULL)
158 return ENOMEM;
159
160 while (true) {
161 rc = vol_get_ids_once(vol, method, arg1, ids, alloc_size,
162 &act_size);
163 if (rc != EOK)
164 return rc;
165
166 if (act_size <= alloc_size)
167 break;
168
169 alloc_size = act_size;
170 ids = realloc(ids, alloc_size);
171 if (ids == NULL)
172 return ENOMEM;
173 }
174
175 *count = act_size / sizeof(service_id_t);
176 *data = ids;
177 return EOK;
178}
179
180/** Get list of partitions as array of service IDs.
181 *
182 * @param vol Volume service
183 * @param data Place to store pointer to array
184 * @param count Place to store length of array (number of entries)
185 *
186 * @return EOK on success or an error code
187 */
188errno_t vol_get_parts(vol_t *vol, service_id_t **data, size_t *count)
189{
190 return vol_get_ids_internal(vol, VOL_GET_PARTS, 0, data, count);
191}
192
193/** Add partition.
194 *
195 * After a partition is created (e.g. as a result of deleting a label
196 * the dummy partition is created), it can take some (unknown) time
197 * until it is discovered.
198 */
199errno_t vol_part_add(vol_t *vol, service_id_t sid)
200{
201 async_exch_t *exch;
202 errno_t retval;
203
204 exch = async_exchange_begin(vol->sess);
205 retval = async_req_1_0(exch, VOL_PART_ADD, sid);
206 async_exchange_end(exch);
207
208 if (retval != EOK)
209 return retval;
210
211 return EOK;
212}
213
214/** Get partition information. */
215errno_t vol_part_info(vol_t *vol, service_id_t sid, vol_part_info_t *vinfo)
216{
217 async_exch_t *exch;
218 errno_t retval;
219 ipc_call_t answer;
220
221 exch = async_exchange_begin(vol->sess);
222 aid_t req = async_send_1(exch, VOL_PART_INFO, sid, &answer);
223
224 errno_t rc = async_data_read_start(exch, vinfo, sizeof(vol_part_info_t));
225 async_exchange_end(exch);
226 if (rc != EOK) {
227 async_forget(req);
228 return EIO;
229 }
230
231 async_wait_for(req, &retval);
232 if (retval != EOK)
233 return EIO;
234
235 return EOK;
236}
237
238/** Unmount partition (and possibly eject the media). */
239errno_t vol_part_eject(vol_t *vol, service_id_t sid)
240{
241 async_exch_t *exch;
242 errno_t retval;
243
244 exch = async_exchange_begin(vol->sess);
245 retval = async_req_1_0(exch, VOL_PART_EJECT, sid);
246 async_exchange_end(exch);
247
248 if (retval != EOK)
249 return retval;
250
251 return EOK;
252}
253
254/** Erase partition (to the extent where we will consider it not containing
255 * a file system.
256 */
257errno_t vol_part_empty(vol_t *vol, service_id_t sid)
258{
259 async_exch_t *exch;
260 errno_t retval;
261
262 exch = async_exchange_begin(vol->sess);
263 retval = async_req_1_0(exch, VOL_PART_EMPTY, sid);
264 async_exchange_end(exch);
265
266 if (retval != EOK)
267 return retval;
268
269 return EOK;
270}
271
272/** Get volume label support. */
273errno_t vol_part_get_lsupp(vol_t *vol, vol_fstype_t fstype,
274 vol_label_supp_t *vlsupp)
275{
276 async_exch_t *exch;
277 errno_t retval;
278 ipc_call_t answer;
279
280 exch = async_exchange_begin(vol->sess);
281 aid_t req = async_send_1(exch, VOL_PART_LSUPP, fstype, &answer);
282 errno_t rc = async_data_read_start(exch, vlsupp, sizeof(vol_label_supp_t));
283 async_exchange_end(exch);
284
285 if (rc != EOK) {
286 async_forget(req);
287 return EIO;
288 }
289
290 async_wait_for(req, &retval);
291 if (retval != EOK)
292 return EIO;
293
294 return EOK;
295}
296
297/** Create file system.
298 *
299 * @param vol Volume service
300 * @param sid Partition service ID
301 * @param fstype File system type
302 * @param label Volume label
303 * @param mountp Mount point
304 *
305 * @return EOK on success or an error code
306 */
307errno_t vol_part_mkfs(vol_t *vol, service_id_t sid, vol_fstype_t fstype,
308 const char *label, const char *mountp)
309{
310 async_exch_t *exch;
311 ipc_call_t answer;
312 errno_t retval;
313
314 exch = async_exchange_begin(vol->sess);
315 aid_t req = async_send_2(exch, VOL_PART_MKFS, sid, fstype, &answer);
316
317 retval = async_data_write_start(exch, label, str_size(label));
318 if (retval != EOK) {
319 async_exchange_end(exch);
320 async_forget(req);
321 return retval;
322 }
323
324 retval = async_data_write_start(exch, mountp, str_size(mountp));
325 if (retval != EOK) {
326 async_exchange_end(exch);
327 async_forget(req);
328 return retval;
329 }
330
331 async_exchange_end(exch);
332 async_wait_for(req, &retval);
333
334 if (retval != EOK)
335 return retval;
336
337 return EOK;
338}
339
340/** Format file system type as string.
341 *
342 * @param fstype File system type
343 * @param rstr Place to store pointer to newly allocated string
344 * @return EOK on success, ENOMEM if out of memory
345 */
346errno_t vol_fstype_format(vol_fstype_t fstype, char **rstr)
347{
348 const char *sfstype;
349 char *s;
350
351 sfstype = NULL;
352 switch (fstype) {
353 case fs_exfat:
354 sfstype = "ExFAT";
355 break;
356 case fs_fat:
357 sfstype = "FAT";
358 break;
359 case fs_minix:
360 sfstype = "MINIX";
361 break;
362 case fs_ext4:
363 sfstype = "Ext4";
364 break;
365 case fs_cdfs:
366 sfstype = "ISO 9660";
367 break;
368 }
369
370 s = str_dup(sfstype);
371 if (s == NULL)
372 return ENOMEM;
373
374 *rstr = s;
375 return EOK;
376}
377
378/** Format partition content / file system type as string.
379 *
380 * @param pcnt Partition content
381 * @param fstype File system type
382 * @param rstr Place to store pointer to newly allocated string
383 * @return EOK on success, ENOMEM if out of memory
384 */
385errno_t vol_pcnt_fs_format(vol_part_cnt_t pcnt, vol_fstype_t fstype,
386 char **rstr)
387{
388 int rc;
389 char *s = NULL;
390
391 switch (pcnt) {
392 case vpc_empty:
393 s = str_dup("Empty");
394 if (s == NULL)
395 return ENOMEM;
396 break;
397 case vpc_fs:
398 rc = vol_fstype_format(fstype, &s);
399 if (rc != EOK)
400 return ENOMEM;
401 break;
402 case vpc_unknown:
403 s = str_dup("Unknown");
404 if (s == NULL)
405 return ENOMEM;
406 break;
407 }
408
409 assert(s != NULL);
410 *rstr = s;
411 return EOK;
412}
413
414/** Validate mount point.
415 *
416 * Verify that mount point is valid. A valid mount point is
417 * one of:
418 * - 'Auto'
419 * - 'None'
420 * - /path (string beginning with '/') to an existing directory
421 *
422 * @return EOK if mount point is in valid, EINVAL if the format is invalid,
423 * ENOENT if the directory does not exist
424 */
425errno_t vol_mountp_validate(const char *mountp)
426{
427 errno_t rc;
428 vfs_stat_t stat;
429
430 if (str_cmp(mountp, "Auto") == 0 || str_cmp(mountp, "auto") == 0)
431 return EOK;
432
433 if (str_casecmp(mountp, "None") == 0 || str_cmp(mountp, "none") == 0)
434 return EOK;
435
436 if (mountp[0] == '/') {
437 rc = vfs_stat_path(mountp, &stat);
438 if (rc != EOK || !stat.is_directory)
439 return ENOENT;
440
441 return EOK;
442 }
443
444 return EINVAL;
445}
446
447/** @}
448 */
Note: See TracBrowser for help on using the repository browser.