source: mainline/uspace/lib/fdisk/src/fdisk.c@ 3faa03d

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

VBD client API, liblabel API, pass partition creation/deletion through to VBD.

  • Property mode set to 100644
File size: 9.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 libfdisk
30 * @{
31 */
32/**
33 * @file Disk management library.
34 */
35
36#include <adt/list.h>
37#include <block.h>
38#include <errno.h>
39#include <fdisk.h>
40#include <loc.h>
41#include <mem.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <str.h>
45#include <vbd.h>
46#include <vol.h>
47
48static const char *cu_str[] = {
49 [cu_byte] = "B",
50 [cu_kbyte] = "kB",
51 [cu_mbyte] = "MB",
52 [cu_gbyte] = "GB",
53 [cu_tbyte] = "TB",
54 [cu_pbyte] = "PB",
55 [cu_ebyte] = "EB",
56 [cu_zbyte] = "ZB",
57 [cu_ybyte] = "YB"
58};
59
60static void fdisk_dev_info_delete(fdisk_dev_info_t *info)
61{
62 if (info == NULL)
63 return;
64
65 if (info->blk_inited)
66 block_fini(info->svcid);
67
68 free(info->svcname);
69 free(info);
70}
71
72int fdisk_create(fdisk_t **rfdisk)
73{
74 fdisk_t *fdisk = NULL;
75 int rc;
76
77 fdisk = calloc(1, sizeof(fdisk_t));
78 if (fdisk == NULL) {
79 rc = ENOMEM;
80 goto error;
81 }
82
83 rc = vol_create(&fdisk->vol);
84 if (rc != EOK) {
85 rc = EIO;
86 goto error;
87 }
88
89 rc = vbd_create(&fdisk->vbd);
90 if (rc != EOK) {
91 rc = EIO;
92 goto error;
93 }
94
95 *rfdisk = fdisk;
96 return EOK;
97error:
98 fdisk_destroy(fdisk);
99
100 return rc;
101}
102
103void fdisk_destroy(fdisk_t *fdisk)
104{
105 if (fdisk == NULL)
106 return;
107
108 vol_destroy(fdisk->vol);
109 vbd_destroy(fdisk->vbd);
110 free(fdisk);
111}
112
113int fdisk_dev_list_get(fdisk_t *fdisk, fdisk_dev_list_t **rdevlist)
114{
115 fdisk_dev_list_t *devlist = NULL;
116 fdisk_dev_info_t *info;
117 service_id_t *svcs = NULL;
118 size_t count, i;
119 int rc;
120
121 devlist = calloc(1, sizeof(fdisk_dev_list_t));
122 if (devlist == NULL)
123 return ENOMEM;
124
125 list_initialize(&devlist->devinfos);
126
127 rc = vol_get_disks(fdisk->vol, &svcs, &count);
128 if (rc != EOK) {
129 rc = EIO;
130 goto error;
131 }
132
133 for (i = 0; i < count; i++) {
134 info = calloc(1, sizeof(fdisk_dev_info_t));
135 if (info == NULL) {
136 rc = ENOMEM;
137 goto error;
138 }
139
140 info->svcid = svcs[i];
141 info->devlist = devlist;
142 list_append(&info->ldevlist, &devlist->devinfos);
143 }
144
145 *rdevlist = devlist;
146 free(svcs);
147 return EOK;
148error:
149 free(svcs);
150 fdisk_dev_list_free(devlist);
151 return rc;
152}
153
154void fdisk_dev_list_free(fdisk_dev_list_t *devlist)
155{
156 fdisk_dev_info_t *info;
157
158 if (devlist == NULL)
159 return;
160
161 while (!list_empty(&devlist->devinfos)) {
162 info = list_get_instance(list_first(
163 &devlist->devinfos), fdisk_dev_info_t,
164 ldevlist);
165
166 list_remove(&info->ldevlist);
167 fdisk_dev_info_delete(info);
168 }
169
170 free(devlist);
171}
172
173fdisk_dev_info_t *fdisk_dev_first(fdisk_dev_list_t *devlist)
174{
175 if (list_empty(&devlist->devinfos))
176 return NULL;
177
178 return list_get_instance(list_first(&devlist->devinfos),
179 fdisk_dev_info_t, ldevlist);
180}
181
182fdisk_dev_info_t *fdisk_dev_next(fdisk_dev_info_t *devinfo)
183{
184 link_t *lnext;
185
186 lnext = list_next(&devinfo->ldevlist,
187 &devinfo->devlist->devinfos);
188 if (lnext == NULL)
189 return NULL;
190
191 return list_get_instance(lnext, fdisk_dev_info_t,
192 ldevlist);
193}
194
195void fdisk_dev_info_get_svcid(fdisk_dev_info_t *info, service_id_t *rsid)
196{
197 *rsid = info->svcid;
198}
199
200int fdisk_dev_info_get_svcname(fdisk_dev_info_t *info, char **rname)
201{
202 char *name;
203 int rc;
204
205 if (info->svcname == NULL) {
206 rc = loc_service_get_name(info->svcid,
207 &info->svcname);
208 if (rc != EOK)
209 return rc;
210 }
211
212 name = str_dup(info->svcname);
213 if (name == NULL)
214 return ENOMEM;
215
216 *rname = name;
217 return EOK;
218}
219
220int fdisk_dev_info_capacity(fdisk_dev_info_t *info, fdisk_cap_t *cap)
221{
222 size_t bsize;
223 aoff64_t nblocks;
224 int rc;
225
226 if (!info->blk_inited) {
227 rc = block_init(EXCHANGE_SERIALIZE, info->svcid, 2048);
228 if (rc != EOK)
229 return rc;
230
231 info->blk_inited = true;
232 }
233
234 rc = block_get_bsize(info->svcid, &bsize);
235 if (rc != EOK)
236 return EIO;
237
238 rc = block_get_nblocks(info->svcid, &nblocks);
239 if (rc != EOK)
240 return EIO;
241
242 cap->value = bsize * nblocks;
243 cap->cunit = cu_byte;
244
245 return EOK;
246}
247
248int fdisk_dev_open(fdisk_t *fdisk, service_id_t sid, fdisk_dev_t **rdev)
249{
250 fdisk_dev_t *dev;
251
252 dev = calloc(1, sizeof(fdisk_dev_t));
253 if (dev == NULL)
254 return ENOMEM;
255
256 dev->fdisk = fdisk;
257 dev->sid = sid;
258 list_initialize(&dev->parts);
259 *rdev = dev;
260 return EOK;
261}
262
263void fdisk_dev_close(fdisk_dev_t *dev)
264{
265 free(dev);
266}
267
268int fdisk_dev_get_svcname(fdisk_dev_t *dev, char **rname)
269{
270 char *name;
271 int rc;
272
273 rc = loc_service_get_name(dev->sid, &name);
274 if (rc != EOK)
275 return rc;
276
277 *rname = name;
278 return EOK;
279}
280
281int fdisk_dev_capacity(fdisk_dev_t *dev, fdisk_cap_t *cap)
282{
283 size_t bsize;
284 aoff64_t nblocks;
285 int rc;
286
287 rc = block_init(EXCHANGE_SERIALIZE, dev->sid, 2048);
288 if (rc != EOK)
289 return rc;
290
291 rc = block_get_bsize(dev->sid, &bsize);
292 if (rc != EOK)
293 return EIO;
294
295 rc = block_get_nblocks(dev->sid, &nblocks);
296 if (rc != EOK)
297 return EIO;
298
299 block_fini(dev->sid);
300
301 cap->value = bsize * nblocks;
302 cap->cunit = cu_byte;
303
304 return EOK;
305}
306
307int fdisk_label_get_info(fdisk_dev_t *dev, fdisk_label_info_t *info)
308{
309 vol_disk_info_t vinfo;
310 int rc;
311
312 rc = vol_disk_info(dev->fdisk->vol, dev->sid, &vinfo);
313 if (rc != EOK) {
314 rc = EIO;
315 goto error;
316 }
317
318 info->dcnt = vinfo.dcnt;
319 info->ltype = vinfo.ltype;
320 return EOK;
321error:
322 return rc;
323}
324
325int fdisk_label_create(fdisk_dev_t *dev, label_type_t ltype)
326{
327 return vol_label_create(dev->fdisk->vol, dev->sid, ltype);
328}
329
330int fdisk_label_destroy(fdisk_dev_t *dev)
331{
332 fdisk_part_t *part;
333 int rc;
334
335 part = fdisk_part_first(dev);
336 while (part != NULL) {
337 (void) fdisk_part_destroy(part); /* XXX */
338 part = fdisk_part_first(dev);
339 }
340
341 rc = vol_disk_empty(dev->fdisk->vol, dev->sid);
342 if (rc != EOK)
343 return EIO;
344
345 dev->dcnt = dc_empty;
346 return EOK;
347}
348
349fdisk_part_t *fdisk_part_first(fdisk_dev_t *dev)
350{
351 link_t *link;
352
353 link = list_first(&dev->parts);
354 if (link == NULL)
355 return NULL;
356
357 return list_get_instance(link, fdisk_part_t, ldev);
358}
359
360fdisk_part_t *fdisk_part_next(fdisk_part_t *part)
361{
362 link_t *link;
363
364 link = list_next(&part->ldev, &part->dev->parts);
365 if (link == NULL)
366 return NULL;
367
368 return list_get_instance(link, fdisk_part_t, ldev);
369}
370
371int fdisk_part_get_info(fdisk_part_t *part, fdisk_part_info_t *info)
372{
373 info->capacity = part->capacity;
374 info->fstype = part->fstype;
375 return EOK;
376}
377
378int fdisk_part_get_max_avail(fdisk_dev_t *dev, fdisk_cap_t *cap)
379{
380 return EOK;
381}
382
383int fdisk_part_create(fdisk_dev_t *dev, fdisk_part_spec_t *pspec,
384 fdisk_part_t **rpart)
385{
386 fdisk_part_t *part;
387 vbd_part_spec_t vpspec;
388 vbd_part_id_t partid;
389 int rc;
390
391 part = calloc(1, sizeof(fdisk_part_t));
392 if (part == NULL)
393 return ENOMEM;
394
395 rc = vbd_part_create(dev->fdisk->vbd, dev->sid, &vpspec, &partid);
396 if (rc != EOK) {
397 free(part);
398 return EIO;
399 }
400
401 part->dev = dev;
402 list_append(&part->ldev, &dev->parts);
403 part->capacity = pspec->capacity;
404 part->fstype = pspec->fstype;
405 part->part_id = partid;
406
407 if (rpart != NULL)
408 *rpart = part;
409 return EOK;
410}
411
412int fdisk_part_destroy(fdisk_part_t *part)
413{
414 int rc;
415
416 rc = vbd_part_delete(part->dev->fdisk->vbd, part->part_id);
417 if (rc != EOK)
418 return EIO;
419
420 list_remove(&part->ldev);
421 free(part);
422 return EOK;
423}
424
425void fdisk_pspec_init(fdisk_part_spec_t *pspec)
426{
427 memset(pspec, 0, sizeof(fdisk_part_spec_t));
428}
429
430int fdisk_cap_format(fdisk_cap_t *cap, char **rstr)
431{
432 int rc;
433 const char *sunit;
434
435 sunit = NULL;
436
437 if (cap->cunit < 0 || cap->cunit >= CU_LIMIT)
438 assert(false);
439
440 sunit = cu_str[cap->cunit];
441 rc = asprintf(rstr, "%" PRIu64 " %s", cap->value, sunit);
442 if (rc < 0)
443 return ENOMEM;
444
445 return EOK;
446}
447
448int fdisk_cap_parse(const char *str, fdisk_cap_t *cap)
449{
450 char *eptr;
451 char *p;
452 unsigned long val;
453 int i;
454
455 val = strtoul(str, &eptr, 10);
456
457 while (*eptr == ' ')
458 ++eptr;
459
460 if (*eptr == '\0') {
461 cap->cunit = cu_byte;
462 } else {
463 for (i = 0; i < CU_LIMIT; i++) {
464 if (str_lcasecmp(eptr, cu_str[i],
465 str_length(cu_str[i])) == 0) {
466 p = eptr + str_size(cu_str[i]);
467 while (*p == ' ')
468 ++p;
469 if (*p == '\0')
470 goto found;
471 }
472 }
473
474 return EINVAL;
475found:
476 cap->cunit = i;
477 }
478
479 cap->value = val;
480 return EOK;
481}
482
483int fdisk_ltype_format(label_type_t ltype, char **rstr)
484{
485 const char *sltype;
486 char *s;
487
488 sltype = NULL;
489 switch (ltype) {
490 case lt_mbr:
491 sltype = "MBR";
492 break;
493 case lt_gpt:
494 sltype = "GPT";
495 break;
496 }
497
498 s = str_dup(sltype);
499 if (s == NULL)
500 return ENOMEM;
501
502 *rstr = s;
503 return EOK;
504}
505
506int fdisk_fstype_format(fdisk_fstype_t fstype, char **rstr)
507{
508 const char *sfstype;
509 char *s;
510
511 sfstype = NULL;
512 switch (fstype) {
513 case fdfs_none:
514 sfstype = "None";
515 break;
516 case fdfs_unknown:
517 sfstype = "Unknown";
518 break;
519 case fdfs_exfat:
520 sfstype = "ExFAT";
521 break;
522 case fdfs_fat:
523 sfstype = "FAT";
524 break;
525 case fdfs_minix:
526 sfstype = "MINIX";
527 break;
528 case fdfs_ext4:
529 sfstype = "Ext4";
530 break;
531 }
532
533 s = str_dup(sfstype);
534 if (s == NULL)
535 return ENOMEM;
536
537 *rstr = s;
538 return EOK;
539}
540
541/** @}
542 */
Note: See TracBrowser for help on using the repository browser.