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

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

Most of extended (but not logical) partition support.

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