source: mainline/uspace/lib/c/generic/vol.c@ 72c72d4

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

Basic volume eject implementation.

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