source: mainline/uspace/app/fdisk/fdisk.c@ cca80a2

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

Fix broken partition creation in fdisk (oops).

  • Property mode set to 100644
File size: 25.0 KB
Line 
1/*
2 * Copyright (c) 2018 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 <cap.h>
38#include <errno.h>
39#include <fdisk.h>
40#include <io/label.h>
41#include <nchoice.h>
42#include <stdbool.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <str.h>
46#include <vol.h>
47
48#define NO_LABEL_CAPTION "(No name)"
49
50static bool quit = false;
51static fdisk_t *fdisk;
52
53/** Device menu actions */
54typedef enum {
55 /** Create label */
56 devac_create_label,
57 /** Delete label */
58 devac_delete_label,
59 /** Erase disk */
60 devac_erase_disk,
61 /** Create (primary) partition */
62 devac_create_pri_part,
63 /** Create extended partition */
64 devac_create_ext_part,
65 /** Create logical partition */
66 devac_create_log_part,
67 /** Modify partition */
68 devac_modify_part,
69 /** Delete partition */
70 devac_delete_part,
71 /** Exit */
72 devac_exit
73} devac_t;
74
75/** Partition property to modify */
76typedef enum {
77 /** Modify mount point */
78 pm_mountp,
79 /** Cancel */
80 pm_cancel
81} pmprop_t;
82
83/** Confirm user selection. */
84static errno_t fdsk_confirm(const char *msg, bool *rconfirm)
85{
86 tinput_t *tinput = NULL;
87 char *answer;
88 errno_t rc;
89
90 tinput = tinput_new();
91 if (tinput == NULL) {
92 rc = ENOMEM;
93 goto error;
94 }
95
96 rc = tinput_set_prompt(tinput, "y/n> ");
97 if (rc != EOK)
98 goto error;
99
100 while (true) {
101 printf("%s\n", msg);
102
103 rc = tinput_read(tinput, &answer);
104 if (rc == ENOENT) {
105 *rconfirm = false;
106 free(answer);
107 break;
108 }
109
110 if (rc != EOK)
111 goto error;
112
113 if (str_cmp(answer, "y") == 0) {
114 *rconfirm = true;
115 free(answer);
116 break;
117 } else if (str_cmp(answer, "n") == 0) {
118 *rconfirm = false;
119 free(answer);
120 break;
121 }
122 }
123
124 tinput_destroy(tinput);
125 return EOK;
126error:
127 if (tinput != NULL)
128 tinput_destroy(tinput);
129 return rc;
130}
131
132/** Device selection */
133static errno_t fdsk_dev_sel_choice(service_id_t *rsvcid)
134{
135 fdisk_dev_list_t *devlist = NULL;
136 fdisk_dev_info_t *info;
137 nchoice_t *choice = NULL;
138 char *svcname = NULL;
139 cap_spec_t cap;
140 fdisk_dev_info_t *sdev;
141 char *scap = NULL;
142 char *dtext = NULL;
143 service_id_t svcid;
144 void *sel;
145 int ndevs;
146 errno_t rc;
147
148 rc = nchoice_create(&choice);
149 if (rc != EOK) {
150 assert(rc == ENOMEM);
151 printf("Out of memory.\n");
152 goto error;
153 }
154
155 rc = nchoice_set_prompt(choice, "Select device");
156 if (rc != EOK) {
157 assert(rc == ENOMEM);
158 printf("Out of memory.\n");
159 goto error;
160 }
161
162 rc = fdisk_dev_list_get(fdisk, &devlist);
163 if (rc != EOK) {
164 printf("Error getting device list.\n");
165 goto error;
166 }
167
168 info = fdisk_dev_first(devlist);
169 ndevs = 0;
170 while (info != NULL) {
171 rc = fdisk_dev_info_get_svcname(info, &svcname);
172 if (rc != EOK) {
173 fdisk_dev_info_get_svcid(info, &svcid);
174 printf("Error getting device service name "
175 "(service ID %zu).\n", svcid);
176 info = fdisk_dev_next(info);
177 continue;
178 }
179
180 rc = fdisk_dev_info_capacity(info, &cap);
181 if (rc != EOK) {
182 printf("Error getting device capacity "
183 "(device %s).\n", svcname);
184 info = fdisk_dev_next(info);
185 continue;
186 }
187
188 cap_simplify(&cap);
189
190 rc = cap_format(&cap, &scap);
191 if (rc != EOK) {
192 assert(rc == ENOMEM);
193 printf("Out of memory.\n");
194 goto error;
195 }
196
197 int ret = asprintf(&dtext, "%s (%s)", svcname, scap);
198 if (ret < 0) {
199 rc = ENOMEM;
200 printf("Out of memory.\n");
201 goto error;
202 }
203
204 free(svcname);
205 svcname = NULL;
206 free(scap);
207 scap = NULL;
208
209 rc = nchoice_add(choice, dtext, info, 0);
210 if (rc != EOK) {
211 assert(rc == ENOMEM);
212 printf("Out of memory.\n");
213 goto error;
214 }
215
216 ++ndevs;
217
218 free(dtext);
219 dtext = NULL;
220
221 info = fdisk_dev_next(info);
222 }
223
224 if (ndevs == 0) {
225 printf("No disk devices found.\n");
226 rc = ENOENT;
227 goto error;
228 }
229
230 rc = nchoice_add(choice, "Exit", NULL, 0);
231 if (rc != EOK) {
232 assert(rc == ENOMEM);
233 printf("Out of memory.\n");
234 goto error;
235 }
236
237 rc = nchoice_get(choice, &sel);
238 if (rc != EOK) {
239 printf("Error getting user selection.\n");
240 return rc;
241 }
242
243 sdev = (fdisk_dev_info_t *)sel;
244 if (sdev != NULL) {
245 fdisk_dev_info_get_svcid(sdev, &svcid);
246 } else {
247 svcid = 0;
248 }
249
250 fdisk_dev_list_free(devlist);
251
252 nchoice_destroy(choice);
253 *rsvcid = svcid;
254 return EOK;
255error:
256 assert(rc != EOK);
257 *rsvcid = 0;
258 if (devlist != NULL)
259 fdisk_dev_list_free(devlist);
260 if (choice != NULL)
261 nchoice_destroy(choice);
262 free(dtext);
263 free(svcname);
264 free(scap);
265 return rc;
266}
267
268static errno_t fdsk_create_label(fdisk_dev_t *dev)
269{
270 nchoice_t *choice = NULL;
271 void *sel;
272 char *sltype = NULL;
273 int i;
274 errno_t rc;
275
276 rc = nchoice_create(&choice);
277 if (rc != EOK) {
278 assert(rc == ENOMEM);
279 printf("Out of memory.\n");
280 goto error;
281 }
282
283 rc = nchoice_set_prompt(choice, "Select label type");
284 if (rc != EOK) {
285 assert(rc == ENOMEM);
286 printf("Out of memory.\n");
287 goto error;
288 }
289
290 for (i = LT_FIRST; i < LT_LIMIT; i++) {
291 rc = label_type_format(i, &sltype);
292 if (rc != EOK)
293 goto error;
294
295 rc = nchoice_add(choice, sltype, (void *)(uintptr_t)i,
296 i == LT_DEFAULT);
297 if (rc != EOK) {
298 assert(rc == ENOMEM);
299 printf("Out of memory.\n");
300 goto error;
301 }
302
303 free(sltype);
304 sltype = NULL;
305 }
306
307 rc = nchoice_get(choice, &sel);
308 if (rc != EOK) {
309 printf("Error getting user selection.\n");
310 goto error;
311 }
312
313 rc = fdisk_label_create(dev, (label_type_t)sel);
314 if (rc != EOK) {
315 printf("Error creating label.\n");
316 goto error;
317 }
318
319 nchoice_destroy(choice);
320 return EOK;
321error:
322 free(sltype);
323 if (choice != NULL)
324 nchoice_destroy(choice);
325 return rc;
326}
327
328static errno_t fdsk_delete_label(fdisk_dev_t *dev)
329{
330 bool confirm;
331 errno_t rc;
332
333 rc = fdsk_confirm("Warning. Any data on disk will be lost. "
334 "Really delete label?", &confirm);
335 if (rc != EOK) {
336 printf("Error getting user confirmation.\n");
337 return rc;
338 }
339
340 if (!confirm)
341 return EOK;
342
343 rc = fdisk_label_destroy(dev);
344 if (rc != EOK) {
345 printf("Error deleting label.\n");
346 return rc;
347 }
348
349 return EOK;
350}
351
352static errno_t fdsk_erase_disk(fdisk_dev_t *dev)
353{
354 bool confirm;
355 errno_t rc;
356
357 rc = fdsk_confirm("Warning. Any data on disk will be lost. "
358 "Really erase disk?", &confirm);
359 if (rc != EOK) {
360 printf("Error getting user confirmation.\n");
361 return rc;
362 }
363
364 if (!confirm)
365 return EOK;
366
367 rc = fdisk_dev_erase(dev);
368 if (rc != EOK) {
369 printf("Error erasing disk.\n");
370 return rc;
371 }
372
373 return EOK;
374}
375
376static errno_t fdsk_select_fstype(vol_fstype_t *fstype)
377{
378 nchoice_t *choice = NULL;
379 void *sel;
380 char *sfstype;
381 int i;
382 errno_t rc;
383
384 rc = nchoice_create(&choice);
385 if (rc != EOK) {
386 assert(rc == ENOMEM);
387 printf("Out of memory.\n");
388 goto error;
389 }
390
391 rc = nchoice_set_prompt(choice, "Select file system type");
392 if (rc != EOK) {
393 assert(rc == ENOMEM);
394 printf("Out of memory.\n");
395 goto error;
396 }
397
398 for (i = 0; i < VOL_FSTYPE_LIMIT; i++) {
399 rc = vol_fstype_format(i, &sfstype);
400 if (rc != EOK)
401 goto error;
402
403 rc = nchoice_add(choice, sfstype, (void *)(uintptr_t)i,
404 i == VOL_FSTYPE_DEFAULT);
405 if (rc != EOK) {
406 assert(rc == ENOMEM);
407 printf("Out of memory.\n");
408 goto error;
409 }
410
411 free(sfstype);
412 sfstype = NULL;
413 }
414
415 rc = nchoice_get(choice, &sel);
416 if (rc != EOK) {
417 printf("Error getting user selection.\n");
418 goto error;
419 }
420
421 nchoice_destroy(choice);
422 *fstype = (vol_fstype_t)sel;
423 return EOK;
424error:
425 free(sfstype);
426 if (choice != NULL)
427 nchoice_destroy(choice);
428 return rc;
429}
430
431static errno_t fdsk_create_part(fdisk_dev_t *dev, label_pkind_t pkind)
432{
433 errno_t rc;
434 fdisk_part_spec_t pspec;
435 cap_spec_t cap;
436 cap_spec_t mcap;
437 vol_label_supp_t vlsupp;
438 vol_fstype_t fstype = 0;
439 tinput_t *tinput = NULL;
440 fdisk_spc_t spc;
441 char *scap;
442 char *smcap = NULL;
443 char *label = NULL;
444 char *mountp = NULL;
445
446 if (pkind == lpk_logical)
447 spc = spc_log;
448 else
449 spc = spc_pri;
450
451 rc = fdisk_part_get_max_avail(dev, spc, &mcap);
452 if (rc != EOK) {
453 rc = EIO;
454 goto error;
455 }
456
457 cap_simplify(&mcap);
458
459 rc = cap_format(&mcap, &smcap);
460 if (rc != EOK) {
461 rc = ENOMEM;
462 goto error;
463 }
464
465 tinput = tinput_new();
466 if (tinput == NULL) {
467 rc = ENOMEM;
468 goto error;
469 }
470
471 rc = tinput_set_prompt(tinput, "?> ");
472 if (rc != EOK)
473 goto error;
474
475 while (true) {
476 printf("Enter capacity of new partition.\n");
477 rc = tinput_read_i(tinput, smcap, &scap);
478 if (rc != EOK)
479 goto error;
480
481 rc = cap_parse(scap, &cap);
482 if (rc == EOK)
483 break;
484 }
485
486 tinput_destroy(tinput);
487 tinput = NULL;
488 free(smcap);
489 smcap = NULL;
490
491 if (pkind != lpk_extended) {
492 rc = fdsk_select_fstype(&fstype);
493 if (rc != EOK)
494 goto error;
495 }
496
497 fdisk_get_vollabel_support(dev, fstype, &vlsupp);
498 if (vlsupp.supported) {
499 tinput = tinput_new();
500 if (tinput == NULL) {
501 rc = ENOMEM;
502 goto error;
503 }
504
505 rc = tinput_set_prompt(tinput, "?> ");
506 if (rc != EOK)
507 goto error;
508
509 /* Ask for volume label */
510 printf("Enter volume label for new partition.\n");
511 rc = tinput_read_i(tinput, "New volume", &label);
512 if (rc != EOK)
513 goto error;
514
515 tinput_destroy(tinput);
516 tinput = NULL;
517 }
518
519 /* Ask for mount point */
520 tinput = tinput_new();
521 if (tinput == NULL) {
522 rc = ENOMEM;
523 goto error;
524 }
525
526 rc = tinput_set_prompt(tinput, "?> ");
527 if (rc != EOK)
528 goto error;
529
530 while (true) {
531 printf("Enter mount point for new partition (Auto, None or /path).\n");
532 rc = tinput_read_i(tinput, "Auto", &mountp);
533 if (rc != EOK)
534 goto error;
535
536 rc = vol_mountp_validate(mountp);
537 if (rc == EOK)
538 break;
539
540 free(mountp);
541 mountp = NULL;
542 }
543
544 tinput_destroy(tinput);
545 tinput = NULL;
546
547 fdisk_pspec_init(&pspec);
548 pspec.capacity = cap;
549 pspec.pkind = pkind;
550 pspec.fstype = fstype;
551 pspec.label = label;
552 pspec.mountp = mountp;
553
554 rc = fdisk_part_create(dev, &pspec, NULL);
555 if (rc != EOK) {
556 printf("Error creating partition.\n");
557 goto error;
558 }
559
560 free(label);
561 free(mountp);
562 return EOK;
563error:
564 free(smcap);
565 free(label);
566 free(mountp);
567 if (tinput != NULL)
568 tinput_destroy(tinput);
569 return rc;
570}
571
572/** Add an option to choice for each partition.
573 *
574 * @param dev Fdisk device
575 * @param choice Choice to add optionts to
576 *
577 * @return EOK on sucess or error code
578 */
579static errno_t fdsk_add_part_choices(fdisk_dev_t *dev,
580 nchoice_t *choice)
581{
582 fdisk_part_t *part;
583 fdisk_part_info_t pinfo;
584 char *scap = NULL;
585 char *spkind = NULL;
586 char *sfstype = NULL;
587 char *sdesc = NULL;
588 const char *label;
589 errno_t rc;
590
591 part = fdisk_part_first(dev);
592 while (part != NULL) {
593 rc = fdisk_part_get_info(part, &pinfo);
594 if (rc != EOK) {
595 printf("Error getting partition information.\n");
596 goto error;
597 }
598
599 cap_simplify(&pinfo.capacity);
600
601 rc = cap_format(&pinfo.capacity, &scap);
602 if (rc != EOK) {
603 printf("Out of memory.\n");
604 goto error;
605 }
606
607 rc = label_pkind_format(pinfo.pkind, &spkind);
608 if (rc != EOK) {
609 printf("\nOut of memory.\n");
610 goto error;
611 }
612
613 if (pinfo.pkind != lpk_extended) {
614 rc = vol_pcnt_fs_format(pinfo.pcnt, pinfo.fstype, &sfstype);
615 if (rc != EOK) {
616 printf("Out of memory.\n");
617 goto error;
618 }
619
620 if (str_size(pinfo.label) > 0)
621 label = pinfo.label;
622 else
623 label = "(No name)";
624
625 int ret = asprintf(&sdesc, "%s %s, %s, %s", label,
626 scap, spkind, sfstype);
627 if (ret < 0) {
628 rc = ENOMEM;
629 goto error;
630 }
631
632 } else {
633 int ret = asprintf(&sdesc, "%s, %s", scap, spkind);
634 if (ret < 0) {
635 rc = ENOMEM;
636 goto error;
637 }
638 }
639
640 rc = nchoice_add(choice, sdesc, (void *)part, 0);
641 if (rc != EOK) {
642 assert(rc == ENOMEM);
643 printf("Out of memory.\n");
644 goto error;
645 }
646
647 free(scap);
648 scap = NULL;
649 free(spkind);
650 spkind = NULL;
651 free(sfstype);
652 sfstype = NULL;
653 free(sdesc);
654 sdesc = NULL;
655
656 part = fdisk_part_next(part);
657 }
658
659 return EOK;
660error:
661 free(scap);
662 free(spkind);
663 free(sfstype);
664 free(sdesc);
665
666 return rc;
667}
668
669/** Modify partition mount point.
670 *
671 * Run the interaction to modify a partition mount point
672 *
673 * @part Fdisk partition
674 * @return EOK on success or error code
675 */
676static errno_t fdsk_modify_mountp(fdisk_part_t *part)
677{
678 tinput_t *tinput = NULL;
679 errno_t rc;
680 char *mountp = NULL;
681
682 /* Ask for mount point */
683 tinput = tinput_new();
684 if (tinput == NULL) {
685 rc = ENOMEM;
686 goto error;
687 }
688
689 rc = tinput_set_prompt(tinput, "?> ");
690 if (rc != EOK)
691 goto error;
692
693 while (true) {
694 printf("Enter mount point for new partition (Auto, None or /path).\n");
695 rc = tinput_read_i(tinput, "Auto", &mountp);
696 if (rc != EOK)
697 goto error;
698
699 rc = vol_mountp_validate(mountp);
700 if (rc == EOK)
701 break;
702
703 free(mountp);
704 mountp = NULL;
705 }
706
707 rc = fdisk_part_set_mountp(part, mountp);
708 if (rc != EOK)
709 goto error;
710
711 free(mountp);
712
713 tinput_destroy(tinput);
714 tinput = NULL;
715 return EOK;
716error:
717 if (mountp != NULL)
718 free(mountp);
719 if (tinput != NULL)
720 tinput_destroy(tinput);
721 return rc;
722}
723
724/** Modify partition.
725 *
726 * Run the interaction to modify a partition.
727 *
728 * @param dev Fdisk device
729 * @return EOK on success or error code
730 */
731static errno_t fdsk_modify_part(fdisk_dev_t *dev)
732{
733 nchoice_t *choice = NULL;
734 fdisk_part_t *part;
735 void *sel;
736 errno_t rc;
737
738 rc = nchoice_create(&choice);
739 if (rc != EOK) {
740 assert(rc == ENOMEM);
741 printf("Out of memory.\n");
742 goto error;
743 }
744
745 rc = nchoice_set_prompt(choice, "Select partition to modify");
746 if (rc != EOK) {
747 assert(rc == ENOMEM);
748 printf("Out of memory.\n");
749 goto error;
750 }
751
752 rc = fdsk_add_part_choices(dev, choice);
753 if (rc != EOK)
754 goto error;
755
756 rc = nchoice_add(choice, "Cancel", NULL, 0);
757 if (rc != EOK) {
758 assert(rc == ENOMEM);
759 printf("Out of memory.\n");
760 goto error;
761 }
762
763 rc = nchoice_get(choice, &sel);
764 if (rc == ENOENT)
765 return EOK;
766 if (rc != EOK) {
767 printf("Error getting user selection.\n");
768 goto error;
769 }
770
771 nchoice_destroy(choice);
772 choice = NULL;
773
774 if (sel == NULL)
775 return EOK;
776
777 part = (fdisk_part_t *)sel;
778
779 rc = nchoice_create(&choice);
780 if (rc != EOK) {
781 assert(rc == ENOMEM);
782 printf("Out of memory.\n");
783 goto error;
784 }
785
786 rc = nchoice_set_prompt(choice, "Select property to modify");
787 if (rc != EOK) {
788 assert(rc == ENOMEM);
789 printf("Out of memory.\n");
790 goto error;
791 }
792
793 rc = nchoice_add(choice, "Mount point", (void *)pm_mountp, 0);
794 if (rc != EOK) {
795 assert(rc == ENOMEM);
796 printf("Out of memory.\n");
797 goto error;
798 }
799
800 rc = nchoice_add(choice, "Cancel", (void *)pm_cancel, 0);
801 if (rc != EOK) {
802 assert(rc == ENOMEM);
803 printf("Out of memory.\n");
804 goto error;
805 }
806
807 rc = nchoice_get(choice, &sel);
808 if (rc == ENOENT)
809 return EOK;
810 if (rc != EOK) {
811 printf("Error getting user selection.\n");
812 goto error;
813 }
814
815 nchoice_destroy(choice);
816 choice = NULL;
817
818 switch ((pmprop_t)sel) {
819 case pm_mountp:
820 rc = fdsk_modify_mountp(part);
821 break;
822 case pm_cancel:
823 rc = EOK;
824 break;
825 }
826
827 return rc;
828error:
829 if (choice != NULL)
830 nchoice_destroy(choice);
831 return rc;
832}
833
834static errno_t fdsk_delete_part(fdisk_dev_t *dev)
835{
836 nchoice_t *choice = NULL;
837 bool confirm;
838 void *sel;
839 errno_t rc;
840
841 rc = nchoice_create(&choice);
842 if (rc != EOK) {
843 assert(rc == ENOMEM);
844 printf("Out of memory.\n");
845 goto error;
846 }
847
848 rc = nchoice_set_prompt(choice, "Select partition to delete");
849 if (rc != EOK) {
850 assert(rc == ENOMEM);
851 printf("Out of memory.\n");
852 goto error;
853 }
854
855 rc = fdsk_add_part_choices(dev, choice);
856 if (rc != EOK)
857 goto error;
858
859 rc = nchoice_add(choice, "Cancel", NULL, 0);
860 if (rc != EOK) {
861 assert(rc == ENOMEM);
862 printf("Out of memory.\n");
863 goto error;
864 }
865
866 rc = nchoice_get(choice, &sel);
867 if (rc == ENOENT)
868 return EOK;
869 if (rc != EOK) {
870 printf("Error getting user selection.\n");
871 goto error;
872 }
873
874
875 nchoice_destroy(choice);
876 choice = NULL;
877
878 if (sel == NULL)
879 return EOK;
880
881 rc = fdsk_confirm("Warning. Any data in partition will be lost. "
882 "Really delete partition?", &confirm);
883 if (rc != EOK) {
884 printf("Error getting user confirmation.\n");
885 goto error;
886 }
887
888 if (!confirm)
889 return EOK;
890
891 rc = fdisk_part_destroy((fdisk_part_t *)sel);
892 if (rc != EOK) {
893 printf("Error deleting partition.\n");
894 return rc;
895 }
896
897 return EOK;
898error:
899 if (choice != NULL)
900 nchoice_destroy(choice);
901 return rc;
902}
903
904/** Device menu */
905static errno_t fdsk_dev_menu(fdisk_dev_t *dev)
906{
907 nchoice_t *choice = NULL;
908 fdisk_label_info_t linfo;
909 fdisk_part_t *part;
910 fdisk_part_info_t pinfo;
911 cap_spec_t cap;
912 cap_spec_t mcap;
913 fdisk_dev_flags_t dflags;
914 char *sltype = NULL;
915 char *sdcap = NULL;
916 char *scap = NULL;
917 char *smcap = NULL;
918 char *sfstype = NULL;
919 char *svcname = NULL;
920 char *spkind;
921 const char *label;
922 errno_t rc;
923 int npart;
924 void *sel;
925
926 rc = nchoice_create(&choice);
927 if (rc != EOK) {
928 assert(rc == ENOMEM);
929 printf("Out of memory.\n");
930 goto error;
931 }
932
933 rc = nchoice_set_prompt(choice, "Select action");
934 if (rc != EOK) {
935 assert(rc == ENOMEM);
936 printf("Out of memory.\n");
937 goto error;
938 }
939
940 rc = fdisk_dev_capacity(dev, &cap);
941 if (rc != EOK) {
942 printf("Error getting device capacity.\n");
943 goto error;
944 }
945
946 cap_simplify(&cap);
947
948 rc = cap_format(&cap, &sdcap);
949 if (rc != EOK) {
950 printf("Out of memory.\n");
951 goto error;
952 }
953
954 rc = fdisk_dev_get_svcname(dev, &svcname);
955 if (rc != EOK) {
956 printf("Error getting device service name.\n");
957 goto error;
958 }
959
960 fdisk_dev_get_flags(dev, &dflags);
961
962 printf("Device: %s (%s)\n", svcname, sdcap);
963 free(sdcap);
964 sdcap = NULL;
965
966 rc = fdisk_label_get_info(dev, &linfo);
967 if (rc != EOK) {
968 printf("Error getting label information.\n");
969 goto error;
970 }
971
972 switch (linfo.ltype) {
973 case lt_none:
974 printf("Disk contains no label.\n");
975 break;
976 default:
977 rc = label_type_format(linfo.ltype, &sltype);
978 if (rc != EOK) {
979 assert(rc == ENOMEM);
980 printf("Out of memory.\n");
981 goto error;
982 }
983
984 printf("Label type: %s\n", sltype);
985 free(sltype);
986 sltype = NULL;
987 break;
988 }
989
990 part = fdisk_part_first(dev);
991 npart = 0;
992 while (part != NULL) {
993 ++npart;
994 rc = fdisk_part_get_info(part, &pinfo);
995 if (rc != EOK) {
996 printf("Error getting partition information.\n");
997 goto error;
998 }
999
1000 cap_simplify(&pinfo.capacity);
1001
1002 rc = cap_format(&pinfo.capacity, &scap);
1003 if (rc != EOK) {
1004 printf("Out of memory.\n");
1005 goto error;
1006 }
1007
1008 rc = vol_pcnt_fs_format(pinfo.pcnt, pinfo.fstype, &sfstype);
1009 if (rc != EOK) {
1010 printf("Out of memory.\n");
1011 goto error;
1012 }
1013
1014 if (str_size(pinfo.label) > 0)
1015 label = pinfo.label;
1016 else
1017 label = "(No name)";
1018
1019 if (linfo.ltype == lt_none)
1020 printf("Entire disk: %s %s", label, scap);
1021 else
1022 printf("Partition %d: %s %s", npart, label, scap);
1023
1024 if ((linfo.flags & lf_ext_supp) != 0) {
1025 rc = label_pkind_format(pinfo.pkind, &spkind);
1026 if (rc != EOK) {
1027 printf("\nOut of memory.\n");
1028 goto error;
1029 }
1030
1031 printf(", %s", spkind);
1032 free(spkind);
1033 }
1034
1035 if (pinfo.pkind != lpk_extended) {
1036 printf(", %s", sfstype);
1037 }
1038
1039 printf("\n");
1040
1041 free(scap);
1042 scap = NULL;
1043 free(sfstype);
1044 sfstype = NULL;
1045
1046 part = fdisk_part_next(part);
1047 }
1048
1049 /* Display available space */
1050 if ((linfo.flags & lf_can_create_pri) != 0) {
1051 rc = fdisk_part_get_max_avail(dev, spc_pri, &mcap);
1052 if (rc != EOK) {
1053 rc = EIO;
1054 goto error;
1055 }
1056
1057 cap_simplify(&mcap);
1058
1059 rc = cap_format(&mcap, &smcap);
1060 if (rc != EOK) {
1061 rc = ENOMEM;
1062 goto error;
1063 }
1064
1065 if ((linfo.flags & lf_ext_supp) != 0)
1066 printf("Maximum free primary block: %s\n", smcap);
1067 else
1068 printf("Maximum free block: %s\n", smcap);
1069
1070 free(smcap);
1071 smcap = NULL;
1072
1073 rc = fdisk_part_get_tot_avail(dev, spc_pri, &mcap);
1074 if (rc != EOK) {
1075 rc = EIO;
1076 goto error;
1077 }
1078
1079 cap_simplify(&mcap);
1080
1081 rc = cap_format(&mcap, &smcap);
1082 if (rc != EOK) {
1083 rc = ENOMEM;
1084 goto error;
1085 }
1086
1087 if ((linfo.flags & lf_ext_supp) != 0)
1088 printf("Total free primary space: %s\n", smcap);
1089 else
1090 printf("Total free space: %s\n", smcap);
1091
1092 free(smcap);
1093 smcap = NULL;
1094 }
1095
1096 /* Display available space */
1097 if ((linfo.flags & lf_can_create_log) != 0) {
1098 rc = fdisk_part_get_max_avail(dev, spc_log, &mcap);
1099 if (rc != EOK) {
1100 rc = EIO;
1101 goto error;
1102 }
1103
1104 cap_simplify(&mcap);
1105
1106 rc = cap_format(&mcap, &smcap);
1107 if (rc != EOK) {
1108 rc = ENOMEM;
1109 goto error;
1110 }
1111
1112 printf("Maximum free logical block: %s\n", smcap);
1113 free(smcap);
1114 smcap = NULL;
1115
1116 rc = fdisk_part_get_tot_avail(dev, spc_log, &mcap);
1117 if (rc != EOK) {
1118 rc = EIO;
1119 goto error;
1120 }
1121
1122 cap_simplify(&mcap);
1123
1124 rc = cap_format(&mcap, &smcap);
1125 if (rc != EOK) {
1126 rc = ENOMEM;
1127 goto error;
1128 }
1129
1130 printf("Total free logical space: %s\n", smcap);
1131 free(smcap);
1132 smcap = NULL;
1133 }
1134
1135 rc = nchoice_set_prompt(choice, "Select action");
1136 if (rc != EOK) {
1137 assert(rc == ENOMEM);
1138 printf("Out of memory.\n");
1139 goto error;
1140 }
1141
1142 if ((linfo.flags & lf_ext_supp) != 0) {
1143 if ((linfo.flags & lf_can_create_pri) != 0) {
1144 rc = nchoice_add(choice, "Create primary "
1145 "partition",
1146 (void *)devac_create_pri_part, 0);
1147 if (rc != EOK) {
1148 assert(rc == ENOMEM);
1149 printf("Out of memory.\n");
1150 goto error;
1151 }
1152 }
1153
1154 if ((linfo.flags & lf_can_create_ext) != 0) {
1155 rc = nchoice_add(choice, "Create extended "
1156 "partition",
1157 (void *)devac_create_ext_part, 0);
1158 if (rc != EOK) {
1159 assert(rc == ENOMEM);
1160 printf("Out of memory.\n");
1161 goto error;
1162 }
1163 }
1164
1165 if ((linfo.flags & lf_can_create_log) != 0) {
1166 rc = nchoice_add(choice, "Create logical "
1167 "partition",
1168 (void *)devac_create_log_part, 0);
1169 if (rc != EOK) {
1170 assert(rc == ENOMEM);
1171 printf("Out of memory.\n");
1172 goto error;
1173 }
1174 }
1175 } else { /* (linfo.flags & lf_ext_supp) == 0 */
1176 if ((linfo.flags & lf_can_create_pri) != 0) {
1177 rc = nchoice_add(choice, "Create partition",
1178 (void *)devac_create_pri_part, 0);
1179 if (rc != EOK) {
1180 assert(rc == ENOMEM);
1181 printf("Out of memory.\n");
1182 goto error;
1183 }
1184 }
1185 }
1186
1187 if ((linfo.flags & lf_can_modify_part) != 0) {
1188 rc = nchoice_add(choice, "Modify partition",
1189 (void *)devac_modify_part, 0);
1190 if (rc != EOK) {
1191 assert(rc == ENOMEM);
1192 printf("Out of memory.\n");
1193 goto error;
1194 }
1195 }
1196
1197 if ((linfo.flags & lf_can_delete_part) != 0) {
1198 rc = nchoice_add(choice, "Delete partition",
1199 (void *)devac_delete_part, 0);
1200 if (rc != EOK) {
1201 assert(rc == ENOMEM);
1202 printf("Out of memory.\n");
1203 goto error;
1204 }
1205 }
1206
1207 if ((dflags & fdf_can_create_label) != 0) {
1208 rc = nchoice_add(choice, "Create label",
1209 (void *)devac_create_label, 0);
1210 if (rc != EOK) {
1211 assert(rc == ENOMEM);
1212 printf("Out of memory.\n");
1213 goto error;
1214 }
1215 }
1216
1217 if ((dflags & fdf_can_delete_label) != 0) {
1218 rc = nchoice_add(choice, "Delete label",
1219 (void *)devac_delete_label, 0);
1220 if (rc != EOK) {
1221 assert(rc == ENOMEM);
1222 printf("Out of memory.\n");
1223 goto error;
1224 }
1225 }
1226
1227 if ((dflags & fdf_can_erase_dev) != 0) {
1228 rc = nchoice_add(choice, "Erase disk",
1229 (void *)devac_erase_disk, 0);
1230 if (rc != EOK) {
1231 assert(rc == ENOMEM);
1232 printf("Out of memory.\n");
1233 goto error;
1234 }
1235 }
1236
1237 rc = nchoice_add(choice, "Exit", (void *)devac_exit, 0);
1238 if (rc != EOK) {
1239 assert(rc == ENOMEM);
1240 printf("Out of memory.\n");
1241 goto error;
1242 }
1243
1244 rc = nchoice_get(choice, &sel);
1245 if (rc != EOK) {
1246 printf("Error getting user selection.\n");
1247 return rc;
1248 }
1249
1250 switch ((devac_t)sel) {
1251 case devac_create_label:
1252 (void) fdsk_create_label(dev);
1253 break;
1254 case devac_delete_label:
1255 (void) fdsk_delete_label(dev);
1256 break;
1257 case devac_erase_disk:
1258 (void) fdsk_erase_disk(dev);
1259 break;
1260 case devac_create_pri_part:
1261 (void) fdsk_create_part(dev, lpk_primary);
1262 break;
1263 case devac_create_ext_part:
1264 (void) fdsk_create_part(dev, lpk_extended);
1265 break;
1266 case devac_create_log_part:
1267 (void) fdsk_create_part(dev, lpk_logical);
1268 break;
1269 case devac_modify_part:
1270 (void) fdsk_modify_part(dev);
1271 break;
1272 case devac_delete_part:
1273 (void) fdsk_delete_part(dev);
1274 break;
1275 case devac_exit:
1276 quit = true;
1277 break;
1278 }
1279
1280 nchoice_destroy(choice);
1281 return EOK;
1282error:
1283 free(sdcap);
1284 free(scap);
1285 free(smcap);
1286 free(sfstype);
1287 free(svcname);
1288 if (choice != NULL)
1289 nchoice_destroy(choice);
1290 return rc;
1291}
1292
1293int main(int argc, char *argv[])
1294{
1295 service_id_t svcid;
1296 fdisk_dev_t *dev;
1297 errno_t rc;
1298
1299 rc = fdisk_create(&fdisk);
1300 if (rc != EOK) {
1301 printf("Error initializing Fdisk.\n");
1302 return 1;
1303 }
1304
1305 rc = fdsk_dev_sel_choice(&svcid);
1306 if (rc != EOK)
1307 return 1;
1308
1309 if (svcid == 0)
1310 return 0;
1311
1312 rc = fdisk_dev_open(fdisk, svcid, &dev);
1313 if (rc != EOK) {
1314 printf("Error opening device.\n");
1315 return 1;
1316 }
1317
1318 while (!quit) {
1319 rc = fdsk_dev_menu(dev);
1320 if (rc != EOK) {
1321 fdisk_dev_close(dev);
1322 return 1;
1323 }
1324 }
1325
1326 fdisk_dev_close(dev);
1327 fdisk_destroy(fdisk);
1328
1329 return 0;
1330}
1331
1332
1333/** @}
1334 */
Note: See TracBrowser for help on using the repository browser.