source: mainline/uspace/lib/c/generic/vol.c@ 8aea932

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8aea932 was fafb8e5, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Mechanically lowercase IPC_SET_*/IPC_GET_*

  • Property mode set to 100644
File size: 13.4 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 *
199 * @param vol Volume service
200 * @param sid Service ID of the partition
201 * @return EOK on success or an error code
202 */
203errno_t vol_part_add(vol_t *vol, service_id_t sid)
204{
205 async_exch_t *exch;
206 errno_t retval;
207
208 exch = async_exchange_begin(vol->sess);
209 retval = async_req_1_0(exch, VOL_PART_ADD, sid);
210 async_exchange_end(exch);
211
212 if (retval != EOK)
213 return retval;
214
215 return EOK;
216}
217
218/** Get partition information.
219 *
220 * @param vol Volume service
221 * @param sid Service ID of the partition
222 * @param vinfo Place to store partition information
223 * @return EOK on success or an error code
224 */
225errno_t vol_part_info(vol_t *vol, service_id_t sid, vol_part_info_t *vinfo)
226{
227 async_exch_t *exch;
228 errno_t retval;
229 ipc_call_t answer;
230
231 exch = async_exchange_begin(vol->sess);
232 aid_t req = async_send_1(exch, VOL_PART_INFO, sid, &answer);
233
234 errno_t rc = async_data_read_start(exch, vinfo, sizeof(vol_part_info_t));
235 async_exchange_end(exch);
236 if (rc != EOK) {
237 async_forget(req);
238 return EIO;
239 }
240
241 async_wait_for(req, &retval);
242 if (retval != EOK)
243 return EIO;
244
245 return EOK;
246}
247
248/** Unmount partition (and possibly eject the media).
249 *
250 * @param vol Volume service
251 * @param sid Service ID of the partition
252 * @return EOK on success or an error code
253 */
254errno_t vol_part_eject(vol_t *vol, service_id_t sid)
255{
256 async_exch_t *exch;
257 errno_t retval;
258
259 exch = async_exchange_begin(vol->sess);
260 retval = async_req_1_0(exch, VOL_PART_EJECT, sid);
261 async_exchange_end(exch);
262
263 if (retval != EOK)
264 return retval;
265
266 return EOK;
267}
268
269/** Erase partition (to the extent where we will consider it not containing
270 * a file system.
271 *
272 * @param vol Volume service
273 * @param sid Service ID of the partition
274 * @return EOK on success or an error code
275 */
276errno_t vol_part_empty(vol_t *vol, service_id_t sid)
277{
278 async_exch_t *exch;
279 errno_t retval;
280
281 exch = async_exchange_begin(vol->sess);
282 retval = async_req_1_0(exch, VOL_PART_EMPTY, sid);
283 async_exchange_end(exch);
284
285 if (retval != EOK)
286 return retval;
287
288 return EOK;
289}
290
291/** Insert volume.
292 *
293 * This will re-mount the volume if it has been ejected previously.
294 *
295 * @param vol Volume service
296 * @param sid Service ID of the partition
297 * @return EOK on success or an error code
298 */
299errno_t vol_part_insert(vol_t *vol, service_id_t sid)
300{
301 async_exch_t *exch;
302 errno_t retval;
303
304 exch = async_exchange_begin(vol->sess);
305 retval = async_req_1_0(exch, VOL_PART_INSERT, sid);
306 async_exchange_end(exch);
307
308 if (retval != EOK)
309 return retval;
310
311 return EOK;
312}
313
314/** Insert volume by path.
315 *
316 * @param vol Volume service
317 * @param path Filesystem path
318 *
319 * @return EOK on success or an error code
320 */
321errno_t vol_part_insert_by_path(vol_t *vol, const char *path)
322{
323 async_exch_t *exch;
324 ipc_call_t answer;
325 errno_t retval;
326
327 exch = async_exchange_begin(vol->sess);
328 aid_t req = async_send_0(exch, VOL_PART_INSERT_BY_PATH, &answer);
329
330 retval = async_data_write_start(exch, path, str_size(path));
331 if (retval != EOK) {
332 async_exchange_end(exch);
333 async_forget(req);
334 return retval;
335 }
336
337 async_exchange_end(exch);
338 async_wait_for(req, &retval);
339
340 if (retval != EOK)
341 return retval;
342
343 return EOK;
344}
345
346/** Get volume label support.
347 *
348 * @param vol Volume service
349 * @param fstype File system type
350 * @param vlsupp Place to store volume label support information
351 * @return EOK on success or an error code
352 */
353errno_t vol_part_get_lsupp(vol_t *vol, vol_fstype_t fstype,
354 vol_label_supp_t *vlsupp)
355{
356 async_exch_t *exch;
357 errno_t retval;
358 ipc_call_t answer;
359
360 exch = async_exchange_begin(vol->sess);
361 aid_t req = async_send_1(exch, VOL_PART_LSUPP, fstype, &answer);
362 errno_t rc = async_data_read_start(exch, vlsupp, sizeof(vol_label_supp_t));
363 async_exchange_end(exch);
364
365 if (rc != EOK) {
366 async_forget(req);
367 return EIO;
368 }
369
370 async_wait_for(req, &retval);
371 if (retval != EOK)
372 return EIO;
373
374 return EOK;
375}
376
377/** Create file system.
378 *
379 * @param vol Volume service
380 * @param sid Partition service ID
381 * @param fstype File system type
382 * @param label Volume label
383 * @param mountp Mount point
384 *
385 * @return EOK on success or an error code
386 */
387errno_t vol_part_mkfs(vol_t *vol, service_id_t sid, vol_fstype_t fstype,
388 const char *label, const char *mountp)
389{
390 async_exch_t *exch;
391 ipc_call_t answer;
392 errno_t retval;
393
394 exch = async_exchange_begin(vol->sess);
395 aid_t req = async_send_2(exch, VOL_PART_MKFS, sid, fstype, &answer);
396
397 retval = async_data_write_start(exch, label, str_size(label));
398 if (retval != EOK) {
399 async_exchange_end(exch);
400 async_forget(req);
401 return retval;
402 }
403
404 retval = async_data_write_start(exch, mountp, str_size(mountp));
405 if (retval != EOK) {
406 async_exchange_end(exch);
407 async_forget(req);
408 return retval;
409 }
410
411 async_exchange_end(exch);
412 async_wait_for(req, &retval);
413
414 if (retval != EOK)
415 return retval;
416
417 return EOK;
418}
419
420/** Set mount point for partition.
421 *
422 * @param vol Volume service
423 * @param sid Partition service ID
424 * @param mountp Mount point
425 *
426 * @return EOK on success or an error code
427 */
428errno_t vol_part_set_mountp(vol_t *vol, service_id_t sid,
429 const char *mountp)
430{
431 async_exch_t *exch;
432 ipc_call_t answer;
433 errno_t retval;
434
435 exch = async_exchange_begin(vol->sess);
436 aid_t req = async_send_1(exch, VOL_PART_SET_MOUNTP, sid,
437 &answer);
438
439 retval = async_data_write_start(exch, mountp, str_size(mountp));
440 if (retval != EOK) {
441 async_exchange_end(exch);
442 async_forget(req);
443 return retval;
444 }
445
446 async_exchange_end(exch);
447 async_wait_for(req, &retval);
448
449 if (retval != EOK)
450 return retval;
451
452 return EOK;
453}
454
455/** Format file system type as string.
456 *
457 * @param fstype File system type
458 * @param rstr Place to store pointer to newly allocated string
459 * @return EOK on success, ENOMEM if out of memory
460 */
461errno_t vol_fstype_format(vol_fstype_t fstype, char **rstr)
462{
463 const char *sfstype;
464 char *s;
465
466 sfstype = NULL;
467 switch (fstype) {
468 case fs_exfat:
469 sfstype = "ExFAT";
470 break;
471 case fs_fat:
472 sfstype = "FAT";
473 break;
474 case fs_minix:
475 sfstype = "MINIX";
476 break;
477 case fs_ext4:
478 sfstype = "Ext4";
479 break;
480 case fs_cdfs:
481 sfstype = "ISO 9660";
482 break;
483 }
484
485 s = str_dup(sfstype);
486 if (s == NULL)
487 return ENOMEM;
488
489 *rstr = s;
490 return EOK;
491}
492
493/** Format partition content / file system type as string.
494 *
495 * @param pcnt Partition content
496 * @param fstype File system type
497 * @param rstr Place to store pointer to newly allocated string
498 * @return EOK on success, ENOMEM if out of memory
499 */
500errno_t vol_pcnt_fs_format(vol_part_cnt_t pcnt, vol_fstype_t fstype,
501 char **rstr)
502{
503 int rc;
504 char *s = NULL;
505
506 switch (pcnt) {
507 case vpc_empty:
508 s = str_dup("Empty");
509 if (s == NULL)
510 return ENOMEM;
511 break;
512 case vpc_fs:
513 rc = vol_fstype_format(fstype, &s);
514 if (rc != EOK)
515 return ENOMEM;
516 break;
517 case vpc_unknown:
518 s = str_dup("Unknown");
519 if (s == NULL)
520 return ENOMEM;
521 break;
522 }
523
524 assert(s != NULL);
525 *rstr = s;
526 return EOK;
527}
528
529/** Validate mount point.
530 *
531 * Verify that mount point is valid. A valid mount point is
532 * one of:
533 * - 'Auto'
534 * - 'None'
535 * - /path (string beginning with '/') to an existing directory
536 *
537 * @return EOK if mount point is in valid, EINVAL if the format is invalid,
538 * ENOENT if the directory does not exist
539 */
540errno_t vol_mountp_validate(const char *mountp)
541{
542 errno_t rc;
543 vfs_stat_t stat;
544
545 if (str_cmp(mountp, "Auto") == 0 || str_cmp(mountp, "auto") == 0)
546 return EOK;
547
548 if (str_casecmp(mountp, "None") == 0 || str_cmp(mountp, "none") == 0)
549 return EOK;
550
551 if (mountp[0] == '/') {
552 rc = vfs_stat_path(mountp, &stat);
553 if (rc != EOK || !stat.is_directory)
554 return ENOENT;
555
556 return EOK;
557 }
558
559 return EINVAL;
560}
561
562/** Get list of volumes as array of volume IDs.
563 *
564 * @param vol Volume service
565 * @param data Place to store pointer to array
566 * @param count Place to store length of array (number of entries)
567 *
568 * @return EOK on success or an error code
569 */
570errno_t vol_get_volumes(vol_t *vol, volume_id_t **data, size_t *count)
571{
572 return vol_get_ids_internal(vol, VOL_GET_VOLUMES, 0,
573 (sysarg_t **) data, count);
574}
575
576/** Get volume configuration information.
577 *
578 * @param vol Volume service
579 * @param vid Volume ID
580 * @param vinfo Place to store volume configuration information
581 * @return EOK on success or an error code
582 */
583errno_t vol_info(vol_t *vol, volume_id_t vid, vol_info_t *vinfo)
584{
585 async_exch_t *exch;
586 errno_t retval;
587 ipc_call_t answer;
588
589 exch = async_exchange_begin(vol->sess);
590 aid_t req = async_send_1(exch, VOL_INFO, vid.id, &answer);
591
592 errno_t rc = async_data_read_start(exch, vinfo, sizeof(vol_info_t));
593 async_exchange_end(exch);
594 if (rc != EOK) {
595 async_forget(req);
596 return EIO;
597 }
598
599 async_wait_for(req, &retval);
600 if (retval != EOK)
601 return EIO;
602
603 return EOK;
604}
605
606/** @}
607 */
Note: See TracBrowser for help on using the repository browser.