source: mainline/uspace/lib/c/generic/vol.c@ 2d78d88

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

Modifying mount point for a partition.

  • Property mode set to 100644
File size: 10.6 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/** Set mount point for partition.
341 *
342 * @param vol Volume service
343 * @param sid Partition service ID
344 * @param mountp Mount point
345 *
346 * @return EOK on success or an error code
347 */
348errno_t vol_part_set_mountp(vol_t *vol, service_id_t sid,
349 const char *mountp)
350{
351 async_exch_t *exch;
352 ipc_call_t answer;
353 errno_t retval;
354
355 exch = async_exchange_begin(vol->sess);
356 aid_t req = async_send_1(exch, VOL_PART_SET_MOUNTP, sid,
357 &answer);
358
359 retval = async_data_write_start(exch, mountp, str_size(mountp));
360 if (retval != EOK) {
361 async_exchange_end(exch);
362 async_forget(req);
363 return retval;
364 }
365
366 async_exchange_end(exch);
367 async_wait_for(req, &retval);
368
369 if (retval != EOK)
370 return retval;
371
372 return EOK;
373}
374
375/** Format file system type as string.
376 *
377 * @param fstype File system type
378 * @param rstr Place to store pointer to newly allocated string
379 * @return EOK on success, ENOMEM if out of memory
380 */
381errno_t vol_fstype_format(vol_fstype_t fstype, char **rstr)
382{
383 const char *sfstype;
384 char *s;
385
386 sfstype = NULL;
387 switch (fstype) {
388 case fs_exfat:
389 sfstype = "ExFAT";
390 break;
391 case fs_fat:
392 sfstype = "FAT";
393 break;
394 case fs_minix:
395 sfstype = "MINIX";
396 break;
397 case fs_ext4:
398 sfstype = "Ext4";
399 break;
400 case fs_cdfs:
401 sfstype = "ISO 9660";
402 break;
403 }
404
405 s = str_dup(sfstype);
406 if (s == NULL)
407 return ENOMEM;
408
409 *rstr = s;
410 return EOK;
411}
412
413/** Format partition content / file system type as string.
414 *
415 * @param pcnt Partition content
416 * @param fstype File system type
417 * @param rstr Place to store pointer to newly allocated string
418 * @return EOK on success, ENOMEM if out of memory
419 */
420errno_t vol_pcnt_fs_format(vol_part_cnt_t pcnt, vol_fstype_t fstype,
421 char **rstr)
422{
423 int rc;
424 char *s = NULL;
425
426 switch (pcnt) {
427 case vpc_empty:
428 s = str_dup("Empty");
429 if (s == NULL)
430 return ENOMEM;
431 break;
432 case vpc_fs:
433 rc = vol_fstype_format(fstype, &s);
434 if (rc != EOK)
435 return ENOMEM;
436 break;
437 case vpc_unknown:
438 s = str_dup("Unknown");
439 if (s == NULL)
440 return ENOMEM;
441 break;
442 }
443
444 assert(s != NULL);
445 *rstr = s;
446 return EOK;
447}
448
449/** Validate mount point.
450 *
451 * Verify that mount point is valid. A valid mount point is
452 * one of:
453 * - 'Auto'
454 * - 'None'
455 * - /path (string beginning with '/') to an existing directory
456 *
457 * @return EOK if mount point is in valid, EINVAL if the format is invalid,
458 * ENOENT if the directory does not exist
459 */
460errno_t vol_mountp_validate(const char *mountp)
461{
462 errno_t rc;
463 vfs_stat_t stat;
464
465 if (str_cmp(mountp, "Auto") == 0 || str_cmp(mountp, "auto") == 0)
466 return EOK;
467
468 if (str_casecmp(mountp, "None") == 0 || str_cmp(mountp, "none") == 0)
469 return EOK;
470
471 if (mountp[0] == '/') {
472 rc = vfs_stat_path(mountp, &stat);
473 if (rc != EOK || !stat.is_directory)
474 return ENOENT;
475
476 return EOK;
477 }
478
479 return EINVAL;
480}
481
482/** @}
483 */
Note: See TracBrowser for help on using the repository browser.