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

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

Disk erasure.

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