source: mainline/uspace/lib/c/generic/vbd.c@ 28a5ebd

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

Avoid memory leak in vdb_get_ids_internal on realloc fails

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[22fb7ab]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 Virtual Block Device client API
33 */
34
[ff381a7]35#include <abi/ipc/interfaces.h>
[22fb7ab]36#include <errno.h>
37#include <ipc/services.h>
38#include <ipc/vbd.h>
39#include <loc.h>
[1626cd4]40#include <macros.h>
[28ed0d9]41#include <mem.h>
[22fb7ab]42#include <stdlib.h>
43#include <types/label.h>
44#include <vbd.h>
45
[b7fd2a0]46static errno_t vbd_get_ids_internal(vbd_t *, sysarg_t, sysarg_t, sysarg_t **,
[372df8f]47 size_t *);
48
[b7fd2a0]49errno_t vbd_create(vbd_t **rvbd)
[22fb7ab]50{
51 vbd_t *vbd;
52 service_id_t vbd_svcid;
[b7fd2a0]53 errno_t rc;
[22fb7ab]54
55 vbd = calloc(1, sizeof(vbd_t));
56 if (vbd == NULL) {
57 rc = ENOMEM;
58 goto error;
59 }
60
61 rc = loc_service_get_id(SERVICE_NAME_VBD, &vbd_svcid,
62 IPC_FLAG_BLOCKING);
63 if (rc != EOK) {
64 rc = EIO;
65 goto error;
66 }
67
[ff381a7]68 vbd->sess = loc_service_connect(vbd_svcid, INTERFACE_VBD,
[22fb7ab]69 IPC_FLAG_BLOCKING);
70 if (vbd->sess == NULL) {
71 rc = EIO;
72 goto error;
73 }
74
75 *rvbd = vbd;
76 return EOK;
77error:
78 free(vbd);
79 return rc;
80}
81
82void vbd_destroy(vbd_t *vbd)
83{
84 if (vbd == NULL)
85 return;
86
87 async_hangup(vbd->sess);
88 free(vbd);
89}
90
[372df8f]91/** Get list of partitions as array of service IDs.
92 *
93 * @param vbd Virtual block device service
94 * @param data Place to store pointer to array
95 * @param count Place to store length of array (number of entries)
96 *
[cde999a]97 * @return EOK on success or an error code
[372df8f]98 */
[b7fd2a0]99errno_t vbd_get_disks(vbd_t *vbd, service_id_t **data, size_t *count)
[22fb7ab]100{
[372df8f]101 return vbd_get_ids_internal(vbd, VBD_GET_DISKS, 0, data, count);
[22fb7ab]102}
103
104/** Get disk information. */
[b7fd2a0]105errno_t vbd_disk_info(vbd_t *vbd, service_id_t sid, vbd_disk_info_t *vinfo)
[22fb7ab]106{
107 async_exch_t *exch;
[b7fd2a0]108 errno_t retval;
[1626cd4]109 ipc_call_t answer;
[22fb7ab]110
111 exch = async_exchange_begin(vbd->sess);
[1626cd4]112 aid_t req = async_send_1(exch, VBD_DISK_INFO, sid, &answer);
[b7fd2a0]113 errno_t rc = async_data_read_start(exch, vinfo, sizeof(vbd_disk_info_t));
[22fb7ab]114 async_exchange_end(exch);
115
[1626cd4]116 if (rc != EOK) {
117 async_forget(req);
118 return EIO;
119 }
120
121 async_wait_for(req, &retval);
[22fb7ab]122 if (retval != EOK)
123 return EIO;
124
125 return EOK;
126}
127
[b7fd2a0]128errno_t vbd_label_create(vbd_t *vbd, service_id_t sid, label_type_t ltype)
[22fb7ab]129{
130 async_exch_t *exch;
[b7fd2a0]131 errno_t retval;
[22fb7ab]132
133 exch = async_exchange_begin(vbd->sess);
134 retval = async_req_2_0(exch, VBD_LABEL_CREATE, sid, ltype);
135 async_exchange_end(exch);
136
137 if (retval != EOK)
138 return EIO;
139
140 return EOK;
141}
142
[b7fd2a0]143errno_t vbd_label_delete(vbd_t *vbd, service_id_t sid)
[22fb7ab]144{
145 async_exch_t *exch;
[b7fd2a0]146 errno_t retval;
[22fb7ab]147
148 exch = async_exchange_begin(vbd->sess);
149 retval = async_req_1_0(exch, VBD_LABEL_DELETE, sid);
150 async_exchange_end(exch);
151
152 if (retval != EOK)
153 return EIO;
154
155 return EOK;
156}
157
[28ed0d9]158/** Get list of IDs into a buffer of fixed size.
159 *
160 * @param vbd Virtual Block Device
161 * @param method IPC method
162 * @param arg1 First argument
163 * @param id_buf Buffer to store IDs
164 * @param buf_size Buffer size
165 * @param act_size Place to store actual size of complete data.
166 *
[cde999a]167 * @return EOK on success or an error code.
[28ed0d9]168 */
[b7fd2a0]169static errno_t vbd_get_ids_once(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
[28ed0d9]170 sysarg_t *id_buf, size_t buf_size, size_t *act_size)
171{
172 async_exch_t *exch = async_exchange_begin(vbd->sess);
173
174 ipc_call_t answer;
175 aid_t req = async_send_1(exch, method, arg1, &answer);
[b7fd2a0]176 errno_t rc = async_data_read_start(exch, id_buf, buf_size);
[28ed0d9]177
178 async_exchange_end(exch);
179
180 if (rc != EOK) {
181 async_forget(req);
182 return rc;
183 }
184
[b7fd2a0]185 errno_t retval;
[28ed0d9]186 async_wait_for(req, &retval);
187
188 if (retval != EOK) {
189 return retval;
190 }
191
[fafb8e5]192 *act_size = ipc_get_arg1(&answer);
[28ed0d9]193 return EOK;
194}
195
196/** Get list of IDs.
197 *
198 * Returns an allocated array of service IDs.
199 *
200 * @param vbd Virtual Block Device
201 * @param method IPC method
202 * @param arg1 IPC argument 1
203 * @param data Place to store pointer to array of IDs
204 * @param count Place to store number of IDs
[cde999a]205 * @return EOK on success or an error code
[28ed0d9]206 */
[b7fd2a0]207static errno_t vbd_get_ids_internal(vbd_t *vbd, sysarg_t method, sysarg_t arg1,
[28ed0d9]208 sysarg_t **data, size_t *count)
209{
210 *data = NULL;
211 *count = 0;
212
213 size_t act_size = 0;
[b7fd2a0]214 errno_t rc = vbd_get_ids_once(vbd, method, arg1, NULL, 0, &act_size);
[28ed0d9]215 if (rc != EOK)
216 return rc;
217
218 size_t alloc_size = act_size;
219 service_id_t *ids = malloc(alloc_size);
220 if (ids == NULL)
221 return ENOMEM;
222
223 while (true) {
224 rc = vbd_get_ids_once(vbd, method, arg1, ids, alloc_size,
225 &act_size);
226 if (rc != EOK)
227 return rc;
228
229 if (act_size <= alloc_size)
230 break;
231
232 alloc_size = act_size;
[27c0e5b]233 service_id_t *tmp = realloc(ids, alloc_size);
234 if (tmp == NULL) {
235 free(ids);
[28ed0d9]236 return ENOMEM;
[27c0e5b]237 }
238 ids = tmp;
[28ed0d9]239 }
240
241 *count = act_size / sizeof(service_id_t);
242 *data = ids;
243 return EOK;
244}
245
246/** Get list of disks as array of service IDs.
247 *
248 * @param vbd Virtual Block Device
249 * @param data Place to store pointer to array
250 * @param count Place to store length of array (number of entries)
251 *
[cde999a]252 * @return EOK on success or an error code
[28ed0d9]253 */
[b7fd2a0]254errno_t vbd_label_get_parts(vbd_t *vbd, service_id_t disk,
[28ed0d9]255 service_id_t **data, size_t *count)
256{
257 return vbd_get_ids_internal(vbd, VBD_LABEL_GET_PARTS, disk,
258 data, count);
259}
260
[b7fd2a0]261errno_t vbd_part_get_info(vbd_t *vbd, vbd_part_id_t part, vbd_part_info_t *pinfo)
[28ed0d9]262{
263 async_exch_t *exch;
[b7fd2a0]264 errno_t retval;
[b7a4d06]265 ipc_call_t answer;
[28ed0d9]266
267 exch = async_exchange_begin(vbd->sess);
[b7a4d06]268 aid_t req = async_send_1(exch, VBD_PART_GET_INFO, part, &answer);
[b7fd2a0]269 errno_t rc = async_data_read_start(exch, pinfo, sizeof(vbd_part_info_t));
[28ed0d9]270 async_exchange_end(exch);
271
[b7a4d06]272 if (rc != EOK) {
273 async_forget(req);
274 return EIO;
275 }
276
277 async_wait_for(req, &retval);
[28ed0d9]278 if (retval != EOK)
279 return EIO;
280
281 return EOK;
282}
283
[b7fd2a0]284errno_t vbd_part_create(vbd_t *vbd, service_id_t disk, vbd_part_spec_t *pspec,
[28ed0d9]285 vbd_part_id_t *rpart)
286{
287 async_exch_t *exch;
[b7fd2a0]288 errno_t retval;
[6bc542b]289 ipc_call_t answer;
[28ed0d9]290
291 exch = async_exchange_begin(vbd->sess);
[6bc542b]292 aid_t req = async_send_1(exch, VBD_PART_CREATE, disk, &answer);
[b7fd2a0]293 errno_t rc = async_data_write_start(exch, pspec, sizeof(vbd_part_spec_t));
[28ed0d9]294 async_exchange_end(exch);
295
[6bc542b]296 if (rc != EOK) {
297 async_forget(req);
298 return EIO;
299 }
300
301 async_wait_for(req, &retval);
[28ed0d9]302 if (retval != EOK)
303 return EIO;
304
[fafb8e5]305 *rpart = (vbd_part_id_t)ipc_get_arg1(&answer);
[28ed0d9]306 return EOK;
[6bc542b]307
[28ed0d9]308}
309
[b7fd2a0]310errno_t vbd_part_delete(vbd_t *vbd, vbd_part_id_t part)
[28ed0d9]311{
312 async_exch_t *exch;
[b7fd2a0]313 errno_t retval;
[28ed0d9]314
315 exch = async_exchange_begin(vbd->sess);
316 retval = async_req_1_0(exch, VBD_PART_DELETE, part);
317 async_exchange_end(exch);
318
319 if (retval != EOK)
320 return EIO;
321
322 return EOK;
323}
324
325void vbd_pspec_init(vbd_part_spec_t *pspec)
326{
327 memset(pspec, 0, sizeof(vbd_part_spec_t));
328}
329
[f57ccb5]330/** Suggest partition type based on partition content.
331 *
332 * @param vbd Virtual Block Device
333 * @param disk Disk on which the partition will be created
334 * @param pcnt Partition content
335 * @param ptype Place to store suggested partition type
336 *
[cde999a]337 * @return EOK on success or an error code
[f57ccb5]338 */
[b7fd2a0]339errno_t vbd_suggest_ptype(vbd_t *vbd, service_id_t disk, label_pcnt_t pcnt,
[f57ccb5]340 label_ptype_t *ptype)
341{
342 async_exch_t *exch;
[b7fd2a0]343 errno_t retval;
[f57ccb5]344 ipc_call_t answer;
345
346 exch = async_exchange_begin(vbd->sess);
347 aid_t req = async_send_2(exch, VBD_SUGGEST_PTYPE, disk, pcnt, &answer);
[b7fd2a0]348 errno_t rc = async_data_read_start(exch, ptype, sizeof(label_ptype_t));
[f57ccb5]349 async_exchange_end(exch);
350
351 if (rc != EOK) {
352 async_forget(req);
353 return EIO;
354 }
355
356 async_wait_for(req, &retval);
357 if (retval != EOK)
358 return EIO;
359
360 return EOK;
361}
362
[22fb7ab]363/** @}
364 */
Note: See TracBrowser for help on using the repository browser.