source: mainline/uspace/app/fdisk/fdisk.c@ 78d50bd

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

Implement partition block device interface in VBD based on data from liblabel.

  • Property mode set to 100644
File size: 13.3 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 fdisk
30 * @brief Disk management tool
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <errno.h>
38#include <nchoice.h>
39#include <stdbool.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <fdisk.h>
43
44static bool quit = false;
45static fdisk_t *fdisk;
46
47/** Device menu actions */
48typedef enum {
49 /** Create label */
50 devac_create_label,
51 /** Delete label */
52 devac_delete_label,
53 /** Create partition */
54 devac_create_part,
55 /** Delete partition */
56 devac_delete_part,
57 /** Exit */
58 devac_exit
59} devac_t;
60
61/** Device selection */
62static int fdsk_dev_sel_choice(service_id_t *rsvcid)
63{
64 fdisk_dev_list_t *devlist = NULL;
65 fdisk_dev_info_t *info;
66 nchoice_t *choice = NULL;
67 char *svcname = NULL;
68 fdisk_cap_t cap;
69 fdisk_dev_info_t *sdev;
70 char *scap = NULL;
71 char *dtext = NULL;
72 service_id_t svcid;
73 void *sel;
74 int ndevs;
75 int rc;
76
77 rc = nchoice_create(&choice);
78 if (rc != EOK) {
79 assert(rc == ENOMEM);
80 printf("Out of memory.\n");
81 goto error;
82 }
83
84 rc = nchoice_set_prompt(choice, "Select device");
85 if (rc != EOK) {
86 assert(rc == ENOMEM);
87 printf("Out of memory.\n");
88 goto error;
89 }
90
91 rc = fdisk_dev_list_get(fdisk, &devlist);
92 if (rc != EOK) {
93 printf("Error getting device list.\n");
94 goto error;
95 }
96
97 info = fdisk_dev_first(devlist);
98 ndevs = 0;
99 while (info != NULL) {
100 ++ndevs;
101
102 rc = fdisk_dev_info_get_svcname(info, &svcname);
103 if (rc != EOK) {
104 printf("Error getting device service name.\n");
105 goto error;
106 }
107
108 rc = fdisk_dev_info_capacity(info, &cap);
109 if (rc != EOK) {
110 printf("Error getting device capacity.\n");
111 goto error;
112 }
113
114 rc = fdisk_cap_format(&cap, &scap);
115 if (rc != EOK) {
116 assert(rc == ENOMEM);
117 printf("Out of memory.\n");
118 goto error;
119 }
120
121 rc = asprintf(&dtext, "%s (%s)", svcname, scap);
122 if (rc < 0) {
123 rc = ENOMEM;
124 printf("Out of memory.\n");
125 goto error;
126 }
127
128 free(svcname);
129 svcname = NULL;
130 free(scap);
131 scap = NULL;
132
133 rc = nchoice_add(choice, dtext, info);
134 if (rc != EOK) {
135 assert(rc == ENOMEM);
136 printf("Out of memory.\n");
137 goto error;
138 }
139
140 free(dtext);
141 dtext = NULL;
142
143 info = fdisk_dev_next(info);
144 }
145
146 if (ndevs == 0) {
147 printf("No disk devices found.\n");
148 rc = ENOENT;
149 goto error;
150 }
151
152 rc = nchoice_add(choice, "Exit", NULL);
153 if (rc != EOK) {
154 assert(rc == ENOMEM);
155 printf("Out of memory.\n");
156 goto error;
157 }
158
159 rc = nchoice_get(choice, &sel);
160 if (rc != EOK) {
161 printf("Error getting user selection.\n");
162 return rc;
163 }
164
165 sdev = (fdisk_dev_info_t *)sel;
166 if (sdev != NULL) {
167 fdisk_dev_info_get_svcid(sdev, &svcid);
168 } else {
169 svcid = 0;
170 }
171
172 fdisk_dev_list_free(devlist);
173
174 nchoice_destroy(choice);
175 *rsvcid = svcid;
176 return EOK;
177error:
178 if (devlist != NULL)
179 fdisk_dev_list_free(devlist);
180 if (choice != NULL)
181 nchoice_destroy(choice);
182 free(dtext);
183 free(svcname);
184 free(scap);
185 return rc;
186}
187
188static int fdsk_create_label(fdisk_dev_t *dev)
189{
190 nchoice_t *choice = NULL;
191 void *sel;
192 char *sltype = NULL;
193 int i;
194 int rc;
195
196 rc = nchoice_create(&choice);
197 if (rc != EOK) {
198 assert(rc == ENOMEM);
199 printf("Out of memory.\n");
200 goto error;
201 }
202
203 rc = nchoice_set_prompt(choice, "Select label type");
204 if (rc != EOK) {
205 assert(rc == ENOMEM);
206 printf("Out of memory.\n");
207 goto error;
208 }
209
210 for (i = 0; i < LT_LIMIT; i++) {
211 rc = fdisk_ltype_format(i, &sltype);
212 if (rc != EOK)
213 goto error;
214
215 rc = nchoice_add(choice, sltype, (void *)(uintptr_t)i);
216 if (rc != EOK) {
217 assert(rc == ENOMEM);
218 printf("Out of memory.\n");
219 goto error;
220 }
221
222 free(sltype);
223 sltype = NULL;
224 }
225
226 rc = nchoice_get(choice, &sel);
227 if (rc != EOK) {
228 printf("Error getting user selection.\n");
229 goto error;
230 }
231
232 rc = fdisk_label_create(dev, (label_type_t)sel);
233 if (rc != EOK) {
234 printf("Error creating label.\n");
235 goto error;
236 }
237
238 nchoice_destroy(choice);
239 return EOK;
240error:
241 free(sltype);
242 if (choice != NULL)
243 nchoice_destroy(choice);
244 return rc;
245}
246
247static int fdsk_delete_label(fdisk_dev_t *dev)
248{
249 int rc;
250
251 rc = fdisk_label_destroy(dev);
252 if (rc != EOK) {
253 printf("Error deleting label.\n");
254 return rc;
255 }
256
257 return EOK;
258}
259
260static int fdsk_select_fstype(fdisk_fstype_t *fstype)
261{
262 nchoice_t *choice = NULL;
263 void *sel;
264 char *sfstype;
265 int i;
266 int rc;
267
268 rc = nchoice_create(&choice);
269 if (rc != EOK) {
270 assert(rc == ENOMEM);
271 printf("Out of memory.\n");
272 goto error;
273 }
274
275 rc = nchoice_set_prompt(choice, "Select file system type");
276 if (rc != EOK) {
277 assert(rc == ENOMEM);
278 printf("Out of memory.\n");
279 goto error;
280 }
281
282 for (i = FDFS_CREATE_LO; i < FDFS_CREATE_HI; i++) {
283 rc = fdisk_fstype_format(i, &sfstype);
284 if (rc != EOK)
285 goto error;
286
287 rc = nchoice_add(choice, sfstype, (void *)(uintptr_t)i);
288 if (rc != EOK) {
289 assert(rc == ENOMEM);
290 printf("Out of memory.\n");
291 goto error;
292 }
293
294 free(sfstype);
295 sfstype = NULL;
296 }
297
298 rc = nchoice_get(choice, &sel);
299 if (rc != EOK) {
300 printf("Error getting user selection.\n");
301 goto error;
302 }
303
304 nchoice_destroy(choice);
305 *fstype = (fdisk_fstype_t)sel;
306 return EOK;
307error:
308 free(sfstype);
309 if (choice != NULL)
310 nchoice_destroy(choice);
311 return rc;
312}
313
314static int fdsk_create_part(fdisk_dev_t *dev)
315{
316 int rc;
317 fdisk_part_spec_t pspec;
318 fdisk_cap_t cap;
319 fdisk_fstype_t fstype;
320 tinput_t *tinput = NULL;
321 char *scap;
322
323 tinput = tinput_new();
324 if (tinput == NULL) {
325 rc = ENOMEM;
326 goto error;
327 }
328
329 rc = tinput_set_prompt(tinput, "?> ");
330 if (rc != EOK)
331 goto error;
332
333 while (true) {
334 printf("Enter capacity of new partition.\n");
335 rc = tinput_read(tinput, &scap);
336 if (rc != EOK)
337 goto error;
338
339 rc = fdisk_cap_parse(scap, &cap);
340 if (rc == EOK)
341 break;
342 }
343
344 tinput_destroy(tinput);
345 tinput = NULL;
346
347 rc = fdsk_select_fstype(&fstype);
348 if (rc != EOK)
349 goto error;
350
351 fdisk_pspec_init(&pspec);
352 pspec.capacity = cap;
353 pspec.fstype = fstype;
354
355 rc = fdisk_part_create(dev, &pspec, NULL);
356 if (rc != EOK) {
357 printf("Error creating partition.\n");
358 goto error;
359 }
360
361 return EOK;
362error:
363 if (tinput != NULL)
364 tinput_destroy(tinput);
365 return rc;
366}
367
368static int fdsk_delete_part(fdisk_dev_t *dev)
369{
370 nchoice_t *choice = NULL;
371 fdisk_part_t *part;
372 fdisk_part_info_t pinfo;
373 char *scap = NULL;
374 char *sfstype = NULL;
375 char *sdesc = NULL;
376 void *sel;
377 int rc;
378
379 rc = nchoice_create(&choice);
380 if (rc != EOK) {
381 assert(rc == ENOMEM);
382 printf("Out of memory.\n");
383 goto error;
384 }
385
386 rc = nchoice_set_prompt(choice, "Select partition to delete");
387 if (rc != EOK) {
388 assert(rc == ENOMEM);
389 printf("Out of memory.\n");
390 goto error;
391 }
392
393 part = fdisk_part_first(dev);
394 while (part != NULL) {
395 rc = fdisk_part_get_info(part, &pinfo);
396 if (rc != EOK) {
397 printf("Error getting partition information.\n");
398 goto error;
399 }
400
401 rc = fdisk_cap_format(&pinfo.capacity, &scap);
402 if (rc != EOK) {
403 printf("Out of memory.\n");
404 goto error;
405 }
406
407 rc = fdisk_fstype_format(pinfo.fstype, &sfstype);
408 if (rc != EOK) {
409 printf("Out of memory.\n");
410 goto error;
411 }
412
413 rc = asprintf(&sdesc, "%s, %s", scap, sfstype);
414 if (rc < 0) {
415 rc = ENOMEM;
416 goto error;
417 }
418
419 rc = nchoice_add(choice, sdesc, (void *)part);
420 if (rc != EOK) {
421 assert(rc == ENOMEM);
422 printf("Out of memory.\n");
423 goto error;
424 }
425
426 free(scap);
427 scap = NULL;
428 free(sfstype);
429 sfstype = NULL;
430 free(sdesc);
431 sdesc = NULL;
432
433 part = fdisk_part_next(part);
434 }
435
436 rc = nchoice_get(choice, &sel);
437 if (rc != EOK) {
438 printf("Error getting user selection.\n");
439 goto error;
440 }
441
442 rc = fdisk_part_destroy((fdisk_part_t *)sel);
443 if (rc != EOK) {
444 printf("Error deleting partition.\n");
445 return rc;
446 }
447
448 nchoice_destroy(choice);
449 return EOK;
450error:
451 free(scap);
452 free(sfstype);
453 free(sdesc);
454
455 if (choice != NULL)
456 nchoice_destroy(choice);
457 return rc;
458}
459
460/** Device menu */
461static int fdsk_dev_menu(fdisk_dev_t *dev)
462{
463 nchoice_t *choice = NULL;
464 fdisk_label_info_t linfo;
465 fdisk_part_t *part;
466 fdisk_part_info_t pinfo;
467 fdisk_cap_t cap;
468 char *sltype = NULL;
469 char *sdcap = NULL;
470 char *scap = NULL;
471 char *sfstype = NULL;
472 char *svcname = NULL;
473 int rc;
474 int npart;
475 void *sel;
476
477 rc = nchoice_create(&choice);
478 if (rc != EOK) {
479 assert(rc == ENOMEM);
480 printf("Out of memory.\n");
481 goto error;
482 }
483
484 rc = nchoice_set_prompt(choice, "Select action");
485 if (rc != EOK) {
486 assert(rc == ENOMEM);
487 printf("Out of memory.\n");
488 goto error;
489 }
490
491 rc = fdisk_dev_capacity(dev, &cap);
492 if (rc != EOK) {
493 printf("Error getting device capacity.\n");
494 goto error;
495 }
496
497 rc = fdisk_cap_format(&cap, &sdcap);
498 if (rc != EOK) {
499 printf("Out of memory.\n");
500 goto error;
501 }
502
503 rc = fdisk_dev_get_svcname(dev, &svcname);
504 if (rc != EOK) {
505 printf("Error getting device service name.\n");
506 goto error;
507 }
508
509 printf("Device: %s, %s\n", sdcap, svcname);
510 free(sdcap);
511 sdcap = NULL;
512
513 rc = fdisk_label_get_info(dev, &linfo);
514 if (rc != EOK) {
515 printf("Error getting label information.\n");
516 goto error;
517 }
518
519 switch (linfo.dcnt) {
520 case dc_empty:
521 printf("Disk is empty.\n");
522 break;
523 case dc_label:
524 rc = fdisk_ltype_format(linfo.ltype, &sltype);
525 if (rc != EOK) {
526 assert(rc == ENOMEM);
527 printf("Out of memory.\n");
528 goto error;
529 }
530
531 printf("Label type: %s\n", sltype);
532 free(sltype);
533 sltype = NULL;
534 break;
535 case dc_fs:
536 printf("Disk contains a file system.\n");
537 break;
538 case dc_unknown:
539 printf("Disk contains unknown data.\n");
540 break;
541 }
542
543 part = fdisk_part_first(dev);
544 npart = 0;
545 while (part != NULL) {
546 ++npart;
547 rc = fdisk_part_get_info(part, &pinfo);
548 if (rc != EOK) {
549 printf("Error getting partition information.\n");
550 goto error;
551 }
552
553 rc = fdisk_cap_format(&pinfo.capacity, &scap);
554 if (rc != EOK) {
555 printf("Out of memory.\n");
556 goto error;
557 }
558
559 rc = fdisk_fstype_format(pinfo.fstype, &sfstype);
560 if (rc != EOK) {
561 printf("Out of memory.\n");
562 goto error;
563 }
564
565 printf("Partition %d: %s, %s\n", npart, scap, sfstype);
566 free(scap);
567 scap = NULL;
568 free(sfstype);
569 sfstype = NULL;
570
571 part = fdisk_part_next(part);
572 }
573
574 rc = nchoice_set_prompt(choice, "Select action");
575 if (rc != EOK) {
576 assert(rc == ENOMEM);
577 printf("Out of memory.\n");
578 goto error;
579 }
580
581 if (linfo.dcnt == dc_label) {
582 rc = nchoice_add(choice, "Create partition",
583 (void *)devac_create_part);
584 if (rc != EOK) {
585 assert(rc == ENOMEM);
586 printf("Out of memory.\n");
587 goto error;
588 }
589 }
590
591 if (npart > 0) {
592 rc = nchoice_add(choice, "Delete partition",
593 (void *)devac_delete_part);
594 if (rc != EOK) {
595 assert(rc == ENOMEM);
596 printf("Out of memory.\n");
597 goto error;
598 }
599 }
600
601 if (linfo.dcnt == dc_empty) {
602 rc = nchoice_add(choice, "Create label",
603 (void *)devac_create_label);
604 if (rc != EOK) {
605 assert(rc == ENOMEM);
606 printf("Out of memory.\n");
607 goto error;
608 }
609 } else {
610 rc = nchoice_add(choice, "Delete label",
611 (void *)devac_delete_label);
612 if (rc != EOK) {
613 assert(rc == ENOMEM);
614 printf("Out of memory.\n");
615 goto error;
616 }
617 }
618
619 rc = nchoice_add(choice, "Exit", (void *)devac_exit);
620 if (rc != EOK) {
621 assert(rc == ENOMEM);
622 printf("Out of memory.\n");
623 goto error;
624 }
625
626 rc = nchoice_get(choice, &sel);
627 if (rc != EOK) {
628 printf("Error getting user selection.\n");
629 return rc;
630 }
631
632 switch ((devac_t)sel) {
633 case devac_create_label:
634 (void) fdsk_create_label(dev);
635 break;
636 case devac_delete_label:
637 (void) fdsk_delete_label(dev);
638 break;
639 case devac_create_part:
640 (void) fdsk_create_part(dev);
641 break;
642 case devac_delete_part:
643 (void) fdsk_delete_part(dev);
644 break;
645 case devac_exit:
646 quit = true;
647 break;
648 }
649
650 nchoice_destroy(choice);
651 return EOK;
652error:
653 free(sdcap);
654 free(scap);
655 free(sfstype);
656 free(svcname);
657 if (choice != NULL)
658 nchoice_destroy(choice);
659 return rc;
660}
661
662int main(int argc, char *argv[])
663{
664 service_id_t svcid;
665 fdisk_dev_t *dev;
666 int rc;
667
668 rc = fdisk_create(&fdisk);
669 if (rc != EOK) {
670 printf("Error initializing Fdisk.\n");
671 return 1;
672 }
673
674 rc = fdsk_dev_sel_choice(&svcid);
675 if (rc != EOK)
676 return 1;
677
678 if (svcid == 0)
679 return 0;
680
681 rc = fdisk_dev_open(fdisk, svcid, &dev);
682 if (rc != EOK) {
683 printf("Error opening device.\n");
684 return 1;
685 }
686
687 while (!quit) {
688 rc = fdsk_dev_menu(dev);
689 if (rc != EOK) {
690 fdisk_dev_close(dev);
691 return 1;
692 }
693 }
694
695 fdisk_dev_close(dev);
696 fdisk_destroy(fdisk);
697
698 return 0;
699}
700
701
702/** @}
703 */
Note: See TracBrowser for help on using the repository browser.